mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-06 19:19:56 +00:00
isolate the sudo-runnable command
This commit is contained in:
parent
857c5204b9
commit
6cf32e445a
@ -291,23 +291,23 @@ exports.init = {
|
|||||||
}).then(resin.models.application.get).then(function(application) {
|
}).then(resin.models.application.get).then(function(application) {
|
||||||
var download;
|
var download;
|
||||||
download = function() {
|
download = function() {
|
||||||
return tmp.tmpNameAsync().then(function(temporalPath) {
|
return tmp.tmpNameAsync().then(function(tempPath) {
|
||||||
return capitano.runAsync("os download " + application.device_type + " --output " + temporalPath + " --version default");
|
return capitano.runAsync("os download " + application.device_type + " --output '" + tempPath + "' --version default");
|
||||||
}).disposer(function(temporalPath) {
|
}).disposer(function(tempPath) {
|
||||||
return rimraf(temporalPath);
|
return rimraf(tempPath);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
return Promise.using(download(), function(temporalPath) {
|
return Promise.using(download(), function(tempPath) {
|
||||||
return capitano.runAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) {
|
return capitano.runAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) {
|
||||||
var configure;
|
var configureCommand;
|
||||||
configure = "os configure " + temporalPath + " " + device.uuid;
|
configureCommand = "os configure '" + tempPath + "' " + device.uuid;
|
||||||
if (options.advanced) {
|
if (options.advanced) {
|
||||||
configure += ' --advanced';
|
configureCommand += ' --advanced';
|
||||||
}
|
}
|
||||||
return capitano.runAsync(configure).then(function() {
|
return capitano.runAsync(configureCommand).then(function() {
|
||||||
var message;
|
var osInitCommand;
|
||||||
message = 'Initializing a device requires administrative permissions\ngiven that we need to access raw devices directly.\n';
|
osInitCommand = "os initialize '" + tempPath + "' --type " + application.device_type;
|
||||||
return helpers.sudo(['os', 'initialize', temporalPath, '--type', application.device_type], message);
|
return capitano.runAsync(osInitCommand);
|
||||||
})["catch"](function(error) {
|
})["catch"](function(error) {
|
||||||
return resin.models.device.remove(device.uuid)["finally"](function() {
|
return resin.models.device.remove(device.uuid)["finally"](function() {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -60,12 +60,13 @@ general = function(params, options, done) {
|
|||||||
console.log(messages.reachingOut);
|
console.log(messages.reachingOut);
|
||||||
console.log('\nPrimary commands:\n');
|
console.log('\nPrimary commands:\n');
|
||||||
commands = _.reject(capitano.state.commands, function(command) {
|
commands = _.reject(capitano.state.commands, function(command) {
|
||||||
return command.isWildcard();
|
return command.hidden || command.isWildcard();
|
||||||
});
|
});
|
||||||
groupedCommands = _.groupBy(commands, function(command) {
|
groupedCommands = _.groupBy(commands, function(command) {
|
||||||
if (command.plugin) {
|
if (command.plugin) {
|
||||||
return 'plugins';
|
return 'plugins';
|
||||||
} else if (command.primary) {
|
}
|
||||||
|
if (command.primary) {
|
||||||
return 'primary';
|
return 'primary';
|
||||||
}
|
}
|
||||||
return 'secondary';
|
return 'secondary';
|
||||||
|
@ -31,5 +31,6 @@ module.exports = {
|
|||||||
settings: require('./settings'),
|
settings: require('./settings'),
|
||||||
config: require('./config'),
|
config: require('./config'),
|
||||||
sync: require('./sync'),
|
sync: require('./sync'),
|
||||||
ssh: require('./ssh')
|
ssh: require('./ssh'),
|
||||||
|
internal: require('./internal')
|
||||||
};
|
};
|
||||||
|
35
build/actions/internal.js
Normal file
35
build/actions/internal.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Generated by CoffeeScript 1.12.4
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2016 Resin.io
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
exports.osInit = {
|
||||||
|
signature: 'internal osinit <image> <type> <config>',
|
||||||
|
description: 'do actual init of the device with the preconfigured os image',
|
||||||
|
help: 'Don\'t use this command directly! Use `resin os initialize <image>` instead.',
|
||||||
|
hidden: true,
|
||||||
|
root: true,
|
||||||
|
action: function(params, options, done) {
|
||||||
|
var Promise, helpers, init;
|
||||||
|
Promise = require('bluebird');
|
||||||
|
init = require('resin-device-init');
|
||||||
|
helpers = require('../utils/helpers');
|
||||||
|
return Promise["try"](function() {
|
||||||
|
var config;
|
||||||
|
config = JSON.parse(params.config);
|
||||||
|
return init.initialize(params.image, params.type, config);
|
||||||
|
}).then(helpers.osProgressHandler).nodeify(done);
|
||||||
|
}
|
||||||
|
};
|
@ -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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
var commandOptions, formatVersion, resolveVersion, stepHandler;
|
var commandOptions, formatVersion, initWarningMessage, resolveVersion;
|
||||||
|
|
||||||
commandOptions = require('./command-options');
|
commandOptions = require('./command-options');
|
||||||
|
|
||||||
@ -120,25 +120,6 @@ exports.download = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
stepHandler = function(step) {
|
|
||||||
var _, bar, helpers, rindle, visuals;
|
|
||||||
_ = require('lodash');
|
|
||||||
rindle = require('rindle');
|
|
||||||
visuals = require('resin-cli-visuals');
|
|
||||||
helpers = require('../utils/helpers');
|
|
||||||
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 rindle.wait(step);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.configure = {
|
exports.configure = {
|
||||||
signature: 'os configure <image> <uuid>',
|
signature: 'os configure <image> <uuid>',
|
||||||
description: 'configure an os image',
|
description: 'configure an os image',
|
||||||
@ -176,16 +157,18 @@ exports.configure = {
|
|||||||
override: override
|
override: override
|
||||||
});
|
});
|
||||||
}).then(function(answers) {
|
}).then(function(answers) {
|
||||||
return init.configure(params.image, params.uuid, answers).then(stepHandler);
|
return init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler);
|
||||||
});
|
});
|
||||||
}).nodeify(done);
|
}).nodeify(done);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
initWarningMessage = 'Note: Initializing the device may ask for administrative permissions\nbecause we need to access the raw devices directly.';
|
||||||
|
|
||||||
exports.initialize = {
|
exports.initialize = {
|
||||||
signature: 'os initialize <image>',
|
signature: 'os initialize <image>',
|
||||||
description: 'initialize an os image',
|
description: 'initialize an os image',
|
||||||
help: 'Use this command to initialize a previously configured operating system image.\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" + initWarningMessage + "\n\nExamples:\n\n $ resin os initialize ../path/rpi.img --type 'raspberry-pi'",
|
||||||
permission: 'user',
|
permission: 'user',
|
||||||
options: [
|
options: [
|
||||||
commandOptions.yes, {
|
commandOptions.yes, {
|
||||||
@ -201,16 +184,14 @@ exports.initialize = {
|
|||||||
alias: 'd'
|
alias: 'd'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
root: true,
|
|
||||||
action: function(params, options, done) {
|
action: function(params, options, done) {
|
||||||
var Promise, form, helpers, init, patterns, umount;
|
var Promise, form, helpers, patterns, umount;
|
||||||
Promise = require('bluebird');
|
Promise = require('bluebird');
|
||||||
umount = Promise.promisifyAll(require('umount'));
|
umount = Promise.promisifyAll(require('umount'));
|
||||||
form = require('resin-cli-form');
|
form = require('resin-cli-form');
|
||||||
init = require('resin-device-init');
|
|
||||||
patterns = require('../utils/patterns');
|
patterns = require('../utils/patterns');
|
||||||
helpers = require('../utils/helpers');
|
helpers = require('../utils/helpers');
|
||||||
console.info('Initializing device');
|
console.info("Initializing device\n\n" + initWarningMessage);
|
||||||
return helpers.getManifest(params.image, options.type).then(function(manifest) {
|
return helpers.getManifest(params.image, options.type).then(function(manifest) {
|
||||||
var ref;
|
var ref;
|
||||||
return (ref = manifest.initialization) != null ? ref.options : void 0;
|
return (ref = manifest.initialization) != null ? ref.options : void 0;
|
||||||
@ -228,7 +209,7 @@ exports.initialize = {
|
|||||||
message = "This will erase " + answers.drive + ". Are you sure?";
|
message = "This will erase " + answers.drive + ". Are you sure?";
|
||||||
return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync);
|
return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync);
|
||||||
}).tap(function(answers) {
|
}).tap(function(answers) {
|
||||||
return init.initialize(params.image, options.type, answers).then(stepHandler);
|
return helpers.sudo(['internal', 'osinit', params.image, options.type, JSON.stringify(answers)]);
|
||||||
}).then(function(answers) {
|
}).then(function(answers) {
|
||||||
if (answers.drive == null) {
|
if (answers.drive == null) {
|
||||||
return;
|
return;
|
||||||
|
35
build/actions/util.js
Normal file
35
build/actions/util.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Generated by CoffeeScript 1.12.4
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2016 Resin.io
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
exports.osInit = {
|
||||||
|
signature: 'util osinit <image> <type> <config>',
|
||||||
|
description: 'do actual init of the device with the preconfigured os image',
|
||||||
|
help: 'Don\'t use this command directly! Use `resin os initialize <image>` instead.',
|
||||||
|
hidden: true,
|
||||||
|
root: true,
|
||||||
|
action: function(params, options, done) {
|
||||||
|
var Promise, helpers, init;
|
||||||
|
Promise = require('bluebird');
|
||||||
|
init = require('resin-device-init');
|
||||||
|
helpers = require('../utils/helpers');
|
||||||
|
return Promise["try"](function() {
|
||||||
|
var config;
|
||||||
|
config = JSON.parse(params.config);
|
||||||
|
return init.initialize(params.image, params.type, config);
|
||||||
|
}).then(helpers.osProgressHandler).nodeify(done);
|
||||||
|
}
|
||||||
|
};
|
@ -179,6 +179,8 @@ capitano.command(actions.local.scan);
|
|||||||
|
|
||||||
capitano.command(actions.local.stop);
|
capitano.command(actions.local.stop);
|
||||||
|
|
||||||
|
capitano.command(actions.internal.osInit);
|
||||||
|
|
||||||
update.notify();
|
update.notify();
|
||||||
|
|
||||||
plugins.register(/^resin-plugin-(.+)$/).then(function() {
|
plugins.register(/^resin-plugin-(.+)$/).then(function() {
|
||||||
|
@ -15,37 +15,27 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
var Promise, _, capitano, chalk, imagefs, os, president, resin, rindle;
|
var Promise, capitano, president;
|
||||||
|
|
||||||
Promise = require('bluebird');
|
Promise = require('bluebird');
|
||||||
|
|
||||||
capitano = Promise.promisifyAll(require('capitano'));
|
capitano = Promise.promisifyAll(require('capitano'));
|
||||||
|
|
||||||
_ = require('lodash');
|
|
||||||
|
|
||||||
_.str = require('underscore.string');
|
|
||||||
|
|
||||||
president = Promise.promisifyAll(require('president'));
|
president = Promise.promisifyAll(require('president'));
|
||||||
|
|
||||||
resin = require('resin-sdk-preconfigured');
|
|
||||||
|
|
||||||
imagefs = require('resin-image-fs');
|
|
||||||
|
|
||||||
rindle = require('rindle');
|
|
||||||
|
|
||||||
os = require('os');
|
|
||||||
|
|
||||||
chalk = require('chalk');
|
|
||||||
|
|
||||||
exports.getGroupDefaults = function(group) {
|
exports.getGroupDefaults = function(group) {
|
||||||
|
var _;
|
||||||
|
_ = require('lodash');
|
||||||
return _.chain(group).get('options').map(function(question) {
|
return _.chain(group).get('options').map(function(question) {
|
||||||
return [question.name, question["default"]];
|
return [question.name, question["default"]];
|
||||||
}).object().value();
|
}).object().value();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.stateToString = function(state) {
|
exports.stateToString = function(state) {
|
||||||
var percentage, result;
|
var _str, chalk, percentage, result;
|
||||||
percentage = _.str.lpad(state.percentage, 3, '0') + '%';
|
_str = require('underscore.string');
|
||||||
|
chalk = require('chalk');
|
||||||
|
percentage = _str.lpad(state.percentage, 3, '0') + '%';
|
||||||
result = (chalk.blue(percentage)) + " " + (chalk.cyan(state.operation.command));
|
result = (chalk.blue(percentage)) + " " + (chalk.cyan(state.operation.command));
|
||||||
switch (state.operation.command) {
|
switch (state.operation.command) {
|
||||||
case 'copy':
|
case 'copy':
|
||||||
@ -59,16 +49,22 @@ exports.stateToString = function(state) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.sudo = function(command, message) {
|
exports.sudo = function(command) {
|
||||||
command = _.union(_.take(process.argv, 2), command);
|
var _, os;
|
||||||
console.log(message);
|
_ = require('lodash');
|
||||||
|
os = require('os');
|
||||||
if (os.platform() !== 'win32') {
|
if (os.platform() !== 'win32') {
|
||||||
console.log('Type your computer password to continue');
|
console.log('If asked please type your computer password to continue');
|
||||||
}
|
}
|
||||||
|
command = _.union(_.take(process.argv, 2), command);
|
||||||
return president.executeAsync(command);
|
return president.executeAsync(command);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getManifest = function(image, deviceType) {
|
exports.getManifest = function(image, deviceType) {
|
||||||
|
var imagefs, resin, rindle;
|
||||||
|
rindle = require('rindle');
|
||||||
|
imagefs = require('resin-image-fs');
|
||||||
|
resin = require('resin-sdk-preconfigured');
|
||||||
return imagefs.read({
|
return imagefs.read({
|
||||||
image: image,
|
image: image,
|
||||||
partition: {
|
partition: {
|
||||||
@ -79,3 +75,20 @@ exports.getManifest = function(image, deviceType) {
|
|||||||
return resin.models.device.getManifestBySlug(deviceType);
|
return resin.models.device.getManifestBySlug(deviceType);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.osProgressHandler = function(step) {
|
||||||
|
var bar, rindle, visuals;
|
||||||
|
rindle = require('rindle');
|
||||||
|
visuals = require('resin-cli-visuals');
|
||||||
|
step.on('stdout', process.stdout.write.bind(process.stdout));
|
||||||
|
step.on('stderr', process.stderr.write.bind(process.stderr));
|
||||||
|
step.on('state', function(state) {
|
||||||
|
if (state.operation.command === 'burn') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return console.log(exports.stateToString(state));
|
||||||
|
});
|
||||||
|
bar = new visuals.Progress('Writing Device OS');
|
||||||
|
step.on('burn', bar.update.bind(bar));
|
||||||
|
return rindle.wait(step);
|
||||||
|
};
|
||||||
|
@ -830,7 +830,10 @@ show advanced commands
|
|||||||
|
|
||||||
## os initialize <image>
|
## os initialize <image>
|
||||||
|
|
||||||
Use this command to initialize a previously configured operating system image.
|
Use this command to initialize a device with previously configured operating system image.
|
||||||
|
|
||||||
|
Note: Initializing the device may ask for administrative permissions
|
||||||
|
because we need to access the raw devices directly.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
@ -392,27 +392,23 @@ exports.init =
|
|||||||
.then (application) ->
|
.then (application) ->
|
||||||
|
|
||||||
download = ->
|
download = ->
|
||||||
tmp.tmpNameAsync().then (temporalPath) ->
|
tmp.tmpNameAsync().then (tempPath) ->
|
||||||
# TODO: allow version selection
|
# TODO: allow version selection
|
||||||
capitano.runAsync("os download #{application.device_type} --output #{temporalPath} --version default")
|
capitano.runAsync("os download #{application.device_type} --output '#{tempPath}' --version default")
|
||||||
.disposer (temporalPath) ->
|
.disposer (tempPath) ->
|
||||||
return rimraf(temporalPath)
|
return rimraf(tempPath)
|
||||||
|
|
||||||
Promise.using download(), (temporalPath) ->
|
Promise.using download(), (tempPath) ->
|
||||||
capitano.runAsync("device register #{application.app_name}")
|
capitano.runAsync("device register #{application.app_name}")
|
||||||
.then(resin.models.device.get)
|
.then(resin.models.device.get)
|
||||||
.tap (device) ->
|
.tap (device) ->
|
||||||
configure = "os configure #{temporalPath} #{device.uuid}"
|
configureCommand = "os configure '#{tempPath}' #{device.uuid}"
|
||||||
configure += ' --advanced' if options.advanced
|
if options.advanced
|
||||||
capitano.runAsync(configure).then ->
|
configureCommand += ' --advanced'
|
||||||
message = '''
|
capitano.runAsync(configureCommand)
|
||||||
Initializing a device requires administrative permissions
|
.then ->
|
||||||
given that we need to access raw devices directly.
|
osInitCommand = "os initialize '#{tempPath}' --type #{application.device_type}"
|
||||||
|
capitano.runAsync(osInitCommand)
|
||||||
'''
|
|
||||||
|
|
||||||
helpers.sudo([ 'os', 'initialize', temporalPath, '--type', application.device_type ], message)
|
|
||||||
|
|
||||||
# Make sure the device resource is removed if there is an
|
# Make sure the device resource is removed if there is an
|
||||||
# error when configuring or initializing a device image
|
# error when configuring or initializing a device image
|
||||||
.catch (error) ->
|
.catch (error) ->
|
||||||
|
@ -54,12 +54,12 @@ general = (params, options, done) ->
|
|||||||
# We do not want the wildcard command
|
# We do not want the wildcard command
|
||||||
# to be printed in the help screen.
|
# to be printed in the help screen.
|
||||||
commands = _.reject capitano.state.commands, (command) ->
|
commands = _.reject capitano.state.commands, (command) ->
|
||||||
return command.isWildcard()
|
return command.hidden or command.isWildcard()
|
||||||
|
|
||||||
groupedCommands = _.groupBy commands, (command) ->
|
groupedCommands = _.groupBy commands, (command) ->
|
||||||
if command.plugin
|
if command.plugin
|
||||||
return 'plugins'
|
return 'plugins'
|
||||||
else if command.primary
|
if command.primary
|
||||||
return 'primary'
|
return 'primary'
|
||||||
return 'secondary'
|
return 'secondary'
|
||||||
|
|
||||||
|
@ -31,3 +31,4 @@ module.exports =
|
|||||||
config: require('./config')
|
config: require('./config')
|
||||||
sync: require('./sync')
|
sync: require('./sync')
|
||||||
ssh: require('./ssh')
|
ssh: require('./ssh')
|
||||||
|
internal: require('./internal')
|
||||||
|
37
lib/actions/internal.coffee
Normal file
37
lib/actions/internal.coffee
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
###
|
||||||
|
Copyright 2016 Resin.io
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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.
|
||||||
|
###
|
||||||
|
|
||||||
|
# These are internal commands we want to be runnable from the outside
|
||||||
|
# One use-case for this is spawning the minimal operation with root priviledges
|
||||||
|
|
||||||
|
exports.osInit =
|
||||||
|
signature: 'internal osinit <image> <type> <config>'
|
||||||
|
description: 'do actual init of the device with the preconfigured os image'
|
||||||
|
help: '''
|
||||||
|
Don't use this command directly! Use `resin os initialize <image>` instead.
|
||||||
|
'''
|
||||||
|
hidden: true
|
||||||
|
root: true
|
||||||
|
action: (params, options, done) ->
|
||||||
|
Promise = require('bluebird')
|
||||||
|
init = require('resin-device-init')
|
||||||
|
helpers = require('../utils/helpers')
|
||||||
|
|
||||||
|
return Promise.try ->
|
||||||
|
config = JSON.parse(params.config)
|
||||||
|
init.initialize(params.image, params.type, config)
|
||||||
|
.then(helpers.osProgressHandler)
|
||||||
|
.nodeify(done)
|
@ -133,25 +133,6 @@ exports.download =
|
|||||||
console.info('The image was downloaded successfully')
|
console.info('The image was downloaded successfully')
|
||||||
.nodeify(done)
|
.nodeify(done)
|
||||||
|
|
||||||
stepHandler = (step) ->
|
|
||||||
_ = require('lodash')
|
|
||||||
rindle = require('rindle')
|
|
||||||
visuals = require('resin-cli-visuals')
|
|
||||||
helpers = require('../utils/helpers')
|
|
||||||
|
|
||||||
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 rindle.wait(step)
|
|
||||||
|
|
||||||
exports.configure =
|
exports.configure =
|
||||||
signature: 'os configure <image> <uuid>'
|
signature: 'os configure <image> <uuid>'
|
||||||
description: 'configure an os image'
|
description: 'configure an os image'
|
||||||
@ -192,19 +173,26 @@ exports.configure =
|
|||||||
|
|
||||||
return form.run(questions, { override })
|
return form.run(questions, { override })
|
||||||
.then (answers) ->
|
.then (answers) ->
|
||||||
init.configure(params.image, params.uuid, answers).then(stepHandler)
|
init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler)
|
||||||
.nodeify(done)
|
.nodeify(done)
|
||||||
|
|
||||||
|
initWarningMessage = '''
|
||||||
|
Note: Initializing the device may ask for administrative permissions
|
||||||
|
because we need to access the raw devices directly.
|
||||||
|
'''
|
||||||
|
|
||||||
exports.initialize =
|
exports.initialize =
|
||||||
signature: 'os initialize <image>'
|
signature: 'os initialize <image>'
|
||||||
description: 'initialize an os image'
|
description: 'initialize an os image'
|
||||||
help: '''
|
help: """
|
||||||
Use this command to initialize a previously configured operating system image.
|
Use this command to initialize a device with previously configured operating system image.
|
||||||
|
|
||||||
|
#{initWarningMessage}
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ resin os initialize ../path/rpi.img --type 'raspberry-pi'
|
$ resin os initialize ../path/rpi.img --type 'raspberry-pi'
|
||||||
'''
|
"""
|
||||||
permission: 'user'
|
permission: 'user'
|
||||||
options: [
|
options: [
|
||||||
commandOptions.yes
|
commandOptions.yes
|
||||||
@ -222,16 +210,18 @@ exports.initialize =
|
|||||||
alias: 'd'
|
alias: 'd'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
root: true
|
|
||||||
action: (params, options, done) ->
|
action: (params, options, done) ->
|
||||||
Promise = require('bluebird')
|
Promise = require('bluebird')
|
||||||
umount = Promise.promisifyAll(require('umount'))
|
umount = Promise.promisifyAll(require('umount'))
|
||||||
form = require('resin-cli-form')
|
form = require('resin-cli-form')
|
||||||
init = require('resin-device-init')
|
|
||||||
patterns = require('../utils/patterns')
|
patterns = require('../utils/patterns')
|
||||||
helpers = require('../utils/helpers')
|
helpers = require('../utils/helpers')
|
||||||
|
|
||||||
console.info('Initializing device')
|
console.info("""
|
||||||
|
Initializing device
|
||||||
|
|
||||||
|
#{initWarningMessage}
|
||||||
|
""")
|
||||||
helpers.getManifest(params.image, options.type)
|
helpers.getManifest(params.image, options.type)
|
||||||
.then (manifest) ->
|
.then (manifest) ->
|
||||||
return manifest.initialization?.options
|
return manifest.initialization?.options
|
||||||
@ -246,7 +236,13 @@ exports.initialize =
|
|||||||
.return(answers.drive)
|
.return(answers.drive)
|
||||||
.then(umount.umountAsync)
|
.then(umount.umountAsync)
|
||||||
.tap (answers) ->
|
.tap (answers) ->
|
||||||
return init.initialize(params.image, options.type, answers).then(stepHandler)
|
return helpers.sudo([
|
||||||
|
'internal'
|
||||||
|
'osinit'
|
||||||
|
params.image
|
||||||
|
options.type
|
||||||
|
JSON.stringify(answers)
|
||||||
|
])
|
||||||
.then (answers) ->
|
.then (answers) ->
|
||||||
return if not answers.drive?
|
return if not answers.drive?
|
||||||
umount.umountAsync(answers.drive).tap ->
|
umount.umountAsync(answers.drive).tap ->
|
||||||
|
@ -142,6 +142,9 @@ capitano.command(actions.local.ssh)
|
|||||||
capitano.command(actions.local.scan)
|
capitano.command(actions.local.scan)
|
||||||
capitano.command(actions.local.stop)
|
capitano.command(actions.local.stop)
|
||||||
|
|
||||||
|
# ---------- Internal utils ----------
|
||||||
|
capitano.command(actions.internal.osInit)
|
||||||
|
|
||||||
update.notify()
|
update.notify()
|
||||||
|
|
||||||
plugins.register(/^resin-plugin-(.+)$/).then ->
|
plugins.register(/^resin-plugin-(.+)$/).then ->
|
||||||
|
@ -16,16 +16,11 @@ limitations under the License.
|
|||||||
|
|
||||||
Promise = require('bluebird')
|
Promise = require('bluebird')
|
||||||
capitano = Promise.promisifyAll(require('capitano'))
|
capitano = Promise.promisifyAll(require('capitano'))
|
||||||
_ = require('lodash')
|
|
||||||
_.str = require('underscore.string')
|
|
||||||
president = Promise.promisifyAll(require('president'))
|
president = Promise.promisifyAll(require('president'))
|
||||||
resin = require('resin-sdk-preconfigured')
|
|
||||||
imagefs = require('resin-image-fs')
|
|
||||||
rindle = require('rindle')
|
|
||||||
os = require('os')
|
|
||||||
chalk = require('chalk')
|
|
||||||
|
|
||||||
exports.getGroupDefaults = (group) ->
|
exports.getGroupDefaults = (group) ->
|
||||||
|
_ = require('lodash')
|
||||||
|
|
||||||
return _.chain(group)
|
return _.chain(group)
|
||||||
.get('options')
|
.get('options')
|
||||||
.map (question) ->
|
.map (question) ->
|
||||||
@ -34,7 +29,10 @@ exports.getGroupDefaults = (group) ->
|
|||||||
.value()
|
.value()
|
||||||
|
|
||||||
exports.stateToString = (state) ->
|
exports.stateToString = (state) ->
|
||||||
percentage = _.str.lpad(state.percentage, 3, '0') + '%'
|
_str = require('underscore.string')
|
||||||
|
chalk = require('chalk')
|
||||||
|
|
||||||
|
percentage = _str.lpad(state.percentage, 3, '0') + '%'
|
||||||
result = "#{chalk.blue(percentage)} #{chalk.cyan(state.operation.command)}"
|
result = "#{chalk.blue(percentage)} #{chalk.cyan(state.operation.command)}"
|
||||||
|
|
||||||
switch state.operation.command
|
switch state.operation.command
|
||||||
@ -47,16 +45,20 @@ exports.stateToString = (state) ->
|
|||||||
else
|
else
|
||||||
throw new Error("Unsupported operation: #{state.operation.type}")
|
throw new Error("Unsupported operation: #{state.operation.type}")
|
||||||
|
|
||||||
exports.sudo = (command, message) ->
|
exports.sudo = (command) ->
|
||||||
command = _.union(_.take(process.argv, 2), command)
|
_ = require('lodash')
|
||||||
console.log(message)
|
os = require('os')
|
||||||
|
|
||||||
if os.platform() isnt 'win32'
|
if os.platform() isnt 'win32'
|
||||||
console.log('Type your computer password to continue')
|
console.log('If asked please type your computer password to continue')
|
||||||
|
|
||||||
|
command = _.union(_.take(process.argv, 2), command)
|
||||||
return president.executeAsync(command)
|
return president.executeAsync(command)
|
||||||
|
|
||||||
exports.getManifest = (image, deviceType) ->
|
exports.getManifest = (image, deviceType) ->
|
||||||
|
rindle = require('rindle')
|
||||||
|
imagefs = require('resin-image-fs')
|
||||||
|
resin = require('resin-sdk-preconfigured')
|
||||||
|
|
||||||
# Attempt to read manifest from the first
|
# Attempt to read manifest from the first
|
||||||
# partition, but fallback to the API if
|
# partition, but fallback to the API if
|
||||||
@ -70,3 +72,20 @@ exports.getManifest = (image, deviceType) ->
|
|||||||
.then(JSON.parse)
|
.then(JSON.parse)
|
||||||
.catch ->
|
.catch ->
|
||||||
resin.models.device.getManifestBySlug(deviceType)
|
resin.models.device.getManifestBySlug(deviceType)
|
||||||
|
|
||||||
|
exports.osProgressHandler = (step) ->
|
||||||
|
rindle = require('rindle')
|
||||||
|
visuals = require('resin-cli-visuals')
|
||||||
|
|
||||||
|
step.on('stdout', process.stdout.write.bind(process.stdout))
|
||||||
|
step.on('stderr', process.stderr.write.bind(process.stderr))
|
||||||
|
|
||||||
|
step.on 'state', (state) ->
|
||||||
|
return if state.operation.command is 'burn'
|
||||||
|
console.log(exports.stateToString(state))
|
||||||
|
|
||||||
|
bar = new visuals.Progress('Writing Device OS')
|
||||||
|
|
||||||
|
step.on('burn', bar.update.bind(bar))
|
||||||
|
|
||||||
|
return rindle.wait(step)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user