mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-21 09:51:58 +00:00
Make use of Capitano for command line parsing
This commit is contained in:
parent
b30b41d4bb
commit
6cfe2bdc49
@ -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)
|
||||
|
@ -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?
|
||||
|
||||
|
@ -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?
|
||||
|
@ -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
111
lib/actions/help.coffee
Normal 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()
|
@ -7,3 +7,4 @@ module.exports =
|
||||
logs: require('./logs')
|
||||
preferences: require('./preferences')
|
||||
os: require('./os')
|
||||
help: require('./help')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
478
lib/app.coffee
478
lib/app.coffee
@ -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)
|
||||
|
@ -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()
|
@ -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)
|
@ -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
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user