mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-31 08:25:36 +00:00
Merge pull request #118 from resin-io/resin-cli-form
Integrate resin-cli-form
This commit is contained in:
commit
d6ae689593
@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var _, async, commandOptions, path, resin, vcs, visuals;
|
||||
var _, async, commandOptions, form, path, resin, vcs, visuals;
|
||||
|
||||
path = require('path');
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
vcs = require('resin-vcs');
|
||||
|
||||
form = require('resin-cli-form');
|
||||
|
||||
exports.create = {
|
||||
signature: 'app create <name>',
|
||||
description: 'create an application',
|
||||
@ -39,7 +41,13 @@
|
||||
if (options.type != null) {
|
||||
return callback(null, options.type);
|
||||
}
|
||||
return visuals.patterns.selectDeviceType(callback);
|
||||
return resin.models.device.getSupportedDeviceTypes().then(function(supportedDeviceTypes) {
|
||||
return form.ask({
|
||||
message: 'Device Type',
|
||||
type: 'list',
|
||||
choices: supportedDeviceTypes
|
||||
});
|
||||
}).nodeify(callback);
|
||||
}, function(type, callback) {
|
||||
options.type = type;
|
||||
return resin.models.application.create(params.name, options.type).nodeify(callback);
|
||||
@ -92,9 +100,24 @@
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
return visuals.patterns.remove('application', options.yes, function(callback) {
|
||||
return resin.models.application.remove(params.name).nodeify(callback);
|
||||
}, done);
|
||||
return async.waterfall([
|
||||
function(callback) {
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: 'Are you sure you want to delete the application?',
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return callback();
|
||||
}
|
||||
return resin.models.application.remove(params.name).nodeify(callback);
|
||||
}
|
||||
], done);
|
||||
}
|
||||
};
|
||||
|
||||
@ -116,7 +139,15 @@
|
||||
return callback(new Error("Invalid application: " + params.name));
|
||||
}
|
||||
message = "Are you sure you want to associate " + currentDirectory + " with " + params.name + "?";
|
||||
return visuals.patterns.confirm(options.yes, message, callback);
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: message,
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return done();
|
||||
@ -149,12 +180,11 @@
|
||||
function(callback) {
|
||||
var currentDirectoryBasename;
|
||||
currentDirectoryBasename = path.basename(currentDirectory);
|
||||
return visuals.form.ask({
|
||||
label: 'What is the name of your application?',
|
||||
name: 'application',
|
||||
type: 'text',
|
||||
value: currentDirectoryBasename
|
||||
}, callback);
|
||||
return form.ask({
|
||||
message: 'What is the name of your application?',
|
||||
type: 'input',
|
||||
"default": currentDirectoryBasename
|
||||
}).nodeify(callback);
|
||||
}, function(applicationName, callback) {
|
||||
return exports.create.action({
|
||||
name: applicationName
|
||||
|
@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var TOKEN_URL, _, async, open, resin, settings, url, visuals;
|
||||
var TOKEN_URL, _, async, form, open, resin, settings, url;
|
||||
|
||||
open = require('open');
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
settings = require('resin-settings-client');
|
||||
|
||||
visuals = require('resin-cli-visuals');
|
||||
form = require('resin-cli-form');
|
||||
|
||||
TOKEN_URL = url.resolve(settings.get('dashboardUrl'), '/preferences');
|
||||
|
||||
@ -32,7 +32,10 @@
|
||||
if (error != null) {
|
||||
console.error("Unable to open a web browser in the current environment.\nPlease visit " + TOKEN_URL + " manually.");
|
||||
}
|
||||
return visuals.patterns.loginWithToken(callback);
|
||||
return form.ask({
|
||||
message: 'What\'s your token? (visible in the preferences page)',
|
||||
type: 'input'
|
||||
}).nodeify(callback);
|
||||
});
|
||||
}, function(token, callback) {
|
||||
return resin.auth.loginWithToken(token).nodeify(callback);
|
||||
@ -97,7 +100,27 @@
|
||||
if (hasOptionCredentials) {
|
||||
return callback(null, options);
|
||||
}
|
||||
return visuals.patterns.register(callback);
|
||||
return form.run([
|
||||
{
|
||||
message: 'Email:',
|
||||
name: 'email',
|
||||
type: 'input'
|
||||
}, {
|
||||
message: 'Username:',
|
||||
name: 'username',
|
||||
type: 'input'
|
||||
}, {
|
||||
message: 'Password:',
|
||||
name: 'password',
|
||||
type: 'password',
|
||||
validate: function(input) {
|
||||
if (input.length < 8) {
|
||||
return 'Password should be 8 characters long';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]).nodeify(callback);
|
||||
}, function(credentials, callback) {
|
||||
return resin.auth.register(credentials)["return"](credentials).nodeify(callback);
|
||||
}, function(credentials, callback) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var _, async, capitano, commandOptions, deviceConfig, fse, image, inject, manager, path, pine, registerDevice, resin, tmp, vcs, visuals;
|
||||
var _, async, capitano, commandOptions, deviceConfig, form, fse, image, inject, manager, path, pine, registerDevice, resin, tmp, vcs, visuals;
|
||||
|
||||
fse = require('fs-extra');
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
|
||||
deviceConfig = require('resin-device-config');
|
||||
|
||||
form = require('resin-cli-form');
|
||||
|
||||
tmp.setGracefulCleanup();
|
||||
|
||||
commandOptions = require('./command-options');
|
||||
@ -80,9 +82,24 @@
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
return visuals.patterns.remove('device', options.yes, function(callback) {
|
||||
return resin.models.device.remove(params.uuid).nodeify(callback);
|
||||
}, done);
|
||||
return async.waterfall([
|
||||
function(callback) {
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: 'Are you sure you want to delete the device?',
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return callback();
|
||||
}
|
||||
return resin.models.device.remove(params.uuid).nodeify(callback);
|
||||
}
|
||||
], done);
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,11 +124,10 @@
|
||||
if (!_.isEmpty(params.newName)) {
|
||||
return callback(null, params.newName);
|
||||
}
|
||||
return visuals.form.ask({
|
||||
label: 'How do you want to name this device?',
|
||||
name: 'device',
|
||||
type: 'text'
|
||||
}, callback);
|
||||
return form.ask({
|
||||
message: 'How do you want to name this device?',
|
||||
type: 'input'
|
||||
}).nodeify(callback);
|
||||
}, function(newName, callback) {
|
||||
return resin.models.device.rename(params.uuid, newName).nodeify(callback);
|
||||
}
|
||||
@ -194,12 +210,39 @@
|
||||
if (params.device != null) {
|
||||
return callback(null, params.device);
|
||||
}
|
||||
return visuals.patterns.selectDrive(callback);
|
||||
return drivelist.list(function(error, drives) {
|
||||
if (error != null) {
|
||||
return callback(error);
|
||||
}
|
||||
return async.reject(drives, drivelist.isSystem, function(removableDrives) {
|
||||
if (_.isEmpty(removableDrives)) {
|
||||
return callback(new Error('No available drives'));
|
||||
}
|
||||
return form.ask({
|
||||
message: 'Drive',
|
||||
type: 'list',
|
||||
choices: _.map(removableDrives, function(item) {
|
||||
return {
|
||||
name: item.device + " (" + item.size + ") - " + item.description,
|
||||
value: item.device
|
||||
};
|
||||
})
|
||||
}).nodeify(callback);
|
||||
});
|
||||
});
|
||||
}, function(device, callback) {
|
||||
var message;
|
||||
params.device = device;
|
||||
message = "This will completely erase " + params.device + ". Are you sure you want to continue?";
|
||||
return visuals.patterns.confirm(options.yes, message, callback);
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: message,
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return done();
|
||||
@ -207,13 +250,30 @@
|
||||
if (networkOptions.network != null) {
|
||||
return callback();
|
||||
}
|
||||
return visuals.patterns.selectNetworkParameters(function(error, parameters) {
|
||||
if (error != null) {
|
||||
return callback(error);
|
||||
return form.run([
|
||||
{
|
||||
message: 'Network Type',
|
||||
name: 'network',
|
||||
type: 'list',
|
||||
choices: ['ethernet', 'wifi']
|
||||
}, {
|
||||
message: 'Wifi Ssid',
|
||||
name: 'wifiSsid',
|
||||
type: 'input',
|
||||
when: {
|
||||
network: 'wifi'
|
||||
}
|
||||
}, {
|
||||
message: 'Wifi Key',
|
||||
name: 'wifiKey',
|
||||
type: 'input',
|
||||
when: {
|
||||
network: 'wifi'
|
||||
}
|
||||
}
|
||||
_.extend(networkOptions, parameters);
|
||||
return callback();
|
||||
});
|
||||
]).then(function(parameters) {
|
||||
return _.extend(networkOptions, parameters);
|
||||
}).nodeify(callback);
|
||||
}, function(callback) {
|
||||
console.info("Checking application: " + options.application);
|
||||
return resin.models.application.get(options.application).nodeify(callback);
|
||||
|
@ -54,13 +54,28 @@
|
||||
options: [commandOptions.yes, commandOptions.booleanDevice],
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
return visuals.patterns.remove('environment variable', options.yes, function(callback) {
|
||||
if (options.device) {
|
||||
return resin.models.environmentVariables.device.remove(params.id).nodeify(callback);
|
||||
} else {
|
||||
return resin.models.environmentVariables.remove(params.id).nodeify(callback);
|
||||
return async.waterfall([
|
||||
function(callback) {
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: 'Are you sure you want to delete the environment variable?',
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return callback();
|
||||
}
|
||||
if (options.device) {
|
||||
return resin.models.environmentVariables.device.remove(params.id).nodeify(callback);
|
||||
} else {
|
||||
return resin.models.environmentVariables.remove(params.id).nodeify(callback);
|
||||
}
|
||||
}
|
||||
}, done);
|
||||
], done);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var SSH_KEY_WIDTH, _, async, capitano, commandOptions, fs, resin, visuals;
|
||||
var SSH_KEY_WIDTH, _, async, capitano, commandOptions, form, fs, resin, visuals;
|
||||
|
||||
_ = require('lodash');
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
|
||||
commandOptions = require('./command-options');
|
||||
|
||||
form = require('resin-cli-form');
|
||||
|
||||
exports.list = {
|
||||
signature: 'keys',
|
||||
description: 'list all ssh keys',
|
||||
@ -50,9 +52,24 @@
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
return visuals.patterns.remove('key', options.yes, function(callback) {
|
||||
return resin.models.key.remove(params.id).nodeify(callback);
|
||||
}, done);
|
||||
return async.waterfall([
|
||||
function(callback) {
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: 'Are you sure you want to delete the key?',
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return callback();
|
||||
}
|
||||
return resin.models.key.remove(params.id).nodeify(callback);
|
||||
}
|
||||
], done);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var _, commandOptions, plugins, visuals;
|
||||
var _, async, commandOptions, form, plugins, visuals;
|
||||
|
||||
_ = require('lodash');
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
|
||||
plugins = require('../plugins');
|
||||
|
||||
form = require('resin-cli-form');
|
||||
|
||||
async = require('async');
|
||||
|
||||
exports.list = {
|
||||
signature: 'plugins',
|
||||
description: 'list all plugins',
|
||||
@ -68,15 +72,30 @@
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
action: function(params, options, done) {
|
||||
return visuals.patterns.remove('plugin', options.yes, function(callback) {
|
||||
return plugins.remove(params.name, callback);
|
||||
}, function(error) {
|
||||
if (error != null) {
|
||||
return done(error);
|
||||
return async.waterfall([
|
||||
function(callback) {
|
||||
if (options.yes) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return form.ask({
|
||||
message: 'Are you sure you want to delete the plugin?',
|
||||
type: 'confirm',
|
||||
"default": false
|
||||
}).nodeify(callback);
|
||||
}
|
||||
}, function(confirmed, callback) {
|
||||
if (!confirmed) {
|
||||
return callback();
|
||||
}
|
||||
return plugins.remove(params.name, callback);
|
||||
}, function(error) {
|
||||
if (error != null) {
|
||||
return done(error);
|
||||
}
|
||||
console.info("Plugin removed: " + params.name);
|
||||
return done();
|
||||
}
|
||||
console.info("Plugin removed: " + params.name);
|
||||
return done();
|
||||
});
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@ resin = require('resin-sdk')
|
||||
visuals = require('resin-cli-visuals')
|
||||
commandOptions = require('./command-options')
|
||||
vcs = require('resin-vcs')
|
||||
form = require('resin-cli-form')
|
||||
|
||||
exports.create =
|
||||
signature: 'app create <name>'
|
||||
@ -34,7 +35,7 @@ exports.create =
|
||||
]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
resin.models.application.has(params.name).nodeify(callback)
|
||||
@ -44,7 +45,12 @@ exports.create =
|
||||
return callback(new Error('You already have an application with that name!'))
|
||||
|
||||
return callback(null, options.type) if options.type?
|
||||
visuals.patterns.selectDeviceType(callback)
|
||||
resin.models.device.getSupportedDeviceTypes().then (supportedDeviceTypes) ->
|
||||
form.ask
|
||||
message: 'Device Type'
|
||||
type: 'list'
|
||||
choices: supportedDeviceTypes
|
||||
.nodeify(callback)
|
||||
|
||||
(type, callback) ->
|
||||
options.type = type
|
||||
@ -54,7 +60,7 @@ exports.create =
|
||||
console.info("Application created: #{params.name} (#{options.type}, id #{applicationId})")
|
||||
return callback()
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
||||
exports.list =
|
||||
signature: 'apps'
|
||||
@ -134,9 +140,22 @@ exports.remove =
|
||||
options: [ commandOptions.yes ]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
visuals.patterns.remove 'application', options.yes, (callback) ->
|
||||
resin.models.application.remove(params.name).nodeify(callback)
|
||||
, done
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: 'Are you sure you want to delete the application?'
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return callback() if not confirmed
|
||||
resin.models.application.remove(params.name).nodeify(callback)
|
||||
], done
|
||||
|
||||
exports.associate =
|
||||
signature: 'app associate <name>'
|
||||
@ -169,7 +188,14 @@ exports.associate =
|
||||
return callback(new Error("Invalid application: #{params.name}"))
|
||||
|
||||
message = "Are you sure you want to associate #{currentDirectory} with #{params.name}?"
|
||||
visuals.patterns.confirm(options.yes, message, callback)
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: message
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return done() if not confirmed
|
||||
@ -207,16 +233,15 @@ exports.init =
|
||||
|
||||
currentDirectory = process.cwd()
|
||||
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
currentDirectoryBasename = path.basename(currentDirectory)
|
||||
visuals.form.ask
|
||||
label: 'What is the name of your application?'
|
||||
name: 'application'
|
||||
type: 'text'
|
||||
value: currentDirectoryBasename
|
||||
, callback
|
||||
form.ask
|
||||
message: 'What is the name of your application?'
|
||||
type: 'input'
|
||||
default: currentDirectoryBasename
|
||||
.nodeify(callback)
|
||||
|
||||
(applicationName, callback) ->
|
||||
|
||||
@ -229,4 +254,4 @@ exports.init =
|
||||
(applicationName, callback) ->
|
||||
exports.associate.action(name: applicationName, options, callback)
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
@ -4,7 +4,7 @@ url = require('url')
|
||||
async = require('async')
|
||||
resin = require('resin-sdk')
|
||||
settings = require('resin-settings-client')
|
||||
visuals = require('resin-cli-visuals')
|
||||
form = require('resin-cli-form')
|
||||
|
||||
TOKEN_URL = url.resolve(settings.get('dashboardUrl'), '/preferences')
|
||||
|
||||
@ -25,7 +25,7 @@ exports.login =
|
||||
"""
|
||||
action: (params, options, done) ->
|
||||
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
return callback(null, params.token) if params.token?
|
||||
@ -44,7 +44,10 @@ exports.login =
|
||||
Please visit #{TOKEN_URL} manually.
|
||||
"""
|
||||
|
||||
visuals.patterns.loginWithToken(callback)
|
||||
form.ask
|
||||
message: 'What\'s your token? (visible in the preferences page)'
|
||||
type: 'input'
|
||||
.nodeify(callback)
|
||||
|
||||
(token, callback) ->
|
||||
resin.auth.loginWithToken(token).nodeify(callback)
|
||||
@ -56,7 +59,7 @@ exports.login =
|
||||
console.info("Successfully logged in as: #{username}")
|
||||
return callback()
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
||||
exports.logout =
|
||||
signature: 'logout'
|
||||
@ -127,11 +130,29 @@ exports.signup =
|
||||
if not options.password?
|
||||
return done(new Error('Missing password'))
|
||||
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
return callback(null, options) if hasOptionCredentials
|
||||
visuals.patterns.register(callback)
|
||||
form.run [
|
||||
message: 'Email:'
|
||||
name: 'email'
|
||||
type: 'input'
|
||||
,
|
||||
message: 'Username:'
|
||||
name: 'username'
|
||||
type: 'input'
|
||||
,
|
||||
message: 'Password:'
|
||||
name: 'password'
|
||||
type: 'password',
|
||||
validate: (input) ->
|
||||
if input.length < 8
|
||||
return 'Password should be 8 characters long'
|
||||
|
||||
return true
|
||||
]
|
||||
.nodeify(callback)
|
||||
|
||||
(credentials, callback) ->
|
||||
resin.auth.register(credentials).return(credentials).nodeify(callback)
|
||||
@ -139,7 +160,7 @@ exports.signup =
|
||||
(credentials, callback) ->
|
||||
resin.auth.login(credentials).nodeify(callback)
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
||||
exports.whoami =
|
||||
signature: 'whoami'
|
||||
|
@ -13,6 +13,7 @@ registerDevice = require('resin-register-device')
|
||||
pine = require('resin-pine')
|
||||
tmp = require('tmp')
|
||||
deviceConfig = require('resin-device-config')
|
||||
form = require('resin-cli-form')
|
||||
|
||||
# Cleanup the temporary files even when an uncaught exception occurs
|
||||
tmp.setGracefulCleanup()
|
||||
@ -110,9 +111,22 @@ exports.remove =
|
||||
options: [ commandOptions.yes ]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
visuals.patterns.remove 'device', options.yes, (callback) ->
|
||||
resin.models.device.remove(params.uuid).nodeify(callback)
|
||||
, done
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: 'Are you sure you want to delete the device?'
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return callback() if not confirmed
|
||||
resin.models.device.remove(params.uuid).nodeify(callback)
|
||||
], done
|
||||
|
||||
exports.identify =
|
||||
signature: 'device identify <uuid>'
|
||||
@ -151,11 +165,10 @@ exports.rename =
|
||||
if not _.isEmpty(params.newName)
|
||||
return callback(null, params.newName)
|
||||
|
||||
visuals.form.ask
|
||||
label: 'How do you want to name this device?'
|
||||
name: 'device'
|
||||
type: 'text'
|
||||
, callback
|
||||
form.ask
|
||||
message: 'How do you want to name this device?'
|
||||
type: 'input'
|
||||
.nodeify(callback)
|
||||
|
||||
(newName, callback) ->
|
||||
resin.models.device.rename(params.uuid, newName).nodeify(callback)
|
||||
@ -263,7 +276,7 @@ exports.init =
|
||||
wifiSsid: options.ssid
|
||||
wifiKey: options.key
|
||||
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
return callback(null, options.application) if options.application?
|
||||
@ -278,20 +291,60 @@ exports.init =
|
||||
return callback(new Error("Invalid application: #{options.application}"))
|
||||
|
||||
return callback(null, params.device) if params.device?
|
||||
visuals.patterns.selectDrive(callback)
|
||||
drivelist.list (error, drives) ->
|
||||
return callback(error) if error?
|
||||
|
||||
async.reject drives, drivelist.isSystem, (removableDrives) ->
|
||||
|
||||
if _.isEmpty(removableDrives)
|
||||
return callback(new Error('No available drives'))
|
||||
|
||||
form.ask
|
||||
message: 'Drive'
|
||||
type: 'list'
|
||||
choices: _.map removableDrives, (item) ->
|
||||
return {
|
||||
name: "#{item.device} (#{item.size}) - #{item.description}"
|
||||
value: item.device
|
||||
}
|
||||
.nodeify(callback)
|
||||
|
||||
(device, callback) ->
|
||||
params.device = device
|
||||
message = "This will completely erase #{params.device}. Are you sure you want to continue?"
|
||||
visuals.patterns.confirm(options.yes, message, callback)
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: message
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return done() if not confirmed
|
||||
return callback() if networkOptions.network?
|
||||
visuals.patterns.selectNetworkParameters (error, parameters) ->
|
||||
return callback(error) if error?
|
||||
form.run [
|
||||
message: 'Network Type'
|
||||
name: 'network'
|
||||
type: 'list'
|
||||
choices: [ 'ethernet', 'wifi' ]
|
||||
,
|
||||
message: 'Wifi Ssid'
|
||||
name: 'wifiSsid'
|
||||
type: 'input'
|
||||
when:
|
||||
network: 'wifi'
|
||||
,
|
||||
message: 'Wifi Key'
|
||||
name: 'wifiKey'
|
||||
type: 'input'
|
||||
when:
|
||||
network: 'wifi'
|
||||
]
|
||||
.then (parameters) ->
|
||||
_.extend(networkOptions, parameters)
|
||||
return callback()
|
||||
.nodeify(callback)
|
||||
|
||||
(callback) ->
|
||||
console.info("Checking application: #{options.application}")
|
||||
@ -366,4 +419,4 @@ exports.init =
|
||||
console.info("Device created: #{device.name}")
|
||||
return callback(null, device.name)
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
@ -34,7 +34,7 @@ exports.list =
|
||||
]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
async.waterfall([
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.application?
|
||||
@ -58,7 +58,7 @@ exports.list =
|
||||
|
||||
return callback()
|
||||
|
||||
], done)
|
||||
], done
|
||||
|
||||
exports.remove =
|
||||
signature: 'env rm <id>'
|
||||
@ -85,12 +85,25 @@ exports.remove =
|
||||
]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
visuals.patterns.remove 'environment variable', options.yes, (callback) ->
|
||||
if options.device
|
||||
resin.models.environmentVariables.device.remove(params.id).nodeify(callback)
|
||||
else
|
||||
resin.models.environmentVariables.remove(params.id).nodeify(callback)
|
||||
, done
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: 'Are you sure you want to delete the environment variable?'
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return callback() if not confirmed
|
||||
if options.device
|
||||
resin.models.environmentVariables.device.remove(params.id).nodeify(callback)
|
||||
else
|
||||
resin.models.environmentVariables.remove(params.id).nodeify(callback)
|
||||
], done
|
||||
|
||||
exports.add =
|
||||
signature: 'env add <key> [value]'
|
||||
|
@ -6,6 +6,7 @@ resin = require('resin-sdk')
|
||||
capitano = require('capitano')
|
||||
visuals = require('resin-cli-visuals')
|
||||
commandOptions = require('./command-options')
|
||||
form = require('resin-cli-form')
|
||||
|
||||
exports.list =
|
||||
signature: 'keys'
|
||||
@ -58,9 +59,22 @@ exports.remove =
|
||||
options: [ commandOptions.yes ]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
visuals.patterns.remove 'key', options.yes, (callback) ->
|
||||
resin.models.key.remove(params.id).nodeify(callback)
|
||||
, done
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: 'Are you sure you want to delete the key?'
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return callback() if not confirmed
|
||||
resin.models.key.remove(params.id).nodeify(callback)
|
||||
], done
|
||||
|
||||
exports.add =
|
||||
signature: 'key add <name> [path]'
|
||||
|
@ -2,6 +2,8 @@ _ = require('lodash')
|
||||
visuals = require('resin-cli-visuals')
|
||||
commandOptions = require('./command-options')
|
||||
plugins = require('../plugins')
|
||||
form = require('resin-cli-form')
|
||||
async = require('async')
|
||||
|
||||
exports.list =
|
||||
signature: 'plugins'
|
||||
@ -86,9 +88,23 @@ exports.remove =
|
||||
options: [ commandOptions.yes ]
|
||||
permission: 'user'
|
||||
action: (params, options, done) ->
|
||||
visuals.patterns.remove 'plugin', options.yes, (callback) ->
|
||||
plugins.remove(params.name, callback)
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
if options.yes
|
||||
return callback(null, true)
|
||||
else
|
||||
form.ask
|
||||
message: 'Are you sure you want to delete the plugin?'
|
||||
type: 'confirm'
|
||||
default: false
|
||||
.nodeify(callback)
|
||||
|
||||
(confirmed, callback) ->
|
||||
return callback() if not confirmed
|
||||
plugins.remove(params.name, callback)
|
||||
, (error) ->
|
||||
return done(error) if error?
|
||||
console.info("Plugin removed: #{params.name}")
|
||||
return done()
|
||||
]
|
||||
|
@ -3,9 +3,9 @@
|
||||
\fBresin\fR \- tab completion for resin
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
It provides basic completion capabilities for \fBzsh\fR and \fBbash\fR\|\.
|
||||
It provides basic completion capabilities for \fBzsh\fP and \fBbash\fP\|\.
|
||||
.P
|
||||
If you're using \fBbash\fR, add the following line to your \fB~/\.bashrc\fR:
|
||||
If you're using \fBbash\fP, add the following line to your \fB~/\.bashrc\fP:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -29,7 +29,7 @@ ln \- /path/to/resin/completion/resin\.sh /usr/local/etc/bash\-completion\.d/res
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
If you're using \fBzsh\fR, add the following to your \fB~/\.zshrc\fR:
|
||||
If you're using \fBzsh\fP, add the following to your \fB~/\.zshrc\fP:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -40,9 +40,9 @@ source /path/to/resin/completion/resin\.sh
|
||||
.RE
|
||||
.SH RESIN PATH
|
||||
.P
|
||||
\fB/path/to/resin\fR refers to the place where resin was globally installed in your system\.
|
||||
\fB/path/to/resin\fP refers to the place where resin was globally installed in your system\.
|
||||
.P
|
||||
This is usually something like \fB/usr/lib/node_modules/resin\fR, or \fBC:\\Users\\AppData\\Roaming\\npm\\node_modules\\resin\fR on Windows\.
|
||||
This is usually something like \fB/usr/lib/node_modules/resin\fP, or \fBC:\\Users\\AppData\\Roaming\\npm\\node_modules\\resin\fP on Windows\.
|
||||
.SH COPYRIGHT
|
||||
.P
|
||||
resin is Copyright (C) 2014 Resin\.io https://resin\.io
|
||||
|
@ -3,18 +3,18 @@
|
||||
\fBresin-plugins\fR \- Creating Resin CLI plugins
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
Resin CLI plugins are managed by NPM\. Installing an NPM module that starts with \fBresin\-plugin\-*\fR globally will automatically make it available to the Resin CLI\.
|
||||
Resin CLI plugins are managed by NPM\. Installing an NPM module that starts with \fBresin\-plugin\-*\fP globally will automatically make it available to the Resin CLI\.
|
||||
.SH TUTORIAL
|
||||
.P
|
||||
In this guide, we'll create a simple hello plugin that greets the user\.
|
||||
.P
|
||||
Create a directory called \fBresin\-plugin\-hello\fR, containing a single \fBindex\.js\fR file\.
|
||||
Create a directory called \fBresin\-plugin\-hello\fP, containing a single \fBindex\.js\fP file\.
|
||||
.P
|
||||
Within the new project, run \fBnpm init\fR and make sure the package name is set to \fBresin\-plugin\-hello\fR as well\.
|
||||
Within the new project, run \fBnpm init\fP and make sure the package name is set to \fBresin\-plugin\-hello\fP as well\.
|
||||
.P
|
||||
Also make sure that you have a \fBmain\fR field in \fBpackage\.json\fR that points to the \fBindex\.js\fR file you created above\.
|
||||
Also make sure that you have a \fBmain\fP field in \fBpackage\.json\fP that points to the \fBindex\.js\fP file you created above\.
|
||||
.P
|
||||
Your \fBpackage\.json\fR should look something like this:
|
||||
Your \fBpackage\.json\fP should look something like this:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -30,26 +30,26 @@ Your \fBpackage\.json\fR should look something like this:
|
||||
.P
|
||||
Your index file should export an object (if exposing a single command) or an array of objects (if exposing multiple commands)\.
|
||||
.P
|
||||
Notice that is very important that your \fBpackage\.json\fR \fBmain\fR field points to the file that is exporting the commands for the plugin to work correctly\.
|
||||
Notice that is very important that your \fBpackage\.json\fP \fBmain\fP field points to the file that is exporting the commands for the plugin to work correctly\.
|
||||
.P
|
||||
Each object describes a single command\. The accepted fields are:
|
||||
.RS 0
|
||||
.IP \(bu 2
|
||||
\fBsignature\fR: A Capitano \fIhttps://github\.com/resin\-io/capitano\fR signature\.
|
||||
\fBsignature\fP: A Capitano \fIhttps://github\.com/resin\-io/capitano\fR signature\.
|
||||
.IP \(bu 2
|
||||
\fBdescription\fR: A string containing a short description of the command\. This will be shown on the Resin general help\.
|
||||
\fBdescription\fP: A string containing a short description of the command\. This will be shown on the Resin general help\.
|
||||
.IP \(bu 2
|
||||
\fBhelp\fR: A string containing an usage help page\. This will be shown when passing the signature to the \fBhelp\fR command\.
|
||||
\fBhelp\fP: A string containing an usage help page\. This will be shown when passing the signature to the \fBhelp\fP command\.
|
||||
.IP \(bu 2
|
||||
\fBaction\fR: A function that defines the action to take when the command is matched\. The function will be given 3 arguments (\fBparams\fR, \fBoptions\fR, \fBdone\fR)\.
|
||||
\fBaction\fP: A function that defines the action to take when the command is matched\. The function will be given 3 arguments (\fBparams\fP, \fBoptions\fP, \fBdone\fP)\.
|
||||
.IP \(bu 2
|
||||
\fBpermission\fR: A string describing the required permissions to run the command\.
|
||||
\fBpermission\fP: A string describing the required permissions to run the command\.
|
||||
.IP \(bu 2
|
||||
\fBoptions\fR: An array of Capitano \fIhttps://github\.com/resin\-io/capitano\fR options\.
|
||||
\fBoptions\fP: An array of Capitano \fIhttps://github\.com/resin\-io/capitano\fR options\.
|
||||
|
||||
.RE
|
||||
.P
|
||||
The \fBindex\.js\fR file should look something like:
|
||||
The \fBindex\.js\fP file should look something like:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -83,7 +83,7 @@ module\.exports = {
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
This example will register a \fBhello\fR command which requires a \fBname\fR parameter, and greets the user in result\.
|
||||
This example will register a \fBhello\fP command which requires a \fBname\fP parameter, and greets the user in result\.
|
||||
.P
|
||||
To test the plugin, first create a global link by running the following command inside your plugin directory:
|
||||
.P
|
||||
@ -93,7 +93,7 @@ $ npm link
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
Now if you run \fB$ resin help\fR you should see your new command at the bottom of the list\.
|
||||
Now if you run \fB$ resin help\fP you should see your new command at the bottom of the list\.
|
||||
.P
|
||||
Try it out:
|
||||
.P
|
||||
@ -105,9 +105,9 @@ Hey there Juan!
|
||||
.RE
|
||||
.SH DONE CALLBACK
|
||||
.P
|
||||
It's very important that you call the \fBdone()\fR callback after your action finishes\. If you pass an \fBError\fR instance to \fBdone()\fR, its message will be displayed by the Resin CLI, exiting with an error code 1\.
|
||||
It's very important that you call the \fBdone()\fP callback after your action finishes\. If you pass an \fBError\fP instance to \fBdone()\fP, its message will be displayed by the Resin CLI, exiting with an error code 1\.
|
||||
.P
|
||||
If your action is synchronous and doesn't return any error, you can omit the \fBdone()\fR callback all together\. For example:
|
||||
If your action is synchronous and doesn't return any error, you can omit the \fBdone()\fP callback all together\. For example:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -123,9 +123,9 @@ module\.exports = {
|
||||
.RE
|
||||
.SH PERMISSIONS
|
||||
.P
|
||||
You can set a command permission to restrict access to the commands\. Currently, the only registered permission is \fBuser\fR, which requires the user to log in to Resin from the CLI\.
|
||||
You can set a command permission to restrict access to the commands\. Currently, the only registered permission is \fBuser\fP, which requires the user to log in to Resin from the CLI\.
|
||||
.P
|
||||
To require the user to login before calling our hello plugin, we can add \fBpermission: 'user'\fR to the command description:
|
||||
To require the user to login before calling our hello plugin, we can add \fBpermission: 'user'\fP to the command description:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -155,7 +155,7 @@ $ resin hello Juan \-\-language spanish
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
We first need to register the \fBlanguage option\fR:
|
||||
We first need to register the \fBlanguage option\fP:
|
||||
.P
|
||||
.RS 2
|
||||
.nf
|
||||
@ -184,10 +184,10 @@ module\.exports = {
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
Here, we declared an option with a signature of \fBlanguage\fR (so we can use it as \fB\-\-language\fR), a parameter name of \fBlanguage\fR as well (this means we'll be able to access the option as the \fBlanguage\fR key: \fBoptions\.language\fR), a nice description and an alias \fBl\fR (which means we can use \fB\-l <language>\fR too)\.
|
||||
Here, we declared an option with a signature of \fBlanguage\fP (so we can use it as \fB\-\-language\fP), a parameter name of \fBlanguage\fP as well (this means we'll be able to access the option as the \fBlanguage\fP key: \fBoptions\.language\fP), a nice description and an alias \fBl\fP (which means we can use \fB\-l <language>\fP too)\.
|
||||
.SH COFFEESCRIPT
|
||||
.P
|
||||
We have CoffeeScript support out of the box\. Implement your commands in \fBindex\.coffee\fR and point \fBpackage\.json\fR \fBmain\fR to that file\.
|
||||
We have CoffeeScript support out of the box\. Implement your commands in \fBindex\.coffee\fP and point \fBpackage\.json\fP \fBmain\fP to that file\.
|
||||
.SH RESIN\-SDK
|
||||
.P
|
||||
You can use the Resin SDK NodeJS module within your own plugins to communicate with Resin\.
|
||||
|
@ -3,7 +3,7 @@
|
||||
\fBresin\fR \- command line tool to interact with resin\.io
|
||||
.SH SYNOPSIS
|
||||
.P
|
||||
\fBresin\fR [options] <command>
|
||||
\fBresin\fP [options] <command>
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
\fBresin\fR is a powerful command line application to interact, develop and deploy resin\.io applications and devices\.
|
||||
|
@ -59,7 +59,8 @@
|
||||
"nplugm": "^2.2.0",
|
||||
"npm": "^2.13.0",
|
||||
"open": "0.0.5",
|
||||
"resin-cli-visuals": "^0.3.3",
|
||||
"resin-cli-form": "^1.1.0",
|
||||
"resin-cli-visuals": "^1.0.0",
|
||||
"resin-config-inject": "^2.0.0",
|
||||
"resin-device-config": "^1.0.0",
|
||||
"resin-image": "^1.1.3",
|
||||
|
Loading…
x
Reference in New Issue
Block a user