mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-19 11:16:38 +00:00
Merge pull request #201 from resin-io/jviotti/feature/os-configure
Implement os configure
This commit is contained in:
commit
61474fba5c
@ -152,26 +152,28 @@
|
||||
}
|
||||
return vcs.getApplicationName(process.cwd());
|
||||
}).then(resin.models.application.get).then(function(application) {
|
||||
console.info('Getting configuration options');
|
||||
return patterns.askDeviceOptions(application.device_type).tap(function(answers) {
|
||||
var message;
|
||||
if (answers.drive != null) {
|
||||
message = "This will erase " + answers.drive + ". Are you sure?";
|
||||
return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync);
|
||||
}
|
||||
}).then(function(answers) {
|
||||
return tmp.tmpNameAsync().then(function(temporalPath) {
|
||||
return capitano.runAsync("os download --output " + temporalPath);
|
||||
}).then(function(temporalPath) {
|
||||
var uuid;
|
||||
uuid = resin.models.device.generateUUID();
|
||||
console.log("Registering to " + application.app_name + ": " + uuid);
|
||||
return resin.models.device.register(application.app_name, uuid).tap(function(device) {
|
||||
console.log('Configuring operating system');
|
||||
return init.configure(temporalPath, device.uuid, answers).then(stepHandler).then(function() {
|
||||
console.log('Initializing device');
|
||||
return init.initialize(temporalPath, device.uuid, answers).then(stepHandler);
|
||||
}).tap(function() {
|
||||
return tmp.tmpNameAsync().then(function(temporalPath) {
|
||||
return capitano.runAsync("os download --output " + temporalPath);
|
||||
}).then(function(temporalPath) {
|
||||
var uuid;
|
||||
uuid = resin.models.device.generateUUID();
|
||||
console.log("Registering to " + application.app_name + ": " + uuid);
|
||||
return resin.models.device.register(application.app_name, uuid).tap(function(device) {
|
||||
console.log('Configuring operating system');
|
||||
return capitano.runAsync("os configure " + temporalPath + " " + uuid).then(function() {
|
||||
console.log('Initializing device');
|
||||
return resin.models.device.getManifestBySlug(application.device_type).then(function(manifest) {
|
||||
var ref;
|
||||
return form.run((ref = manifest.initialization) != null ? ref.options : void 0);
|
||||
}).tap(function(answers) {
|
||||
var message;
|
||||
if (answers.drive != null) {
|
||||
message = "This will erase " + answers.drive + ". Are you sure?";
|
||||
return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync);
|
||||
}
|
||||
}).then(function(answers) {
|
||||
return init.initialize(temporalPath, device.uuid, answers).then(stepHandler)["return"](answers);
|
||||
}).tap(function(answers) {
|
||||
if (answers.drive == null) {
|
||||
return;
|
||||
}
|
||||
@ -179,21 +181,21 @@
|
||||
return console.log("You can safely remove " + answers.drive + " now");
|
||||
});
|
||||
});
|
||||
}).then(function(device) {
|
||||
console.log('Done');
|
||||
return device.uuid;
|
||||
})["finally"](function() {
|
||||
return fs.statAsync(temporalPath).then(function(stat) {
|
||||
if (stat.isDirectory()) {
|
||||
return rimraf(temporalPath);
|
||||
}
|
||||
return fs.unlinkAsync(temporalPath);
|
||||
})["catch"](function(error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
}).then(function(device) {
|
||||
console.log('Done');
|
||||
return device.uuid;
|
||||
})["finally"](function() {
|
||||
return fs.statAsync(temporalPath).then(function(stat) {
|
||||
if (stat.isDirectory()) {
|
||||
return rimraf(temporalPath);
|
||||
}
|
||||
return fs.unlinkAsync(temporalPath);
|
||||
})["catch"](function(error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,20 @@
|
||||
(function() {
|
||||
var fs, helpers, manager, visuals;
|
||||
var _, form, fs, helpers, init, manager, resin, stepHandler, visuals;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
_ = require('lodash');
|
||||
|
||||
resin = require('resin-sdk');
|
||||
|
||||
manager = require('resin-image-manager');
|
||||
|
||||
visuals = require('resin-cli-visuals');
|
||||
|
||||
form = require('resin-cli-form');
|
||||
|
||||
init = require('resin-device-init');
|
||||
|
||||
helpers = require('../utils/helpers');
|
||||
|
||||
exports.download = {
|
||||
@ -47,4 +55,32 @@
|
||||
}
|
||||
};
|
||||
|
||||
stepHandler = function(step) {
|
||||
var bar;
|
||||
step.on('stdout', _.bind(process.stdout.write, process.stdout));
|
||||
step.on('stderr', _.bind(process.stderr.write, process.stderr));
|
||||
step.on('state', function(state) {
|
||||
if (state.operation.command === 'burn') {
|
||||
return;
|
||||
}
|
||||
return console.log(helpers.stateToString(state));
|
||||
});
|
||||
bar = new visuals.Progress('Writing Device OS');
|
||||
step.on('burn', _.bind(bar.update, bar));
|
||||
return helpers.waitStream(step);
|
||||
};
|
||||
|
||||
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 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9',
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
console.info('Configuring operating system image');
|
||||
return resin.models.device.get(params.uuid).get('device_type').then(resin.models.device.getManifestBySlug).get('options').then(form.run).then(function(answers) {
|
||||
return init.configure(params.image, params.uuid, answers).then(stepHandler);
|
||||
}).nodeify(done);
|
||||
}
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
@ -92,6 +92,8 @@
|
||||
|
||||
capitano.command(actions.os.download);
|
||||
|
||||
capitano.command(actions.os.configure);
|
||||
|
||||
capitano.command(actions.logs);
|
||||
|
||||
update.notify();
|
||||
|
@ -39,6 +39,7 @@
|
||||
exports.waitStream = function(stream) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
stream.on('close', resolve);
|
||||
stream.on('end', resolve);
|
||||
return stream.on('error', reject);
|
||||
});
|
||||
};
|
||||
|
@ -98,13 +98,4 @@
|
||||
});
|
||||
};
|
||||
|
||||
exports.askDeviceOptions = function(deviceType) {
|
||||
return resin.models.config.getDeviceOptions(deviceType).then(form.run).then(function(answers) {
|
||||
if (answers.os == null) {
|
||||
answers.os = helpers.getOperatingSystem();
|
||||
}
|
||||
return answers;
|
||||
});
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
@ -72,6 +72,7 @@ Now you have access to all the commands referenced below.
|
||||
- OS
|
||||
|
||||
- [os download <type>](#os-download-60-type-62-)
|
||||
- [os configure <image> <uuid>](#os-configure-60-image-62-60-uuid-62-)
|
||||
|
||||
- Wizard
|
||||
|
||||
@ -560,6 +561,14 @@ Examples:
|
||||
|
||||
output path
|
||||
|
||||
## os configure <image> <uuid>
|
||||
|
||||
Use this command to configure a previously download operating system image with a device.
|
||||
|
||||
Examples:
|
||||
|
||||
$ resin os configure ../path/rpi.img 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9
|
||||
|
||||
# Wizard
|
||||
|
||||
## quickstart [name]
|
||||
|
@ -198,42 +198,44 @@ exports.init =
|
||||
return vcs.getApplicationName(process.cwd())
|
||||
.then(resin.models.application.get)
|
||||
.then (application) ->
|
||||
|
||||
console.info('Getting configuration options')
|
||||
patterns.askDeviceOptions(application.device_type).tap (answers) ->
|
||||
if answers.drive?
|
||||
message = "This will erase #{answers.drive}. Are you sure?"
|
||||
patterns.confirm(options.yes, message)
|
||||
.return(answers.drive)
|
||||
.then(umount.umountAsync)
|
||||
.then (answers) ->
|
||||
tmp.tmpNameAsync().then (temporalPath) ->
|
||||
return capitano.runAsync("os download --output #{temporalPath}")
|
||||
.then (temporalPath) ->
|
||||
uuid = resin.models.device.generateUUID()
|
||||
console.log("Registering to #{application.app_name}: #{uuid}")
|
||||
resin.models.device.register(application.app_name, uuid).tap (device) ->
|
||||
console.log('Configuring operating system')
|
||||
init.configure(temporalPath, device.uuid, answers).then(stepHandler).then ->
|
||||
console.log('Initializing device')
|
||||
init.initialize(temporalPath, device.uuid, answers).then(stepHandler)
|
||||
.tap ->
|
||||
tmp.tmpNameAsync().then (temporalPath) ->
|
||||
return capitano.runAsync("os download --output #{temporalPath}")
|
||||
.then (temporalPath) ->
|
||||
uuid = resin.models.device.generateUUID()
|
||||
console.log("Registering to #{application.app_name}: #{uuid}")
|
||||
resin.models.device.register(application.app_name, uuid).tap (device) ->
|
||||
console.log('Configuring operating system')
|
||||
capitano.runAsync("os configure #{temporalPath} #{uuid}").then ->
|
||||
console.log('Initializing device')
|
||||
resin.models.device.getManifestBySlug(application.device_type).then (manifest) ->
|
||||
return form.run(manifest.initialization?.options)
|
||||
.tap (answers) ->
|
||||
if answers.drive?
|
||||
message = "This will erase #{answers.drive}. Are you sure?"
|
||||
patterns.confirm(options.yes, message)
|
||||
.return(answers.drive)
|
||||
.then(umount.umountAsync)
|
||||
.then (answers) ->
|
||||
init.initialize(temporalPath, device.uuid, answers)
|
||||
.then(stepHandler)
|
||||
.return(answers)
|
||||
.tap (answers) ->
|
||||
return if not answers.drive?
|
||||
umount.umountAsync(answers.drive).tap ->
|
||||
console.log("You can safely remove #{answers.drive} now")
|
||||
.then (device) ->
|
||||
console.log('Done')
|
||||
return device.uuid
|
||||
.then (device) ->
|
||||
console.log('Done')
|
||||
return device.uuid
|
||||
|
||||
.finally ->
|
||||
fs.statAsync(temporalPath).then (stat) ->
|
||||
return rimraf(temporalPath) if stat.isDirectory()
|
||||
return fs.unlinkAsync(temporalPath)
|
||||
.catch (error) ->
|
||||
.finally ->
|
||||
fs.statAsync(temporalPath).then (stat) ->
|
||||
return rimraf(temporalPath) if stat.isDirectory()
|
||||
return fs.unlinkAsync(temporalPath)
|
||||
.catch (error) ->
|
||||
|
||||
# Ignore errors if temporary file does not exist
|
||||
return if error.code is 'ENOENT'
|
||||
# Ignore errors if temporary file does not exist
|
||||
return if error.code is 'ENOENT'
|
||||
|
||||
throw error
|
||||
throw error
|
||||
|
||||
.nodeify(done)
|
||||
|
@ -1,6 +1,10 @@
|
||||
fs = require('fs')
|
||||
_ = require('lodash')
|
||||
resin = require('resin-sdk')
|
||||
manager = require('resin-image-manager')
|
||||
visuals = require('resin-cli-visuals')
|
||||
form = require('resin-cli-form')
|
||||
init = require('resin-device-init')
|
||||
helpers = require('../utils/helpers')
|
||||
|
||||
exports.download =
|
||||
@ -43,3 +47,39 @@ exports.download =
|
||||
.tap (output) ->
|
||||
console.log("The image was downloaded to #{output}")
|
||||
.nodeify(done)
|
||||
|
||||
stepHandler = (step) ->
|
||||
step.on('stdout', _.bind(process.stdout.write, process.stdout))
|
||||
step.on('stderr', _.bind(process.stderr.write, process.stderr))
|
||||
|
||||
step.on 'state', (state) ->
|
||||
return if state.operation.command is 'burn'
|
||||
console.log(helpers.stateToString(state))
|
||||
|
||||
bar = new visuals.Progress('Writing Device OS')
|
||||
|
||||
step.on('burn', _.bind(bar.update, bar))
|
||||
|
||||
return helpers.waitStream(step)
|
||||
|
||||
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.
|
||||
|
||||
Examples:
|
||||
|
||||
$ resin os configure ../path/rpi.img 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
console.info('Configuring operating system image')
|
||||
resin.models.device.get(params.uuid)
|
||||
.get('device_type')
|
||||
.then(resin.models.device.getManifestBySlug)
|
||||
.get('options')
|
||||
.then(form.run)
|
||||
.then (answers) ->
|
||||
init.configure(params.image, params.uuid, answers).then(stepHandler)
|
||||
.nodeify(done)
|
||||
|
@ -66,6 +66,7 @@ capitano.command(actions.env.remove)
|
||||
|
||||
# ---------- OS Module ----------
|
||||
capitano.command(actions.os.download)
|
||||
capitano.command(actions.os.configure)
|
||||
|
||||
# ---------- Logs Module ----------
|
||||
capitano.command(actions.logs)
|
||||
|
@ -26,4 +26,5 @@ exports.stateToString = (state) ->
|
||||
exports.waitStream = (stream) ->
|
||||
return new Promise (resolve, reject) ->
|
||||
stream.on('close', resolve)
|
||||
stream.on('end', resolve)
|
||||
stream.on('error', reject)
|
||||
|
@ -69,9 +69,3 @@ exports.awaitDevice = (uuid) ->
|
||||
resin.models.device.getName(uuid).then (deviceName) ->
|
||||
console.info("Waiting for #{deviceName} to connect to resin...")
|
||||
poll().return(uuid)
|
||||
|
||||
exports.askDeviceOptions = (deviceType) ->
|
||||
resin.models.config.getDeviceOptions(deviceType).then(form.run)
|
||||
.then (answers) ->
|
||||
answers.os ?= helpers.getOperatingSystem()
|
||||
return answers
|
||||
|
Loading…
Reference in New Issue
Block a user