Make use of Capitano for command line parsing

This commit is contained in:
Juan Cruz Viotti 2014-12-12 17:20:29 -04:00
parent b30b41d4bb
commit 6cfe2bdc49
15 changed files with 568 additions and 279 deletions

View File

@ -2,14 +2,14 @@ _ = require('lodash')
async = require('async')
gitCli = require('git-cli')
resin = require('../resin')
cli = require('../cli/cli')
ui = require('../ui')
permissions = require('../permissions/permissions')
exports.create = (name) ->
exports.create = permissions.user (params, options) ->
async.waterfall [
(callback) ->
deviceType = cli.getArgument('type')
deviceType = options.type
if deviceType?
return callback(null, deviceType)
@ -23,11 +23,11 @@ exports.create = (name) ->
# Maybe we should break or handle better?
slugifiedType = resin.device.getDeviceSlug(type)
resin.models.application.create(name, slugifiedType, callback)
resin.models.application.create(params.name, slugifiedType, callback)
], resin.errors.handle
exports.list = ->
exports.list = permissions.user ->
resin.models.application.getAll (error, applications) ->
resin.errors.handle(error) if error?
@ -40,8 +40,8 @@ exports.list = ->
return application
, [ 'ID', 'Name', 'Device Type', 'Online Devices', 'All Devices' ]
exports.info = (id) ->
resin.models.application.get id, (error, application) ->
exports.info = permissions.user (params) ->
resin.models.application.get params.id, (error, application) ->
resin.errors.handle(error) if error?
resin.log.out ui.widgets.table.vertical application, (application) ->
@ -50,18 +50,16 @@ exports.info = (id) ->
return application
, [ 'ID', 'Name', 'Device Type', 'Git Repository', 'Commit' ]
exports.restart = (id) ->
resin.models.application.restart id, (error) ->
exports.restart = permissions.user (params) ->
resin.models.application.restart params.id, (error) ->
resin.errors.handle(error) if error?
exports.remove = (id) ->
confirmArgument = cli.getArgument('yes')
ui.patterns.remove 'application', confirmArgument, (callback) ->
resin.models.application.remove(id, callback)
exports.remove = permissions.user (params, options) ->
ui.patterns.remove 'application', options.yes, (callback) ->
resin.models.application.remove(params.id, callback)
, resin.errors.handle
exports.init = (id) ->
exports.init = permissions.user (params) ->
currentDirectory = process.cwd()
@ -77,7 +75,7 @@ exports.init = (id) ->
return callback()
(callback) ->
resin.models.application.get(id, callback)
resin.models.application.get(params.id, callback)
(application, callback) ->
resin.vcs.initProjectWithApplication(application, currentDirectory, callback)

View File

@ -3,13 +3,14 @@ open = require('open')
async = require('async')
resin = require('../resin')
ui = require('../ui')
permissions = require('../permissions/permissions')
exports.login = (credentials) ->
exports.login = (params) ->
async.waterfall [
(callback) ->
if credentials?
return resin.auth.parseCredentials(credentials, callback)
if params.credentials?
return resin.auth.parseCredentials(params.credentials, callback)
else
return ui.widgets.login(callback)
@ -18,7 +19,7 @@ exports.login = (credentials) ->
], resin.errors.handle
exports.logout = ->
exports.logout = permissions.user ->
resin.auth.logout()
exports.signup = ->
@ -26,7 +27,7 @@ exports.signup = ->
absUrl = url.resolve(resin.settings.get('remoteUrl'), signupUrl)
open(absUrl)
exports.whoami = ->
exports.whoami = permissions.user ->
resin.auth.whoami (error, username) ->
resin.errors.handle(error) if error?

View File

@ -1,9 +1,9 @@
resin = require('../resin')
cli = require('../cli/cli')
ui = require('../ui')
permissions = require('../permissions/permissions')
exports.list = (applicationId) ->
resin.models.device.getAllByApplication applicationId, (error, devices) ->
exports.list = permissions.user (params) ->
resin.models.device.getAllByApplication params.id, (error, devices) ->
resin.errors.handle(error) if error?
resin.log.out ui.widgets.table.horizontal devices, (device) ->
@ -16,8 +16,8 @@ exports.list = (applicationId) ->
return device
, [ 'ID', 'Name', 'Device Type', 'Is Online', 'IP Address', 'Application', 'Status', 'Last Seen' ]
exports.info = (deviceId) ->
resin.models.device.get deviceId, (error, device) ->
exports.info = permissions.user (params) ->
resin.models.device.get params.id, (error, device) ->
resin.errors.handle(error) if error?
resin.log.out ui.widgets.table.vertical device, (device) ->
@ -40,12 +40,11 @@ exports.info = (deviceId) ->
'Note'
]
exports.remove = (id) ->
confirmArgument = cli.getArgument('yes')
ui.patterns.remove 'device', confirmArgument, (callback) ->
resin.models.device.remove(id, callback)
exports.remove = permissions.user (params, options) ->
ui.patterns.remove 'device', options.yes, (callback) ->
resin.models.device.remove(params.id, callback)
, resin.errors.handle
exports.identify = (uuid) ->
resin.models.device.identify uuid, (error) ->
exports.identify = permissions.user (params) ->
resin.models.device.identify params.uuid, (error) ->
resin.errors.handle(error) if error?

View File

@ -1,29 +1,26 @@
_ = require('lodash')
resin = require('../resin')
cli = require('../cli/cli')
ui = require('../ui')
permissions = require('../permissions/permissions')
SYSTEM_VAR_REGEX = /^RESIN_/
isSystemVariable = (environmentVariable) ->
SYSTEM_VAR_REGEX.test(environmentVariable.name)
exports.list = ->
applicationId = cli.getArgument('application')
if not applicationId?
exports.list = permissions.user (params, options) ->
if not options.application?
resin.errors.handle(new Error('You have to specify an application'))
resin.models.environmentVariables.getAllByApplication applicationId, (error, environmentVariables) ->
resin.models.environmentVariables.getAllByApplication options.application, (error, environmentVariables) ->
resin.errors.handle(error) if error?
if not cli.getArgument('verbose')?
if not options.verbose
environmentVariables = _.reject(environmentVariables, isSystemVariable)
resin.log.out(ui.widgets.table.horizontal(environmentVariables))
exports.remove = (id) ->
confirmArgument = cli.getArgument('yes')
ui.patterns.remove 'environment variable', confirmArgument, (callback) ->
resin.models.environmentVariables.remove(id, callback)
exports.remove = permissions.user (params, options) ->
ui.patterns.remove 'environment variable', options.yes, (callback) ->
resin.models.environmentVariables.remove(params.id, callback)
, resin.errors.handle

111
lib/actions/help.coffee Normal file
View File

@ -0,0 +1,111 @@
_ = require('lodash')
_.str = require('underscore.string')
resin = require('../resin')
capitano = require('capitano')
# TODO: Refactor this terrible mess
PADDING_INITIAL = ' '
PADDING_MIDDLE = '\t'
getFieldMaxLength = (array, field) ->
return _.max _.map array, (item) ->
return item[field].toString().length
buildHelpString = (firstColumn, secondColumn) ->
result = "#{PADDING_INITIAL}#{firstColumn}"
result += "#{PADDING_MIDDLE}#{secondColumn}"
return result
addOptionPrefix = (option) ->
return if option.length <= 0
if option.length is 1
return "-#{option}"
else
return "--#{option}"
addAlias = (alias) ->
return ", #{addOptionPrefix(alias)}"
buildOptionSignatureHelp = (option) ->
result = addOptionPrefix(option.signature.toString())
if _.isString(option.alias)
result += addAlias(option.alias)
else if _.isArray(option.alias)
for alias in option.alias
result += addAlias(alias)
if option.parameter?
result += " <#{option.parameter}>"
return result
getCommandHelp = (command) ->
maxSignatureLength = getFieldMaxLength(capitano.state.commands, 'signature')
commandSignature = _.str.rpad(command.signature.toString(), maxSignatureLength, ' ')
return buildHelpString(commandSignature, command.description)
getOptionsParsedSignatures = (optionsHelp) ->
maxLength = _.max _.map optionsHelp, (signature) ->
return signature.length
return _.map optionsHelp, (signature) ->
return _.str.rpad(signature, maxLength, ' ')
getOptionHelp = (option, maxLength) ->
result = PADDING_INITIAL
result += _.str.rpad(option.signature, maxLength, ' ')
result += PADDING_MIDDLE
result += option.description
return result
exports.general = ->
resin.log.out("Usage: #{process.argv[0]} [COMMAND] [OPTIONS]\n")
resin.log.out('Commands:\n')
for command in capitano.state.commands
continue if command.isWildcard()
resin.log.out(getCommandHelp(command))
resin.log.out('\nGlobal Options:\n')
options = _.map capitano.state.globalOptions, (option) ->
option.signature = buildOptionSignatureHelp(option)
return option
optionSignatureMaxLength = _.max _.map options, (option) ->
return option.signature.length
for option in options
resin.log.out(getOptionHelp(option, optionSignatureMaxLength))
resin.log.out()
exports.command = (params) ->
command = capitano.state.getMatchCommand(params.command)
if not command? or command.isWildcard()
return capitano.defaults.actions.commandNotFound(params.command)
resin.log.out("Usage: #{command.signature}")
if command.help?
resin.log.out("\n#{command.help}")
else if command.description?
resin.log.out("\n#{_.str.humanize(command.description)}")
if not _.isEmpty(command.options)
resin.log.out('\nOptions:\n')
options = _.map command.options, (option) ->
option.signature = buildOptionSignatureHelp(option)
return option
optionSignatureMaxLength = _.max _.map options, (option) ->
return option.signature.toString().length
for option in options
resin.log.out(getOptionHelp(option, optionSignatureMaxLength))
resin.log.out()

View File

@ -7,3 +7,4 @@ module.exports =
logs: require('./logs')
preferences: require('./preferences')
os: require('./os')
help: require('./help')

View File

@ -2,10 +2,10 @@ _ = require('lodash')
_.str = require('underscore.string')
resin = require('../resin')
helpers = require('../helpers/helpers')
cli = require('../cli/cli')
ui = require('../ui')
permissions = require('../permissions/permissions')
exports.list = ->
exports.list = permissions.user ->
resin.server.get resin.settings.get('urls.keys'), (error, response, keys) ->
resin.errors.handle(error) if error?
resin.log.out ui.widgets.table.horizontal keys, (key) ->
@ -13,24 +13,22 @@ exports.list = ->
return key
, [ 'ID', 'Title' ]
exports.info = (id) ->
id = _.parseInt(id)
exports.info = permissions.user (params) ->
# TODO: We don't have a way to query a single ssh key yet.
# As a workaround, we request all of them, and filter
# the one we need. Fix once we have a better way.
resin.server.get resin.settings.get('urls.keys'), (error, response, keys) ->
resin.errors.handle(error) if error?
key = _.findWhere(keys, { id })
key = _.findWhere(keys, id: params.id)
if not key?
resin.errors.handle(new resin.errors.NotFound("key #{id}"))
resin.errors.handle(new resin.errors.NotFound("key #{params.id}"))
key.public_key = '\n' + _.chop(key.public_key, resin.settings.get('sshKeyWidth')).join('\n')
key.public_key = '\n' + _.str.chop(key.public_key, resin.settings.get('sshKeyWidth')).join('\n')
resin.log.out(ui.widgets.table.vertical(key, _.identity, [ 'ID', 'Title', 'Public Key' ]))
exports.remove = (id) ->
confirmArgument = cli.getArgument('yes')
ui.patterns.remove 'key', confirmArgument, (callback) ->
url = _.template(resin.settings.get('urls.sshKey'), { id })
exports.remove = permissions.user (params, options) ->
ui.patterns.remove 'key', options.yes, (callback) ->
url = _.template(resin.settings.get('urls.sshKey'), id: params.id)
resin.server.delete(url, callback)
, resin.errors.handle

View File

@ -2,7 +2,7 @@ _ = require('lodash')
PubNub = require('pubnub')
resin = require('../resin')
helpers = require('../helpers/helpers')
cli = require('../cli/cli')
permissions = require('../permissions/permissions')
LOGS_HISTORY_COUNT = 200
@ -15,14 +15,15 @@ printLogs = (logs, number) ->
logs = _.last(logs, number) if _.isNumber(number)
resin.log.array(logs, resin.log.out)
exports.logs = (uuid) ->
numberOfLines = cli.getArgument('num', _.parseInt)
tailOutput = cli.getArgument('tail') or false
exports.logs = permissions.user (params, options) ->
numberOfLines = options.num
tailOutput = options.tail or false
if numberOfLines? and not _.isNumber(numberOfLines)
resin.errors.handle(new Error('n/num should be a number'))
helpers.isDeviceUUIDValid uuid, (error, isValidUUID) ->
helpers.isDeviceUUIDValid params.uuid, (error, isValidUUID) ->
resin.errors.handle(error) if error?
if not isValidUUID
@ -33,7 +34,7 @@ exports.logs = (uuid) ->
# all other actions from exiting on completion
pubnub = PubNub.init(resin.settings.get('pubnub'))
channel = _.template(resin.settings.get('events.deviceLogs'), { uuid })
channel = _.template(resin.settings.get('events.deviceLogs'), uuid: params.uuid)
pubnub.history
count: LOGS_HISTORY_COUNT

View File

@ -5,17 +5,17 @@ mkdirp = require('mkdirp')
url = require('url')
resin = require('../resin')
connection = require('../connection/connection')
cli = require('../cli/cli')
ui = require('../ui')
permissions = require('../permissions/permissions')
exports.download = (id) ->
params =
network: cli.getArgument('network')
wifiSsid: cli.getArgument('wifiSsid')
wifiKey: cli.getArgument('wifiKey')
exports.download = (params, options) ->
networkParams =
network: options.network
wifiSsid: options.ssid
wifiKey: options.key
fileName = resin.os.generateCacheName(id, params)
outputFile = cli.getArgument('output') or path.join(resin.settings.get('directories.os'), fileName)
fileName = resin.os.generateCacheName(params.id, networkParams)
outputFile = options.output or path.join(resin.settings.get('directories.os'), fileName)
async.waterfall [
@ -26,10 +26,10 @@ exports.download = (id) ->
return callback(error)
(callback) ->
connection.parseConnectionParameters(params, callback)
connection.parseConnectionParameters(networkParams, callback)
(parameters, callback) ->
parameters.appId = id
parameters.appId = params.id
query = url.format(query: parameters)
downloadUrl = url.resolve(resin.settings.get('urls.download'), query)

View File

@ -1,8 +1,9 @@
open = require('open')
url = require('url')
resin = require('../resin')
permissions = require('../permissions/permissions')
exports.preferences = ->
exports.preferences = permissions.user ->
preferencesUrl = resin.settings.get('urls.preferences')
absUrl = url.resolve(resin.settings.get('remoteUrl'), preferencesUrl)
open(absUrl)

View File

@ -1,152 +1,434 @@
_ = require('lodash')
capitano = require('capitano')
resin = require('./resin')
packageJSON = require('../package.json')
actions = require('./actions')
cli = require('./cli/cli')
cli.setVersion(packageJSON.version)
capitano.command
signature: 'version'
description: 'output the version number'
action: ->
resin.log.out(packageJSON.version)
capitano.command
signature: 'help [command...]'
description: 'show help'
action: (params) ->
if params.command?
actions.help.command(params)
else
actions.help.general()
capitano.command
signature: '*'
action: ->
capitano.execute(command: 'help')
# ---------- Options ----------
cli.addOption
option: '-y, --yes'
description: 'confirm non interactively'
cli.addOption
option: '-v, --verbose'
description: 'increase verbosity'
cli.addOption
option: '-q, --quiet'
capitano.globalOption
signature: 'quiet'
description: 'quiet (no output)'
boolean: true
alias: 'q'
cli.addOption
option: '-t, --type <type>'
description: 'specify a type when creating an application'
cli.addOption
option: '-n, --num <num>'
description: 'number of lines to display'
cli.addOption
option: '--tail'
description: 'continuously stream output'
# TODO: I have to use 'application' instead of 'app' here
# as Commander gets confused with the app command
cli.addOption
option: '-a, --application <app>'
description: 'application id'
coerce: _.parseInt
cli.addOption
option: '-w, --network <network>'
description: 'network type when downloading OS'
cli.addOption
option: '-s, --wifi-ssid <wifiSsid>'
description: 'wifi ssid, if network is wifi'
cli.addOption
option: '-k, --wifi-key <wifiKey>'
description: 'wifi key, if network is wifi'
cli.addOption
option: '-o, --output <output>'
description: 'output file'
yesOption =
signature: 'yes'
description: 'confirm non interactively'
boolean: true
alias: 'y'
# ---------- Auth Module ----------
cli.addCommand
command: 'login [username:password]'
capitano.command
signature: 'login [credentials]'
description: 'login to resin.io'
help: '''
Use this command to login to your resin.io account.
You need to login before you can use most of the commands this tool provides.
You can pass your credentials as a colon separated string, or you can omit the
credentials, in which case the tool will present you with an interactive login form.
Examples:
$ resin login username:password
$ resin login
'''
action: actions.auth.login
cli.addCommand
command: 'logout'
capitano.command
signature: 'logout'
description: 'logout from resin.io'
action: actions.auth.logout
permission: 'user'
help: '''
Use this command to logout from your resin.io account.o
cli.addCommand
command: 'signup'
Examples:
$ resin logout
'''
action: actions.auth.logout
capitano.command
signature: 'signup'
description: 'signup to resin.io'
help: '''
Use this command to signup for a resin.io account.
In the future, this command may display a form in the terminal and handle
the registration purely from the command line, but for reasons of simplicity,
it opens your default web browser at the web based signup form.
Examples:
$ resin signup
'''
action: actions.auth.signup
cli.addCommand
command: 'whoami'
capitano.command
signature: 'whoami'
description: 'get current username'
help: '''
Use this command to find out the current logged in username.
Examples:
$ resin whoami
'''
action: actions.auth.whoami
# ---------- App Module ----------
cli.addResource
name: 'app'
displayName: 'application'
actions: actions.app
permission: 'user'
capitano.command
signature: 'app create <name>'
description: 'create an application'
help: '''
Use this command to create a new resin.io application.
cli.addCommand
command: 'app:restart <id>'
You can specify the application type with the `--type` option.
Otherwise, an interactive dropdown will be shown for you to select from.
TODO: We should support a command to list all supported device types.
Examples:
$ resin app create MyApp
$ resin app create MyApp --type raspberry-pi
'''
action: actions.app.create
options: [
{
signature: 'type'
parameter: 'type'
description: 'application type'
alias: 't'
}
]
capitano.command
signature: 'apps'
description: 'list all applications'
help: '''
Use this command to list all your applications.
Notice this command only shows the most important bits of information for each app.
If you want detailed information, use resin app <id> instead.
Examples:
$ resin apps
'''
action: actions.app.list
capitano.command
signature: 'app <id>'
description: 'list a single application'
help: '''
Use this command to show detailed information for a single application.
Examples:
$ resin app 91
'''
action: actions.app.info
capitano.command
signature: 'app rm <id>'
description: 'remove an application'
help: '''
Use this command to remove a resin.io application.
Notice this command asks for confirmation interactively.
You can avoid this by passing the `--yes` boolean option.
Examples:
$ resin app rm 91
$ resin app rm 91 --yes
'''
action: actions.app.remove
options: [ yesOption ]
capitano.command
signature: 'app restart <id>'
description: 'restart an application'
action: actions.app.restart
permission: 'user'
help: '''
Use this command to restart all devices that belongs to a certain application.
cli.addCommand
command: 'init <id>'
Examples:
$ resin app restart 91
'''
action: actions.app.restart
capitano.command
signature: 'init <id>'
description: 'init an application'
help: '''
Use this command to associate a local project to an existing resin.io application.
The application should be a git repository before issuing this command.
Notice this command adds a `resin` git remote to your application.
Examples:
$ cd myApp && resin init 91
'''
action: actions.app.init
permission: 'user'
# ---------- Device Module ----------
cli.addResource
name: 'device'
displayName: 'device'
actions: actions.device
permission: 'user'
capitano.command
signature: 'devices <id>'
description: 'list all devices'
help: '''
Use this command to list all devices that belong to a certain application.
cli.addCommand
command: 'device:identify <uuid>'
Examples:
$ resin devices 91
'''
action: actions.device.list
capitano.command
signature: 'device <id>'
description: 'list a single device'
help: '''
Use this command to show information about a single device.
Examples:
$ resin device 317
'''
action: actions.device.info
capitano.command
signature: 'device rm <id>'
description: 'remove a device'
help: '''
Use this command to remove a device from resin.io.
Notice this command asks for confirmation interactively.
You can avoid this by passing the `--yes` boolean option.
Examples:
$ resin device rm 317
$ resin device rm 317 --yes
'''
action: actions.device.remove
options: [ yesOption ]
capitano.command
signature: 'device identify <uuid>'
description: 'identify a device with a UUID'
help: '''
Use this command to identify a device.
In the Raspberry Pi, the ACT led is blinked several times.
Examples:
$ resin device identify 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828
'''
action: actions.device.identify
permission: 'user'
# ---------- Preferences Module ----------
cli.addCommand
command: 'preferences'
capitano.command
signature: 'preferences'
description: 'open preferences form'
help: '''
Use this command to open the preferences form.
In the future, we will allow changing all preferences directly from the terminal.
For now, we open your default web browser and point it to the web based preferences form.
Examples:
$ resin preferences
'''
action: actions.preferences.preferences
permission: 'user'
# ---------- Keys Module ----------
cli.addResource
name: 'key'
displayName: 'ssh key'
actions: actions.keys
permission: 'user'
capitano.command
signature: 'keys'
description: 'list all ssh keys'
help: '''
Use this command to list all your SSH keys.
Examples:
$ resin keys
'''
action: actions.keys.list
capitano.command
signature: 'key <id>'
description: 'list a single ssh key'
help: '''
Use this command to show information about a single SSH key.
Examples:
$ resin key 17
'''
action: actions.keys.info
capitano.command
signature: 'key rm <id>'
description: 'remove a ssh key'
help: '''
Use this command to remove a SSH key from resin.io.
Notice this command asks for confirmation interactively.
You can avoid this by passing the `--yes` boolean option.
Examples:
$ resin key rm 17
$ resin key rm 17 --yes
'''
action: actions.keys.remove
options: [ yesOption ]
# ---------- Env Module ----------
cli.addResource
name: 'env'
displayName: 'environment variable'
actions: actions.env
permission: 'user'
capitano.command
signature: 'envs'
description: 'list all environment variables'
help: '''
Use this command to list all environment variables for a particular application.
Notice we will support per-device environment variables soon.
This command lists all custom environment variables set on the devices running
the application. If you want to see all environment variables, including private
ones used by resin, use the verbose option.
Example:
$ resin envs --application 91
$ resin envs --application 91 --verbose
'''
action: actions.env.list
options: [
{
signature: 'application'
parameter: 'application'
description: 'application id'
alias: [ 'a', 'app' ]
}
{
signature: 'verbose'
description: 'show private environment variables'
boolean: true
alias: 'v'
}
]
capitano.command
signature: 'env rm <id>'
description: 'remove an environment variable'
help: '''
Use this command to remove an environment variable from an application.
Don't remove resin specific variables, as things might not work as expected.
Notice this command asks for confirmation interactively.
You can avoid this by passing the `--yes` boolean option.
Examples:
$ resin env rm 215
$ resin env rm 215 --yes
'''
action: actions.env.remove
options: [ yesOption ]
# ---------- Logs Module ----------
cli.addCommand
command: 'logs <uuid>'
capitano.command
signature: 'logs <uuid>'
description: 'show device logs'
help: '''
Use this command to show logs for a specific device.
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 <uuid> | tail -n X`.
To continuously stream output, and see new logs in real time, use the `--tail` option.
Examples:
$ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828
$ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --num 20
$ resin logs 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828 --tail
'''
action: actions.logs.logs
permission: 'user'
options: [
{
signature: 'num'
parameter: 'num'
description: 'number of lines to display'
alias: 'n'
}
{
signature: 'tail'
description: 'continuously stream output'
boolean: true
alias: 't'
}
]
# ---------- OS Module ----------
cli.addCommand
command: 'os:download <id>'
capitano.command
signature: 'os download <id>'
description: 'download device OS'
help: '''
Use this command to download the device OS configured to a specific network.
Ethernet:
You can setup the device OS to use ethernet by setting the `--network` option to "ethernet".
Wifi:
You can setup the device OS to use wifi by setting the `--network` option to "wifi".
If you set "network" to "wifi", you will need to specify the `--ssid` and `--key` option as well.
By default, this command saved the downloaded image into a resin specific directory.
You can save it to a custom location by specifying the `--output` option.
Examples:
$ resin os download 91 --network ethernet
$ resin os download 91 --network wifi --ssid MyNetwork --key secreykey123
$ resin os download 91 --network ethernet --output ~/MyResinOS.zip
'''
action: actions.os.download
permission: 'user'
options: [
{
signature: 'network'
parameter: 'network'
description: 'network type'
alias: 'n'
}
{
signature: 'ssid'
parameter: 'ssid'
description: 'wifi ssid, if network is wifi'
alias: 's'
}
{
signature: 'key'
parameter: 'key'
description: 'wifi key, if network is wifi'
alias: 'k'
}
{
signature: 'output'
parameter: 'output'
description: 'output file'
alias: 'o'
}
]
cli = capitano.parse(process.argv)
resin.data.prefix.set resin.settings.get('dataPrefix'), (error) ->
resin.errors.handle(error) if error?
cli.parse(process.argv)
resin.log.setQuiet(cli.global.quiet)
quiet = cli.getArgument('quiet')
resin.log.setQuiet(quiet)
capitano.execute(cli)

View File

@ -1,101 +0,0 @@
_ = require('lodash')
program = require('commander')
pluralize = require('pluralize')
indefiniteArticle = require('indefinite-article')
resin = require('../resin')
cliPermissions = require('./cli-permissions')
exports.getArgument = (name, coerceFunction) ->
argument = program[name]
return if not argument?
if _.isFunction(coerceFunction)
argument = coerceFunction(argument)
return argument
exports.setVersion = (version) ->
program.version(version)
# Set version command automatically
exports.addCommand
command: 'version'
description: 'show version'
action: ->
resin.log.out(version)
applyPermissions = (permission, action, onError) ->
permissionFunction = cliPermissions[permission]
if not _.isFunction(permissionFunction)
throw new Error("Invalid permission #{permission}")
return permissionFunction(action, onError)
exports.addCommand = (options = {}) ->
_.defaults options,
onError: resin.errors.handle
if options.permission?
action = applyPermissions(options.permission, options.action, options.onError)
else
action = options.action
program
.command(options.command)
.description(options.description)
.action(action)
return program
exports.addOption = (options = {}) ->
program.option(options.option, options.description, options.coerce)
exports.addResource = (options = {}) ->
options.displayName ?= options.name
nameArticle = indefiniteArticle(options.displayName)
pluralizedName = pluralize(options.name)
pluralizedDisplayName = pluralize(options.displayName)
if _.isFunction(options.actions.create)
exports.addCommand
command: "#{options.name}:create <name>"
description: "create #{nameArticle} #{options.displayName}"
action: options.actions.create
permission: options.permission
if _.isFunction(options.actions.list)
exports.addCommand
command: "#{pluralizedName}"
description: "list all #{pluralizedDisplayName}"
action: options.actions.list
permission: options.permission
if _.isFunction(options.actions.info)
exports.addCommand
command: "#{options.name} <id>"
description: "list a single #{options.displayName}"
action: options.actions.info
permission: options.permission
if _.isFunction(options.actions.remove)
exports.addCommand
command: "#{options.name}:rm <id>"
description: "remove #{nameArticle} #{options.displayName}"
action: options.actions.remove
permission: options.permission
exports.parse = (argv) ->
# Matches unknown commands
exports.addCommand
command: '*'
description: ''
action: ->
program.outputHelp()
program.parse(argv)
# Show help if no command is passed
if _.isEmpty(program.args)
program.outputHelp()

View File

@ -10,6 +10,7 @@ exports.user = (fn, onError) ->
if onError?
return onError(error)
else
throw error
console.error(error.message)
process.exit(1)
fn.apply(null, args)

View File

@ -3,11 +3,11 @@ nock = require('nock')
sinon = require('sinon')
expect = require('chai').expect
resin = require('../resin')
cliPermissions = require('./cli-permissions')
permissions = require('./permissions')
johnDoeFixture = require('../../tests/fixtures/johndoe')
mock = require('../../tests/utils/mock')
describe 'CLI Permissions:', ->
describe 'Permissions:', ->
describe '#user()', ->
@ -31,14 +31,14 @@ describe 'CLI Permissions:', ->
it 'should not call the function', (done) ->
spy = sinon.spy()
cliPermissions.user(spy, _.noop)()
permissions.user(spy, _.noop)()
_.defer ->
expect(spy).to.not.have.been.called
done()
it 'it should call the second function with an error', (done) ->
func = cliPermissions.user _.noop, (error) ->
func = permissions.user _.noop, (error) ->
expect(error).to.be.an.instanceof(Error)
done()
func()
@ -56,7 +56,7 @@ describe 'CLI Permissions:', ->
args = [ 1, 2, 3, 'foo', 'bar' ]
spy = sinon.spy()
cliPermissions.user(spy, _.noop).apply(null, args)
permissions.user(spy, _.noop).apply(null, args)
_.defer ->
expect(spy).to.have.been.calledWith(args...)
@ -64,7 +64,7 @@ describe 'CLI Permissions:', ->
it 'should not call the second function', (done) ->
spy = sinon.spy()
cliPermissions.user(_.noop, spy)()
permissions.user(_.noop, spy)()
_.defer ->
expect(spy).to.not.have.been.called

View File

@ -52,7 +52,6 @@
"lodash": "~2.4.1",
"async": "~0.9.0",
"rimraf": "~2.2.8",
"commander": "~2.5.0",
"mkdirp": "~0.5.0",
"pinejs-client-js": "git+ssh://git@bitbucket.org/rulemotion/pinejs-client-js.git",
"bluebird": "~2.3.11",
@ -73,6 +72,7 @@
"lodash-contrib": "~241.4.14",
"conf.js": "~0.1.1",
"coffee-script": "~1.8.0",
"git-cli": "~0.8.2"
"git-cli": "~0.8.2",
"capitano": "~1.0.0"
}
}