Update various commands to support organizations

Change-type: minor
Connects-to: #2119
Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
Scott Lowe 2020-12-10 13:30:17 +01:00
parent 6fc3b0df58
commit c898747468
28 changed files with 645 additions and 344 deletions

View File

@ -164,10 +164,10 @@ Users are encouraged to regularly update the balena CLI to the latest version.
- [apps](#apps)
- [app &#60;nameorslug&#62;](#app-nameorslug)
- [app create &#60;name&#62;](#app-create-name)
- [app purge &#60;name&#62;](#app-purge-name)
- [app rename &#60;nameorslug&#62; [newname]](#app-rename-nameorslug-newname)
- [app restart &#60;name&#62;](#app-restart-name)
- [app rm &#60;name&#62;](#app-rm-name)
- [app purge &#60;application&#62;](#app-purge-application)
- [app rename &#60;application&#62; [newname]](#app-rename-application-newname)
- [app restart &#60;application&#62;](#app-restart-application)
- [app rm &#60;application&#62;](#app-rm-application)
- Authentication
@ -312,7 +312,7 @@ the API key name
list all your balena applications.
For detailed information on a particular application,
use `balena app <name> instead`.
use `balena app <application>` instead.
Examples:
@ -328,6 +328,19 @@ No-op since release v12.0.0
Display detailed information about a single balena application.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena app MyApp
@ -335,9 +348,9 @@ Examples:
### Arguments
#### NAMEORSLUG
#### APPLICATION
application name or org/name slug
application name, slug (preferred), or numeric ID (deprecated)
### Options
@ -382,30 +395,57 @@ handle of the organization the application should belong to
application device type (Check available types with `balena devices supported`)
## app purge &#60;name&#62;
## app purge &#60;application&#62;
Purge data from all devices belonging to an application.
This will clear the application's /data directory.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena app purge MyApp
$ balena app purge myorg/myapp
### Arguments
#### NAME
#### APPLICATION
application name or numeric ID
application name, slug (preferred), or numeric ID (deprecated)
### Options
## app rename &#60;nameOrSlug&#62; [newName]
## app rename &#60;application&#62; [newName]
Rename an application.
Note, if the `newName` parameter is omitted, it will be
prompted for interactively.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena app rename OldName
@ -414,9 +454,9 @@ Examples:
### Arguments
#### NAMEORSLUG
#### APPLICATION
application name or org/name slug
application name, slug (preferred), or numeric ID (deprecated)
#### NEWNAME
@ -424,38 +464,66 @@ the new name for the application
### Options
## app restart &#60;name&#62;
## app restart &#60;application&#62;
Restart all devices belonging to an application.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena app restart MyApp
$ balena app restart myorg/myapp
### Arguments
#### NAME
#### APPLICATION
application name or numeric ID
application name, slug (preferred), or numeric ID (deprecated)
### Options
## app rm &#60;name&#62;
## app rm &#60;application&#62;
Permanently remove a balena application.
The --yes option may be used to avoid interactive confirmation.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena app rm MyApp
$ balena app rm MyApp --yes
$ balena app rm myorg/myapp
### Arguments
#### NAME
#### APPLICATION
application name or numeric ID
application name, slug (preferred), or numeric ID (deprecated)
### Options
@ -546,6 +614,19 @@ list all devices that belong to you.
You can filter the devices by application by using the `--application` option.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it
better represents data types like arrays, empty strings and null values.
@ -558,12 +639,13 @@ Examples:
$ balena devices --application MyApp
$ balena devices --app MyApp
$ balena devices -a MyApp
$ balena devices -a myorg/myapp
### Options
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
@ -642,22 +724,36 @@ the uuid of the device to identify
## device init
Initialise a device by downloading the OS image of a certain application
Initialize a device by downloading the OS image of a certain application
and writing it to an SD Card.
Note, if the application option is omitted it will be prompted
for interactively.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena device init
$ balena device init --application MyApp
$ balena device init -a myorg/myapp
### Options
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
@ -696,11 +792,25 @@ Move one or more devices to another application.
Note, if the application option is omitted it will be prompted
for interactively.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena device move 7cf02a6
$ balena device move 7cf02a6,dc39e52
$ balena device move 7cf02a6 --application MyNewApp
$ balena device move 7cf02a6 -a myorg/mynewapp
### Arguments
@ -712,7 +822,7 @@ comma-separated list (no blank spaces) of device UUIDs to be moved
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
@ -833,16 +943,30 @@ force action if the update lock is set
Register a device to an application.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena device register MyApp
$ balena device register MyApp --uuid <uuid>
$ balena device register myorg/myapp --uuid <uuid>
### Arguments
#### APPLICATION
the name or id of application to register device with
application name, slug (preferred), or numeric ID (deprecated)
### Options
@ -983,9 +1107,23 @@ application linked to the device is no longer accessible by the current user
(for example, in case the current user has been removed from the application
by its owner).
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena envs --application MyApp
$ balena envs --application myorg/myapp
$ balena envs --application MyApp --json
$ balena envs --application MyApp --service MyService
$ balena envs --application MyApp --service MyService
@ -1003,7 +1141,7 @@ No-op since balena CLI v12.0.0.
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### -c, --config
@ -1118,10 +1256,24 @@ therefore the --service option cannot be used when the variable name starts
with a reserved prefix. When defining custom application variables, please
avoid the reserved prefixes.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena env add TERM --application MyApp
$ balena env add EDITOR vim --application MyApp
$ balena env add EDITOR vim -a myorg/myapp
$ balena env add EDITOR vim --application MyApp,MyApp2
$ balena env add EDITOR vim --application MyApp --service MyService
$ balena env add EDITOR vim --application MyApp,MyApp2 --service MyService,MyService2
@ -1144,7 +1296,7 @@ variable value; if omitted, use value from this process' environment
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### -d, --device DEVICE
@ -1228,9 +1380,23 @@ select a service variable (may be used together with the --device option)
List all tags and their values for a particular application,
device or release.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena tags --application MyApp
$ balena tags -a myorg/myapp
$ balena tags --device 7cf02a6
$ balena tags --release 1234
$ balena tags --release b376b0e544e9429483b656490e5b9443b4349bd6
@ -1239,7 +1405,11 @@ Examples:
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
same as '--application'
#### -d, --device DEVICE
@ -1249,17 +1419,27 @@ device UUID
release id
#### --app APP
same as '--application'
## tag rm &#60;tagKey&#62;
Remove a tag from an application, device or release.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena tag rm myTagKey --application MyApp
$ balena tag rm myTagKey -a myorg/myapp
$ balena tag rm myTagKey --device 7cf02a6
$ balena tag rm myTagKey --release 1234
$ balena tag rm myTagKey --release b376b0e544e9429483b656490e5b9443b4349bd6
@ -1274,7 +1454,11 @@ the key string of the tag
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
same as '--application'
#### -d, --device DEVICE
@ -1284,10 +1468,6 @@ device UUID
release id
#### --app APP
same as '--application'
## tag set &#60;tagKey&#62; [value]
Set a tag on an application, device or release.
@ -1296,9 +1476,23 @@ You can optionally provide a value to be associated with the created
tag, as an extra argument after the tag key. If a value isn't
provided, a tag with an empty value is created.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena tag set mySimpleTag --application MyApp
$ balena tag set mySimpleTag -a myorg/myapp
$ balena tag set myCompositeTag myTagValue --application MyApp
$ balena tag set myCompositeTag myTagValue --device 7cf02a6
$ balena tag set myCompositeTag "my tag value with whitespaces" --device 7cf02a6
@ -1320,7 +1514,11 @@ the optional value associated with the tag
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
same as '--application'
#### -d, --device DEVICE
@ -1330,10 +1528,6 @@ device UUID
release id
#### --app APP
same as '--application'
# Help and Version
## help [command]
@ -1828,6 +2022,19 @@ https://developer.gnome.org/NetworkManager/stable/nm-settings.html
The --device-api-key option is deprecated and will be removed in a future release.
A suitable key is automatically generated or fetched if this option is omitted.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Note: This command is currently not supported on Windows natively. Windows users
are advised to install the Windows Subsystem for Linux (WSL) with Ubuntu, and use
the Linux release of the balena CLI:
@ -1838,6 +2045,7 @@ Examples:
$ balena os configure ../path/rpi3.img --device 7cf02a6
$ balena os configure ../path/rpi3.img --device 7cf02a6 --device-api-key <existingDeviceKey>
$ balena os configure ../path/rpi3.img --app MyApp
$ balena os configure ../path/rpi3.img -a myorg/myapp
$ balena os configure ../path/rpi3.img --app MyApp --version 2.12.7
$ balena os configure ../path/rpi3.img --app MyFinApp --device-type raspberrypi3
$ balena os configure ../path/rpi3.img --app MyFinApp --device-type raspberrypi3 --config myWifiConfig.json
@ -1854,14 +2062,14 @@ path to a balenaOS image file, e.g. "rpi3.img"
ask advanced configuration questions (when in interactive mode)
#### -a, --application APPLICATION
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
same as '--application'
#### -a, --application APPLICATION
application name
#### --config CONFIG
path to a pre-generated config.json file to be injected in the OS image
@ -1954,7 +2162,20 @@ by specifying an option for each question on the command line, if you know the q
that will be asked for the relevant device type.
In case that you want to configure an image for an application with mixed device types,
you can pass the --device-type argument along with --app to specify the target device type.
you can pass the --deviceType argument along with --application to specify the target device type.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
@ -1963,7 +2184,8 @@ Examples:
$ balena config generate --device 7cf02a6 --version 2.12.7 --device-api-key <existingDeviceKey>
$ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json
$ balena config generate --app MyApp --version 2.12.7
$ balena config generate --app MyApp --version 2.12.7 --device-type fincm3
$ balena config generate --app myorg/myapp --version 2.12.7
$ balena config generate --app MyApp --version 2.12.7 --deviceType fincm3
$ balena config generate --app MyApp --version 2.12.7 --output config.json
$ balena config generate --app MyApp --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1
@ -1975,7 +2197,7 @@ a balenaOS version
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### --app APP
@ -2129,13 +2351,27 @@ After preloading, the balenaOS image file can be flashed to a device's SD card.
When the device boots, it will not need to download the application, as it was
preloaded.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Warning: "balena preload" requires Docker to be correctly installed in
your shell environment. For more information (including Windows support)
check: https://github.com/balena-io/balena-cli/blob/master/INSTALL.md
Examples:
$ balena preload balena.img --app 1234 --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0 --splash-image image.png
$ balena preload balena.img --app MyApp --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0
$ balena preload balena.img --app myorg/myapp --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0 --splash-image image.png
$ balena preload balena.img
### Arguments
@ -2148,7 +2384,7 @@ the image file path
#### -a, --app APP
name of the application to preload
application name, slug (preferred), or numeric ID (deprecated)
#### -c, --commit COMMIT
@ -2946,11 +3182,25 @@ scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This requires root privileges. Likewise, if
the application flag is not provided then a picker will be shown.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
$ balena join
$ balena join balena.local
$ balena join balena.local --application MyApp
$ balena join balena.local -a myorg/myapp
$ balena join 192.168.1.25
$ balena join 192.168.1.25 --application MyApp
@ -2964,7 +3214,7 @@ the IP or hostname of device
#### -a, --application APPLICATION
application name
application name, slug (preferred), or numeric ID (deprecated)
#### -i, --pollInterval POLLINTERVAL
@ -3020,11 +3270,24 @@ or hours, e.g. '12h', '2d'.
Both --device and --application flags accept multiple values, specified as
a comma-separated list (with no spaces).
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the `balena apps` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.
Examples:
balena support enable --device ab346f,cd457a --duration 3d
balena support enable --application app3 --duration 12h
balena support disable -a myApp
balena support disable -a myorg/myapp
### Arguments
@ -3040,7 +3303,7 @@ comma-separated list (no spaces) of device UUIDs
#### -a, --application APPLICATION
comma-separated list (no spaces) of application names
comma-separated list (no spaces) of application names or org/name slugs
#### -t, --duration DURATION

View File

@ -18,7 +18,9 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import type { Release } from 'balena-sdk';
interface FlagsDef {
@ -26,7 +28,7 @@ interface FlagsDef {
}
interface ArgsDef {
nameOrSlug: string;
application: string;
}
export default class AppCmd extends Command {
@ -34,16 +36,12 @@ export default class AppCmd extends Command {
Display information about a single application.
Display detailed information about a single balena application.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = ['$ balena app MyApp', '$ balena app myorg/myapp'];
public static args = [
{
name: 'nameOrSlug',
description: 'application name or org/name slug',
required: true,
},
];
public static args = [ca.applicationRequired];
public static usage = 'app <nameOrSlug>';
@ -61,7 +59,7 @@ export default class AppCmd extends Command {
const application = (await getApplication(
getBalenaSdk(),
params.nameOrSlug,
params.application,
{
$expand: {
is_for__device_type: { $select: 'slug' },

View File

@ -18,35 +18,36 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
help: void;
}
interface ArgsDef {
name: string;
application: string;
}
export default class AppRestartCmd extends Command {
export default class AppPurgeCmd extends Command {
public static description = stripIndent`
Purge data from an application.
Purge data from all devices belonging to an application.
This will clear the application's /data directory.
`;
public static examples = ['$ balena app purge MyApp'];
public static args = [
{
name: 'name',
description: 'application name or numeric ID',
required: true,
},
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena app purge MyApp',
'$ balena app purge myorg/myapp',
];
public static usage = 'app purge <name>';
public static args = [ca.applicationRequired];
public static usage = 'app purge <application>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
@ -55,21 +56,18 @@ export default class AppRestartCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(AppRestartCmd);
const { args: params } = this.parse<FlagsDef, ArgsDef>(AppPurgeCmd);
const { getApplication } = await import('../../utils/sdk');
const balena = getBalenaSdk();
// balena.models.application.purge only accepts a numeric id
// so we must first fetch the app to get it's id, if we have been given a name
let nameOrId = tryAsInteger(params.name);
if (typeof nameOrId === 'string') {
const app = await balena.models.application.get(nameOrId);
nameOrId = app.id;
}
// so we must first fetch the app to get it's id,
const application = await getApplication(balena, params.application);
try {
await balena.models.application.purge(nameOrId);
await balena.models.application.purge(application.id);
} catch (e) {
if (e.message.toLowerCase().includes('no online device(s) found')) {
// application.purge throws an error if no devices are online

View File

@ -16,11 +16,11 @@
*/
import { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { lowercaseIfSlug } from '../../utils/normalization';
import { applicationIdInfo } from '../../utils/messages';
import type { ApplicationType } from 'balena-sdk';
interface FlagsDef {
@ -28,7 +28,7 @@ interface FlagsDef {
}
interface ArgsDef {
nameOrSlug: string;
application: string;
newName?: string;
}
@ -40,6 +40,8 @@ export default class AppRenameCmd extends Command {
Note, if the \`newName\` parameter is omitted, it will be
prompted for interactively.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
@ -48,20 +50,15 @@ export default class AppRenameCmd extends Command {
'$ balena app rename myorg/oldname NewName',
];
public static args: Array<IArg<any>> = [
{
name: 'nameOrSlug',
description: 'application name or org/name slug',
parse: lowercaseIfSlug,
required: true,
},
public static args = [
ca.applicationRequired,
{
name: 'newName',
description: 'the new name for the application',
},
];
public static usage = 'app rename <nameOrSlug> [newName]';
public static usage = 'app rename <application> [newName]';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
@ -77,9 +74,9 @@ export default class AppRenameCmd extends Command {
const balena = getBalenaSdk();
// Disambiguate target application (if nameOrSlug is a number, it could either be an ID or a numerical name)
// Disambiguate target application (if params.params is a number, it could either be an ID or a numerical name)
const { getApplication } = await import('../../utils/sdk');
const application = await getApplication(balena, params.nameOrSlug, {
const application = await getApplication(balena, params.application, {
$expand: {
application_type: {
$select: ['is_legacy'],
@ -98,7 +95,7 @@ export default class AppRenameCmd extends Command {
const appType = (application.application_type as ApplicationType[])?.[0];
if (appType.is_legacy) {
throw new ExpectedError(
`Application ${params.nameOrSlug} is of 'legacy' type, and cannot be renamed.`,
`Application ${params.application} is of 'legacy' type, and cannot be renamed.`,
);
}
@ -119,13 +116,24 @@ export default class AppRenameCmd extends Command {
// BalenaRequestError: Request error: "organization" and "app_name" must be unique.
if ((e.message || '').toLowerCase().includes('unique')) {
throw new ExpectedError(
`Error: application ${params.nameOrSlug} already exists.`,
`Error: application ${params.application} already exists.`,
);
}
throw e;
}
// Get application again, to be sure of results
const renamedApplication = await balena.models.application.get(
application.id,
);
// Output result
console.log(`Application ${params.nameOrSlug} renamed to ${newName}`);
console.log(`Application renamed`);
console.log('From:');
console.log(`\tname: ${application.app_name}`);
console.log(`\tslug: ${application.slug}`);
console.log('To:');
console.log(`\tname: ${renamedApplication.app_name}`);
console.log(`\tslug: ${renamedApplication.slug}`);
}
}

View File

@ -18,15 +18,16 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
help: void;
}
interface ArgsDef {
name: string;
application: string;
}
export default class AppRestartCmd extends Command {
@ -34,18 +35,18 @@ export default class AppRestartCmd extends Command {
Restart an application.
Restart all devices belonging to an application.
`;
public static examples = ['$ balena app restart MyApp'];
public static args = [
{
name: 'name',
description: 'application name or numeric ID',
required: true,
},
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena app restart MyApp',
'$ balena app restart myorg/myapp',
];
public static usage = 'app restart <name>';
public static args = [ca.applicationRequired];
public static usage = 'app restart <application>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
@ -56,6 +57,13 @@ export default class AppRestartCmd extends Command {
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(AppRestartCmd);
await getBalenaSdk().models.application.restart(tryAsInteger(params.name));
const { getApplication } = await import('../../utils/sdk');
const balena = getBalenaSdk();
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
const application = await getApplication(balena, params.application);
await balena.models.application.restart(application.id);
}
}

View File

@ -18,8 +18,9 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
yes: boolean;
@ -27,7 +28,7 @@ interface FlagsDef {
}
interface ArgsDef {
name: string;
application: string;
}
export default class AppRmCmd extends Command {
@ -37,21 +38,19 @@ export default class AppRmCmd extends Command {
Permanently remove a balena application.
The --yes option may be used to avoid interactive confirmation.
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena app rm MyApp',
'$ balena app rm MyApp --yes',
'$ balena app rm myorg/myapp',
];
public static args = [
{
name: 'name',
description: 'application name or numeric ID',
required: true,
},
];
public static args = [ca.applicationRequired];
public static usage = 'app rm <name>';
public static usage = 'app rm <application>';
public static flags: flags.Input<FlagsDef> = {
yes: cf.yes,
@ -65,15 +64,20 @@ export default class AppRmCmd extends Command {
AppRmCmd,
);
const patterns = await import('../../utils/patterns');
const { confirm } = await import('../../utils/patterns');
const { getApplication } = await import('../../utils/sdk');
const balena = getBalenaSdk();
// Confirm
await patterns.confirm(
await confirm(
options.yes ?? false,
`Are you sure you want to delete application ${params.name}?`,
`Are you sure you want to delete application ${params.application}?`,
);
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
const application = await getApplication(balena, params.application);
// Remove
await getBalenaSdk().models.application.remove(tryAsInteger(params.name));
await balena.models.application.remove(application.id);
}
}

View File

@ -37,8 +37,9 @@ export default class AppsCmd extends Command {
list all your balena applications.
For detailed information on a particular application,
use \`balena app <name> instead\`.
`;
use \`balena app <application>\` instead.
`;
public static examples = ['$ balena apps'];
public static usage = 'apps';

View File

@ -19,6 +19,7 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import type { PineDeferred } from 'balena-sdk';
interface FlagsDef {
@ -51,7 +52,9 @@ export default class ConfigGenerateCmd extends Command {
that will be asked for the relevant device type.
In case that you want to configure an image for an application with mixed device types,
you can pass the --device-type argument along with --app to specify the target device type.
you can pass the --deviceType argument along with --application to specify the target device type.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
@ -60,7 +63,8 @@ export default class ConfigGenerateCmd extends Command {
'$ balena config generate --device 7cf02a6 --version 2.12.7 --device-api-key <existingDeviceKey>',
'$ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json',
'$ balena config generate --app MyApp --version 2.12.7',
'$ balena config generate --app MyApp --version 2.12.7 --device-type fincm3',
'$ balena config generate --app myorg/myapp --version 2.12.7',
'$ balena config generate --app MyApp --version 2.12.7 --deviceType fincm3',
'$ balena config generate --app MyApp --version 2.12.7 --output config.json',
'$ balena config generate --app MyApp --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 1',
];
@ -72,15 +76,8 @@ export default class ConfigGenerateCmd extends Command {
description: 'a balenaOS version',
required: true,
}),
application: flags.string({
description: 'application name',
char: 'a',
exclusive: ['app', 'device'],
}),
app: flags.string({
description: "same as '--application'",
exclusive: ['application', 'device'],
}),
application: { ...cf.application, exclusive: ['app', 'device'] },
app: { ...cf.app, exclusive: ['application', 'device'] },
device: flags.string({
description: 'device uuid',
char: 'd',
@ -154,6 +151,7 @@ export default class ConfigGenerateCmd extends Command {
};
resourceDeviceType = device.is_of__device_type[0].slug;
} else {
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
application = (await getApplication(balena, options.application!, {
$expand: {
is_for__device_type: { $select: 'slug' },
@ -227,17 +225,8 @@ export default class ConfigGenerateCmd extends Command {
$ balena help config generate
`;
protected readonly deviceTypeNotAllowedMessage = stripIndent`
Specifying a different device type is only supported when
generating a config for an application:
* An application, with --app <appname>
* A specific device type, with --device-type <deviceTypeSlug>
See the help page for examples:
$ balena help config generate
`;
protected readonly deviceTypeNotAllowedMessage =
'The --deviceType option can only be used alongside the --application option';
protected async validateOptions(options: FlagsDef) {
const { ExpectedError } = await import('../../errors');

View File

@ -19,6 +19,7 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { runCommand } from '../../utils/helpers';
interface FlagsDef {
@ -34,17 +35,21 @@ interface FlagsDef {
export default class DeviceInitCmd extends Command {
public static description = stripIndent`
Initialise a device with balenaOS.
Initialize a device with balenaOS.
Initialise a device by downloading the OS image of a certain application
Initialize a device by downloading the OS image of a certain application
and writing it to an SD Card.
Note, if the application option is omitted it will be prompted
for interactively.
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena device init',
'$ balena device init --application MyApp',
'$ balena device init -a myorg/myapp',
];
public static usage = 'device init';
@ -98,7 +103,7 @@ export default class DeviceInitCmd extends Command {
const application = (await getApplication(
balena,
options['application'] ||
(await (await import('../../utils/patterns')).selectApplication()),
(await (await import('../../utils/patterns')).selectApplication()).id,
{
$expand: {
is_for__device_type: {

View File

@ -20,9 +20,8 @@ import type { IArg } from '@oclif/parser/lib/args';
import type { Application, BalenaSDK } from 'balena-sdk';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
import { ExpectedError } from '../../errors';
interface ExtendedDevice extends DeviceWithDeviceType {
@ -47,11 +46,15 @@ export default class DeviceMoveCmd extends Command {
Note, if the application option is omitted it will be prompted
for interactively.
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena device move 7cf02a6',
'$ balena device move 7cf02a6,dc39e52',
'$ balena device move 7cf02a6 --application MyNewApp',
'$ balena device move 7cf02a6 -a myorg/mynewapp',
];
public static args: Array<IArg<any>> = [
@ -80,6 +83,9 @@ export default class DeviceMoveCmd extends Command {
const balena = getBalenaSdk();
const { tryAsInteger } = await import('../../utils/validation');
const { expandForAppName } = await import('../../utils/helpers');
options.application = options.application || options.app;
delete options.app;
@ -106,16 +112,21 @@ export default class DeviceMoveCmd extends Command {
: 'N/a';
}
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
const { getApplication } = await import('../../utils/sdk');
// Get destination application
const application =
options.application ||
(await this.interactivelySelectApplication(balena, devices));
const application = options.application
? await getApplication(balena, options.application)
: await this.interactivelySelectApplication(balena, devices);
// Move each device
for (const uuid of deviceIds) {
try {
await balena.models.device.move(uuid, tryAsInteger(application));
console.info(`${uuid} was moved to ${application}`);
await balena.models.device.move(uuid, application.id);
console.info(
`Device ${uuid} was moved to application ${application.slug}`,
);
} catch (err) {
console.info(`${err.message}, uuid: ${uuid}`);
process.exitCode = 1;

View File

@ -19,7 +19,9 @@ import { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
uuid?: string;
@ -35,19 +37,17 @@ export default class DeviceRegisterCmd extends Command {
Register a device.
Register a device to an application.
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena device register MyApp',
'$ balena device register MyApp --uuid <uuid>',
'$ balena device register myorg/myapp --uuid <uuid>',
];
public static args: Array<IArg<any>> = [
{
name: 'application',
description: 'the name or id of application to register device with',
required: true,
},
];
public static args: Array<IArg<any>> = [ca.applicationRequired];
public static usage = 'device register <application>';

View File

@ -20,7 +20,7 @@ import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo, jsonInfo } from '../../utils/messages';
import type { Application } from 'balena-sdk';
interface ExtendedDevice extends DeviceWithDeviceType {
@ -44,17 +44,16 @@ export default class DevicesCmd extends Command {
You can filter the devices by application by using the \`--application\` option.
The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it
better represents data types like arrays, empty strings and null values.
The 'jq' utility may be helpful for querying JSON fields in shell scripts
(https://stedolan.github.io/jq/manual/).
${applicationIdInfo.split('\n').join('\n\t\t')}
${jsonInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena devices',
'$ balena devices --application MyApp',
'$ balena devices --app MyApp',
'$ balena devices -a MyApp',
'$ balena devices -a myorg/myapp',
];
public static usage = 'devices';
@ -62,11 +61,8 @@ export default class DevicesCmd extends Command {
public static flags: flags.Input<FlagsDef> = {
application: cf.application,
app: cf.app,
json: cf.json,
help: cf.help,
json: flags.boolean({
char: 'j',
description: 'produce JSON output instead of tabular output',
}),
};
public static primary = true;
@ -85,8 +81,10 @@ export default class DevicesCmd extends Command {
let devices;
if (options.application != null) {
const { getApplication } = await import('../../utils/sdk');
const application = await getApplication(balena, options.application);
devices = (await balena.models.device.getAllByApplication(
tryAsInteger(options.application),
application.id,
expandForAppName,
)) as ExtendedDevice[];
} else {

View File

@ -18,13 +18,13 @@
import { flags } from '@oclif/command';
import type * as BalenaSdk from 'balena-sdk';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
application?: string; // application name
application?: string;
device?: string; // device UUID
help: void;
quiet: boolean;
@ -63,10 +63,14 @@ export default class EnvAddCmd extends Command {
therefore the --service option cannot be used when the variable name starts
with a reserved prefix. When defining custom application variables, please
avoid the reserved prefixes.
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena env add TERM --application MyApp',
'$ balena env add EDITOR vim --application MyApp',
'$ balena env add EDITOR vim -a myorg/myapp',
'$ balena env add EDITOR vim --application MyApp,MyApp2',
'$ balena env add EDITOR vim --application MyApp --service MyService',
'$ balena env add EDITOR vim --application MyApp,MyApp2 --service MyService,MyService2',
@ -93,8 +97,8 @@ export default class EnvAddCmd extends Command {
public static usage = 'env add <name> [value]';
public static flags: flags.Input<FlagsDef> = {
application: { exclusive: ['device'], ...cf.application },
device: { exclusive: ['application'], ...cf.device },
application: { ...cf.application, exclusive: ['device'] },
device: { ...cf.device, exclusive: ['application'] },
help: cf.help,
quiet: cf.quiet,
service: cf.service,
@ -108,7 +112,7 @@ export default class EnvAddCmd extends Command {
if (!options.application && !options.device) {
throw new ExpectedError(
'Either the --application or the --device option must always be used',
'Either the --application or the --device option must be specified',
);
}

View File

@ -18,14 +18,14 @@ import { flags } from '@oclif/command';
import type * as SDK from 'balena-sdk';
import * as _ from 'lodash';
import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
import { isV13 } from '../utils/version';
interface FlagsDef {
application?: string; // application name
application?: string;
config: boolean;
device?: string; // device UUID
json: boolean;
@ -88,9 +88,13 @@ export default class EnvsCmd extends Command {
application linked to the device is no longer accessible by the current user
(for example, in case the current user has been removed from the application
by its owner).
`;
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena envs --application MyApp',
'$ balena envs --application myorg/myapp',
'$ balena envs --application MyApp --json',
'$ balena envs --application MyApp --service MyService',
'$ balena envs --application MyApp --service MyService',
@ -124,11 +128,7 @@ export default class EnvsCmd extends Command {
}),
device: { exclusive: ['application'], ...cf.device },
help: cf.help,
json: flags.boolean({
default: false,
char: 'j',
description: 'produce JSON output instead of tabular output',
}),
json: cf.json,
verbose: cf.verbose,
service: { exclusive: ['config'], ...cf.service },
};
@ -145,7 +145,7 @@ export default class EnvsCmd extends Command {
const balena = getBalenaSdk();
let appName = options.application;
let appNameOrSlug = options.application;
let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID
if (options.device) {
@ -158,16 +158,16 @@ export default class EnvsCmd extends Command {
);
fullUUID = device.uuid;
if (app) {
appName = app.app_name;
appNameOrSlug = app.app_name;
}
}
if (appName && options.service) {
await validateServiceName(balena, options.service, appName);
if (appNameOrSlug && options.service) {
await validateServiceName(balena, options.service, appNameOrSlug);
}
variables.push(...(await getAppVars(balena, appName, options)));
variables.push(...(await getAppVars(balena, appNameOrSlug, options)));
if (fullUUID) {
variables.push(
...(await getDeviceVars(balena, fullUUID, appName, options)),
...(await getDeviceVars(balena, fullUUID, appNameOrSlug, options)),
);
}
if (!options.json && variables.length === 0) {
@ -241,17 +241,17 @@ async function validateServiceName(
*/
async function getAppVars(
sdk: SDK.BalenaSDK,
appName: string | undefined,
appNameOrSlug: string | undefined,
options: FlagsDef,
): Promise<EnvironmentVariableInfo[]> {
const appVars: EnvironmentVariableInfo[] = [];
if (!appName) {
if (!appNameOrSlug) {
return appVars;
}
const vars = await sdk.models.application[
options.config ? 'configVar' : 'envVar'
].getAllByApplication(appName);
fillInInfoFields(vars, appName);
].getAllByApplication(appNameOrSlug);
fillInInfoFields(vars, appNameOrSlug);
appVars.push(...vars);
if (!options.config) {
const pineOpts: SDK.PineOptions<SDK.ServiceEnvironmentVariable> = {
@ -267,10 +267,10 @@ async function getAppVars(
};
}
const serviceVars = await sdk.models.service.var.getAllByApplication(
appName,
appNameOrSlug,
pineOpts,
);
fillInInfoFields(serviceVars, appName);
fillInInfoFields(serviceVars, appNameOrSlug);
appVars.push(...serviceVars);
}
return appVars;
@ -283,7 +283,7 @@ async function getAppVars(
async function getDeviceVars(
sdk: SDK.BalenaSDK,
fullUUID: string,
appName: string | undefined,
appNameOrSlug: string | undefined,
options: FlagsDef,
): Promise<EnvironmentVariableInfo[]> {
const printedUUID = options.json ? fullUUID : options.device!;
@ -292,7 +292,7 @@ async function getDeviceVars(
const deviceConfigVars = await sdk.models.device.configVar.getAllByDevice(
fullUUID,
);
fillInInfoFields(deviceConfigVars, appName, printedUUID);
fillInInfoFields(deviceConfigVars, appNameOrSlug, printedUUID);
deviceVars.push(...deviceConfigVars);
} else {
const pineOpts: SDK.PineOptions<SDK.DeviceServiceEnvironmentVariable> = {
@ -313,13 +313,13 @@ async function getDeviceVars(
fullUUID,
pineOpts,
);
fillInInfoFields(deviceServiceVars, appName, printedUUID);
fillInInfoFields(deviceServiceVars, appNameOrSlug, printedUUID);
deviceVars.push(...deviceServiceVars);
const deviceEnvVars = await sdk.models.device.envVar.getAllByDevice(
fullUUID,
);
fillInInfoFields(deviceEnvVars, appName, printedUUID);
fillInInfoFields(deviceEnvVars, appNameOrSlug, printedUUID);
deviceVars.push(...deviceEnvVars);
}
return deviceVars;
@ -335,7 +335,7 @@ function fillInInfoFields(
| EnvironmentVariableInfo[]
| DeviceServiceEnvironmentVariableInfo[]
| ServiceEnvironmentVariableInfo[],
appName?: string,
appNameOrSlug?: string,
deviceUUID?: string,
) {
for (const envVar of varArray) {
@ -347,7 +347,7 @@ function fillInInfoFields(
envVar.serviceName = ((envVar.service_install as SDK.ServiceInstall[])[0]
?.installs__service as SDK.Service[])[0]?.service_name;
}
envVar.appName = appName;
envVar.appName = appNameOrSlug;
envVar.serviceName = envVar.serviceName || '*';
envVar.deviceUUID = deviceUUID || '*';
}

View File

@ -19,6 +19,7 @@ import { flags } from '@oclif/command';
import Command from '../command';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
import { parseAsLocalHostnameOrIp } from '../utils/validation';
interface FlagsDef {
@ -49,12 +50,15 @@ export default class JoinCmd extends Command {
scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This requires root privileges. Likewise, if
the application flag is not provided then a picker will be shown.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena join',
'$ balena join balena.local',
'$ balena join balena.local --application MyApp',
'$ balena join balena.local -a myorg/myapp',
'$ balena join 192.168.1.25',
'$ balena join 192.168.1.25 --application MyApp',
];
@ -71,10 +75,7 @@ export default class JoinCmd extends Command {
public static usage = 'join [deviceIpOrHostname]';
public static flags: flags.Input<FlagsDef> = {
application: {
description: 'the name of the application the device should join',
...cf.application,
},
application: cf.application,
pollInterval: flags.integer({
description: 'the interval in minutes to check for updates',
char: 'i',

View File

@ -18,20 +18,19 @@
import { flags } from '@oclif/command';
import type * as BalenaSdk from 'balena-sdk';
import * as _ from 'lodash';
import * as path from 'path';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
const BOOT_PARTITION = 1;
const CONNECTIONS_FOLDER = '/system-connections';
interface FlagsDef {
advanced?: boolean;
app?: string;
application?: string;
app?: string;
config?: string;
'config-app-update-poll-interval'?: number;
'config-network'?: string;
@ -88,15 +87,19 @@ export default class OsConfigureCmd extends Command {
${deviceApiKeyDeprecationMsg.split('\n').join('\n\t\t')}
${applicationIdInfo.split('\n').join('\n\t\t')}
Note: This command is currently not supported on Windows natively. Windows users
are advised to install the Windows Subsystem for Linux (WSL) with Ubuntu, and use
the Linux release of the balena CLI:
https://docs.microsoft.com/en-us/windows/wsl/about
`;
public static examples = [
'$ balena os configure ../path/rpi3.img --device 7cf02a6',
'$ balena os configure ../path/rpi3.img --device 7cf02a6 --device-api-key <existingDeviceKey>',
'$ balena os configure ../path/rpi3.img --app MyApp',
'$ balena os configure ../path/rpi3.img -a myorg/myapp',
'$ balena os configure ../path/rpi3.img --app MyApp --version 2.12.7',
'$ balena os configure ../path/rpi3.img --app MyFinApp --device-type raspberrypi3',
'$ balena os configure ../path/rpi3.img --app MyFinApp --device-type raspberrypi3 --config myWifiConfig.json',
@ -118,11 +121,8 @@ export default class OsConfigureCmd extends Command {
description:
'ask advanced configuration questions (when in interactive mode)',
}),
app: flags.string({
description: "same as '--application'",
exclusive: ['application', 'device'],
}),
application: { exclusive: ['app', 'device'], ...cf.application },
application: { ...cf.application, exclusive: ['app', 'device'] },
app: { ...cf.app, exclusive: ['application', 'device'] },
config: flags.string({
description:
'path to a pre-generated config.json file to be injected in the OS image',
@ -155,7 +155,6 @@ export default class OsConfigureCmd extends Command {
description:
'This option will set the device name when the device provisions',
}),
help: cf.help,
version: flags.string({
description: 'balenaOS version, for example "2.32.0" or "2.44.0+rev1"',
}),
@ -166,6 +165,7 @@ export default class OsConfigureCmd extends Command {
description:
"paths to local files to place into the 'system-connections' directory",
}),
help: cf.help,
};
public async run() {
@ -174,7 +174,7 @@ export default class OsConfigureCmd extends Command {
);
// Prefer options.application over options.app
options.application = options.application || options.app;
options.app = undefined;
delete options.app;
await validateOptions(options);
@ -266,6 +266,8 @@ export default class OsConfigureCmd extends Command {
);
if (options['system-connection']) {
const path = await import('path');
const files = await Promise.all(
options['system-connection'].map(async (filePath) => {
const content = await fs.readFile(filePath, 'utf8');

View File

@ -17,12 +17,14 @@
import { flags } from '@oclif/command';
import Command from '../command';
import * as cf from '../utils/common-flags';
import {
getBalenaSdk,
getCliForm,
getVisuals,
stripIndent,
} from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
import type { DockerConnectionCliFlags } from '../utils/docker';
import { dockerConnectionCliFlags } from '../utils/docker';
import * as _ from 'lodash';
@ -62,13 +64,16 @@ export default class PreloadCmd extends Command {
When the device boots, it will not need to download the application, as it was
preloaded.
${applicationIdInfo.split('\n').join('\n\t\t')}
Warning: "balena preload" requires Docker to be correctly installed in
your shell environment. For more information (including Windows support)
check: https://github.com/balena-io/balena-cli/blob/master/INSTALL.md
`;
public static examples = [
'$ balena preload balena.img --app 1234 --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0 --splash-image image.png',
'$ balena preload balena.img --app MyApp --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0',
'$ balena preload balena.img --app myorg/myapp --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0 --splash-image image.png',
'$ balena preload balena.img',
];
@ -83,10 +88,8 @@ export default class PreloadCmd extends Command {
public static usage = 'preload <image>';
public static flags: flags.Input<FlagsDef> = {
app: flags.string({
description: 'name of the application to preload',
char: 'a',
}),
// TODO: Replace with application/a in #v13?
app: cf.application,
commit: flags.string({
description: `\
The commit hash for a specific application release to preload, use "current" to specify the current
@ -160,6 +163,7 @@ Can be repeated to add multiple certificates.\
// balena-preload currently does not work with numerical app IDs
// Load app here, and use app slug from hereon
if (options.app && !options.app.includes('/')) {
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
const { getApplication } = await import('../utils/sdk');
const application = await getApplication(balena, options.app);
if (!application) {

View File

@ -20,6 +20,7 @@ import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getCliUx, stripIndent } from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
interface FlagsDef {
application?: string;
@ -45,12 +46,14 @@ export default class SupportCmd extends Command {
Both --device and --application flags accept multiple values, specified as
a comma-separated list (with no spaces).
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'balena support enable --device ab346f,cd457a --duration 3d',
'balena support enable --application app3 --duration 12h',
'balena support disable -a myApp',
'balena support disable -a myorg/myapp',
];
public static args = [
@ -68,10 +71,11 @@ export default class SupportCmd extends Command {
description: 'comma-separated list (no spaces) of device UUIDs',
char: 'd',
}),
application: flags.string({
description: 'comma-separated list (no spaces) of application names',
char: 'a',
}),
application: {
...cf.application,
description:
'comma-separated list (no spaces) of application names or org/name slugs',
},
duration: flags.string({
description:
'length of time to enable support for, in (h)ours or (d)ays, e.g. 12h, 2d',

View File

@ -17,11 +17,9 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { disambiguateReleaseParam } from '../../utils/normalization';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
application?: string;
@ -40,10 +38,13 @@ export default class TagRmCmd extends Command {
Remove a tag from an application, device or release.
Remove a tag from an application, device or release.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena tag rm myTagKey --application MyApp',
'$ balena tag rm myTagKey -a myorg/myapp',
'$ balena tag rm myTagKey --device 7cf02a6',
'$ balena tag rm myTagKey --release 1234',
'$ balena tag rm myTagKey --release b376b0e544e9429483b656490e5b9443b4349bd6',
@ -64,6 +65,10 @@ export default class TagRmCmd extends Command {
...cf.application,
exclusive: ['app', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'device', 'release'],
},
device: {
...cf.device,
exclusive: ['app', 'application', 'release'],
@ -73,10 +78,6 @@ export default class TagRmCmd extends Command {
exclusive: ['app', 'application', 'device'],
},
help: cf.help,
app: flags.string({
description: "same as '--application'",
exclusive: ['application', 'device', 'release'],
}),
};
public static authenticated = true;
@ -94,9 +95,12 @@ export default class TagRmCmd extends Command {
// Check user has specified one of application/device/release
if (!options.application && !options.device && !options.release) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(TagRmCmd.missingResourceMessage);
}
const { tryAsInteger } = await import('../../utils/validation');
if (options.application) {
return balena.models.application.tags.remove(
tryAsInteger(options.application),
@ -110,6 +114,9 @@ export default class TagRmCmd extends Command {
);
}
if (options.release) {
const { disambiguateReleaseParam } = await import(
'../../utils/normalization'
);
const releaseParam = await disambiguateReleaseParam(
balena,
options.release,
@ -122,7 +129,7 @@ export default class TagRmCmd extends Command {
protected static missingResourceMessage = stripIndent`
To remove a resource tag, you must provide exactly one of:
* An application, with --application <appname>
* An application, with --application <appNameOrSlug>
* A device, with --device <uuid>
* A release, with --release <id or commit>

View File

@ -17,11 +17,9 @@
import { flags } from '@oclif/command';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { disambiguateReleaseParam } from '../../utils/normalization';
import { tryAsInteger } from '../../utils/validation';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
application?: string;
@ -45,10 +43,13 @@ export default class TagSetCmd extends Command {
You can optionally provide a value to be associated with the created
tag, as an extra argument after the tag key. If a value isn't
provided, a tag with an empty value is created.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena tag set mySimpleTag --application MyApp',
'$ balena tag set mySimpleTag -a myorg/myapp',
'$ balena tag set myCompositeTag myTagValue --application MyApp',
'$ balena tag set myCompositeTag myTagValue --device 7cf02a6',
'$ balena tag set myCompositeTag "my tag value with whitespaces" --device 7cf02a6',
@ -77,6 +78,10 @@ export default class TagSetCmd extends Command {
...cf.application,
exclusive: ['app', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'device', 'release'],
},
device: {
...cf.device,
exclusive: ['app', 'application', 'release'],
@ -86,10 +91,6 @@ export default class TagSetCmd extends Command {
exclusive: ['app', 'application', 'device'],
},
help: cf.help,
app: flags.string({
description: "same as '--application'",
exclusive: ['application', 'device', 'release'],
}),
};
public static authenticated = true;
@ -107,11 +108,14 @@ export default class TagSetCmd extends Command {
// Check user has specified one of application/device/release
if (!options.application && !options.device && !options.release) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(TagSetCmd.missingResourceMessage);
}
params.value ??= '';
const { tryAsInteger } = await import('../../utils/validation');
if (options.application) {
return balena.models.application.tags.set(
tryAsInteger(options.application),
@ -127,6 +131,9 @@ export default class TagSetCmd extends Command {
);
}
if (options.release) {
const { disambiguateReleaseParam } = await import(
'../../utils/normalization'
);
const releaseParam = await disambiguateReleaseParam(
balena,
options.release,
@ -143,7 +150,7 @@ export default class TagSetCmd extends Command {
protected static missingResourceMessage = stripIndent`
To set a resource tag, you must provide exactly one of:
* An application, with --application <appname>
* An application, with --application <appNameOrSlug>
* A device, with --device <uuid>
* A release, with --release <id or commit>

View File

@ -20,8 +20,7 @@ import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import { disambiguateReleaseParam } from '../utils/normalization';
import { tryAsInteger } from '../utils/validation';
import { applicationIdInfo } from '../utils/messages';
interface FlagsDef {
application?: string;
@ -37,10 +36,13 @@ export default class TagsCmd extends Command {
List all tags and their values for a particular application,
device or release.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena tags --application MyApp',
'$ balena tags -a myorg/myapp',
'$ balena tags --device 7cf02a6',
'$ balena tags --release 1234',
'$ balena tags --release b376b0e544e9429483b656490e5b9443b4349bd6',
@ -53,6 +55,10 @@ export default class TagsCmd extends Command {
...cf.application,
exclusive: ['app', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'device', 'release'],
},
device: {
...cf.device,
exclusive: ['app', 'application', 'release'],
@ -62,10 +68,6 @@ export default class TagsCmd extends Command {
exclusive: ['app', 'application', 'device'],
},
help: cf.help,
app: flags.string({
description: "same as '--application'",
exclusive: ['application', 'device', 'release'],
}),
};
public static authenticated = true;
@ -84,6 +86,8 @@ export default class TagsCmd extends Command {
throw new ExpectedError(this.missingResourceMessage);
}
const { tryAsInteger } = await import('../utils/validation');
let tags;
if (options.application) {
@ -97,6 +101,9 @@ export default class TagsCmd extends Command {
);
}
if (options.release) {
const { disambiguateReleaseParam } = await import(
'../utils/normalization'
);
const releaseParam = await disambiguateReleaseParam(
balena,
options.release,
@ -115,7 +122,7 @@ export default class TagsCmd extends Command {
protected missingResourceMessage = stripIndent`
To list tags for a resource, you must provide exactly one of:
* An application, with --application <appname>
* An application, with --application <appNameOrSlug>
* A device, with --device <uuid>
* A release, with --release <id or commit>

24
lib/utils/common-args.ts Normal file
View File

@ -0,0 +1,24 @@
/**
* @license
* Copyright 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 { lowercaseIfSlug } from './normalization';
export const applicationRequired = {
name: 'application',
description: 'application name, slug (preferred), or numeric ID (deprecated)',
required: true,
parse: lowercaseIfSlug,
};

View File

@ -19,14 +19,17 @@ import { flags } from '@oclif/command';
import type { IBooleanFlag } from '@oclif/parser/lib/flags';
import { stripIndent } from './lazy';
import { lowercaseIfSlug } from './normalization';
export const application = flags.string({
char: 'a',
description: 'application name',
description: 'application name, slug (preferred), or numeric ID (deprecated)',
parse: lowercaseIfSlug,
});
// TODO: Consider remove second alias 'app' when we can, to simplify.
export const app = flags.string({
description: "same as '--application'",
parse: lowercaseIfSlug,
});
export const device = flags.string({
@ -78,3 +81,9 @@ export const drive = flags.string({
Check \`balena util available-drives\` for available options.
`,
});
export const json: IBooleanFlag<boolean> = flags.boolean({
char: 'j',
description: 'produce JSON output instead of tabular output',
default: false,
});

View File

@ -38,9 +38,9 @@ export const balenaAsciiArt = `\
|_.__/ \\__,_||_| \\____/|_| |_| \\__,_|
`;
export const registrySecretsHelp = `\
REGISTRY SECRETS
The --registry-secrets option specifies a JSON or YAML file containing private
export const registrySecretsHelp =
'REGISTRY SECRETS \n' +
`The --registry-secrets option specifies a JSON or YAML file containing private
Docker registry usernames and passwords to be used when pulling base images.
Sample registry-secrets YAML file:
\`\`\`
@ -61,9 +61,9 @@ If the --registry-secrets option is not specified, and a secrets.yml or
secrets.json file exists in the balena directory (usually $HOME/.balena),
this file will be used instead.`;
export const dockerignoreHelp = `\
DOCKERIGNORE AND GITIGNORE FILES
By default, the balena CLI will use a single ".dockerignore" file (if any) at
export const dockerignoreHelp =
'DOCKERIGNORE AND GITIGNORE FILES \n' +
`By default, the balena CLI will use a single ".dockerignore" file (if any) at
the project root (--source directory) in order to decide which source files to
exclude from the "build context" (tar stream) sent to balenaCloud, Docker
daemon or balenaEngine. In a microservices (multicontainer) application, the
@ -94,8 +94,8 @@ option if compatibility is required. This option is mutually exclusive with
--multi-dockerignore (-m) and will be removed in the CLI's next major version
release (v13).
Default .dockerignore patterns
When --gitignore (-g) is NOT used (i.e. when not in v11 compatibility mode), a
Default .dockerignore patterns \n` +
`When --gitignore (-g) is NOT used (i.e. when not in v11 compatibility mode), a
few default/hardcoded dockerignore patterns are "merged" (in memory) with the
patterns found in the applicable .dockerignore files, in the following order:
\`\`\`
@ -113,3 +113,24 @@ adding counter patterns to the applicable .dockerignore file(s), for example
\`!mysubmodule/.git\`. For documentation on pattern format, see:
- https://docs.docker.com/engine/reference/builder/#dockerignore-file
- https://www.npmjs.com/package/@balena/dockerignore`;
export const applicationIdInfo = `\
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
can be listed with the \`balena apps\` command. Note that slugs may change
if the application is renamed.
App names are not unique and may result in "Application is ambiguous" errors
at any time (even if it "used to work in the past"), for example if the name
clashes with a newly created public application, or with apps from other balena
accounts that you may have been invited to as a member. For this reason, app
names are especially discouraged in scripts (e.g. CI environments).
Numeric app IDs are deprecated because they consist of an implementation detail
of the balena backend. We intend to remove support for numeric IDs at some point
in the future.`;
export const jsonInfo = `\
The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it
better represents data types like arrays, empty strings and null values.
The 'jq' utility may be helpful for querying JSON fields in shell scripts
(https://stedolan.github.io/jq/manual/).`;

View File

@ -187,7 +187,6 @@ export function selectApplication(
}
const apps = (await balena.models.application.getAll({
$select: 'app_name',
$expand: {
is_for__device_type: {
$select: 'slug',
@ -204,8 +203,8 @@ export function selectApplication(
message: 'Select an application',
type: 'list',
choices: _.map(applications, (application) => ({
name: `${application.app_name} (${application.is_for__device_type[0].slug})`,
value: application.app_name,
name: `${application.app_name} (${application.slug}) [${application.is_for__device_type[0].slug}]`,
value: application,
})),
});
});

View File

@ -26,6 +26,7 @@ import type {
* Wraps the sdk application.get method,
* adding disambiguation in cases where the provided
* identifier could be interpreted in multiple valid ways.
* // TODO: Remove this once support for numeric App IDs is removed.
*/
export async function getApplication(
sdk: BalenaSDK,

View File

@ -19,32 +19,6 @@ import { expect } from 'chai';
import { BalenaAPIMock } from '../../balena-api-mock';
import { cleanOutput, runCommand } from '../../helpers';
const HELP_RESPONSE = `
Move one or more devices to another application.
USAGE
$ balena device move <uuid(s)>
ARGUMENTS
<uuid> comma-separated list (no blank spaces) of device UUIDs to be moved
OPTIONS
-a, --application <application> application name
-h, --help show CLI help
--app <app> same as '--application'
DESCRIPTION
Move one or more devices to another application.
Note, if the application option is omitted it will be prompted
for interactively.
EXAMPLES
$ balena device move 7cf02a6
$ balena device move 7cf02a6,dc39e52
$ balena device move 7cf02a6 --application MyNewApp
`;
describe('balena device move', function () {
let api: BalenaAPIMock;
@ -59,14 +33,6 @@ describe('balena device move', function () {
api.done();
});
it('should print help text with the -h flag', async () => {
const { out, err } = await runCommand('device move -h');
expect(cleanOutput(out)).to.deep.equal(cleanOutput([HELP_RESPONSE]));
expect(err).to.eql([]);
});
it('should error if uuid not provided', async () => {
const { out, err } = await runCommand('device move');
const errLines = cleanOutput(err);

View File

@ -21,36 +21,6 @@ import * as path from 'path';
import { apiResponsePath, BalenaAPIMock } from '../../balena-api-mock';
import { cleanOutput, runCommand } from '../../helpers';
const HELP_RESPONSE = `
List all devices.
USAGE
$ balena devices
OPTIONS
-a, --application <application> application name
-h, --help show CLI help
-j, --json produce JSON output instead of tabular output
--app <app> same as '--application'
DESCRIPTION
list all devices that belong to you.
You can filter the devices by application by using the \`--application\` option.
The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it
better represents data types like arrays, empty strings and null values.
The 'jq' utility may be helpful for querying JSON fields in shell scripts
(https://stedolan.github.io/jq/manual/).
EXAMPLES
$ balena devices
$ balena devices --application MyApp
$ balena devices --app MyApp
$ balena devices -a MyApp
`;
describe('balena devices', function () {
let api: BalenaAPIMock;
@ -65,14 +35,6 @@ describe('balena devices', function () {
api.done();
});
it('should print help text with the -h flag', async () => {
const { out, err } = await runCommand('devices -h');
expect(cleanOutput(out)).to.deep.equal(cleanOutput([HELP_RESPONSE]));
expect(err).to.eql([]);
});
it('should list devices from own and collaborator apps', async () => {
api.scope
.get(