diff --git a/doc/cli.markdown b/doc/cli.markdown index e750cec7..9151bbd0 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -977,17 +977,20 @@ the path to the output JSON file Use this command to configure a previously downloaded operating system image for the specific device or for an application generally. +Calling this command without --version is not recommended, and may fail in +future releases if the OS version cannot be inferred. + Note that device api keys are only supported on ResinOS 2.0.3+. -This comand still supports the *deprecated* format where the UUID and optionally device key +This command still supports the *deprecated* format where the UUID and optionally device key are passed directly on the command line, but the recommended way is to pass either an --app or --device argument. The deprecated format will be remove in a future release. Examples: - $ resin os configure ../path/rpi.img --device 7cf02a6 - $ resin os configure ../path/rpi.img --device 7cf02a6 --deviceApiKey - $ resin os configure ../path/rpi.img --app MyApp + $ resin os configure ../path/rpi.img --device 7cf02a6 --version 2.12.7 + $ resin os configure ../path/rpi.img --device 7cf02a6 --version 2.12.7 --device-api-key + $ resin os configure ../path/rpi.img --app MyApp --version 2.12.7 ### Options @@ -1007,6 +1010,10 @@ device uuid custom device key - note that this is only supported on ResinOS 2.0.3+ +#### --version <version> + +a ResinOS version + #### --config <config> path to the config JSON file, see `resin os build-config` @@ -1125,22 +1132,29 @@ show advanced commands Use this command to generate a config.json for a device or application. +Calling this command without --version is not recommended, and may fail in +future releases if the OS version cannot be inferred. + This is interactive by default, but you can do this automatically without interactivity by specifying an option for each question on the command line, if you know the questions that will be asked for the relevant device type. Examples: - $ resin config generate --device 7cf02a6 - $ resin config generate --device 7cf02a6 --generate-device-api-key - $ resin config generate --device 7cf02a6 --device-api-key - $ resin config generate --device 7cf02a6 --output config.json - $ resin config generate --app MyApp - $ resin config generate --app MyApp --output config.json - $ resin config generate --app MyApp --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1 + $ resin config generate --device 7cf02a6 --version 2.12.7 + $ resin config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key + $ resin config generate --device 7cf02a6 --version 2.12.7 --device-api-key + $ resin config generate --device 7cf02a6 --version 2.12.7 --output config.json + $ resin config generate --app MyApp --version 2.12.7 + $ resin config generate --app MyApp --version 2.12.7 --output config.json + $ resin config generate --app MyApp --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1 ### Options +#### --version <version> + +a ResinOS version + #### --application, -a, --app <application> application name diff --git a/lib/actions/command-options.coffee b/lib/actions/command-options.coffee index 4b78cc31..de721f81 100644 --- a/lib/actions/command-options.coffee +++ b/lib/actions/command-options.coffee @@ -44,6 +44,11 @@ exports.optionalDeviceApiKey = parameter: 'device-api-key' alias: 'k' +exports.optionalOsVersion = + signature: 'version' + description: 'a ResinOS version' + parameter: 'version' + exports.booleanDevice = signature: 'device' description: 'device' diff --git a/lib/actions/config.coffee b/lib/actions/config.coffee index 055e8e00..361dd88e 100644 --- a/lib/actions/config.coffee +++ b/lib/actions/config.coffee @@ -223,21 +223,26 @@ exports.generate = help: ''' Use this command to generate a config.json for a device or application. + Calling this command without --version is not recommended, and may fail in + future releases if the OS version cannot be inferred. + This is interactive by default, but you can do this automatically without interactivity by specifying an option for each question on the command line, if you know the questions that will be asked for the relevant device type. Examples: - $ resin config generate --device 7cf02a6 - $ resin config generate --device 7cf02a6 --generate-device-api-key - $ resin config generate --device 7cf02a6 --device-api-key - $ resin config generate --device 7cf02a6 --output config.json - $ resin config generate --app MyApp - $ resin config generate --app MyApp --output config.json - $ resin config generate --app MyApp --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1 + $ resin config generate --device 7cf02a6 --version 2.12.7 + $ resin config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key + $ resin config generate --device 7cf02a6 --version 2.12.7 --device-api-key + $ resin config generate --device 7cf02a6 --version 2.12.7 --output config.json + $ resin config generate --app MyApp --version 2.12.7 + $ resin config generate --app MyApp --version 2.12.7 --output config.json + $ resin config generate --app MyApp --version 2.12.7 \ + --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1 ''' options: [ + commandOptions.optionalOsVersion commandOptions.optionalApplication commandOptions.optionalDevice commandOptions.optionalDeviceApiKey @@ -308,6 +313,8 @@ exports.generate = # required option, that value is used (and the corresponding question is not asked) form.run(formOptions, override: options) .then (answers) -> + answers.version = options.version + if resource.uuid? generateDeviceConfig(resource, options.deviceApiKey || options['generate-device-api-key'], answers) else diff --git a/lib/actions/os.coffee b/lib/actions/os.coffee index 03c42ed1..1adb2eb5 100644 --- a/lib/actions/os.coffee +++ b/lib/actions/os.coffee @@ -203,17 +203,20 @@ exports.configure = Use this command to configure a previously downloaded operating system image for the specific device or for an application generally. + Calling this command without --version is not recommended, and may fail in + future releases if the OS version cannot be inferred. + Note that device api keys are only supported on ResinOS 2.0.3+. - This comand still supports the *deprecated* format where the UUID and optionally device key + This command still supports the *deprecated* format where the UUID and optionally device key are passed directly on the command line, but the recommended way is to pass either an --app or --device argument. The deprecated format will be remove in a future release. Examples: - $ resin os configure ../path/rpi.img --device 7cf02a6 - $ resin os configure ../path/rpi.img --device 7cf02a6 --deviceApiKey - $ resin os configure ../path/rpi.img --app MyApp + $ resin os configure ../path/rpi.img --device 7cf02a6 --version 2.12.7 + $ resin os configure ../path/rpi.img --device 7cf02a6 --version 2.12.7 --device-api-key + $ resin os configure ../path/rpi.img --app MyApp --version 2.12.7 ''' permission: 'user' options: [ @@ -221,6 +224,7 @@ exports.configure = commandOptions.optionalApplication commandOptions.optionalDevice commandOptions.optionalDeviceApiKey + commandOptions.optionalOsVersion { signature: 'config' description: 'path to the config JSON file, see `resin os build-config`' @@ -279,6 +283,8 @@ exports.configure = .then(JSON.parse) return buildConfig(params.image, appOrDevice.device_type, options.advanced) .then (answers) -> + answers.version = options.version + (if configurationResourceType == 'device' generateDeviceConfig(appOrDevice, deviceApiKey, answers) else diff --git a/lib/utils/config.ts b/lib/utils/config.ts index 6e3e5fc4..8eebb655 100644 --- a/lib/utils/config.ts +++ b/lib/utils/config.ts @@ -17,16 +17,17 @@ import Promise = require('bluebird'); import ResinSdk = require('resin-sdk'); import _ = require('lodash'); import deviceConfig = require('resin-device-config'); +import * as semver from 'resin-semver'; const resin = ResinSdk.fromSharedOptions(); export function generateBaseConfig( application: ResinSdk.Application, - options: { appUpdatePollInterval?: number }, + options: { version?: string; appUpdatePollInterval?: number }, ) { options = _.mapValues(options, function(value, key) { if (key === 'appUpdatePollInterval') { - return value! * 60 * 1000; + return value * 60 * 1000; } else { return value; } @@ -66,27 +67,30 @@ export function generateBaseConfig( export function generateApplicationConfig( application: ResinSdk.Application, - options: {}, + options: { version?: string }, ) { - return generateBaseConfig(application, options).tap(config => - addApplicationKey(config, application.id), - ); + return generateBaseConfig(application, options).tap(config => { + if (semver.satisfies(options.version, '>=2.7.8')) { + return addProvisioningKey(config, application.id); + } else { + return addApplicationKey(config, application.id); + } + }); } export function generateDeviceConfig( device: ResinSdk.Device & { belongs_to__application: ResinSdk.PineDeferred }, deviceApiKey: string | true | null, - options: {}, + options: { version?: string }, ) { return resin.models.application .get(device.belongs_to__application.__id) .then(application => { return generateBaseConfig(application, options).tap(config => { - // Device API keys are only safe for ResinOS 2.0.3+. We could somehow obtain - // the expected version for this config and generate one when we know it's safe, - // but instead for now we fall back to app keys unless the user has explicitly opted in. if (deviceApiKey) { return addDeviceKey(config, device.uuid, deviceApiKey); + } else if (semver.satisfies(options.version, '>=2.0.3')) { + return addDeviceKey(config, device.uuid, true); } else { return addApplicationKey(config, application.id); } @@ -111,6 +115,14 @@ function addApplicationKey(config: any, applicationNameOrId: string | number) { }); } +function addProvisioningKey(config: any, applicationNameOrId: string | number) { + return resin.models.application + .generateProvisioningKey(applicationNameOrId) + .tap(apiKey => { + config.apiKey = apiKey; + }); +} + function addDeviceKey( config: any, uuid: string, diff --git a/package.json b/package.json index 934193b5..ff08fc69 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "dependencies": { "@resin.io/valid-email": "^0.1.0", "@types/stream-to-promise": "^2.2.0", + "JSONStream": "^1.0.3", "ansi-escapes": "^2.0.0", "any-promise": "^1.3.0", "archiver": "^2.1.0", @@ -119,7 +120,6 @@ "inquirer": "^3.1.1", "is-root": "^1.0.0", "js-yaml": "^3.10.0", - "JSONStream": "^1.0.3", "klaw": "^1.3.1", "lodash": "^4.17.4", "mixpanel": "^0.4.0", @@ -151,6 +151,7 @@ "resin-release": "^1.2.0", "resin-sdk": "10.0.0-beta1", "resin-sdk-preconfigured": "^6.9.0", + "resin-semver": "^1.2.2", "resin-settings-client": "^3.6.1", "resin-stream-logger": "^0.1.0", "resin-sync": "^9.3.3",