mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-31 08:25:36 +00:00
Convert lib/actions/device.coffee to javascript
Change-type: patch
This commit is contained in:
parent
00ce3ab751
commit
0cfa1a0dfb
@ -1,443 +0,0 @@
|
||||
###
|
||||
Copyright 2016-2017 Balena
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
###
|
||||
|
||||
commandOptions = require('./command-options')
|
||||
_ = require('lodash')
|
||||
{ normalizeUuidProp } = require('../utils/normalization')
|
||||
{ getBalenaSdk, getVisuals } = require('../utils/lazy')
|
||||
|
||||
expandForAppName = {
|
||||
$expand: belongs_to__application: $select: 'app_name'
|
||||
}
|
||||
|
||||
exports.list =
|
||||
signature: 'devices'
|
||||
description: 'list all devices'
|
||||
help: '''
|
||||
Use this command to list all devices that belong to you.
|
||||
|
||||
You can filter the devices by application by using the `--application` option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena devices
|
||||
$ balena devices --application MyApp
|
||||
$ balena devices --app MyApp
|
||||
$ balena devices -a MyApp
|
||||
'''
|
||||
options: [ commandOptions.optionalApplication ]
|
||||
permission: 'user'
|
||||
primary: true
|
||||
action: (params, options) ->
|
||||
Promise = require('bluebird')
|
||||
balena = getBalenaSdk()
|
||||
|
||||
Promise.try ->
|
||||
if options.application?
|
||||
return balena.models.device.getAllByApplication(options.application, expandForAppName)
|
||||
return balena.models.device.getAll(expandForAppName)
|
||||
|
||||
.tap (devices) ->
|
||||
devices = _.map devices, (device) ->
|
||||
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid)
|
||||
device.application_name =
|
||||
if device.belongs_to__application?[0] then device.belongs_to__application[0].app_name else 'N/a'
|
||||
device.uuid = device.uuid.slice(0, 7)
|
||||
return device
|
||||
|
||||
console.log getVisuals().table.horizontal devices, [
|
||||
'id'
|
||||
'uuid'
|
||||
'device_name'
|
||||
'device_type'
|
||||
'application_name'
|
||||
'status'
|
||||
'is_online'
|
||||
'supervisor_version'
|
||||
'os_version'
|
||||
'dashboard_url'
|
||||
]
|
||||
|
||||
exports.info =
|
||||
signature: 'device <uuid>'
|
||||
description: 'list a single device'
|
||||
help: '''
|
||||
Use this command to show information about a single device.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device 7cf02a6
|
||||
'''
|
||||
permission: 'user'
|
||||
primary: true
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
|
||||
balena.models.device.get(params.uuid, expandForAppName)
|
||||
.then (device) ->
|
||||
balena.models.device.getStatus(device).then (status) ->
|
||||
device.status = status
|
||||
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid)
|
||||
device.application_name =
|
||||
if device.belongs_to__application?[0] then device.belongs_to__application[0].app_name else 'N/a'
|
||||
device.commit = device.is_on__commit
|
||||
|
||||
console.log getVisuals().table.vertical device, [
|
||||
"$#{device.device_name}$"
|
||||
'id'
|
||||
'device_type'
|
||||
'status'
|
||||
'is_online'
|
||||
'ip_address'
|
||||
'application_name'
|
||||
'last_seen'
|
||||
'uuid'
|
||||
'commit'
|
||||
'supervisor_version'
|
||||
'is_web_accessible'
|
||||
'note'
|
||||
'os_version'
|
||||
'dashboard_url'
|
||||
]
|
||||
|
||||
exports.register =
|
||||
signature: 'device register <application>'
|
||||
description: 'register a device'
|
||||
help: '''
|
||||
Use this command to register a device to an application.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device register MyApp
|
||||
$ balena device register MyApp --uuid <uuid>
|
||||
'''
|
||||
permission: 'user'
|
||||
options: [
|
||||
{
|
||||
signature: 'uuid'
|
||||
description: 'custom uuid'
|
||||
parameter: 'uuid'
|
||||
alias: 'u'
|
||||
}
|
||||
]
|
||||
action: (params, options) ->
|
||||
Promise = require('bluebird')
|
||||
balena = getBalenaSdk()
|
||||
|
||||
Promise.join(
|
||||
balena.models.application.get(params.application)
|
||||
options.uuid ? balena.models.device.generateUniqueKey()
|
||||
(application, uuid) ->
|
||||
console.info("Registering to #{application.app_name}: #{uuid}")
|
||||
return balena.models.device.register(application.id, uuid)
|
||||
)
|
||||
.get('uuid')
|
||||
|
||||
exports.remove =
|
||||
signature: 'device rm <uuid>'
|
||||
description: 'remove a device'
|
||||
help: '''
|
||||
Use this command to remove a device from balena.
|
||||
|
||||
Notice this command asks for confirmation interactively.
|
||||
You can avoid this by passing the `--yes` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device rm 7cf02a6
|
||||
$ balena device rm 7cf02a6 --yes
|
||||
'''
|
||||
options: [ commandOptions.yes ]
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
patterns = require('../utils/patterns')
|
||||
|
||||
patterns.confirm(options.yes, 'Are you sure you want to delete the device?').then ->
|
||||
balena.models.device.remove(params.uuid)
|
||||
|
||||
exports.identify =
|
||||
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:
|
||||
|
||||
$ balena device identify 23c73a1
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.identify(params.uuid)
|
||||
|
||||
exports.reboot =
|
||||
signature: 'device reboot <uuid>'
|
||||
description: 'restart a device'
|
||||
help: '''
|
||||
Use this command to remotely reboot a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device reboot 23c73a1
|
||||
'''
|
||||
options: [ commandOptions.forceUpdateLock ]
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.reboot(params.uuid, options)
|
||||
|
||||
exports.shutdown =
|
||||
signature: 'device shutdown <uuid>'
|
||||
description: 'shutdown a device'
|
||||
help: '''
|
||||
Use this command to remotely shutdown a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device shutdown 23c73a1
|
||||
'''
|
||||
options: [ commandOptions.forceUpdateLock ]
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.shutdown(params.uuid, options)
|
||||
|
||||
exports.enableDeviceUrl =
|
||||
signature: 'device public-url enable <uuid>'
|
||||
description: 'enable public URL for a device'
|
||||
help: '''
|
||||
Use this command to enable public URL for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url enable 23c73a1
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.enableDeviceUrl(params.uuid)
|
||||
|
||||
exports.disableDeviceUrl =
|
||||
signature: 'device public-url disable <uuid>'
|
||||
description: 'disable public URL for a device'
|
||||
help: '''
|
||||
Use this command to disable public URL for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url disable 23c73a1
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.disableDeviceUrl(params.uuid)
|
||||
|
||||
exports.getDeviceUrl =
|
||||
signature: 'device public-url <uuid>'
|
||||
description: 'gets the public URL of a device'
|
||||
help: '''
|
||||
Use this command to get the public URL of a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url 23c73a1
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.getDeviceUrl(params.uuid).then (url) ->
|
||||
console.log(url)
|
||||
|
||||
exports.hasDeviceUrl =
|
||||
signature: 'device public-url status <uuid>'
|
||||
description: 'Returns true if public URL is enabled for a device'
|
||||
help: '''
|
||||
Use this command to determine if public URL is enabled for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url status 23c73a1
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
balena.models.device.hasDeviceUrl(params.uuid).then (hasDeviceUrl) ->
|
||||
console.log(hasDeviceUrl)
|
||||
|
||||
exports.rename =
|
||||
signature: 'device rename <uuid> [newName]'
|
||||
description: 'rename a balena device'
|
||||
help: '''
|
||||
Use this command to rename a device.
|
||||
|
||||
If you omit the name, you'll get asked for it interactively.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device rename 7cf02a6
|
||||
$ balena device rename 7cf02a6 MyPi
|
||||
'''
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
Promise = require('bluebird')
|
||||
balena = getBalenaSdk()
|
||||
form = require('resin-cli-form')
|
||||
|
||||
Promise.try ->
|
||||
return params.newName if not _.isEmpty(params.newName)
|
||||
|
||||
form.ask
|
||||
message: 'How do you want to name this device?'
|
||||
type: 'input'
|
||||
|
||||
.then(_.partial(balena.models.device.rename, params.uuid))
|
||||
|
||||
exports.move =
|
||||
signature: 'device move <uuid>'
|
||||
description: 'move a device to another application'
|
||||
help: '''
|
||||
Use this command to move a device to another application you own.
|
||||
|
||||
If you omit the application, you'll get asked for it interactively.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device move 7cf02a6
|
||||
$ balena device move 7cf02a6 --application MyNewApp
|
||||
'''
|
||||
permission: 'user'
|
||||
options: [ commandOptions.optionalApplication ]
|
||||
action: (params, options) ->
|
||||
normalizeUuidProp(params)
|
||||
balena = getBalenaSdk()
|
||||
patterns = require('../utils/patterns')
|
||||
|
||||
balena.models.device.get(params.uuid, expandForAppName).then (device) ->
|
||||
device.application_name =
|
||||
if device.belongs_to__application?[0] then device.belongs_to__application[0].app_name else 'N/a'
|
||||
return options.application if options.application
|
||||
|
||||
return Promise.all([
|
||||
balena.models.device.getManifestBySlug(device.device_type)
|
||||
balena.models.config.getDeviceTypes()
|
||||
]).then ([deviceDeviceType, deviceTypes]) ->
|
||||
compatibleDeviceTypes = deviceTypes.filter (dt) ->
|
||||
balena.models.os.isArchitectureCompatibleWith(deviceDeviceType.arch, dt.arch) &&
|
||||
!!dt.isDependent == !!deviceDeviceType.isDependent &&
|
||||
dt.state != 'DISCONTINUED'
|
||||
|
||||
return patterns.selectApplication (application) ->
|
||||
return _.every [
|
||||
_.some(compatibleDeviceTypes, (dt) -> dt.slug == application.device_type)
|
||||
device.application_name isnt application.app_name
|
||||
]
|
||||
.tap (application) ->
|
||||
return balena.models.device.move(params.uuid, application)
|
||||
.then (application) ->
|
||||
console.info("#{params.uuid} was moved to #{application}")
|
||||
|
||||
exports.init =
|
||||
signature: 'device init'
|
||||
description: 'initialise a device with balenaOS'
|
||||
help: '''
|
||||
Use this command to download the OS image of a certain application and write it to an SD Card.
|
||||
|
||||
Notice this command may ask for confirmation interactively.
|
||||
You can avoid this by passing the `--yes` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device init
|
||||
$ balena device init --application MyApp
|
||||
'''
|
||||
options: [
|
||||
commandOptions.optionalApplication
|
||||
commandOptions.yes
|
||||
commandOptions.advancedConfig
|
||||
_.assign({}, commandOptions.osVersionOrSemver, { signature: 'os-version', parameter: 'os-version' })
|
||||
commandOptions.drive
|
||||
{
|
||||
signature: 'config'
|
||||
description: 'path to the config JSON file, see `balena os build-config`'
|
||||
parameter: 'config'
|
||||
}
|
||||
]
|
||||
permission: 'user'
|
||||
action: (params, options) ->
|
||||
Promise = require('bluebird')
|
||||
rimraf = Promise.promisify(require('rimraf'))
|
||||
tmp = require('tmp')
|
||||
tmpNameAsync = Promise.promisify(tmp.tmpName)
|
||||
tmp.setGracefulCleanup()
|
||||
|
||||
balena = getBalenaSdk()
|
||||
patterns = require('../utils/patterns')
|
||||
{ runCommand } = require('../utils/helpers')
|
||||
|
||||
Promise.try ->
|
||||
return options.application if options.application?
|
||||
return patterns.selectApplication()
|
||||
.then(balena.models.application.get)
|
||||
.then (application) ->
|
||||
|
||||
download = ->
|
||||
tmpNameAsync().then (tempPath) ->
|
||||
osVersion = options['os-version'] or 'default'
|
||||
runCommand("os download #{application.device_type} --output '#{tempPath}' --version #{osVersion}")
|
||||
.disposer (tempPath) ->
|
||||
return rimraf(tempPath)
|
||||
|
||||
Promise.using download(), (tempPath) ->
|
||||
runCommand("device register #{application.app_name}")
|
||||
.then(balena.models.device.get)
|
||||
.tap (device) ->
|
||||
configureCommand = "os configure '#{tempPath}' --device #{device.uuid}"
|
||||
if options.config
|
||||
configureCommand += " --config '#{options.config}'"
|
||||
else if options.advanced
|
||||
configureCommand += ' --advanced'
|
||||
runCommand(configureCommand)
|
||||
.then ->
|
||||
osInitCommand = "os initialize '#{tempPath}' --type #{application.device_type}"
|
||||
if options.yes
|
||||
osInitCommand += ' --yes'
|
||||
if options.drive
|
||||
osInitCommand += " --drive #{options.drive}"
|
||||
runCommand(osInitCommand)
|
||||
# Make sure the device resource is removed if there is an
|
||||
# error when configuring or initializing a device image
|
||||
.catch (error) ->
|
||||
balena.models.device.remove(device.uuid).finally ->
|
||||
throw error
|
||||
.then (device) ->
|
||||
console.log('Done')
|
||||
return device.uuid
|
||||
|
||||
tsActions = require('./device_ts')
|
||||
exports.osUpdate = tsActions.osUpdate
|
535
lib/actions/device.js
Normal file
535
lib/actions/device.js
Normal file
@ -0,0 +1,535 @@
|
||||
/*
|
||||
Copyright 2016-2020 Balena Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import * as commandOptions from './command-options';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
import { normalizeUuidProp } from '../utils/normalization';
|
||||
import { getBalenaSdk, getVisuals } from '../utils/lazy';
|
||||
|
||||
/** @type {import('balena-sdk').PineOptionsFor<import('balena-sdk').Device>} */
|
||||
const expandForAppName = {
|
||||
$expand: { belongs_to__application: { $select: 'app_name' } },
|
||||
};
|
||||
|
||||
export const list = {
|
||||
signature: 'devices',
|
||||
description: 'list all devices',
|
||||
help: `\
|
||||
Use this command to list all devices that belong to you.
|
||||
|
||||
You can filter the devices by application by using the \`--application\` option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena devices
|
||||
$ balena devices --application MyApp
|
||||
$ balena devices --app MyApp
|
||||
$ balena devices -a MyApp\
|
||||
`,
|
||||
options: [commandOptions.optionalApplication],
|
||||
permission: 'user',
|
||||
primary: true,
|
||||
action(_params, options) {
|
||||
const Promise = require('bluebird');
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
return Promise.try(function() {
|
||||
if (options.application != null) {
|
||||
return balena.models.device.getAllByApplication(
|
||||
options.application,
|
||||
expandForAppName,
|
||||
);
|
||||
}
|
||||
return balena.models.device.getAll(expandForAppName);
|
||||
}).tap(function(devices) {
|
||||
devices = _.map(devices, function(device) {
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.dashboard_url = balena.models.device.getDashboardUrl(
|
||||
device.uuid,
|
||||
);
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.application_name = device.belongs_to__application?.[0]
|
||||
? device.belongs_to__application[0].app_name
|
||||
: 'N/a';
|
||||
device.uuid = device.uuid.slice(0, 7);
|
||||
return device;
|
||||
});
|
||||
|
||||
console.log(
|
||||
getVisuals().table.horizontal(devices, [
|
||||
'id',
|
||||
'uuid',
|
||||
'device_name',
|
||||
'device_type',
|
||||
'application_name',
|
||||
'status',
|
||||
'is_online',
|
||||
'supervisor_version',
|
||||
'os_version',
|
||||
'dashboard_url',
|
||||
]),
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const info = {
|
||||
signature: 'device <uuid>',
|
||||
description: 'list a single device',
|
||||
help: `\
|
||||
Use this command to show information about a single device.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device 7cf02a6\
|
||||
`,
|
||||
permission: 'user',
|
||||
primary: true,
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
return balena.models.device
|
||||
.get(params.uuid, expandForAppName)
|
||||
.then(device =>
|
||||
// @ts-ignore `device.getStatus` requires a device with service info, but
|
||||
// this device isn't typed with them, possibly needs fixing?
|
||||
balena.models.device.getStatus(device).then(function(status) {
|
||||
device.status = status;
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.dashboard_url = balena.models.device.getDashboardUrl(
|
||||
device.uuid,
|
||||
);
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.application_name = device.belongs_to__application?.[0]
|
||||
? device.belongs_to__application[0].app_name
|
||||
: 'N/a';
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.commit = device.is_on__commit;
|
||||
|
||||
console.log(
|
||||
getVisuals().table.vertical(device, [
|
||||
`$${device.device_name}$`,
|
||||
'id',
|
||||
'device_type',
|
||||
'status',
|
||||
'is_online',
|
||||
'ip_address',
|
||||
'application_name',
|
||||
'last_seen',
|
||||
'uuid',
|
||||
'commit',
|
||||
'supervisor_version',
|
||||
'is_web_accessible',
|
||||
'note',
|
||||
'os_version',
|
||||
'dashboard_url',
|
||||
]),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const register = {
|
||||
signature: 'device register <application>',
|
||||
description: 'register a device',
|
||||
help: `\
|
||||
Use this command to register a device to an application.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device register MyApp
|
||||
$ balena device register MyApp --uuid <uuid>\
|
||||
`,
|
||||
permission: 'user',
|
||||
options: [
|
||||
{
|
||||
signature: 'uuid',
|
||||
description: 'custom uuid',
|
||||
parameter: 'uuid',
|
||||
alias: 'u',
|
||||
},
|
||||
],
|
||||
action(params, options) {
|
||||
const Promise = require('bluebird');
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
return Promise.join(
|
||||
balena.models.application.get(params.application),
|
||||
options.uuid ?? balena.models.device.generateUniqueKey(),
|
||||
function(application, uuid) {
|
||||
console.info(`Registering to ${application.app_name}: ${uuid}`);
|
||||
return balena.models.device.register(application.id, uuid);
|
||||
},
|
||||
).get('uuid');
|
||||
},
|
||||
};
|
||||
|
||||
export const remove = {
|
||||
signature: 'device rm <uuid>',
|
||||
description: 'remove a device',
|
||||
help: `\
|
||||
Use this command to remove a device from balena.
|
||||
|
||||
Notice this command asks for confirmation interactively.
|
||||
You can avoid this by passing the \`--yes\` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device rm 7cf02a6
|
||||
$ balena device rm 7cf02a6 --yes\
|
||||
`,
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
action(params, options) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
const patterns = require('../utils/patterns');
|
||||
|
||||
return patterns
|
||||
.confirm(options.yes, 'Are you sure you want to delete the device?')
|
||||
.then(() => balena.models.device.remove(params.uuid));
|
||||
},
|
||||
};
|
||||
|
||||
export const identify = {
|
||||
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:
|
||||
|
||||
$ balena device identify 23c73a1\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.identify(params.uuid);
|
||||
},
|
||||
};
|
||||
|
||||
export const reboot = {
|
||||
signature: 'device reboot <uuid>',
|
||||
description: 'restart a device',
|
||||
help: `\
|
||||
Use this command to remotely reboot a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device reboot 23c73a1\
|
||||
`,
|
||||
options: [commandOptions.forceUpdateLock],
|
||||
permission: 'user',
|
||||
action(params, options) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.reboot(params.uuid, options);
|
||||
},
|
||||
};
|
||||
|
||||
export const shutdown = {
|
||||
signature: 'device shutdown <uuid>',
|
||||
description: 'shutdown a device',
|
||||
help: `\
|
||||
Use this command to remotely shutdown a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device shutdown 23c73a1\
|
||||
`,
|
||||
options: [commandOptions.forceUpdateLock],
|
||||
permission: 'user',
|
||||
action(params, options) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.shutdown(params.uuid, options);
|
||||
},
|
||||
};
|
||||
|
||||
export const enableDeviceUrl = {
|
||||
signature: 'device public-url enable <uuid>',
|
||||
description: 'enable public URL for a device',
|
||||
help: `\
|
||||
Use this command to enable public URL for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url enable 23c73a1\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.enableDeviceUrl(params.uuid);
|
||||
},
|
||||
};
|
||||
|
||||
export const disableDeviceUrl = {
|
||||
signature: 'device public-url disable <uuid>',
|
||||
description: 'disable public URL for a device',
|
||||
help: `\
|
||||
Use this command to disable public URL for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url disable 23c73a1\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.disableDeviceUrl(params.uuid);
|
||||
},
|
||||
};
|
||||
|
||||
export const getDeviceUrl = {
|
||||
signature: 'device public-url <uuid>',
|
||||
description: 'gets the public URL of a device',
|
||||
help: `\
|
||||
Use this command to get the public URL of a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url 23c73a1\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.getDeviceUrl(params.uuid).then(url => {
|
||||
console.log(url);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const hasDeviceUrl = {
|
||||
signature: 'device public-url status <uuid>',
|
||||
description: 'Returns true if public URL is enabled for a device',
|
||||
help: `\
|
||||
Use this command to determine if public URL is enabled for a device
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device public-url status 23c73a1\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.device.hasDeviceUrl(params.uuid).then(hasUrl => {
|
||||
console.log(hasUrl);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const rename = {
|
||||
signature: 'device rename <uuid> [newName]',
|
||||
description: 'rename a balena device',
|
||||
help: `\
|
||||
Use this command to rename a device.
|
||||
|
||||
If you omit the name, you'll get asked for it interactively.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device rename 7cf02a6
|
||||
$ balena device rename 7cf02a6 MyPi\
|
||||
`,
|
||||
permission: 'user',
|
||||
action(params) {
|
||||
normalizeUuidProp(params);
|
||||
const Promise = require('bluebird');
|
||||
const balena = getBalenaSdk();
|
||||
const form = require('resin-cli-form');
|
||||
|
||||
return Promise.try(function() {
|
||||
if (!_.isEmpty(params.newName)) {
|
||||
return params.newName;
|
||||
}
|
||||
|
||||
return form.ask({
|
||||
message: 'How do you want to name this device?',
|
||||
type: 'input',
|
||||
});
|
||||
}).then(_.partial(balena.models.device.rename, params.uuid));
|
||||
},
|
||||
};
|
||||
|
||||
export const move = {
|
||||
signature: 'device move <uuid>',
|
||||
description: 'move a device to another application',
|
||||
help: `\
|
||||
Use this command to move a device to another application you own.
|
||||
|
||||
If you omit the application, you'll get asked for it interactively.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device move 7cf02a6
|
||||
$ balena device move 7cf02a6 --application MyNewApp\
|
||||
`,
|
||||
permission: 'user',
|
||||
options: [commandOptions.optionalApplication],
|
||||
action(params, options) {
|
||||
normalizeUuidProp(params);
|
||||
const balena = getBalenaSdk();
|
||||
const patterns = require('../utils/patterns');
|
||||
|
||||
return balena.models.device
|
||||
.get(params.uuid, expandForAppName)
|
||||
.then(function(device) {
|
||||
// @ts-ignore extending the device object with extra props
|
||||
device.application_name = device.belongs_to__application?.[0]
|
||||
? device.belongs_to__application[0].app_name
|
||||
: 'N/a';
|
||||
if (options.application) {
|
||||
return options.application;
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
balena.models.device.getManifestBySlug(device.device_type),
|
||||
balena.models.config.getDeviceTypes(),
|
||||
]).then(function([deviceDeviceType, deviceTypes]) {
|
||||
const compatibleDeviceTypes = deviceTypes.filter(
|
||||
dt =>
|
||||
balena.models.os.isArchitectureCompatibleWith(
|
||||
deviceDeviceType.arch,
|
||||
dt.arch,
|
||||
) &&
|
||||
!!dt.isDependent === !!deviceDeviceType.isDependent &&
|
||||
dt.state !== 'DISCONTINUED',
|
||||
);
|
||||
|
||||
return patterns.selectApplication(application =>
|
||||
_.every([
|
||||
_.some(
|
||||
compatibleDeviceTypes,
|
||||
dt => dt.slug === application.device_type,
|
||||
),
|
||||
// @ts-ignore using the extended device object prop
|
||||
device.application_name !== application.app_name,
|
||||
]),
|
||||
);
|
||||
});
|
||||
})
|
||||
.tap(application => balena.models.device.move(params.uuid, application))
|
||||
.then(application => {
|
||||
console.info(`${params.uuid} was moved to ${application}`);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const init = {
|
||||
signature: 'device init',
|
||||
description: 'initialise a device with balenaOS',
|
||||
help: `\
|
||||
Use this command to download the OS image of a certain application and write it to an SD Card.
|
||||
|
||||
Notice this command may ask for confirmation interactively.
|
||||
You can avoid this by passing the \`--yes\` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena device init
|
||||
$ balena device init --application MyApp\
|
||||
`,
|
||||
options: [
|
||||
commandOptions.optionalApplication,
|
||||
commandOptions.yes,
|
||||
commandOptions.advancedConfig,
|
||||
_.assign({}, commandOptions.osVersionOrSemver, {
|
||||
signature: 'os-version',
|
||||
parameter: 'os-version',
|
||||
}),
|
||||
commandOptions.drive,
|
||||
{
|
||||
signature: 'config',
|
||||
description: 'path to the config JSON file, see `balena os build-config`',
|
||||
parameter: 'config',
|
||||
},
|
||||
],
|
||||
permission: 'user',
|
||||
action(_params, options) {
|
||||
const Promise = require('bluebird');
|
||||
const rimraf = Promise.promisify(require('rimraf'));
|
||||
const tmp = require('tmp');
|
||||
const tmpNameAsync = Promise.promisify(tmp.tmpName);
|
||||
tmp.setGracefulCleanup();
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
const patterns = require('../utils/patterns');
|
||||
const { runCommand } = require('../utils/helpers');
|
||||
|
||||
return Promise.try(function() {
|
||||
if (options.application != null) {
|
||||
return options.application;
|
||||
}
|
||||
return patterns.selectApplication();
|
||||
})
|
||||
.then(balena.models.application.get)
|
||||
.then(function(application) {
|
||||
const download = () =>
|
||||
tmpNameAsync()
|
||||
.then(function(tempPath) {
|
||||
const osVersion = options['os-version'] || 'default';
|
||||
return runCommand(
|
||||
`os download ${application.device_type} --output '${tempPath}' --version ${osVersion}`,
|
||||
);
|
||||
})
|
||||
.disposer(tempPath => rimraf(tempPath));
|
||||
|
||||
return Promise.using(download(), tempPath =>
|
||||
runCommand(`device register ${application.app_name}`)
|
||||
.then(balena.models.device.get)
|
||||
.tap(function(device) {
|
||||
let configureCommand = `os configure '${tempPath}' --device ${device.uuid}`;
|
||||
if (options.config) {
|
||||
configureCommand += ` --config '${options.config}'`;
|
||||
} else if (options.advanced) {
|
||||
configureCommand += ' --advanced';
|
||||
}
|
||||
return runCommand(configureCommand)
|
||||
.then(function() {
|
||||
let osInitCommand = `os initialize '${tempPath}' --type ${application.device_type}`;
|
||||
if (options.yes) {
|
||||
osInitCommand += ' --yes';
|
||||
}
|
||||
if (options.drive) {
|
||||
osInitCommand += ` --drive ${options.drive}`;
|
||||
}
|
||||
return runCommand(osInitCommand);
|
||||
})
|
||||
.catch(error =>
|
||||
balena.models.device.remove(device.uuid).finally(function() {
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
}),
|
||||
).then(function(device) {
|
||||
console.log('Done');
|
||||
return device.uuid;
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export { osUpdate } from './device_ts';
|
@ -94,7 +94,7 @@ export async function sudo(
|
||||
await executeWithPrivileges(command, stderr, isCLIcmd);
|
||||
}
|
||||
|
||||
export function runCommand(command: string): Bluebird<void> {
|
||||
export function runCommand<T>(command: string): Bluebird<T> {
|
||||
const capitano = require('capitano');
|
||||
return Bluebird.fromCallback(resolver => capitano.run(command, resolver));
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ export function confirm(
|
||||
}
|
||||
|
||||
export function selectApplication(
|
||||
filter: (app: BalenaSdk.Application) => boolean,
|
||||
filter?: (app: BalenaSdk.Application) => boolean,
|
||||
) {
|
||||
const balena = getBalenaSdk();
|
||||
return balena.models.application
|
||||
|
6
npm-shrinkwrap.json
generated
6
npm-shrinkwrap.json
generated
@ -1336,6 +1336,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/tmp": {
|
||||
"version": "0.0.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.34.tgz",
|
||||
"integrity": "sha512-Tx7JYeYR+pkAnDQjN1Cj43KuOuUvyybZHl+fAezReXuH/SQoxLhsuPvHZH/SA4XtrBEhaTcbb5gVc1WQcjQgdg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/tough-cookie": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.6.tgz",
|
||||
|
@ -138,6 +138,7 @@
|
||||
"@types/stream-to-promise": "2.2.0",
|
||||
"@types/tar-stream": "^2.1.0",
|
||||
"@types/through2": "^2.0.34",
|
||||
"@types/tmp": "0.0.34",
|
||||
"@types/which": "^1.3.2",
|
||||
"catch-uncommitted": "^1.5.0",
|
||||
"chai": "^4.2.0",
|
||||
|
Loading…
x
Reference in New Issue
Block a user