diff --git a/build/actions/app.js b/build/actions/app.js index 44f28fec..f45c4b0a 100644 --- a/build/actions/app.js +++ b/build/actions/app.js @@ -31,7 +31,7 @@ action: function(params, options, done) { return async.waterfall([ function(callback) { - return resin.models.application.has(params.name, callback); + return resin.models.application.has(params.name).nodeify(callback); }, function(hasApplication, callback) { if (hasApplication) { return callback(new Error('You already have an application with that name!')); @@ -42,7 +42,7 @@ return visuals.patterns.selectDeviceType(callback); }, function(type, callback) { options.type = type; - return resin.models.application.create(params.name, options.type, callback); + return resin.models.application.create(params.name, options.type).nodeify(callback); }, function(applicationId, callback) { console.info("Application created: " + params.name + " (" + options.type + ", id " + applicationId + ")"); return callback(); @@ -57,13 +57,9 @@ help: 'Use this command to list all your applications.\n\nNotice this command only shows the most important bits of information for each app.\nIf you want detailed information, use resin app instead.\n\nExamples:\n\n $ resin apps', permission: 'user', action: function(params, options, done) { - return resin.models.application.getAll(function(error, applications) { - if (error != null) { - return done(error); - } - console.log(visuals.widgets.table.horizontal(applications, ['id', 'app_name', 'device_type', 'online_devices', 'devices_length'])); - return done(); - }); + return resin.models.application.getAll().then(function(applications) { + return console.log(visuals.widgets.table.horizontal(applications, ['id', 'app_name', 'device_type', 'online_devices', 'devices_length'])); + }).nodeify(done); } }; @@ -73,13 +69,9 @@ help: 'Use this command to show detailed information for a single application.\n\nExamples:\n\n $ resin app MyApp', permission: 'user', action: function(params, options, done) { - return resin.models.application.get(params.name, function(error, application) { - if (error != null) { - return done(error); - } - console.log(visuals.widgets.table.vertical(application, ['id', 'app_name', 'device_type', 'git_repository', 'commit'])); - return done(); - }); + return resin.models.application.get(params.name).then(function(application) { + return console.log(visuals.widgets.table.vertical(application, ['id', 'app_name', 'device_type', 'git_repository', 'commit'])); + }).nodeify(done); } }; @@ -89,7 +81,7 @@ help: 'Use this command to restart all devices that belongs to a certain application.\n\nExamples:\n\n $ resin app restart MyApp', permission: 'user', action: function(params, options, done) { - return resin.models.application.restart(params.name, done); + return resin.models.application.restart(params.name).nodeify(done); } }; @@ -101,7 +93,7 @@ permission: 'user', action: function(params, options, done) { return visuals.patterns.remove('application', options.yes, function(callback) { - return resin.models.application.remove(params.name, callback); + return resin.models.application.remove(params.name).nodeify(callback); }, done); } }; @@ -117,7 +109,7 @@ currentDirectory = process.cwd(); return async.waterfall([ function(callback) { - return resin.models.application.has(params.name, callback); + return resin.models.application.has(params.name).nodeify(callback); }, function(hasApp, callback) { var message; if (!hasApp) { @@ -131,7 +123,7 @@ } return vcs.initialize(currentDirectory).nodeify(callback); }, function(callback) { - return resin.models.application.get(params.name, callback); + return resin.models.application.get(params.name).nodeify(callback); }, function(application, callback) { return vcs.associate(currentDirectory, application.git_repository).nodeify(callback); } diff --git a/build/actions/auth.js b/build/actions/auth.js index 99b677cd..e7b772f5 100644 --- a/build/actions/auth.js +++ b/build/actions/auth.js @@ -35,9 +35,9 @@ return visuals.patterns.loginWithToken(callback); }); }, function(token, callback) { - return resin.auth.loginWithToken(token, callback); + return resin.auth.loginWithToken(token).nodeify(callback); }, function(callback) { - return resin.auth.whoami(callback); + return resin.auth.whoami().nodeify(callback); }, function(username, callback) { console.info("Successfully logged in as: " + username); return callback(); @@ -52,7 +52,7 @@ help: 'Use this command to logout from your resin.io account.o\n\nExamples:\n\n $ resin logout', permission: 'user', action: function(params, options, done) { - return resin.auth.logout(done); + return resin.auth.logout().nodeify(done); } }; @@ -99,11 +99,9 @@ } return visuals.patterns.register(callback); }, function(credentials, callback) { - return resin.auth.register(credentials, function(error, token) { - return callback(error, credentials); - }); + return resin.auth.register(credentials)["return"](credentials).nodeify(callback); }, function(credentials, callback) { - return resin.auth.login(credentials, callback); + return resin.auth.login(credentials).nodeify(callback); } ], done); } @@ -115,16 +113,12 @@ help: 'Use this command to find out the current logged in username.\n\nExamples:\n\n $ resin whoami', permission: 'user', action: function(params, options, done) { - return resin.auth.whoami(function(error, username) { - if (error != null) { - return done(error); - } + return resin.auth.whoami().then(function(username) { if (username == null) { - return done(new Error('Username not found')); + throw new Error('Username not found'); } - console.log(username); - return done(); - }); + return console.log(username); + }).nodeify(done); } }; diff --git a/build/actions/device.js b/build/actions/device.js index 6efe2322..233a3468 100644 --- a/build/actions/device.js +++ b/build/actions/device.js @@ -1,5 +1,5 @@ (function() { - var _, async, capitano, commandOptions, fse, image, inject, manager, path, pine, registerDevice, resin, tmp, vcs, visuals; + var _, async, capitano, commandOptions, deviceConfig, fse, image, inject, manager, path, pine, registerDevice, resin, tmp, vcs, visuals; fse = require('fs-extra'); @@ -29,6 +29,8 @@ tmp = require('tmp'); + deviceConfig = require('resin-device-config'); + tmp.setGracefulCleanup(); commandOptions = require('./command-options'); @@ -57,33 +59,29 @@ }; exports.info = { - signature: 'device ', + signature: 'device ', description: 'list a single device', - help: 'Use this command to show information about a single device.\n\nExamples:\n\n $ resin device MyDevice', + help: 'Use this command to show information about a single device.\n\nExamples:\n\n $ resin device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9', permission: 'user', action: function(params, options, done) { - return resin.models.device.get(params.name, function(error, device) { - if (error != null) { - return done(error); - } + return resin.models.device.get(params.uuid).then(function(device) { if (device.last_seen == null) { device.last_seen = 'Not seen'; } - console.log(visuals.widgets.table.vertical(device, ['id', 'name', 'device_type', 'is_online', 'ip_address', 'application_name', 'status', 'last_seen', 'uuid', 'commit', 'supervisor_version', 'is_web_accessible', 'note'])); - return done(); - }); + return console.log(visuals.widgets.table.vertical(device, ['id', 'name', 'device_type', 'is_online', 'ip_address', 'application_name', 'status', 'last_seen', 'uuid', 'commit', 'supervisor_version', 'is_web_accessible', 'note'])); + }).nodeify(done); } }; exports.remove = { - signature: 'device rm ', + signature: 'device rm ', description: 'remove a device', - help: 'Use this command to remove a device from resin.io.\n\nNotice this command asks for confirmation interactively.\nYou can avoid this by passing the `--yes` boolean option.\n\nExamples:\n\n $ resin device rm MyDevice\n $ resin device rm MyDevice --yes', + help: 'Use this command to remove a device from resin.io.\n\nNotice this command asks for confirmation interactively.\nYou can avoid this by passing the `--yes` boolean option.\n\nExamples:\n\n $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9\n $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 --yes', 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.name, callback); + return resin.models.device.remove(params.uuid).nodeify(callback); }, done); } }; @@ -94,14 +92,14 @@ help: 'Use this command to identify a device.\n\nIn the Raspberry Pi, the ACT led is blinked several times.\n\nExamples:\n\n $ resin device identify 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828', permission: 'user', action: function(params, options, done) { - return resin.models.device.identify(params.uuid, done); + return resin.models.device.identify(params.uuid).nodeify(done); } }; exports.rename = { - signature: 'device rename [newName]', + signature: 'device rename [newName]', description: 'rename a resin device', - help: 'Use this command to rename a device.\n\nIf you omit the name, you\'ll get asked for it interactively.\n\nExamples:\n\n $ resin device rename MyDevice MyPi\n $ resin device rename MyDevice', + help: 'Use this command to rename a device.\n\nIf you omit the name, you\'ll get asked for it interactively.\n\nExamples:\n\n $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 MyPi\n $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9', permission: 'user', action: function(params, options, done) { return async.waterfall([ @@ -115,7 +113,7 @@ type: 'text' }, callback); }, function(newName, callback) { - return resin.models.device.rename(params.name, newName, callback); + return resin.models.device.rename(params.uuid, newName).nodeify(callback); } ], done); } @@ -127,20 +125,16 @@ help: 'Use this command to get the list of all supported devices\n\nExamples:\n\n $ resin devices supported', permission: 'user', action: function(params, options, done) { - return resin.models.device.getSupportedDeviceTypes(function(error, devices) { - if (error != null) { - return done(error); - } - _.each(devices, _.unary(console.log)); - return done(); - }); + return resin.models.device.getSupportedDeviceTypes().each(function(device) { + return console.log(device); + }).nodeify(done); } }; exports.await = { - signature: 'device await ', + signature: 'device await ', description: 'await for a device to become online', - help: 'Use this command to await for a device to become online.\n\nThe process will exit when the device becomes online.\n\nNotice that there is no time limit for this command, so it might run forever.\n\nYou can configure the poll interval with the --interval option (defaults to 3000ms).\n\nExamples:\n\n $ resin device await MyDevice\n $ resin device await MyDevice --interval 1000', + help: 'Use this command to await for a device to become online.\n\nThe process will exit when the device becomes online.\n\nNotice that there is no time limit for this command, so it might run forever.\n\nYou can configure the poll interval with the --interval option (defaults to 3000ms).\n\nExamples:\n\n $ resin device await 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9\n $ resin device await 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 --interval 1000', options: [ { signature: 'interval', @@ -155,21 +149,18 @@ if (options.interval == null) { options.interval = 3000; } - poll = function() { - return resin.models.device.isOnline(params.name, function(error, isOnline) { - if (error != null) { - return done(error); - } + return poll = function() { + return resin.models.device.isOnline(params.uuid).then(function(isOnline) { if (isOnline) { - console.info("Device became online: " + params.name); - return done(); + console.info("Device became online: " + params.uuid); + return; } else { - console.info("Polling device network status: " + params.name); - return setTimeout(poll, options.interval); + console.info("Polling device network status: " + params.uuid); + return Promise.delay(options.interval).then(poll); } + return poll().nodeify(done); }); }; - return poll(); } }; @@ -195,7 +186,7 @@ return vcs.getApplicationName(process.cwd()).nodeify(callback); }, function(applicationName, callback) { options.application = applicationName; - return resin.models.application.has(options.application, callback); + return resin.models.application.has(options.application).nodeify(callback); }, function(hasApplication, callback) { if (!hasApplication) { return callback(new Error("Invalid application: " + options.application)); @@ -225,16 +216,16 @@ }); }, function(callback) { console.info("Checking application: " + options.application); - return resin.models.application.get(options.application, callback); + return resin.models.application.get(options.application).nodeify(callback); }, function(application, callback) { return async.parallel({ manifest: function(callback) { console.info('Getting device manifest for the application'); - return resin.models.device.getManifestBySlug(application.device_type, callback); + return resin.models.device.getManifestBySlug(application.device_type).nodeify(callback); }, config: function(callback) { console.info('Fetching application configuration'); - return resin.models.application.getConfiguration(options.application, networkOptions, callback); + return deviceConfig.get(options.application, networkOptions).nodeify(callback); } }, callback); }, function(results, callback) { @@ -284,7 +275,7 @@ console.info('Image written successfully'); return removeCallback(callback); }, function(callback) { - return resin.models.device.getByUUID(params.uuid, callback); + return resin.models.device.get(params.uuid).nodeify(callback); }, function(device, callback) { console.info("Device created: " + device.name); return callback(null, device.name); diff --git a/build/actions/environment-variables.js b/build/actions/environment-variables.js index 6a022b3b..9536c70c 100644 --- a/build/actions/environment-variables.js +++ b/build/actions/environment-variables.js @@ -28,9 +28,9 @@ return async.waterfall([ function(callback) { if (options.application != null) { - return resin.models.environmentVariables.getAllByApplication(options.application, callback); + return resin.models.environmentVariables.getAllByApplication(options.application).nodeify(callback); } else if (options.device != null) { - return resin.models.environmentVariables.device.getAll(options.device, callback); + return resin.models.environmentVariables.device.getAll(options.device).nodeify(callback); } else { return callback(new Error('You must specify an application or device')); } @@ -56,9 +56,9 @@ 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, callback); + return resin.models.environmentVariables.device.remove(params.id).nodeify(callback); } else { - return resin.models.environmentVariables.remove(params.id, callback); + return resin.models.environmentVariables.remove(params.id).nodeify(callback); } }, done); } @@ -80,9 +80,9 @@ } } if (options.application != null) { - return resin.models.environmentVariables.create(options.application, params.key, params.value, done); + return resin.models.environmentVariables.create(options.application, params.key, params.value).nodeify(done); } else if (options.device != null) { - return resin.models.environmentVariables.device.create(options.device, params.key, params.value, done); + return resin.models.environmentVariables.device.create(options.device, params.key, params.value).nodeify(done); } else { return done(new Error('You must specify an application or device')); } @@ -97,9 +97,9 @@ options: [commandOptions.booleanDevice], action: function(params, options, done) { if (options.device) { - return resin.models.environmentVariables.device.update(params.id, params.value, done); + return resin.models.environmentVariables.device.update(params.id, params.value).nodeify(done); } else { - return resin.models.environmentVariables.update(params.id, params.value, done); + return resin.models.environmentVariables.update(params.id, params.value).nodeify(done); } } }; diff --git a/build/actions/examples.js b/build/actions/examples.js index ac572033..53fa83a7 100644 --- a/build/actions/examples.js +++ b/build/actions/examples.js @@ -1,5 +1,5 @@ (function() { - var _, async, examplesData, fs, mkdirp, path, resin, vcs, visuals; + var _, async, examplesData, fs, mkdirp, path, vcs, visuals; mkdirp = require('mkdirp'); @@ -11,8 +11,6 @@ _ = require('lodash'); - resin = require('resin-sdk'); - visuals = require('resin-cli-visuals'); vcs = require('resin-vcs'); diff --git a/build/actions/help.js b/build/actions/help.js index 383780a8..e5cd5ed2 100644 --- a/build/actions/help.js +++ b/build/actions/help.js @@ -1,12 +1,10 @@ (function() { - var PADDING_INITIAL, PADDING_MIDDLE, _, addAlias, addOptionPrefix, buildHelpString, buildOptionSignatureHelp, capitano, command, general, getCommandHelp, getFieldMaxLength, getOptionHelp, getOptionsParsedSignatures, resin; + var PADDING_INITIAL, PADDING_MIDDLE, _, addAlias, addOptionPrefix, buildHelpString, buildOptionSignatureHelp, capitano, command, general, getCommandHelp, getFieldMaxLength, getOptionHelp, getOptionsParsedSignatures; _ = require('lodash'); _.str = require('underscore.string'); - resin = require('resin-sdk'); - capitano = require('capitano'); PADDING_INITIAL = ' '; diff --git a/build/actions/keys.js b/build/actions/keys.js index 3fd8bf95..fa23e1e1 100644 --- a/build/actions/keys.js +++ b/build/actions/keys.js @@ -23,13 +23,9 @@ help: 'Use this command to list all your SSH keys.\n\nExamples:\n\n $ resin keys', permission: 'user', action: function(params, options, done) { - return resin.models.key.getAll(function(error, keys) { - if (error != null) { - return done(error); - } - console.log(visuals.widgets.table.horizontal(keys, ['id', 'title'])); - return done(); - }); + return resin.models.key.getAll().then(function(keys) { + return console.log(visuals.widgets.table.horizontal(keys, ['id', 'title'])); + }).nodeify(done); } }; @@ -41,13 +37,9 @@ help: 'Use this command to show information about a single SSH key.\n\nExamples:\n\n $ resin key 17', permission: 'user', action: function(params, options, done) { - return resin.models.key.get(params.id, function(error, key) { - if (error != null) { - return done(error); - } - console.log(visuals.widgets.table.vertical(key, ['id', 'title', 'public_key'])); - return done(); - }); + return resin.models.key.get(params.id).then(function(key) { + return console.log(visuals.widgets.table.vertical(key, ['id', 'title', 'public_key'])); + }).nodeify(done); } }; @@ -59,7 +51,7 @@ permission: 'user', action: function(params, options, done) { return visuals.patterns.remove('key', options.yes, function(callback) { - return resin.models.key.remove(params.id, callback); + return resin.models.key.remove(params.id).nodeify(callback); }, done); } }; @@ -82,7 +74,7 @@ }); } }, function(key, callback) { - return resin.models.key.create(params.name, key, callback); + return resin.models.key.create(params.name, key).nodeify(callback); } ], done); } diff --git a/build/actions/logs.js b/build/actions/logs.js index cb4a7244..33562661 100644 --- a/build/actions/logs.js +++ b/build/actions/logs.js @@ -1,23 +1,16 @@ (function() { - var LOGS_HISTORY_COUNT, _, resin; + var _, resin; _ = require('lodash'); resin = require('resin-sdk'); - LOGS_HISTORY_COUNT = 200; - module.exports = { signature: 'logs ', description: 'show device logs', - help: 'Use this command to show logs for a specific device.\n\nBy default, the command prints all log messages and exit.\n\nTo limit the output to the n last lines, use the `--num` option along with a number.\nThis is similar to doing `resin logs | tail -n X`.\n\nTo continuously stream output, and see new logs in real time, use the `--tail` option.\n\nNote that for now you need to provide the whole UUID for this command to work correctly.\n\nThis is due to some technical limitations that we plan to address soon.\n\nExamples:\n\n $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828\n $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --num 20\n $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --tail', + help: 'Use this command to show logs for a specific device.\n\nBy default, the command prints all log messages and exit.\n\nTo continuously stream output, and see new logs in real time, use the `--tail` option.\n\nNote that for now you need to provide the whole UUID for this command to work correctly.\n\nThis is due to some technical limitations that we plan to address soon.\n\nExamples:\n\n $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828\n $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --tail', options: [ { - signature: 'num', - parameter: 'num', - description: 'number of lines to display', - alias: 'n' - }, { signature: 'tail', description: 'continuously stream output', boolean: true, @@ -26,22 +19,21 @@ ], permission: 'user', action: function(params, options, done) { - return resin.logs.subscribe(params.uuid, { - history: options.num || LOGS_HISTORY_COUNT, - tail: options.tail - }, function(error, message) { - if (error != null) { - return done(error); - } - if (_.isArray(message)) { - _.each(message, function(line) { + var promise; + promise = resin.logs.history(params.uuid).each(function(line) { + return console.log(line.message); + }); + if (!options.tail) { + return promise.nodeify(done); + } + return promise.then(function() { + return resin.logs.subscribe(params.uuid).then(function(logs) { + logs.on('line', function(line) { return console.log(line.message); }); - } else { - console.log(message.message); - } - return done(); - }); + return logs.on('error', done); + }); + })["catch"](done); } }; diff --git a/build/actions/notes.js b/build/actions/notes.js index 224a9cee..9c672fdf 100644 --- a/build/actions/notes.js +++ b/build/actions/notes.js @@ -10,12 +10,12 @@ exports.set = { signature: 'note <|note>', description: 'set a device note', - help: 'Use this command to set or update a device note.\n\nIf note command isn\'t passed, the tool attempts to read from `stdin`.\n\nTo view the notes, use $ resin device .\n\nExamples:\n\n $ resin note "My useful note" --device MyDevice\n $ cat note.txt | resin note --device MyDevice', + help: 'Use this command to set or update a device note.\n\nIf note command isn\'t passed, the tool attempts to read from `stdin`.\n\nTo view the notes, use $ resin device .\n\nExamples:\n\n $ resin note "My useful note" --device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9\n $ cat note.txt | resin note --device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9', options: [ { signature: 'device', parameter: 'device', - description: 'device name', + description: 'device uuid', alias: ['d', 'dev'], required: 'You have to specify a device' } @@ -25,7 +25,7 @@ if (_.isEmpty(params.note)) { return done(new Error('Missing note content')); } - return resin.models.device.note(options.device, params.note, done); + return resin.models.device.note(options.device, params.note).nodeify(done); } }; diff --git a/build/app.js b/build/app.js index a5ca805c..8c89c8c5 100644 --- a/build/app.js +++ b/build/app.js @@ -18,15 +18,11 @@ update = require('./update'); capitano.permission('user', function(done) { - return resin.auth.isLoggedIn(function(error, isLoggedIn) { - if (error != null) { - return done(error); - } + return resin.auth.isLoggedIn().then(function(isLoggedIn) { if (!isLoggedIn) { - return done(new Error('You have to log in')); + throw new Error('You have to log in'); } - return done(); - }); + }).nodeify(done); }); capitano.command({ diff --git a/lib/actions/app.coffee b/lib/actions/app.coffee index 5fe815a5..f279718b 100644 --- a/lib/actions/app.coffee +++ b/lib/actions/app.coffee @@ -37,7 +37,7 @@ exports.create = async.waterfall([ (callback) -> - resin.models.application.has(params.name, callback) + resin.models.application.has(params.name).nodeify(callback) (hasApplication, callback) -> if hasApplication @@ -48,7 +48,7 @@ exports.create = (type, callback) -> options.type = type - resin.models.application.create(params.name, options.type, callback) + resin.models.application.create(params.name, options.type).nodeify(callback) (applicationId, callback) -> console.info("Application created: #{params.name} (#{options.type}, id #{applicationId})") @@ -71,8 +71,7 @@ exports.list = ''' permission: 'user' action: (params, options, done) -> - resin.models.application.getAll (error, applications) -> - return done(error) if error? + resin.models.application.getAll().then (applications) -> console.log visuals.widgets.table.horizontal applications, [ 'id' 'app_name' @@ -80,7 +79,7 @@ exports.list = 'online_devices' 'devices_length' ] - return done() + .nodeify(done) exports.info = signature: 'app ' @@ -94,8 +93,7 @@ exports.info = ''' permission: 'user' action: (params, options, done) -> - resin.models.application.get params.name, (error, application) -> - return done(error) if error? + resin.models.application.get(params.name).then (application) -> console.log visuals.widgets.table.vertical application, [ 'id' 'app_name' @@ -103,7 +101,7 @@ exports.info = 'git_repository' 'commit' ] - return done() + .nodeify(done) exports.restart = signature: 'app restart ' @@ -117,7 +115,7 @@ exports.restart = ''' permission: 'user' action: (params, options, done) -> - resin.models.application.restart(params.name, done) + resin.models.application.restart(params.name).nodeify(done) exports.remove = signature: 'app rm ' @@ -137,7 +135,7 @@ exports.remove = permission: 'user' action: (params, options, done) -> visuals.patterns.remove 'application', options.yes, (callback) -> - resin.models.application.remove(params.name, callback) + resin.models.application.remove(params.name).nodeify(callback) , done exports.associate = @@ -164,7 +162,7 @@ exports.associate = async.waterfall [ (callback) -> - resin.models.application.has(params.name, callback) + resin.models.application.has(params.name).nodeify(callback) (hasApp, callback) -> if not hasApp @@ -178,7 +176,7 @@ exports.associate = vcs.initialize(currentDirectory).nodeify(callback) (callback) -> - resin.models.application.get(params.name, callback) + resin.models.application.get(params.name).nodeify(callback) (application, callback) -> vcs.associate(currentDirectory, application.git_repository).nodeify(callback) diff --git a/lib/actions/auth.coffee b/lib/actions/auth.coffee index 797f20ef..ff258b18 100644 --- a/lib/actions/auth.coffee +++ b/lib/actions/auth.coffee @@ -47,10 +47,10 @@ exports.login = visuals.patterns.loginWithToken(callback) (token, callback) -> - resin.auth.loginWithToken(token, callback) + resin.auth.loginWithToken(token).nodeify(callback) (callback) -> - resin.auth.whoami(callback) + resin.auth.whoami().nodeify(callback) (username, callback) -> console.info("Successfully logged in as: #{username}") @@ -70,7 +70,7 @@ exports.logout = ''' permission: 'user' action: (params, options, done) -> - resin.auth.logout(done) + resin.auth.logout().nodeify(done) exports.signup = signature: 'signup' @@ -134,11 +134,10 @@ exports.signup = visuals.patterns.register(callback) (credentials, callback) -> - resin.auth.register credentials, (error, token) -> - return callback(error, credentials) + resin.auth.register(credentials).return(credentials).nodeify(callback) (credentials, callback) -> - resin.auth.login(credentials, callback) + resin.auth.login(credentials).nodeify(callback) ], done) @@ -154,11 +153,8 @@ exports.whoami = ''' permission: 'user' action: (params, options, done) -> - resin.auth.whoami (error, username) -> - return done(error) if error? - + resin.auth.whoami().then (username) -> if not username? - return done(new Error('Username not found')) - + throw new Error('Username not found') console.log(username) - return done() + .nodeify(done) diff --git a/lib/actions/device.coffee b/lib/actions/device.coffee index 2e766c0a..2edfe298 100644 --- a/lib/actions/device.coffee +++ b/lib/actions/device.coffee @@ -12,6 +12,7 @@ inject = require('resin-config-inject') registerDevice = require('resin-register-device') pine = require('resin-pine') tmp = require('tmp') +deviceConfig = require('resin-device-config') # Cleanup the temporary files even when an uncaught exception occurs tmp.setGracefulCleanup() @@ -36,7 +37,6 @@ exports.list = options: [ commandOptions.optionalApplication ] permission: 'user' action: (params, options, done) -> - if options.application? getFunction = _.partial(resin.models.device.getAllByApplication, options.application) else @@ -57,19 +57,18 @@ exports.list = return done(null, devices) exports.info = - signature: 'device ' + signature: 'device ' description: 'list a single device' help: ''' Use this command to show information about a single device. Examples: - $ resin device MyDevice + $ resin device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 ''' permission: 'user' action: (params, options, done) -> - resin.models.device.get params.name, (error, device) -> - return done(error) if error? + resin.models.device.get(params.uuid).then (device) -> # TODO: We should outsource this logic and probably # other last_seen edge cases to either Resin CLI Visuals @@ -92,10 +91,10 @@ exports.info = 'note' ] - return done() + .nodeify(done) exports.remove = - signature: 'device rm ' + signature: 'device rm ' description: 'remove a device' help: ''' Use this command to remove a device from resin.io. @@ -105,14 +104,14 @@ exports.remove = Examples: - $ resin device rm MyDevice - $ resin device rm MyDevice --yes + $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 + $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 --yes ''' options: [ commandOptions.yes ] permission: 'user' action: (params, options, done) -> visuals.patterns.remove 'device', options.yes, (callback) -> - resin.models.device.remove(params.name, callback) + resin.models.device.remove(params.uuid).nodeify(callback) , done exports.identify = @@ -129,10 +128,10 @@ exports.identify = ''' permission: 'user' action: (params, options, done) -> - resin.models.device.identify(params.uuid, done) + resin.models.device.identify(params.uuid).nodeify(done) exports.rename = - signature: 'device rename [newName]' + signature: 'device rename [newName]' description: 'rename a resin device' help: ''' Use this command to rename a device. @@ -141,8 +140,8 @@ exports.rename = Examples: - $ resin device rename MyDevice MyPi - $ resin device rename MyDevice + $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 MyPi + $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 ''' permission: 'user' action: (params, options, done) -> @@ -159,7 +158,7 @@ exports.rename = , callback (newName, callback) -> - resin.models.device.rename(params.name, newName, callback) + resin.models.device.rename(params.uuid, newName).nodeify(callback) ], done @@ -175,13 +174,12 @@ exports.supported = ''' permission: 'user' action: (params, options, done) -> - resin.models.device.getSupportedDeviceTypes (error, devices) -> - return done(error) if error? - _.each(devices, _.unary(console.log)) - done() + resin.models.device.getSupportedDeviceTypes().each (device) -> + console.log(device) + .nodeify(done) exports.await = - signature: 'device await ' + signature: 'device await ' description: 'await for a device to become online' help: ''' Use this command to await for a device to become online. @@ -194,8 +192,8 @@ exports.await = Examples: - $ resin device await MyDevice - $ resin device await MyDevice --interval 1000 + $ resin device await 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 + $ resin device await 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 --interval 1000 ''' options: [ signature: 'interval' @@ -208,17 +206,14 @@ exports.await = options.interval ?= 3000 poll = -> - resin.models.device.isOnline params.name, (error, isOnline) -> - return done(error) if error? - + resin.models.device.isOnline(params.uuid).then (isOnline) -> if isOnline - console.info("Device became online: #{params.name}") - return done() + console.info("Device became online: #{params.uuid}") + return else - console.info("Polling device network status: #{params.name}") - setTimeout(poll, options.interval) - - poll() + console.info("Polling device network status: #{params.uuid}") + return Promise.delay(options.interval).then(poll) + poll().nodeify(done) exports.init = signature: 'device init [device]' @@ -276,7 +271,7 @@ exports.init = (applicationName, callback) -> options.application = applicationName - resin.models.application.has(options.application, callback) + resin.models.application.has(options.application).nodeify(callback) (hasApplication, callback) -> if not hasApplication @@ -300,18 +295,18 @@ exports.init = (callback) -> console.info("Checking application: #{options.application}") - resin.models.application.get(options.application, callback) + resin.models.application.get(options.application).nodeify(callback) (application, callback) -> async.parallel manifest: (callback) -> console.info('Getting device manifest for the application') - resin.models.device.getManifestBySlug(application.device_type, callback) + resin.models.device.getManifestBySlug(application.device_type).nodeify(callback) config: (callback) -> console.info('Fetching application configuration') - resin.models.application.getConfiguration(options.application, networkOptions, callback) + deviceConfig.get(options.application, networkOptions).nodeify(callback) , callback @@ -364,7 +359,7 @@ exports.init = removeCallback(callback) (callback) -> - resin.models.device.getByUUID(params.uuid, callback) + resin.models.device.get(params.uuid).nodeify(callback) (device, callback) -> console.info("Device created: #{device.name}") diff --git a/lib/actions/environment-variables.coffee b/lib/actions/environment-variables.coffee index 7ba65ecc..d50c2623 100644 --- a/lib/actions/environment-variables.coffee +++ b/lib/actions/environment-variables.coffee @@ -38,9 +38,9 @@ exports.list = (callback) -> if options.application? - resin.models.environmentVariables.getAllByApplication(options.application, callback) + resin.models.environmentVariables.getAllByApplication(options.application).nodeify(callback) else if options.device? - resin.models.environmentVariables.device.getAll(options.device, callback) + resin.models.environmentVariables.device.getAll(options.device).nodeify(callback) else return callback(new Error('You must specify an application or device')) @@ -87,9 +87,9 @@ exports.remove = action: (params, options, done) -> visuals.patterns.remove 'environment variable', options.yes, (callback) -> if options.device - resin.models.environmentVariables.device.remove(params.id, callback) + resin.models.environmentVariables.device.remove(params.id).nodeify(callback) else - resin.models.environmentVariables.remove(params.id, callback) + resin.models.environmentVariables.remove(params.id).nodeify(callback) , done exports.add = @@ -128,9 +128,9 @@ exports.add = console.info("Warning: using #{params.key}=#{params.value} from host environment") if options.application? - resin.models.environmentVariables.create(options.application, params.key, params.value, done) + resin.models.environmentVariables.create(options.application, params.key, params.value).nodeify(done) else if options.device? - resin.models.environmentVariables.device.create(options.device, params.key, params.value, done) + resin.models.environmentVariables.device.create(options.device, params.key, params.value).nodeify(done) else return done(new Error('You must specify an application or device')) @@ -151,6 +151,6 @@ exports.rename = options: [ commandOptions.booleanDevice ] action: (params, options, done) -> if options.device - resin.models.environmentVariables.device.update(params.id, params.value, done) + resin.models.environmentVariables.device.update(params.id, params.value).nodeify(done) else - resin.models.environmentVariables.update(params.id, params.value, done) + resin.models.environmentVariables.update(params.id, params.value).nodeify(done) diff --git a/lib/actions/examples.coffee b/lib/actions/examples.coffee index 36c9f14f..30f54499 100644 --- a/lib/actions/examples.coffee +++ b/lib/actions/examples.coffee @@ -3,7 +3,6 @@ async = require('async') fs = require('fs') path = require('path') _ = require('lodash') -resin = require('resin-sdk') visuals = require('resin-cli-visuals') vcs = require('resin-vcs') examplesData = require('../data/examples.json') diff --git a/lib/actions/help.coffee b/lib/actions/help.coffee index c69c5af6..89bfb5f3 100644 --- a/lib/actions/help.coffee +++ b/lib/actions/help.coffee @@ -1,6 +1,5 @@ _ = require('lodash') _.str = require('underscore.string') -resin = require('resin-sdk') capitano = require('capitano') # TODO: Refactor this terrible mess diff --git a/lib/actions/keys.coffee b/lib/actions/keys.coffee index cfad1736..25178abf 100644 --- a/lib/actions/keys.coffee +++ b/lib/actions/keys.coffee @@ -19,10 +19,9 @@ exports.list = ''' permission: 'user' action: (params, options, done) -> - resin.models.key.getAll (error, keys) -> - return done(error) if error? + resin.models.key.getAll().then (keys) -> console.log visuals.widgets.table.horizontal keys, [ 'id', 'title' ] - return done() + .nodeify(done) SSH_KEY_WIDTH = 43 @@ -38,10 +37,9 @@ exports.info = ''' permission: 'user' action: (params, options, done) -> - resin.models.key.get params.id, (error, key) -> - return done(error) if error? + resin.models.key.get(params.id).then (key) -> console.log(visuals.widgets.table.vertical(key, [ 'id', 'title', 'public_key' ])) - return done() + .nodeify(done) exports.remove = signature: 'key rm ' @@ -61,7 +59,7 @@ exports.remove = permission: 'user' action: (params, options, done) -> visuals.patterns.remove 'key', options.yes, (callback) -> - resin.models.key.remove(params.id, callback) + resin.models.key.remove(params.id).nodeify(callback) , done exports.add = @@ -90,6 +88,6 @@ exports.add = return callback(null, data) (key, callback) -> - resin.models.key.create(params.name, key, callback) + resin.models.key.create(params.name, key).nodeify(callback) ], done diff --git a/lib/actions/logs.coffee b/lib/actions/logs.coffee index dcc124d2..72a6451f 100644 --- a/lib/actions/logs.coffee +++ b/lib/actions/logs.coffee @@ -1,38 +1,26 @@ _ = require('lodash') resin = require('resin-sdk') -LOGS_HISTORY_COUNT = 200 - module.exports = signature: 'logs ' description: 'show device logs' help: ''' - Use this command to show logs for a specific device. + Use this command to show logs for a specific device. - By default, the command prints all log messages and exit. + By default, the command prints all log messages and exit. - To limit the output to the n last lines, use the `--num` option along with a number. - This is similar to doing `resin logs | tail -n X`. + To continuously stream output, and see new logs in real time, use the `--tail` option. - To continuously stream output, and see new logs in real time, use the `--tail` option. + Note that for now you need to provide the whole UUID for this command to work correctly. - Note that for now you need to provide the whole UUID for this command to work correctly. + This is due to some technical limitations that we plan to address soon. - This is due to some technical limitations that we plan to address soon. + Examples: - Examples: - - $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 - $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --num 20 - $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --tail - ''' + $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 + $ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --tail + ''' options: [ - { - signature: 'num' - parameter: 'num' - description: 'number of lines to display' - alias: 'n' - } { signature: 'tail' description: 'continuously stream output' @@ -42,14 +30,15 @@ module.exports = ] permission: 'user' action: (params, options, done) -> - resin.logs.subscribe params.uuid, { - history: options.num or LOGS_HISTORY_COUNT - tail: options.tail - }, (error, message) -> - return done(error) if error? - if _.isArray(message) - _.each message, (line) -> + promise = resin.logs.history(params.uuid).each (line) -> + console.log(line.message) + + if not options.tail + return promise.nodeify(done) + + promise.then -> + resin.logs.subscribe(params.uuid).then (logs) -> + logs.on 'line', (line) -> console.log(line.message) - else - console.log(message.message) - return done() + logs.on('error', done) + .catch(done) diff --git a/lib/actions/notes.coffee b/lib/actions/notes.coffee index 28317323..95d53d23 100644 --- a/lib/actions/notes.coffee +++ b/lib/actions/notes.coffee @@ -10,17 +10,17 @@ exports.set = If note command isn't passed, the tool attempts to read from `stdin`. - To view the notes, use $ resin device . + To view the notes, use $ resin device . Examples: - $ resin note "My useful note" --device MyDevice - $ cat note.txt | resin note --device MyDevice + $ resin note "My useful note" --device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 + $ cat note.txt | resin note --device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 ''' options: [ signature: 'device' parameter: 'device' - description: 'device name' + description: 'device uuid' alias: [ 'd', 'dev' ] required: 'You have to specify a device' ] @@ -30,4 +30,4 @@ exports.set = if _.isEmpty(params.note) return done(new Error('Missing note content')) - resin.models.device.note(options.device, params.note, done) + resin.models.device.note(options.device, params.note).nodeify(done) diff --git a/lib/app.coffee b/lib/app.coffee index ce9be871..1945d87d 100644 --- a/lib/app.coffee +++ b/lib/app.coffee @@ -8,11 +8,10 @@ plugins = require('./plugins') update = require('./update') capitano.permission 'user', (done) -> - resin.auth.isLoggedIn (error, isLoggedIn) -> - return done(error) if error? + resin.auth.isLoggedIn().then (isLoggedIn) -> if not isLoggedIn - return done(new Error('You have to log in')) - return done() + throw new Error ('You have to log in') + .nodeify(done) capitano.command signature: '*' diff --git a/package.json b/package.json index 1fe4af57..e1efde18 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,12 @@ "open": "0.0.5", "resin-cli-visuals": "^0.3.3", "resin-config-inject": "^2.0.0", + "resin-device-config": "^1.0.0", "resin-image": "^1.1.3", "resin-image-manager": "^1.1.0", "resin-pine": "^1.3.0", "resin-register-device": "^1.0.1", - "resin-sdk": "^1.7.4", + "resin-sdk": "^2.2.0", "resin-settings-client": "^1.4.0", "resin-vcs": "^2.0.0", "selfupdate": "^1.1.0",