mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-18 21:27:51 +00:00
allow prebuilding the device config and reusing it
This commit is contained in:
parent
9fb5b52069
commit
2e7e033bb9
2
.gitignore
vendored
2
.gitignore
vendored
@ -31,3 +31,5 @@ resinrc.yml
|
||||
.idea
|
||||
.vscode
|
||||
.DS_Store
|
||||
|
||||
/tmp
|
||||
|
@ -15,6 +15,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Actually tolerate the `--yes` param to `resin device init`
|
||||
- Allows passing `--drive` to `resin device init`
|
||||
- List detected drives with `resin os available-drives`
|
||||
- Add the `resin os build-config` method to pass the interactive config step once
|
||||
and reuse the built file for consequent `resin os configure` calls (added the new `--config` param to it),
|
||||
and for `resin device init` (same `--config` param)
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -276,6 +276,10 @@ exports.init = {
|
||||
description: 'the drive to write the image to, like /dev/sdb. Careful with this as you can erase your hard drive. Check `resin os available-drives` for available options.',
|
||||
parameter: 'drive',
|
||||
alias: 'd'
|
||||
}, {
|
||||
signature: 'config',
|
||||
description: 'stringified JSON with the device config, see `resin os build-config`',
|
||||
parameter: 'config'
|
||||
}
|
||||
],
|
||||
permission: 'user',
|
||||
@ -310,7 +314,9 @@ exports.init = {
|
||||
return capitanoRunAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) {
|
||||
var configureCommand;
|
||||
configureCommand = "os configure '" + tempPath + "' " + device.uuid;
|
||||
if (options.advanced) {
|
||||
if (options.config) {
|
||||
configureCommand += " --config '" + options.config + "'";
|
||||
} else if (options.advanced) {
|
||||
configureCommand += ' --advanced';
|
||||
}
|
||||
return capitanoRunAsync(configureCommand).then(function() {
|
||||
|
@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
var _, commandOptions, formatVersion, initWarningMessage, resolveVersion;
|
||||
var INIT_WARNING_MESSAGE, _, buildConfig, commandOptions, formatVersion, resolveVersion;
|
||||
|
||||
commandOptions = require('./command-options');
|
||||
|
||||
@ -135,10 +135,34 @@ exports.download = {
|
||||
}
|
||||
};
|
||||
|
||||
exports.configure = {
|
||||
signature: 'os configure <image> <uuid>',
|
||||
description: 'configure an os image',
|
||||
help: 'Use this command to configure a previously download operating system image with a device.\n\nExamples:\n\n $ resin os configure ../path/rpi.img 7cf02a6',
|
||||
buildConfig = function(image, deviceType, advanced) {
|
||||
var form, helpers;
|
||||
if (advanced == null) {
|
||||
advanced = false;
|
||||
}
|
||||
form = require('resin-cli-form');
|
||||
helpers = require('../utils/helpers');
|
||||
return helpers.getManifest(image, deviceType).get('options').then(function(questions) {
|
||||
var advancedGroup, override;
|
||||
if (!advanced) {
|
||||
advancedGroup = _.findWhere(questions, {
|
||||
name: 'advanced',
|
||||
isGroup: true
|
||||
});
|
||||
if (advancedGroup != null) {
|
||||
override = helpers.getGroupDefaults(advancedGroup);
|
||||
}
|
||||
}
|
||||
return form.run(questions, {
|
||||
override: override
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.buildConfig = {
|
||||
signature: 'os build-config <image> <device-type>',
|
||||
description: 'build the OS config and save it to the JSON file',
|
||||
help: 'Use this command to prebuild the OS config once and skip the interactive part of `resin os configure`.\n\nExamples:\n\n $ resin os build-config ../path/rpi3.img raspberrypi3 --output rpi3-config.json\n $ resin os configure ../path/rpi3.img 7cf02a6 --config "$(cat rpi3-config.json)"',
|
||||
permission: 'user',
|
||||
options: [
|
||||
{
|
||||
@ -146,38 +170,58 @@ exports.configure = {
|
||||
description: 'show advanced commands',
|
||||
boolean: true,
|
||||
alias: 'v'
|
||||
}, {
|
||||
signature: 'output',
|
||||
description: 'the path to the output JSON file',
|
||||
alias: 'o',
|
||||
required: 'the output path is required',
|
||||
parameter: 'output'
|
||||
}
|
||||
],
|
||||
action: function(params, options, done) {
|
||||
var form, helpers, init, resin;
|
||||
resin = require('resin-sdk-preconfigured');
|
||||
form = require('resin-cli-form');
|
||||
init = require('resin-device-init');
|
||||
helpers = require('../utils/helpers');
|
||||
console.info('Configuring operating system image');
|
||||
return resin.models.device.get(params.uuid).then(function(device) {
|
||||
return helpers.getManifest(params.image, device.device_type).get('options').then(function(questions) {
|
||||
var advancedGroup, override;
|
||||
if (!options.advanced) {
|
||||
advancedGroup = _.findWhere(questions, {
|
||||
name: 'advanced',
|
||||
isGroup: true
|
||||
});
|
||||
if (advancedGroup != null) {
|
||||
override = helpers.getGroupDefaults(advancedGroup);
|
||||
}
|
||||
}
|
||||
return form.run(questions, {
|
||||
override: override
|
||||
});
|
||||
}).then(function(answers) {
|
||||
return init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler);
|
||||
});
|
||||
var Promise, fs, writeFileAsync;
|
||||
fs = require('fs');
|
||||
Promise = require('bluebird');
|
||||
writeFileAsync = Promise.promisify(fs.writeFile);
|
||||
return buildConfig(params.image, params['device-type'], options.advanced).then(function(answers) {
|
||||
return writeFileAsync(options.output, JSON.stringify(answers, null, 4));
|
||||
}).nodeify(done);
|
||||
}
|
||||
};
|
||||
|
||||
initWarningMessage = 'Note: Initializing the device may ask for administrative permissions\nbecause we need to access the raw devices directly.';
|
||||
exports.configure = {
|
||||
signature: 'os configure <image> <uuid>',
|
||||
description: 'configure an os image',
|
||||
help: 'Use this command to configure a previously downloaded operating system image for the specific device.\n\nExamples:\n\n $ resin os configure ../path/rpi.img 7cf02a6',
|
||||
permission: 'user',
|
||||
options: [
|
||||
{
|
||||
signature: 'advanced',
|
||||
description: 'show advanced commands',
|
||||
boolean: true,
|
||||
alias: 'v'
|
||||
}, {
|
||||
signature: 'config',
|
||||
description: 'stringified JSON with the device config, see `resin os build-config`',
|
||||
parameter: 'config'
|
||||
}
|
||||
],
|
||||
action: function(params, options, done) {
|
||||
var helpers, init, resin;
|
||||
resin = require('resin-sdk-preconfigured');
|
||||
init = require('resin-device-init');
|
||||
helpers = require('../utils/helpers');
|
||||
console.info('Configuring operating system image');
|
||||
return resin.models.device.get(params.uuid).then(function(device) {
|
||||
if (options.config) {
|
||||
return JSON.parse(options.config);
|
||||
}
|
||||
return buildConfig(params.image, device.device_type, options.advanced);
|
||||
}).then(function(answers) {
|
||||
return init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler);
|
||||
}).nodeify(done);
|
||||
}
|
||||
};
|
||||
|
||||
exports.availableDrives = {
|
||||
signature: 'os available-drives',
|
||||
@ -212,10 +256,12 @@ exports.availableDrives = {
|
||||
}
|
||||
};
|
||||
|
||||
INIT_WARNING_MESSAGE = 'Note: Initializing the device may ask for administrative permissions\nbecause we need to access the raw devices directly.';
|
||||
|
||||
exports.initialize = {
|
||||
signature: 'os initialize <image>',
|
||||
description: 'initialize an os image',
|
||||
help: "Use this command to initialize a device with previously configured operating system image.\n\n" + initWarningMessage + "\n\nExamples:\n\n $ resin os initialize ../path/rpi.img --type 'raspberry-pi'",
|
||||
help: "Use this command to initialize a device with previously configured operating system image.\n\n" + INIT_WARNING_MESSAGE + "\n\nExamples:\n\n $ resin os initialize ../path/rpi.img --type 'raspberry-pi'",
|
||||
permission: 'user',
|
||||
options: [
|
||||
commandOptions.yes, {
|
||||
@ -238,7 +284,7 @@ exports.initialize = {
|
||||
form = require('resin-cli-form');
|
||||
patterns = require('../utils/patterns');
|
||||
helpers = require('../utils/helpers');
|
||||
console.info("Initializing device\n\n" + initWarningMessage);
|
||||
console.info("Initializing device\n\n" + INIT_WARNING_MESSAGE);
|
||||
return helpers.getManifest(params.image, options.type).then(function(manifest) {
|
||||
var ref;
|
||||
return (ref = manifest.initialization) != null ? ref.options : void 0;
|
||||
|
@ -172,6 +172,8 @@ capitano.command(actions.os.availableDrives);
|
||||
|
||||
capitano.command(actions.os.download);
|
||||
|
||||
capitano.command(actions.os.buildConfig);
|
||||
|
||||
capitano.command(actions.os.configure);
|
||||
|
||||
capitano.command(actions.os.initialize);
|
||||
|
@ -380,6 +380,11 @@ exports.init =
|
||||
parameter: 'drive'
|
||||
alias: 'd'
|
||||
}
|
||||
{
|
||||
signature: 'config'
|
||||
description: 'stringified JSON with the device config, see `resin os build-config`'
|
||||
parameter: 'config'
|
||||
}
|
||||
]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
@ -412,7 +417,9 @@ exports.init =
|
||||
.then(resin.models.device.get)
|
||||
.tap (device) ->
|
||||
configureCommand = "os configure '#{tempPath}' #{device.uuid}"
|
||||
if options.advanced
|
||||
if options.config
|
||||
configureCommand += " --config '#{options.config}'"
|
||||
else if options.advanced
|
||||
configureCommand += ' --advanced'
|
||||
capitanoRunAsync(configureCommand)
|
||||
.then ->
|
||||
|
@ -144,11 +144,65 @@ exports.download =
|
||||
console.info('The image was downloaded successfully')
|
||||
.nodeify(done)
|
||||
|
||||
buildConfig = (image, deviceType, advanced = false) ->
|
||||
form = require('resin-cli-form')
|
||||
helpers = require('../utils/helpers')
|
||||
|
||||
helpers.getManifest(image, deviceType)
|
||||
.get('options')
|
||||
.then (questions) ->
|
||||
if not advanced
|
||||
advancedGroup = _.findWhere questions,
|
||||
name: 'advanced'
|
||||
isGroup: true
|
||||
|
||||
if advancedGroup?
|
||||
override = helpers.getGroupDefaults(advancedGroup)
|
||||
|
||||
return form.run(questions, { override })
|
||||
|
||||
exports.buildConfig =
|
||||
signature: 'os build-config <image> <device-type>'
|
||||
description: 'build the OS config and save it to the JSON file'
|
||||
help: '''
|
||||
Use this command to prebuild the OS config once and skip the interactive part of `resin os configure`.
|
||||
|
||||
Examples:
|
||||
|
||||
$ resin os build-config ../path/rpi3.img raspberrypi3 --output rpi3-config.json
|
||||
$ resin os configure ../path/rpi3.img 7cf02a6 --config "$(cat rpi3-config.json)"
|
||||
'''
|
||||
permission: 'user'
|
||||
options: [
|
||||
{
|
||||
signature: 'advanced'
|
||||
description: 'show advanced commands'
|
||||
boolean: true
|
||||
alias: 'v'
|
||||
}
|
||||
{
|
||||
signature: 'output'
|
||||
description: 'the path to the output JSON file'
|
||||
alias: 'o'
|
||||
required: 'the output path is required'
|
||||
parameter: 'output'
|
||||
}
|
||||
]
|
||||
action: (params, options, done) ->
|
||||
fs = require('fs')
|
||||
Promise = require('bluebird')
|
||||
writeFileAsync = Promise.promisify(fs.writeFile)
|
||||
|
||||
buildConfig(params.image, params['device-type'], options.advanced)
|
||||
.then (answers) ->
|
||||
writeFileAsync(options.output, JSON.stringify(answers, null, 4))
|
||||
.nodeify(done)
|
||||
|
||||
exports.configure =
|
||||
signature: 'os configure <image> <uuid>'
|
||||
description: 'configure an os image'
|
||||
help: '''
|
||||
Use this command to configure a previously download operating system image with a device.
|
||||
Use this command to configure a previously downloaded operating system image for the specific device.
|
||||
|
||||
Examples:
|
||||
|
||||
@ -156,41 +210,32 @@ exports.configure =
|
||||
'''
|
||||
permission: 'user'
|
||||
options: [
|
||||
signature: 'advanced'
|
||||
description: 'show advanced commands'
|
||||
boolean: true
|
||||
alias: 'v'
|
||||
{
|
||||
signature: 'advanced'
|
||||
description: 'show advanced commands'
|
||||
boolean: true
|
||||
alias: 'v'
|
||||
}
|
||||
{
|
||||
signature: 'config'
|
||||
description: 'stringified JSON with the device config, see `resin os build-config`'
|
||||
parameter: 'config'
|
||||
}
|
||||
]
|
||||
action: (params, options, done) ->
|
||||
resin = require('resin-sdk-preconfigured')
|
||||
form = require('resin-cli-form')
|
||||
init = require('resin-device-init')
|
||||
helpers = require('../utils/helpers')
|
||||
|
||||
console.info('Configuring operating system image')
|
||||
resin.models.device.get(params.uuid).then (device) ->
|
||||
helpers.getManifest(params.image, device.device_type)
|
||||
.get('options')
|
||||
.then (questions) ->
|
||||
|
||||
if not options.advanced
|
||||
advancedGroup = _.findWhere questions,
|
||||
name: 'advanced'
|
||||
isGroup: true
|
||||
|
||||
if advancedGroup?
|
||||
override = helpers.getGroupDefaults(advancedGroup)
|
||||
|
||||
return form.run(questions, { override })
|
||||
.then (answers) ->
|
||||
init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler)
|
||||
if options.config
|
||||
return JSON.parse(options.config)
|
||||
buildConfig(params.image, device.device_type, options.advanced)
|
||||
.then (answers) ->
|
||||
init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler)
|
||||
.nodeify(done)
|
||||
|
||||
initWarningMessage = '''
|
||||
Note: Initializing the device may ask for administrative permissions
|
||||
because we need to access the raw devices directly.
|
||||
'''
|
||||
|
||||
exports.availableDrives =
|
||||
# TODO: dedupe with https://github.com/resin-io-modules/resin-cli-visuals/blob/master/lib/widgets/drive/index.coffee
|
||||
signature: 'os available-drives'
|
||||
@ -217,6 +262,10 @@ exports.availableDrives =
|
||||
drives.forEach (drive) ->
|
||||
console.log(formatDrive(drive))
|
||||
|
||||
INIT_WARNING_MESSAGE = '''
|
||||
Note: Initializing the device may ask for administrative permissions
|
||||
because we need to access the raw devices directly.
|
||||
'''
|
||||
|
||||
exports.initialize =
|
||||
signature: 'os initialize <image>'
|
||||
@ -224,7 +273,7 @@ exports.initialize =
|
||||
help: """
|
||||
Use this command to initialize a device with previously configured operating system image.
|
||||
|
||||
#{initWarningMessage}
|
||||
#{INIT_WARNING_MESSAGE}
|
||||
|
||||
Examples:
|
||||
|
||||
@ -257,7 +306,7 @@ exports.initialize =
|
||||
console.info("""
|
||||
Initializing device
|
||||
|
||||
#{initWarningMessage}
|
||||
#{INIT_WARNING_MESSAGE}
|
||||
""")
|
||||
helpers.getManifest(params.image, options.type)
|
||||
.then (manifest) ->
|
||||
|
@ -138,6 +138,7 @@ capitano.command(actions.env.remove)
|
||||
capitano.command(actions.os.versions)
|
||||
capitano.command(actions.os.availableDrives)
|
||||
capitano.command(actions.os.download)
|
||||
capitano.command(actions.os.buildConfig)
|
||||
capitano.command(actions.os.configure)
|
||||
capitano.command(actions.os.initialize)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user