Compare commits

..

65 Commits

Author SHA1 Message Date
cf3e8ff909 v14.3.0 2022-08-17 15:26:40 +03:00
36d1af1e33 Merge pull request #2523 from balena-io/add-release-validate-and-invalidate-commands
release: Add `invalidate` and `validate` commands for invalidating and validating releases (respectively)
2022-08-17 12:24:14 +00:00
18f83092fe v14.2.0 2022-08-16 23:32:01 +03:00
ee3c796787 Merge pull request #2522 from balena-io/add-fleet-pin-and-track-latest-commands
Add fleet `pin` and `track-latest` commands
2022-08-16 20:29:51 +00:00
934c3ddf38 release: Add validate command for validating releases
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-15 19:44:54 +00:00
66e6daf78c release: Add invalidate command for invalidating releases
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-15 19:41:25 +00:00
97eb107de4 fleet: Add track-latest command for tracking the latest release
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-15 15:34:54 -04:00
def205f1fb fleet: Add pin command for pinning fleets to a specific release
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-15 15:06:10 -04:00
5c8f78678b v14.1.0 2022-08-04 17:52:53 +04:00
769f1ca5b4 Merge pull request #2493 from balena-io/add-device-track-command
Add device track command
2022-08-04 13:51:04 +00:00
cb26a736fc Add device track command for pinning a device to the latest release or a specific release
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-03 14:42:25 -04:00
d28847d5aa v14.0.0 2022-08-02 19:08:30 +04:00
c0902bb119 Merge pull request #2514 from balena-io/v14
Release v14
2022-08-02 15:05:58 +00:00
26aae0afab v13.10.1 2022-08-02 02:07:46 +04:00
5f3cf75c1a Merge pull request #2516 from balena-io/2515-fix-balena-deploy-jsesc-dependency
Fix balena deploy missing dependency error
2022-08-01 22:05:55 +00:00
8a7fbdb55d Drop undocumented support for numeric ids in balena device commands
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 18:52:30 +00:00
b260f80bcc Drop support for the deprecated balena device public-url <enable|disable|status> <uuid> and related format
Resolves: #2501
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 18:52:30 +00:00
9ec37975f3 Drop support for numeric fleet id parameters from all commands
Resolves: #2500
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 18:52:25 +00:00
73c487c2f5 Fix balena deploy missing dependency error
Resolves: #2515
Change-type: patch
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
2022-08-01 19:35:07 +03:00
3cb35ea318 fleet: Add --filter, --no-header, --no-truncate, and --sort options
Resolves: #2503
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
efe6fd22ce fleet: Add --fields and --json options
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
6ee8d8a899 fleet: Use the oclif output formatter
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
c735f13636 config: Drop optional and ignored --type flag
Change-type: patch
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
edb0fdc3c1 Drop deprecated --logs flag
Resolves: #2499
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
14a07ac7f7 Drop support for open-balena-api < v0.131.0
Resolves: #2502
Change-type: major
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-08-01 15:35:13 +00:00
264cd94be5 v13.10.0 2022-07-20 12:25:47 +00:00
2664f4e7fb Merge pull request #2504 from balena-io/add-device-view-option
Add `--view` flag to `device` command for opening a device's dashboard page
2022-07-20 12:23:37 +00:00
3ce2653881 v13.9.0 2022-07-19 12:03:18 +03:00
719860366f Merge pull request #2476 from balena-io/switch-to-compose
Switch to balena-compose
2022-07-19 08:58:59 +00:00
21ded85c7a v13.8.0 2022-07-18 22:55:10 +03:00
c91f67d27e Merge pull request #2505 from balena-io/add-note-option-for-push-and-deploy
Add `--note` option for `push` and `deploy`
2022-07-18 18:26:43 +00:00
18eedfec7f Add --note option for push and deploy
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-07-14 15:44:55 -04:00
1fe0480a8a Add --view flag to device command for opening a device's dashboard page
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-07-14 18:56:51 +00:00
c7f56d92dd Switch to balena-compose
Removes a bunch of individual dependencies by switching to `@balena/compose` which (currently) groups and manages those dependencies together in one package.

Change-type: minor
2022-07-14 13:05:21 +00:00
a92f58134f v13.7.1 2022-07-13 10:50:45 +03:00
cc6a8ef76e Merge pull request #2498 from balena-io/2462-bump-image-manager
os download: Fix resolving to draft releases
2022-07-13 07:48:41 +00:00
88f4a3d88e os download: Fix resolving to draft releases
Resolves: #2462
Change-type: patch
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
2022-07-13 10:14:30 +03:00
f6d668684a v13.7.0 2022-07-07 11:01:22 +03:00
be7c0dc897 Merge pull request #2496 from balena-io/add-fleet-view-command
Add `--view` flag to `fleet` command for opening a fleet's dashboard page
2022-07-07 07:58:02 +00:00
566b7f97e0 Add --view flag to fleet command for opening a fleet's dashboard page
Change-type: minor
Signed-off-by: Matthew Yarmolinsky <matthew-timothy@balena.io>
2022-07-05 13:14:18 -04:00
f55dd81a19 v13.6.1 2022-06-13 21:40:58 +03:00
dba5349390 Merge pull request #2491 from balena-io/update-balena-sdk-16.22.0
Update balena-sdk to use the native OS release phase & variant fields
2022-06-13 17:25:54 +00:00
6a8dfcc664 Update balena-sdk to use the native OS release phase & variant fields
Update balena-sdk from 16.20.4 to 16.22.0

Change-type: patch
2022-06-09 17:51:55 +03:00
59e35d866f v13.6.0 2022-06-07 17:44:48 +03:00
9235c928f1 Merge pull request #2490 from balena-io/kyle/qemu-v7.0.0
Update QEMU to v7.0.0
2022-06-07 14:38:37 +00:00
3d88f0144a Update QEMU to v7.0.0
Change-type: minor
Signed-off-by: Kyle Harding <kyle@balena.io>
2022-06-06 14:56:10 -04:00
a6b461ba91 v13.5.3 2022-05-31 13:31:31 +03:00
b96da951db Merge pull request #2485 from balena-io/drop-needspasswordreset
Drop the needsPasswordReset property from the tests
2022-05-31 10:26:22 +00:00
8235cead07 Drop the needsPasswordReset property from the tests
Change-type: patch
See: https://github.com/balena-io/balena-api/pull/3665
2022-05-31 12:46:49 +03:00
30b9d9141d v13.5.2 2022-05-31 12:34:18 +03:00
03b41d9989 Merge pull request #2486 from balena-io/npm-dd
Deduplicate npm-shrinkwrap.json
2022-05-31 09:28:29 +00:00
aab3af2153 Deduplicate npm-shrinkwrap.json
Change-type: patch
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
2022-05-31 11:46:49 +03:00
600457de61 v13.5.1 2022-05-27 02:21:54 +03:00
17db857e10 Merge pull request #2483 from balena-io/bump-preload-to-v3
Bump balena-preload to 12.1.0
2022-05-26 23:20:10 +00:00
eb45ae2a30 preload: Fix issue where balenaOS v2.98.3+ required an Internet connection to start apps
Devices with a v13+ supervisor will fail to start preloaded apps with a
v2 target state format if connectivity is not available since migration
of apps.json is not possible without API access.

This enables support for preloading v3 target state format in
images with supervisor v13 or above.

Change-type: patch
2022-05-26 20:48:07 +00:00
2eaf70bff3 v13.5.0 2022-05-25 15:01:45 +03:00
226f45f732 Merge pull request #2482 from balena-io/key-expiry
Add provisioning key expiry date option to config generate options
2022-05-25 11:59:06 +00:00
c4990f3a26 Update balena-sdk to 16.20.4
Update balena-sdk from 16.9.0 to 16.20.4

Change-type: patch
2022-05-24 21:53:12 +05:30
0195a3b18c Add provisioning key expiry date option to config generate options
Change-Type: minor
Signed-off-by: Nitish Agarwal <1592163+nitishagar@users.noreply.github.com>
2022-05-22 21:50:48 +05:30
3d90aeb122 v13.4.3 2022-05-19 21:10:42 +03:00
0571039bfe Merge pull request #2481 from balena-io/update-docker-progress
Update docker-progress to 5.1.3
2022-05-19 17:56:34 +00:00
ee668a4c5c Update docker-progress to 5.1.3
Update docker-progress from 5.0.1 to 5.1.3

Change-type: patch
2022-05-18 15:01:27 +01:00
ead4dbfab1 v13.4.2 2022-05-10 21:02:45 +03:00
0b498d09df Merge pull request #2479 from balena-io/kyle/balena-preload
preload: Fix detection of supervisor version for balenaOS v2.93.0
2022-05-10 17:08:59 +00:00
2b2c40c22d preload: Fix detection of supervisor version for balenaOS v2.93.0
Update balena-preload from 12.0.0 to 12.0.1

Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
2022-05-10 11:29:14 -04:00
72 changed files with 2902 additions and 1320 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,341 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).
## 14.3.0 - 2022-08-17
* release: Add `validate` command for validating releases [Matthew Yarmolinsky]
* release: Add `invalidate` command for invalidating releases [Matthew Yarmolinsky]
## 14.2.0 - 2022-08-16
* fleet: Add `track-latest` command for tracking the latest release [Matthew Yarmolinsky]
* fleet: Add `pin` command for pinning fleets to a specific release [Matthew Yarmolinsky]
## 14.1.0 - 2022-08-03
* Add device track command for pinning a device to the latest release or a specific release [Matthew Yarmolinsky]
## 14.0.0 - 2022-08-01
* Drop undocumented support for numeric ids in balena device commands [Matthew Yarmolinsky]
* Drop support for the deprecated `balena device public-url <enable|disable|status> <uuid>` and related format [Matthew Yarmolinsky]
* Drop support for numeric fleet id parameters from all commands [Matthew Yarmolinsky]
* fleet: Add `--filter`, `--no-header`, `--no-truncate`, and `--sort` options [Matthew Yarmolinsky]
* fleet: Add `--fields` and `--json` options [Matthew Yarmolinsky]
* fleet: Use the oclif output formatter [Matthew Yarmolinsky]
* config: Drop optional and ignored `--type` flag [Matthew Yarmolinsky]
* Drop deprecated `--logs` flag [Matthew Yarmolinsky]
* Drop support for open-balena-api < v0.131.0 [Matthew Yarmolinsky]
## 13.10.1 - 2022-08-01
* Fix balena deploy missing dependency error [Thodoris Greasidis]
## 13.10.0 - 2022-07-20
* Add `--view` flag to `device` command for opening a device's dashboard page [Matthew Yarmolinsky]
## 13.9.0 - 2022-07-19
* Switch to balena-compose [Akis Kesoglou]
## 13.8.0 - 2022-07-18
* Add `--note` option for `push` and `deploy` [Matthew Yarmolinsky]
## 13.7.1 - 2022-07-13
* os download: Fix resolving to draft releases [Thodoris Greasidis]
## 13.7.0 - 2022-07-07
* Add `--view` flag to `fleet` command for opening a fleet's dashboard page [Matthew Yarmolinsky]
## 13.6.1 - 2022-06-09
<details>
<summary> Update balena-sdk to use the native OS release phase & variant fields [Thodoris Greasidis] </summary>
> ### balena-sdk-16.22.0 - 2022-06-06
>
> * os: Start using the release.phase field in the available versions [Thodoris Greasidis]
>
> ### balena-sdk-16.21.1 - 2022-06-02
>
> * Add provisioning key expiry date to generateDeviceProvisioningKey [Nitish Agarwal]
>
> ### balena-sdk-16.21.0 - 2022-06-01
>
> * os: Refactor the computation of OS releases [Thodoris Greasidis]
> * os: Use the model's release variant when the native fields are used [Thodoris Greasidis]
>
> ### balena-sdk-16.20.6 - 2022-06-01
>
> * Deprecate the needsPasswordReset field of the JWTUser [Thodoris Greasidis]
>
> ### balena-sdk-16.20.5 - 2022-05-25
>
> * Update TypeScript to v4.7 [Thodoris Greasidis]
>
</details>
## 13.6.0 - 2022-06-06
* Update QEMU to v7.0.0 [Kyle Harding]
## 13.5.3 - 2022-05-31
* Drop the needsPasswordReset property from the tests [Thodoris Greasidis]
## 13.5.2 - 2022-05-31
* Deduplicate npm-shrinkwrap.json [Thodoris Greasidis]
## 13.5.1 - 2022-05-26
* preload: Fix issue where balenaOS v2.98.3+ required an Internet connection to start apps [pipex]
## 13.5.0 - 2022-05-24
<details>
<summary> Update balena-sdk to 16.20.4 [Nitish Agarwal] </summary>
> ### balena-sdk-16.20.4 - 2022-05-09
>
> * bump @types/node from 10.17.60 to 12.20.500 [Thodoris Greasidis]
>
> ### balena-sdk-16.20.3 - 2022-05-06
>
> * patch: bump browserify from 14.5.0 to 17.0.0 [dependabot[bot]]
>
> ### balena-sdk-16.20.2 - 2022-05-05
>
> * patch: bump tmp from 0.0.31 to 0.2.1 [dependabot[bot]]
>
> ### balena-sdk-16.20.1 - 2022-05-05
>
> * Drop the non-populated apiUrl & actionsUrl properties from Config type [Thodoris Greasidis]
>
> ### balena-sdk-16.20.0 - 2022-05-04
>
> * models.apiKey: Update apiKeyInfo with expiryDate option [Nitish Agarwal]
> * os.getConfig: Add typings for the provisioningKeyExpiryDate option [Balena CI]
>
> ### balena-sdk-16.19.14 - 2022-05-04
>
> * config.getAll: Mark the deviceTypes property as optional [Thodoris Greasidis]
>
> ### balena-sdk-16.19.13 - 2022-05-03
>
> * patch: bump mocha from 3.5.3 to 10.0.0 [dependabot[bot]]
>
> ### balena-sdk-16.19.12 - 2022-05-03
>
> * config.getAll: Deprecate the pubnub property and mark as optional [Thodoris Greasidis]
>
> ### balena-sdk-16.19.11 - 2022-05-03
>
> * patch: bump mockttp from 0.9.1 to 2.7.0 [Thodoris Greasidis]
>
> ### balena-sdk-16.19.10 - 2022-04-27
>
> * Reduce the prod typing dependencies [Thodoris Greasidis]
>
> ### balena-sdk-16.19.9 - 2022-04-26
>
> * patch: Remove documentation.md from the NPM package [Vipul Gupta]
>
> ### balena-sdk-16.19.8 - 2022-04-20
>
> * patch: Remove additional quotes [Vipul Gupta (@vipulgupta2048)]
>
> ### balena-sdk-16.19.7 - 2022-04-12
>
> * tests: Update to work with latest major of superagent [Thodoris Greasidis]
> * patch: bump superagent from 3.8.3 to 7.1.2 [dependabot[bot]]
>
> ### balena-sdk-16.19.6 - 2022-04-11
>
> * patch: bump dotenv from 4.0.0 to 16.0.0 [dependabot[bot]]
>
> ### balena-sdk-16.19.5 - 2022-04-09
>
> * Bump karma to v6 [Thodoris Greasidis]
>
> ### balena-sdk-16.19.4 - 2022-04-09
>
> * Add dependabot configuration [Thodoris Greasidis]
>
> ### balena-sdk-16.19.3 - 2022-04-06
>
> * tests: Update v5 model endpoint prefix references [Thodoris Greasidis]
>
> ### balena-sdk-16.19.2 - 2022-04-06
>
>
> <details>
> <summary> Fix extracting a meaningful error message instead of "[object Object]" [Thodoris Greasidis] </summary>
>
>> #### balena-request-11.5.5 - 2022-04-06
>>
>> * Fix extracting the response error from object response bodies [Thodoris Greasidis]
>>
>> #### balena-request-11.5.4 - 2022-04-06
>>
>> * Drop explicit karma-chrome-launcher devDependency [Thodoris Greasidis]
>>
> </details>
>
>
> ### balena-sdk-16.19.1 - 2022-04-05
>
> * Update balena-request dependency to v11.5.3 [Matthew Yarmolinsky]
>
> ### balena-sdk-16.19.0 - 2022-03-16
>
> * Add release.setKnownIssueList function for setting a release's known issue list [Matthew Yarmolinsky]
>
> ### balena-sdk-16.18.0 - 2022-03-14
>
> * minor: Add trying SDK in the browser [Vipul Gupta (@vipulgupta2048)]
>
> ### balena-sdk-16.17.0 - 2022-03-11
>
> * device.getWithServiceDetails: Add the release id in the service info [Matthew Yarmolinsky]
>
> ### balena-sdk-16.16.1 - 2022-03-08
>
> * Replace internal use of deprecated OsVersion.rawVersion with raw_version [Thodoris Greasidis]
>
> ### balena-sdk-16.16.0 - 2022-03-03
>
> * Add support for named imports from .mjs files [Thodoris Greasidis]
> * Update npx command to fix ts-compatibility tests [Thodoris Greasidis]
> * Regenerate Documentation [Thodoris Greasidis]
> * Update typescript to 4.6.2 [Thodoris Greasidis]
>
> ### balena-sdk-16.15.1 - 2022-02-24
>
> * Remove unnecessary vpn address filtering when fetching local addresses [Pagan Gazzard]
>
> ### balena-sdk-16.15.0 - 2022-02-16
>
> * Add applicationClass parameter to application create function for setting is_of__class property [Matthew Yarmolinsky]
>
> ### balena-sdk-16.14.0 - 2022-02-15
>
> * Add name and description field to generateDeviceKey for device. [Nitish Agarwal]
>
> ### balena-sdk-16.13.4 - 2022-01-27
>
> * typings: Fix conditional $or/$and/$not $filters [Thodoris Greasidis]
>
> ### balena-sdk-16.13.3 - 2022-01-27
>
> * Deprecate the supportsBlink field of the DeviceTypeJson.DeviceType type [Thodoris Greasidis]
>
> ### balena-sdk-16.13.2 - 2022-01-25
>
> * Deprecate the logoUrl field of the DeviceTypeJson.DeviceType type [Thodoris Greasidis]
>
> ### balena-sdk-16.13.1 - 2022-01-21
>
> * Replace internal use of release.contains__image with release_image [Thodoris Greasidis]
>
> ### balena-sdk-16.13.0 - 2022-01-21
>
> * models: Deprecate the release.contains__image in favor of the term form [Thodoris Greasidis]
> * models: Add the release_image term form property in the Release typings [Thodoris Greasidis]
>
> ### balena-sdk-16.12.1 - 2022-01-17
>
> * config.getConfigVarSchema: Send the token only when using a device type [Thodoris Greasidis]
>
> ### balena-sdk-16.12.0 - 2022-01-10
>
> * Replace DeviceTypeJson usage for alias resolution with model queries [Thodoris Greasidis]
> * models/device-type: Support aliases as argument of the get() method [Thodoris Greasidis]
>
> ### balena-sdk-16.11.3 - 2022-01-09
>
> * Fix jsdoc example for balena.errors [Ken Bannister]
>
> ### balena-sdk-16.11.2 - Invalid date
>
> * tests: Convert auth spec to async await [Thodoris Greasidis]
>
> ### balena-sdk-16.11.1 - Invalid date
>
> * Fix buggy tests causing flakiness on node 16 [Thodoris Greasidis]
>
> ### balena-sdk-16.11.0 - Invalid date
>
> * Alias device.getManifestBySlug as config.getDeviceTypeManifestBySlug [Thodoris Greasidis]
> * Deprecate device.getManifestByApplication [Thodoris Greasidis]
>
> ### balena-sdk-16.10.0 - Invalid date
>
> * application.get: Add support for retrieving applications by uuid [Thodoris Greasidis]
> * package.json: Rename the lint-fix npm script to lint:fix [Thodoris Greasidis]
>
> ### balena-sdk-16.9.4 - 2021-12-29
>
> * os: Avoid mutating the args in getAvailableOsVersions & getAllOsVersion [Thodoris Greasidis]
>
> ### balena-sdk-16.9.3 - 2021-12-28
>
> * os: Replace semver normalization with balena-semver [Thodoris Greasidis]
>
> ### balena-sdk-16.9.2 - 2021-12-28
>
> * Stop relying on the balena-pine module [Thodoris Greasidis]
>
> ### balena-sdk-16.9.1 - 2021-12-28
>
> * Enable nested changelogs for balena-hup-action-utils [Thodoris Greasidis]
>
</details>
* Add provisioning key expiry date option to config generate options [Balena CI]
## 13.4.3 - 2022-05-19
<details>
<summary> Update docker-progress to 5.1.3 [Pagan Gazzard] </summary>
> ### docker-progress-5.1.3 - 2022-05-11
>
> * Reject on the stream closing if it has not already ended successfully [Pagan Gazzard]
>
> ### docker-progress-5.1.2 - 2022-05-10
>
> * Update dependencies [Pagan Gazzard]
>
> ### docker-progress-5.1.1 - 2022-05-10
>
> * Avoid breaking changes to PushPullOptions required properties [Kyle Harding]
>
> ### docker-progress-5.1.0 - 2022-03-10
>
> * Add support for building images with progress [Felipe Lalanne]
>
</details>
## 13.4.2 - 2022-05-10
<details>
<summary> preload: Fix detection of supervisor version for balenaOS v2.93.0 [Kyle Harding] </summary>
> ### balena-preload-12.0.1 - 2022-05-10
>
> * Update supervisor image regex to include tagged images [Kyle Harding]
>
</details>
## 13.4.1 - 2022-04-11
* leave: Update log message to advise that device still needs deleting [Taro Murao]

View File

@ -12,15 +12,15 @@ _balena() {
# Sub-completions
api_key_cmds=( generate )
config_cmds=( generate inject read reconfigure write )
device_cmds=( deactivate identify init local-mode move os-update public-url purge reboot register rename restart rm shutdown )
device_cmds=( deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet )
devices_cmds=( supported )
env_cmds=( add rename rm )
fleet_cmds=( create purge rename restart rm )
fleet_cmds=( create pin purge rename restart rm track-latest )
internal_cmds=( osinit )
key_cmds=( add rm )
local_cmds=( configure flash )
os_cmds=( build-config configure download initialize versions )
release_cmds=( finalize )
release_cmds=( finalize invalidate validate )
tag_cmds=( rm set )

View File

@ -11,15 +11,15 @@ _balena_complete()
# Sub-completions
api_key_cmds="generate"
config_cmds="generate inject read reconfigure write"
device_cmds="deactivate identify init local-mode move os-update public-url purge reboot register rename restart rm shutdown"
device_cmds="deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet"
devices_cmds="supported"
env_cmds="add rename rm"
fleet_cmds="create purge rename restart rm"
fleet_cmds="create pin purge rename restart rm track-latest"
internal_cmds="osinit"
key_cmds="add rm"
local_cmds="configure flash"
os_cmds="build-config configure download initialize versions"
release_cmds="finalize"
release_cmds="finalize invalidate validate"
tag_cmds="rm set"

View File

@ -333,11 +333,35 @@ Examples:
### Options
#### --fields FIELDS
only show provided fields (comma-separated)
#### -j, --json
output in json format
#### --filter FILTER
filter results by substring matching of a given field, eg: --filter field=foo
#### --no-header
hide table header from output
#### --no-truncate
do not truncate output to fit screen
#### --sort SORT
field to sort by (prepend '-' for descending order)
## fleet &#60;fleet&#62;
Display detailed information about a single fleet.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -345,23 +369,34 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
$ balena fleet MyFleet
$ balena fleet myorg/myfleet
$ balena fleet myorg/myfleet --view
### Arguments
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
### Options
#### --view
open fleet dashboard page
#### --fields FIELDS
only show provided fields (comma-separated)
#### -j, --json
output in json format
## fleet create &#60;name&#62;
Create a new balena fleet.
@ -408,7 +443,7 @@ fleet device type (Check available types with `balena devices supported`)
Purge data from all devices belonging to a fleet.
This will clear the fleet's '/data' directory.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -416,9 +451,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -429,7 +462,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
### Options
@ -440,7 +473,7 @@ Rename a fleet.
Note, if the `newName` parameter is omitted, it will be
prompted for interactively.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -448,9 +481,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -462,7 +493,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### NEWNAME
@ -474,7 +505,7 @@ the new name for the fleet
Restart all devices belonging to a fleet.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -482,9 +513,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -495,7 +524,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
### Options
@ -505,7 +534,7 @@ Permanently remove a fleet.
The --yes option may be used to avoid interactive confirmation.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -513,9 +542,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -527,7 +554,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
### Options
@ -618,7 +645,7 @@ List all of your devices.
Devices can be filtered by fleet with the `--fleet` option.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -626,9 +653,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
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
@ -646,7 +671,7 @@ Examples:
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -j, --json
@ -680,6 +705,7 @@ Show information about a single device.
Examples:
$ balena device 7cf02a6
$ balena device 7cf02a6 --view
### Arguments
@ -689,6 +715,10 @@ the device uuid
### Options
#### --view
open device dashboard page
## device deactivate &#60;uuid&#62;
Deactivate a device.
@ -753,7 +783,7 @@ If the '--fleet' or '--drive' options are omitted, interactive menus will be
presented with values to choose from. If the '--os-version' option is omitted,
the latest released OS version for the fleet's default device type will be used.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -761,9 +791,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Image configuration questions will be asked interactively unless a pre-configured
'config.json' file is provided with the '--config' option. The file can be
@ -779,7 +807,7 @@ Examples:
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -y, --yes
@ -811,6 +839,10 @@ path to the config JSON file, see `balena os build-config`
custom key name assigned to generated provisioning api key
#### --provisioning-key-expiry-date PROVISIONING-KEY-EXPIRY-DATE
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
## device local-mode &#60;uuid&#62;
Output current local mode status, or enable/disable local mode
@ -849,7 +881,7 @@ Move one or more devices to another fleet.
If --fleet is omitted, the fleet will be prompted for interactively.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -857,9 +889,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -878,7 +908,7 @@ comma-separated list (no blank spaces) of device UUIDs to be moved
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
## device os-update &#60;uuid&#62;
@ -916,9 +946,6 @@ This command will output the current public URL for the
specified device. It can also enable or disable the URL,
or output the enabled status, using the respective options.
The old command style 'balena device public-url enable <uuid>'
is deprecated, but still supported.
Examples:
$ balena device public-url 23c73a1
@ -932,10 +959,6 @@ Examples:
the uuid of the device to manage
#### LEGACYUUID
### Options
#### --enable
@ -997,7 +1020,7 @@ Register a new device with a balena fleet.
If --uuid is not provided, a new UUID will be automatically assigned.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1005,9 +1028,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1019,7 +1040,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
### Options
@ -1233,7 +1254,7 @@ name may be null in JSON output (or 'N/A' in tabular output) if the fleet that
the device belonged to is no longer accessible by the current user (for example,
in case the current user was removed from the fleet by the fleet's owner).
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1241,9 +1262,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1261,7 +1280,7 @@ Examples:
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -c, --config
@ -1371,7 +1390,7 @@ therefore the --service option cannot be used when the variable name starts
with a reserved prefix. When defining custom fleet variables, please avoid
these reserved prefixes.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1379,9 +1398,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1409,7 +1426,7 @@ variable value; if omitted, use value from this process' environment
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -d, --device DEVICE
@ -1492,7 +1509,7 @@ select a service variable (may be used together with the --device option)
List all tags and their values for the specified fleet, device or release.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1500,9 +1517,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1516,7 +1531,7 @@ Examples:
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -d, --device DEVICE
@ -1530,7 +1545,7 @@ release id
Remove a tag from a fleet, device or release.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1538,9 +1553,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1560,7 +1573,7 @@ the key string of the tag
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -d, --device DEVICE
@ -1578,7 +1591,7 @@ 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.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -1586,9 +1599,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -1615,7 +1626,7 @@ the optional value associated with the tag
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -d, --device DEVICE
@ -1900,7 +1911,7 @@ Examples:
#### FLEETORDEVICE
fleet name/slug/id, device uuid, or address of local device
fleet name/slug, device uuid, or address of local device
#### SERVICE
@ -1968,7 +1979,7 @@ Examples:
#### DEVICEORFLEET
device UUID or fleet name/slug/ID
device UUID or fleet name/slug
### Options
@ -2147,7 +2158,7 @@ are multiple files to inject. See connection profile examples and reference at:
https://www.balena.io/docs/reference/OS/network/2.x/
https://developer.gnome.org/NetworkManager/stable/ref-settings.html
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -2155,9 +2166,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
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
@ -2186,7 +2195,7 @@ ask advanced configuration questions (when in interactive mode)
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### --config CONFIG
@ -2236,6 +2245,10 @@ paths to local files to place into the 'system-connections' directory
custom key name assigned to generated provisioning api key
#### --provisioning-key-expiry-date PROVISIONING-KEY-EXPIRY-DATE
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
## os initialize &#60;image&#62;
Initialize an os image for a device with a previously
@ -2296,7 +2309,7 @@ alongside the --deviceType option to specify the target device type.
To avoid interactive questions, specify a command line option for each question that
would otherwise be asked.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -2304,9 +2317,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -2327,7 +2338,7 @@ a balenaOS version
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### --dev
@ -2373,6 +2384,10 @@ supervisor cloud polling interval in minutes (e.g. for device variables)
custom key name assigned to generated provisioning api key
#### --provisioning-key-expiry-date PROVISIONING-KEY-EXPIRY-DATE
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
## config inject &#60;file&#62;
Inject a 'config.json' file to a balenaOS image file or attached SD card or
@ -2394,10 +2409,6 @@ the path to the config.json file to inject
### Options
#### -t, --type TYPE
ignored - no longer required
#### -d, --drive DRIVE
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
@ -2418,10 +2429,6 @@ Examples:
### Options
#### -t, --type TYPE
ignored - no longer required
#### -d, --drive DRIVE
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
@ -2449,10 +2456,6 @@ Examples:
### Options
#### -t, --type TYPE
ignored - no longer required
#### -d, --drive DRIVE
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
@ -2491,10 +2494,6 @@ the value of the config parameter to write
### Options
#### -t, --type TYPE
ignored - no longer required
#### -d, --drive DRIVE
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
@ -2515,7 +2514,7 @@ Check also the Preloading and Preregistering section of the balena CLI's advance
masterclass document:
https://www.balena.io/docs/learn/more/masterclasses/advanced-cli/#5-preloading-and-preregistering
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -2523,9 +2522,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Note that the this command requires Docker to be installed, as further detailed
in the balena CLI's installation instructions:
@ -2551,7 +2548,7 @@ the image file path
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -c, --commit COMMIT
@ -2715,6 +2712,7 @@ Examples:
$ balena push myFleet
$ balena push myFleet --source <source directory>
$ balena push myFleet -s <source directory>
$ balena push myFleet --source <source directory> --note "this is the note for this release"
$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"
$ balena push myorg/myfleet
@ -2831,6 +2829,10 @@ by the 'track latest' release policy but can be used through release pinning.
Draft releases can be marked as final through the API. Releases are created
as final by default unless this option is given.
#### --note NOTE
The notes for this release
# Settings
## settings
@ -3010,7 +3012,7 @@ the type of device this build is for
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -e, --emulated
@ -3020,14 +3022,6 @@ Use QEMU for ARM architecture emulation during the image build
Alternative Dockerfile name/path, relative to the source folder
#### --dockercompose DOCKERCOMPOSE
Alternative docker-compose.yml name in the source root folder
#### --logs
No-op and deprecated since balena CLI v12.0.0. Build logs are now shown by default.
#### --nologs
Hide the image build log output (produce less verbose output)
@ -3200,6 +3194,7 @@ Examples:
$ balena deploy myFleet
$ balena deploy myorg/myfleet --build --source myBuildDir/
$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"
$ balena deploy myorg/myfleet myRepo/myImage
$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"
@ -3207,7 +3202,7 @@ Examples:
#### FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### IMAGE
@ -3240,6 +3235,10 @@ by the 'track latest' release policy but can be used through release pinning.
Draft releases can be marked as final through the API. Releases are created
as final by default unless this option is given.
#### --note NOTE
The notes for this release
#### -e, --emulated
Use QEMU for ARM architecture emulation during the image build
@ -3248,14 +3247,6 @@ Use QEMU for ARM architecture emulation during the image build
Alternative Dockerfile name/path, relative to the source folder
#### --dockercompose DOCKERCOMPOSE
Alternative docker-compose.yml name in the source root folder
#### --logs
No-op and deprecated since balena CLI v12.0.0. Build logs are now shown by default.
#### --nologs
Hide the image build log output (produce less verbose output)
@ -3349,7 +3340,7 @@ scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This may require administrator/root privileges.
Likewise, if the fleet option is not provided then a picker will be shown.
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -3357,9 +3348,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:
@ -3380,7 +3369,7 @@ the IP or hostname of device
#### -f, --fleet FLEET
fleet name, slug (preferred), or numeric ID (deprecated)
fleet name or slug (preferred)
#### -i, --pollInterval POLLINTERVAL
@ -3436,7 +3425,7 @@ or hours, e.g. '12h', '2d'.
Both --device and --fleet flags accept multiple values, specified as
a comma-separated list (with no spaces).
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the `balena fleets` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -3444,9 +3433,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.
environments).
Examples:

View File

@ -37,6 +37,7 @@ interface FlagsDef {
wifiKey?: string;
appUpdatePollInterval?: string;
'provisioning-key-name'?: string;
'provisioning-key-expiry-date'?: string;
help: void;
}
@ -81,7 +82,11 @@ export default class ConfigGenerateCmd extends Command {
dev: cf.dev,
device: {
...cf.device,
exclusive: ['fleet', 'provisioning-key-name'],
exclusive: [
'fleet',
'provisioning-key-name',
'provisioning-key-expiry-date',
],
},
deviceApiKey: flags.string({
description:
@ -120,6 +125,11 @@ export default class ConfigGenerateCmd extends Command {
description: 'custom key name assigned to generated provisioning api key',
exclusive: ['device'],
}),
'provisioning-key-expiry-date': flags.string({
description:
'expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)',
exclusive: ['device'],
}),
help: cf.help,
};
@ -140,11 +150,9 @@ export default class ConfigGenerateCmd extends Command {
| (DeviceWithDeviceType & { belongs_to__application: PineDeferred })
| null = null;
if (options.device != null) {
const { tryAsInteger } = await import('../../utils/validation');
const rawDevice = await balena.models.device.get(
tryAsInteger(options.device),
{ $expand: { is_of__device_type: { $select: 'slug' } } },
);
const rawDevice = await balena.models.device.get(options.device, {
$expand: { is_of__device_type: { $select: 'slug' } },
});
if (!rawDevice.belongs_to__application) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(stripIndent`
@ -196,6 +204,7 @@ export default class ConfigGenerateCmd extends Command {
answers.version = options.version;
answers.developmentMode = options.dev;
answers.provisioningKeyName = options['provisioning-key-name'];
answers.provisioningKeyExpiryDate = options['provisioning-key-expiry-date'];
// Generate config
const { generateDeviceConfig, generateApplicationConfig } = await import(

View File

@ -57,7 +57,6 @@ export default class ConfigInjectCmd extends Command {
public static usage = 'config inject <file>';
public static flags: flags.Input<FlagsDef> = {
...cf.deviceTypeIgnored,
drive: cf.driveOrImg,
help: cf.help,
};

View File

@ -47,7 +47,6 @@ export default class ConfigReadCmd extends Command {
public static usage = 'config read';
public static flags: flags.Input<FlagsDef> = {
...cf.deviceTypeIgnored,
drive: cf.driveOrImg,
help: cf.help,
json: cf.json,

View File

@ -50,7 +50,6 @@ export default class ConfigReconfigureCmd extends Command {
public static usage = 'config reconfigure';
public static flags: flags.Input<FlagsDef> = {
...cf.deviceTypeIgnored,
drive: cf.driveOrImg,
advanced: flags.boolean({
description: 'show advanced commands',

View File

@ -64,7 +64,6 @@ export default class ConfigWriteCmd extends Command {
public static usage = 'config write <key> <value>';
public static flags: flags.Input<FlagsDef> = {
...cf.deviceTypeIgnored,
drive: cf.driveOrImg,
help: cf.help,
};

View File

@ -16,7 +16,7 @@
*/
import { flags } from '@oclif/command';
import type { ImageDescriptor } from 'resin-compose-parse';
import type { ImageDescriptor } from '@balena/compose/dist/parse';
import Command from '../command';
import { ExpectedError } from '../errors';
@ -60,6 +60,7 @@ interface FlagsDef extends ComposeCliFlags, DockerCliFlags {
nologupload: boolean;
'release-tag'?: string[];
draft: boolean;
note?: string;
help: void;
}
@ -101,6 +102,7 @@ ${dockerignoreHelp}
public static examples = [
'$ balena deploy myFleet',
'$ balena deploy myorg/myfleet --build --source myBuildDir/',
'$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"',
'$ balena deploy myorg/myfleet myRepo/myImage',
'$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"',
];
@ -114,7 +116,7 @@ ${dockerignoreHelp}
];
public static usage = 'deploy <fleet> [image]';
// TODO: docker-compose naming
public static flags: flags.Input<FlagsDef> = {
source: flags.string({
description:
@ -145,6 +147,7 @@ ${dockerignoreHelp}
as final by default unless this option is given.`,
default: false,
}),
note: flags.string({ description: 'The notes for this release' }),
...composeCliFlags,
...dockerCliFlags,
// NOTE: Not supporting -h for help, because of clash with -h in DockerCliFlags
@ -231,6 +234,9 @@ ${dockerignoreHelp}
releaseTagKeys,
releaseTagValues,
);
if (options.note) {
await sdk.models.release.note(release.id, options.note);
}
}
async deployProject(

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { ExpectedError } from '../../errors';
interface FlagsDef {
@ -43,7 +42,6 @@ export default class DeviceIdentifyCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to identify',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];

View File

@ -21,7 +21,6 @@ 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 type { Application, Release } from 'balena-sdk';
@ -44,6 +43,7 @@ interface ExtendedDevice extends DeviceWithDeviceType {
interface FlagsDef {
help: void;
view: boolean;
}
interface ArgsDef {
@ -56,13 +56,15 @@ export default class DeviceCmd extends Command {
Show information about a single device.
`;
public static examples = ['$ balena device 7cf02a6'];
public static examples = [
'$ balena device 7cf02a6',
'$ balena device 7cf02a6 --view',
];
public static args: Array<IArg<any>> = [
{
name: 'uuid',
description: 'the device uuid',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];
@ -71,13 +73,19 @@ export default class DeviceCmd extends Command {
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
view: flags.boolean({
default: false,
description: 'open device dashboard page',
}),
};
public static authenticated = true;
public static primary = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(DeviceCmd);
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
DeviceCmd,
);
const balena = getBalenaSdk();
@ -108,6 +116,14 @@ export default class DeviceCmd extends Command {
],
...expandForAppName,
})) as ExtendedDevice;
if (options.view) {
const open = await import('open');
const dashboardUrl = balena.models.device.getDashboardUrl(device.uuid);
await open(dashboardUrl, { wait: false });
return;
}
device.status = device.overall_status;
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid);

View File

@ -31,6 +31,7 @@ interface FlagsDef {
config?: string;
help: void;
'provisioning-key-name'?: string;
'provisioning-key-expiry-date'?: string;
}
export default class DeviceInitCmd extends Command {
@ -97,6 +98,10 @@ export default class DeviceInitCmd extends Command {
'provisioning-key-name': flags.string({
description: 'custom key name assigned to generated provisioning api key',
}),
'provisioning-key-expiry-date': flags.string({
description:
'expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)',
}),
help: cf.help,
};
@ -123,7 +128,7 @@ export default class DeviceInitCmd extends Command {
options.fleet ||
(
await (await import('../../utils/patterns')).selectApplication()
).id,
).slug,
{
$expand: {
is_for__device_type: {
@ -185,6 +190,14 @@ export default class DeviceInitCmd extends Command {
options['provisioning-key-name'],
);
}
if (options['provisioning-key-expiry-date']) {
configureCommand.push(
'--provisioning-key-expiry-date',
options['provisioning-key-expiry-date'],
);
}
await runCommand(configureCommand);
}

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
enable: boolean;
@ -52,7 +51,6 @@ export default class DeviceLocalModeCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to manage',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];

View File

@ -88,17 +88,14 @@ export default class DeviceMoveCmd extends Command {
const balena = getBalenaSdk();
const { tryAsInteger } = await import('../../utils/validation');
const { expandForAppNameAndCpuArch } = await import('../../utils/helpers');
// Parse ids string into array of correct types
const deviceIds: Array<string | number> = params.uuid
.split(',')
.map((id) => tryAsInteger(id));
// Split uuids string into array of uuids
const deviceUuids = params.uuid.split(',');
// Get devices
const devices = await Promise.all(
deviceIds.map(
deviceUuids.map(
(uuid) =>
balena.models.device.get(
uuid,
@ -115,7 +112,7 @@ export default class DeviceMoveCmd extends Command {
: 'N/a';
}
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
// Disambiguate application
const { getApplication } = await import('../../utils/sdk');
// Get destination application
@ -124,7 +121,7 @@ export default class DeviceMoveCmd extends Command {
: await this.interactivelySelectApplication(balena, devices);
// Move each device
for (const uuid of deviceIds) {
for (const uuid of deviceUuids) {
try {
await balena.models.device.move(uuid, application.id);
console.info(`Device ${uuid} was moved to fleet ${application.slug}`);

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import type { Device } from 'balena-sdk';
import { ExpectedError } from '../../errors';
@ -54,7 +53,6 @@ export default class DeviceOsUpdateCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to update',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];

103
lib/commands/device/pin.ts Normal file
View File

@ -0,0 +1,103 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getExpandedProp } from '../../utils/pine';
interface FlagsDef {
help: void;
}
interface ArgsDef {
uuid: string;
releaseToPinTo?: string;
}
export default class DevicePinCmd extends Command {
public static description = stripIndent`
Pin a device to a release.
Pin a device to a release.
Note, if the commit is omitted, the currently pinned release will be printed, with instructions for how to see a list of releases
`;
public static examples = [
'$ balena device pin 7cf02a6',
'$ balena device pin 7cf02a6 91165e5',
];
public static args: Array<IArg<any>> = [
{
name: 'uuid',
description: 'the uuid of the device to pin to a release',
required: true,
},
{
name: 'releaseToPinTo',
description: 'the commit of the release for the device to get pinned to',
},
];
public static usage = 'device pin <uuid> [releaseToPinTo]';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(DevicePinCmd);
const balena = getBalenaSdk();
const device = await balena.models.device.get(params.uuid, {
$expand: {
should_be_running__release: {
$select: 'commit',
},
belongs_to__application: {
$select: 'slug',
},
},
});
const pinnedRelease = getExpandedProp(
device.should_be_running__release,
'commit',
);
const appSlug = getExpandedProp(device.belongs_to__application, 'slug');
const releaseToPinTo = params.releaseToPinTo;
if (!releaseToPinTo) {
console.log(
`${
pinnedRelease
? `This device is currently pinned to ${pinnedRelease}.`
: 'This device is not currently pinned to any release.'
} \n\nTo see a list of all releases this device can be pinned to, run \`balena releases ${appSlug}\`.`,
);
} else {
await balena.models.device.pinToRelease(params.uuid, releaseToPinTo);
}
}
}

View File

@ -21,7 +21,6 @@ import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
enable: boolean;
@ -32,8 +31,6 @@ interface FlagsDef {
interface ArgsDef {
uuid: string;
// Optional hidden arg to support old command format
legacyUuid?: string;
}
export default class DevicePublicUrlCmd extends Command {
@ -43,9 +40,6 @@ export default class DevicePublicUrlCmd extends Command {
This command will output the current public URL for the
specified device. It can also enable or disable the URL,
or output the enabled status, using the respective options.
The old command style 'balena device public-url enable <uuid>'
is deprecated, but still supported.
`;
public static examples = [
@ -59,15 +53,8 @@ export default class DevicePublicUrlCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to manage',
parse: (dev) => tryAsInteger(dev),
required: true,
},
{
// Optional hidden arg to support old command format
name: 'legacyUuid',
parse: (dev) => tryAsInteger(dev),
hidden: true,
},
];
public static usage = 'device public-url <uuid>';
@ -95,25 +82,6 @@ export default class DevicePublicUrlCmd extends Command {
DevicePublicUrlCmd,
);
// Legacy command format support.
// Previously this command used the following format
// (changed due to oclif technicalities):
// `balena device public-url enable|disable|status <uuid>`
if (params.legacyUuid) {
const action = params.uuid;
if (!['enable', 'disable', 'status'].includes(action)) {
throw new ExpectedError(
`Unexpected arguments: ${params.uuid} ${params.legacyUuid}`,
);
}
options.enable = action === 'enable';
options.disable = action === 'disable';
options.status = action === 'status';
params.uuid = params.legacyUuid;
delete params.legacyUuid;
}
const balena = getBalenaSdk();
if (options.enable) {

View File

@ -63,17 +63,14 @@ export default class DevicePurgeCmd extends Command {
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(DevicePurgeCmd);
const { tryAsInteger } = await import('../../utils/validation');
const balena = getBalenaSdk();
const ux = getCliUx();
const deviceIds = params.uuid.split(',').map((id) => {
return tryAsInteger(id);
});
const deviceUuids = params.uuid.split(',');
for (const deviceId of deviceIds) {
ux.action.start(`Purging data from device ${deviceId}`);
await balena.models.device.purge(deviceId);
for (const uuid of deviceUuids) {
ux.action.start(`Purging data from device ${uuid}`);
await balena.models.device.purge(uuid);
ux.action.stop();
}
}

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
force: boolean;
@ -43,7 +42,6 @@ export default class DeviceRebootCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to reboot',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
help: void;
@ -48,7 +47,6 @@ export default class DeviceRenameCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to rename',
parse: (dev) => tryAsInteger(dev),
required: true,
},
{

View File

@ -82,24 +82,21 @@ export default class DeviceRestartCmd extends Command {
DeviceRestartCmd,
);
const { tryAsInteger } = await import('../../utils/validation');
const balena = getBalenaSdk();
const ux = getCliUx();
const deviceIds = params.uuid.split(',').map((id) => {
return tryAsInteger(id);
});
const deviceUuids = params.uuid.split(',');
const serviceNames = options.service?.split(',');
// Iterate sequentially through deviceIds.
// Iterate sequentially through deviceUuids.
// We may later want to add a batching feature,
// so that n devices are processed in parallel
for (const deviceId of deviceIds) {
ux.action.start(`Restarting services on device ${deviceId}`);
for (const uuid of deviceUuids) {
ux.action.start(`Restarting services on device ${uuid}`);
if (serviceNames) {
await this.restartServices(balena, deviceId, serviceNames);
await this.restartServices(balena, uuid, serviceNames);
} else {
await this.restartAllServices(balena, deviceId);
await this.restartAllServices(balena, uuid);
}
ux.action.stop();
}
@ -107,7 +104,7 @@ export default class DeviceRestartCmd extends Command {
async restartServices(
balena: BalenaSDK,
deviceId: number | string,
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError, instanceOf } = await import('../../errors');
@ -116,7 +113,7 @@ export default class DeviceRestartCmd extends Command {
// Get device
let device: DeviceWithServiceDetails<CurrentServiceWithCommit>;
try {
device = await balena.models.device.getWithServiceDetails(deviceId, {
device = await balena.models.device.getWithServiceDetails(deviceUuid, {
$expand: {
is_running__release: { $select: 'commit' },
},
@ -124,7 +121,7 @@ export default class DeviceRestartCmd extends Command {
} catch (e) {
const { BalenaDeviceNotFound } = await import('balena-errors');
if (instanceOf(e, BalenaDeviceNotFound)) {
throw new ExpectedError(`Device ${deviceId} not found.`);
throw new ExpectedError(`Device ${deviceUuid} not found.`);
} else {
throw e;
}
@ -136,7 +133,7 @@ export default class DeviceRestartCmd extends Command {
serviceNames.forEach((service) => {
if (!device.current_services[service]) {
throw new ExpectedError(
`Service ${service} not found on device ${deviceId}.`,
`Service ${service} not found on device ${deviceUuid}.`,
);
}
});
@ -155,7 +152,7 @@ export default class DeviceRestartCmd extends Command {
if (serviceContainer) {
restartPromises.push(
balena.models.device.restartService(
deviceId,
deviceUuid,
serviceContainer.image_id,
),
);
@ -166,32 +163,32 @@ export default class DeviceRestartCmd extends Command {
await Promise.all(restartPromises);
} catch (e) {
if (e.message.toLowerCase().includes('no online device')) {
throw new ExpectedError(`Device ${deviceId} is not online.`);
throw new ExpectedError(`Device ${deviceUuid} is not online.`);
} else {
throw e;
}
}
}
async restartAllServices(balena: BalenaSDK, deviceId: number | string) {
async restartAllServices(balena: BalenaSDK, deviceUuid: string) {
// Note: device.restartApplication throws `BalenaDeviceNotFound: Device not found` if device not online.
// Need to use device.get first to distinguish between non-existant and offline devices.
// Remove this workaround when SDK issue resolved: https://github.com/balena-io/balena-sdk/issues/649
const { instanceOf, ExpectedError } = await import('../../errors');
try {
const device = await balena.models.device.get(deviceId);
const device = await balena.models.device.get(deviceUuid);
if (!device.is_online) {
throw new ExpectedError(`Device ${deviceId} is not online.`);
throw new ExpectedError(`Device ${deviceUuid} is not online.`);
}
} catch (e) {
const { BalenaDeviceNotFound } = await import('balena-errors');
if (instanceOf(e, BalenaDeviceNotFound)) {
throw new ExpectedError(`Device ${deviceId} not found.`);
throw new ExpectedError(`Device ${deviceUuid} not found.`);
} else {
throw e;
}
}
await balena.models.device.restartApplication(deviceId);
await balena.models.device.restartApplication(deviceUuid);
}
}

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
yes: boolean;
@ -84,7 +83,7 @@ export default class DeviceRmCmd extends Command {
// Remove
for (const uuid of uuids) {
try {
await balena.models.device.remove(tryAsInteger(uuid));
await balena.models.device.remove(uuid);
} catch (err) {
console.info(`${err.message}, uuid: ${uuid}`);
process.exitCode = 1;

View File

@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
import { ExpectedError } from '../../errors';
interface FlagsDef {
@ -44,7 +43,6 @@ export default class DeviceShutdownCmd extends Command {
{
name: 'uuid',
description: 'the uuid of the device to shutdown',
parse: (dev) => tryAsInteger(dev),
required: true,
},
];

View File

@ -0,0 +1,63 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
interface FlagsDef {
help: void;
}
interface ArgsDef {
uuid: string;
}
export default class DeviceTrackFleetCmd extends Command {
public static description = stripIndent`
Make a device track the fleet's pinned release.
Make a device track the fleet's pinned release.
`;
public static examples = ['$ balena device track-fleet 7cf02a6'];
public static args: Array<IArg<any>> = [
{
name: 'uuid',
description: "the uuid of the device to make track the fleet's release",
required: true,
},
];
public static usage = 'device track-fleet <uuid>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(DeviceTrackFleetCmd);
const balena = getBalenaSdk();
await balena.models.device.trackApplicationRelease(params.uuid);
}
}

View File

@ -15,19 +15,20 @@
* limitations under the License.
*/
import type { flags } from '@oclif/command';
import type { flags as flagsType } from '@oclif/command';
import { flags } from '@oclif/command';
import type { Release } from 'balena-sdk';
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 { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { isV14 } from '../../utils/version';
import type { DataOutputOptions } from '../../framework';
interface FlagsDef extends DataOutputOptions {
help: void;
view: boolean;
}
interface ArgsDef {
@ -45,15 +46,20 @@ export default class FleetCmd extends Command {
public static examples = [
'$ balena fleet MyFleet',
'$ balena fleet myorg/myfleet',
'$ balena fleet myorg/myfleet --view',
];
public static args = [ca.fleetRequired];
public static usage = 'fleet <fleet>';
public static flags: flags.Input<FlagsDef> = {
public static flags: flagsType.Input<FlagsDef> = {
help: cf.help,
...(isV14() ? cf.dataOutputFlags : {}),
view: flags.boolean({
default: false,
description: 'open fleet dashboard page',
}),
...cf.dataOutputFlags,
};
public static authenticated = true;
@ -66,7 +72,9 @@ export default class FleetCmd extends Command {
const { getApplication } = await import('../../utils/sdk');
const application = (await getApplication(getBalenaSdk(), params.fleet, {
const balena = getBalenaSdk();
const application = (await getApplication(balena, params.fleet, {
$expand: {
is_for__device_type: { $select: 'slug' },
should_be_running__release: { $select: 'commit' },
@ -78,26 +86,22 @@ export default class FleetCmd extends Command {
commit?: string;
};
if (options.view) {
const open = await import('open');
const dashboardUrl = balena.models.application.getDashboardUrl(
application.id,
);
await open(dashboardUrl, { wait: false });
return;
}
application.device_type = application.is_for__device_type[0].slug;
application.commit = application.should_be_running__release[0]?.commit;
if (isV14()) {
await this.outputData(
application,
['app_name', 'id', 'device_type', 'slug', 'commit'],
options,
);
} else {
// Emulate table.vertical title output, but avoid uppercasing and inserting spaces
console.log(`== ${application.slug}`);
console.log(
getVisuals().table.vertical(application, [
'id',
'device_type',
'slug',
'commit',
]),
);
}
await this.outputData(
application,
['app_name', 'id', 'device_type', 'slug', 'commit'],
options,
);
}
}

100
lib/commands/fleet/pin.ts Normal file
View File

@ -0,0 +1,100 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getExpandedProp } from '../../utils/pine';
interface FlagsDef {
help: void;
}
interface ArgsDef {
slug: string;
releaseToPinTo?: string;
}
export default class FleetPinCmd extends Command {
public static description = stripIndent`
Pin a fleet to a release.
Pin a fleet to a release.
Note, if the commit is omitted, the currently pinned release will be printed, with instructions for how to see a list of releases
`;
public static examples = [
'$ balena fleet pin myfleet',
'$ balena fleet pin myorg/myfleet 91165e5',
];
public static args: Array<IArg<any>> = [
{
name: 'slug',
description: 'the slug of the fleet to pin to a release',
required: true,
},
{
name: 'releaseToPinTo',
description: 'the commit of the release for the fleet to get pinned to',
},
];
public static usage = 'fleet pin <slug> [releaseToPinTo]';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(FleetPinCmd);
const balena = getBalenaSdk();
const fleet = await balena.models.application.get(params.slug, {
$expand: {
should_be_running__release: {
$select: 'commit',
},
},
});
const pinnedRelease = getExpandedProp(
fleet.should_be_running__release,
'commit',
);
const releaseToPinTo = params.releaseToPinTo;
const slug = params.slug;
if (!releaseToPinTo) {
console.log(
`${
pinnedRelease
? `This fleet is currently pinned to ${pinnedRelease}.`
: 'This fleet is not currently pinned to any release.'
} \n\nTo see a list of all releases this fleet can be pinned to, run \`balena releases ${slug}\`.`,
);
} else {
await balena.models.application.pinToRelease(slug, releaseToPinTo);
}
}
}

View File

@ -62,9 +62,9 @@ export default class FleetRestartCmd extends Command {
const balena = getBalenaSdk();
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
// Disambiguate application
const application = await getApplication(balena, params.fleet);
await balena.models.application.restart(application.id);
await balena.models.application.restart(application.slug);
}
}

View File

@ -79,6 +79,6 @@ export default class FleetRmCmd extends Command {
const application = await getApplication(balena, params.fleet);
// Remove
await balena.models.application.remove(application.id);
await balena.models.application.remove(application.slug);
}
}

View File

@ -0,0 +1,66 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
interface FlagsDef {
help: void;
}
interface ArgsDef {
slug: string;
}
export default class FleetTrackLatestCmd extends Command {
public static description = stripIndent`
Make this fleet track the latest release.
Make this fleet track the latest release.
`;
public static examples = [
'$ balena fleet track-latest myorg/myfleet',
'$ balena fleet track-latest myfleet',
];
public static args: Array<IArg<any>> = [
{
name: 'slug',
description: 'the slug of the fleet to make track the latest release',
required: true,
},
];
public static usage = 'fleet track-latest <slug>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(FleetTrackLatestCmd);
const balena = getBalenaSdk();
await balena.models.application.trackLatestRelease(params.slug);
}
}

View File

@ -19,8 +19,7 @@ import { flags } from '@oclif/command';
import Command from '../command';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import { isV14 } from '../utils/version';
import { getBalenaSdk, stripIndent } from '../utils/lazy';
import type { DataSetOutputOptions } from '../framework';
interface ExtendedApplication extends ApplicationWithDeviceType {
@ -49,7 +48,7 @@ export default class FleetsCmd extends Command {
public static usage = 'fleets';
public static flags: flags.Input<FlagsDef> = {
...(isV14() ? cf.dataSetOutputFlags : {}),
...cf.dataSetOutputFlags,
help: cf.help,
};
@ -79,30 +78,17 @@ export default class FleetsCmd extends Command {
application.device_type = application.is_for__device_type[0].slug;
});
if (isV14()) {
await this.outputData(
applications,
[
'id',
'app_name',
'slug',
'device_type',
'device_count',
'online_devices',
],
options,
);
} else {
console.log(
getVisuals().table.horizontal(applications, [
'id',
'app_name => NAME',
'slug',
'device_type',
'online_devices',
'device_count',
]),
);
}
await this.outputData(
applications,
[
'id',
'app_name',
'slug',
'device_type',
'device_count',
'online_devices',
],
options,
);
}
}

View File

@ -43,6 +43,7 @@ interface FlagsDef {
'system-connection': string[];
'initial-device-name'?: string;
'provisioning-key-name'?: string;
'provisioning-key-expiry-date'?: string;
}
interface ArgsDef {
@ -58,6 +59,7 @@ interface Answers {
wifiSsid?: string;
wifiKey?: string;
provisioningKeyName?: string;
provisioningKeyExpiryDate?: string;
}
export default class OsConfigureCmd extends Command {
@ -121,7 +123,7 @@ export default class OsConfigureCmd extends Command {
config: flags.string({
description:
'path to a pre-generated config.json file to be injected in the OS image',
exclusive: ['provisioning-key-name'],
exclusive: ['provisioning-key-name', 'provisioning-key-expiry-date'],
}),
'config-app-update-poll-interval': flags.integer({
description:
@ -138,7 +140,14 @@ export default class OsConfigureCmd extends Command {
description: 'WiFi SSID (network name) (non-interactive configuration)',
}),
dev: cf.dev,
device: { ...cf.device, exclusive: ['fleet', 'provisioning-key-name'] },
device: {
...cf.device,
exclusive: [
'fleet',
'provisioning-key-name',
'provisioning-key-expiry-date',
],
},
'device-type': flags.string({
description:
'device type slug (e.g. "raspberrypi3") to override the fleet device type',
@ -161,6 +170,11 @@ export default class OsConfigureCmd extends Command {
description: 'custom key name assigned to generated provisioning api key',
exclusive: ['config', 'device'],
}),
'provisioning-key-expiry-date': flags.string({
description:
'expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)',
exclusive: ['config', 'device'],
}),
help: cf.help,
};
@ -235,6 +249,7 @@ export default class OsConfigureCmd extends Command {
answers.version = osVersion;
answers.developmentMode = options.dev;
answers.provisioningKeyName = options['provisioning-key-name'];
answers.provisioningKeyExpiryDate = options['provisioning-key-expiry-date'];
if (_.isEmpty(configJson)) {
if (device) {

View File

@ -288,7 +288,7 @@ Can be repeated to add multiple certificates.\
preloader.on('error', reject);
resolve(
this.prepareAndPreload(preloader, balena, {
appId: fleetSlug,
slug: fleetSlug,
commit,
pinDevice,
}),
@ -491,10 +491,10 @@ Would you like to disable automatic updates for this fleet now?\
});
}
async getAppWithReleases(balenaSdk: BalenaSDK, appId: string) {
async getAppWithReleases(balenaSdk: BalenaSDK, slug: string) {
const { getApplication } = await import('../utils/sdk');
return (await getApplication(balenaSdk, appId, {
return (await getApplication(balenaSdk, slug, {
$expand: this.applicationExpandOptions,
})) as Application & { should_be_running__release: [Release?] };
}
@ -503,15 +503,15 @@ Would you like to disable automatic updates for this fleet now?\
preloader: Preloader,
balenaSdk: BalenaSDK,
options: {
appId?: string;
slug?: string;
commit?: string;
pinDevice: boolean;
},
) {
await preloader.prepare();
const application = options.appId
? await this.getAppWithReleases(balenaSdk, options.appId)
const application = options.slug
? await this.getAppWithReleases(balenaSdk, options.slug)
: await this.selectApplication(preloader.config.deviceType);
let commit: string; // commit hash or the strings 'latest' or 'current'
@ -523,7 +523,7 @@ Would you like to disable automatic updates for this fleet now?\
if (this.isCurrentCommit(options.commit)) {
if (!appCommit) {
throw new Error(
`Unexpected empty commit hash for fleet ID "${application.id}"`,
`Unexpected empty commit hash for fleet slug "${application.slug}"`,
);
}
// handle `--commit current` (and its `--commit latest` synonym)

View File

@ -22,7 +22,7 @@ import { getBalenaSdk, stripIndent } from '../utils/lazy';
import { dockerignoreHelp, registrySecretsHelp } from '../utils/messages';
import type { BalenaSDK } from 'balena-sdk';
import { ExpectedError, instanceOf } from '../errors';
import { RegistrySecrets } from 'resin-multibuild';
import { RegistrySecrets } from '@balena/compose/dist/multibuild';
import { lowercaseIfSlug } from '../utils/normalization';
import {
applyReleaseTagKeysAndValues,
@ -55,6 +55,7 @@ interface FlagsDef {
'multi-dockerignore': boolean;
'release-tag'?: string[];
draft: boolean;
note?: string;
help: void;
}
@ -97,6 +98,7 @@ export default class PushCmd extends Command {
'$ balena push myFleet',
'$ balena push myFleet --source <source directory>',
'$ balena push myFleet -s <source directory>',
'$ balena push myFleet --source <source directory> --note "this is the note for this release"',
'$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"',
'$ balena push myorg/myfleet',
'',
@ -138,7 +140,6 @@ export default class PushCmd extends Command {
char: 'e',
default: false,
}),
// TODO: docker-compose naming
dockerfile: flags.string({
description:
'Alternative Dockerfile name/path, relative to the source folder',
@ -242,6 +243,7 @@ export default class PushCmd extends Command {
as final by default unless this option is given.`,
default: false,
}),
note: flags.string({ description: 'The notes for this release' }),
help: cf.help,
};
@ -355,6 +357,9 @@ export default class PushCmd extends Command {
releaseTagKeys,
releaseTagValues,
);
if (options.note) {
await sdk.models.release.note(releaseId, options.note);
}
} else if (releaseTagKeys.length > 0) {
throw new Error(stripIndent`
A release ID could not be parsed out of the builder's output.

View File

@ -0,0 +1,83 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
help: void;
}
interface ArgsDef {
commitOrId: string | number;
}
export default class ReleaseInvalidateCmd extends Command {
public static description = stripIndent`
Invalidate a release.
Invalidate a release.
Invalid releases are not automatically deployed to devices tracking the latest
release. For an invalid release to be deployed to a device, the device should be
explicity pinned to that release.
`;
public static examples = [
'$ balena release invalidate a777f7345fe3d655c1c981aa642e5555',
'$ balena release invalidate 1234567',
];
public static usage = 'release invalidate <commitOrId>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static args = [
{
name: 'commitOrId',
description: 'the commit or ID of the release to invalidate',
required: true,
parse: (commitOrId: string) => tryAsInteger(commitOrId),
},
];
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(
ReleaseInvalidateCmd,
);
const balena = getBalenaSdk();
const release = await balena.models.release.get(params.commitOrId, {
$select: ['id', 'is_invalidated'],
});
if (release.is_invalidated) {
console.log(`Release ${params.commitOrId} is already invalidated!`);
return;
}
await balena.models.release.setIsInvalidated(release.id, true);
console.log(`Release ${params.commitOrId} invalidated`);
}
}

View File

@ -0,0 +1,80 @@
/**
* @license
* 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 { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation';
interface FlagsDef {
help: void;
}
interface ArgsDef {
commitOrId: string | number;
}
export default class ReleaseValidateCmd extends Command {
public static description = stripIndent`
Validate a release.
Validate a release.
Valid releases are automatically deployed to devices tracking the latest
release if they are finalized.
`;
public static examples = [
'$ balena release validate a777f7345fe3d655c1c981aa642e5555',
'$ balena release validate 1234567',
];
public static usage = 'release validate <commitOrId>';
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
};
public static args = [
{
name: 'commitOrId',
description: 'the commit or ID of the release to validate',
required: true,
parse: (commitOrId: string) => tryAsInteger(commitOrId),
},
];
public static authenticated = true;
public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(ReleaseValidateCmd);
const balena = getBalenaSdk();
const release = await balena.models.release.get(params.commitOrId, {
$select: ['id', 'is_invalidated'],
});
if (!release.is_invalidated) {
console.log(`Release ${params.commitOrId} is already validated!`);
return;
}
await balena.models.release.setIsInvalidated(release.id, false);
console.log(`Release ${params.commitOrId} validated`);
}
}

View File

@ -76,8 +76,7 @@ export default class SshCmd extends Command {
public static args = [
{
name: 'fleetOrDevice',
description:
'fleet name/slug/id, device uuid, or address of local device',
description: 'fleet name/slug, device uuid, or address of local device',
required: true,
},
{

View File

@ -90,8 +90,6 @@ export default class TagRmCmd extends Command {
throw new ExpectedError(TagRmCmd.missingResourceMessage);
}
const { tryAsInteger } = await import('../../utils/validation');
if (options.fleet) {
const { getFleetSlug } = await import('../../utils/sdk');
return balena.models.application.tags.remove(
@ -100,10 +98,7 @@ export default class TagRmCmd extends Command {
);
}
if (options.device) {
return balena.models.device.tags.remove(
tryAsInteger(options.device),
params.tagKey,
);
return balena.models.device.tags.remove(options.device, params.tagKey);
}
if (options.release) {
const { disambiguateReleaseParam } = await import(

View File

@ -105,8 +105,6 @@ export default class TagSetCmd extends Command {
params.value ??= '';
const { tryAsInteger } = await import('../../utils/validation');
if (options.fleet) {
const { getFleetSlug } = await import('../../utils/sdk');
return balena.models.application.tags.set(
@ -117,7 +115,7 @@ export default class TagSetCmd extends Command {
}
if (options.device) {
return balena.models.device.tags.set(
tryAsInteger(options.device),
options.device,
params.tagKey,
params.value,
);

View File

@ -76,8 +76,6 @@ export default class TagsCmd extends Command {
throw new ExpectedError(this.missingResourceMessage);
}
const { tryAsInteger } = await import('../utils/validation');
let tags;
if (options.fleet) {
@ -87,9 +85,7 @@ export default class TagsCmd extends Command {
);
}
if (options.device) {
tags = await balena.models.device.tags.getAllByDevice(
tryAsInteger(options.device),
);
tags = await balena.models.device.tags.getAllByDevice(options.device);
}
if (options.release) {
const { disambiguateReleaseParam } = await import(

View File

@ -82,7 +82,7 @@ export default class TunnelCmd extends Command {
public static args = [
{
name: 'deviceOrFleet',
description: 'device UUID or fleet name/slug/ID',
description: 'device UUID or fleet name/slug',
required: true,
parse: lowercaseIfSlug,
},

View File

@ -24,7 +24,7 @@ import { stripIndent } from './utils/lazy';
* @param commandSignature A string like, for example:
* "push <fleetOrDevice>"
* That's literally so: "fleetOrDevice" is NOT replaced with the actual
* fleet ID or device ID. The purpose is to find out the most / least
* fleet slug or device uuid. The purpose is to find out the most / least
* used command verbs, so we can focus our development effort where it is most
* beneficial to end users.
*

View File

@ -18,7 +18,7 @@ import { lowercaseIfSlug } from './normalization';
export const fleetRequired = {
name: 'fleet',
description: 'fleet name, slug (preferred), or numeric ID (deprecated)',
description: 'fleet name or slug (preferred)',
required: true,
parse: lowercaseIfSlug,
};

View File

@ -19,13 +19,12 @@ import { flags } from '@oclif/command';
import { stripIndent } from './lazy';
import { lowercaseIfSlug } from './normalization';
import { isV14 } from './version';
import type { IBooleanFlag } from '@oclif/parser/lib/flags';
import type { DataOutputOptions, DataSetOutputOptions } from '../framework';
export const fleet = flags.string({
char: 'f',
description: 'fleet name, slug (preferred), or numeric ID (deprecated)',
description: 'fleet name or slug (preferred)',
parse: lowercaseIfSlug,
});
@ -97,19 +96,6 @@ export const deviceType = flags.string({
required: true,
});
export const deviceTypeIgnored = {
...(isV14()
? {}
: {
type: flags.string({
description: 'ignored - no longer required',
char: 't',
required: false,
hidden: true,
}),
}),
};
export const json: IBooleanFlag<boolean> = flags.boolean({
char: 'j',
description: 'produce JSON output instead of tabular output',

View File

@ -15,8 +15,11 @@
* limitations under the License.
*/
import type { ImageModel, ReleaseModel } from 'balena-release/build/models';
import type { Composition, ImageDescriptor } from 'resin-compose-parse';
import type {
ImageModel,
ReleaseModel,
} from '@balena/compose/dist/release/models';
import type { Composition, ImageDescriptor } from '@balena/compose/dist/parse';
import type { Pack } from 'tar-stream';
interface Image {
@ -39,7 +42,7 @@ export interface BuiltImage {
export interface TaggedImage {
localImage: import('dockerode').Image;
serviceImage: import('balena-release/build/models').ImageModel;
serviceImage: import('@balena/compose/dist/release/models').ImageModel;
serviceName: string;
logs: string;
props: BuiltImage.props;
@ -61,8 +64,6 @@ export interface ComposeOpts {
export interface ComposeCliFlags {
emulated: boolean;
dockerfile?: string;
dockercompose?: string;
logs: boolean;
nologs: boolean;
'multi-dockerignore': boolean;
'noparent-check': boolean;
@ -79,7 +80,9 @@ export interface ComposeProject {
}
export interface Release {
client: ReturnType<typeof import('balena-release').createClient>;
client: ReturnType<
typeof import('@balena/compose/dist/release').createClient
>;
release: Pick<
ReleaseModel,
| 'id'

View File

@ -19,7 +19,7 @@ import type { Renderer } from './compose_ts';
import type * as SDK from 'balena-sdk';
import type Dockerode = require('dockerode');
import * as path from 'path';
import type { Composition, ImageDescriptor } from 'resin-compose-parse';
import type { Composition, ImageDescriptor } from '@balena/compose/dist/parse';
import type {
BuiltImage,
ComposeOpts,
@ -64,7 +64,7 @@ export function createProject(
): ComposeProject {
const yml = require('js-yaml') as typeof import('js-yaml');
const compose =
require('resin-compose-parse') as typeof import('resin-compose-parse');
require('@balena/compose/dist/parse') as typeof import('@balena/compose/dist/parse');
// both methods below may throw.
const rawComposition = yml.load(composeStr);
@ -107,7 +107,7 @@ export const createRelease = async function (
const _ = require('lodash') as typeof import('lodash');
const crypto = require('crypto') as typeof import('crypto');
const releaseMod =
require('balena-release') as typeof import('balena-release');
require('@balena/compose/dist/release') as typeof import('@balena/compose/dist/release');
const client = releaseMod.createClient({ apiEndpoint, auth });
@ -214,7 +214,7 @@ export const getPreviousRepos = (
image: [SDK.Image];
}>;
const { getRegistryAndName } =
require('resin-multibuild') as typeof import('resin-multibuild');
require('@balena/compose/dist/multibuild') as typeof import('@balena/compose/dist/multibuild');
return Promise.all(
images.map(function (d) {
const imageName = d.image[0].is_stored_at__image_location || '';

View File

@ -16,7 +16,7 @@
*/
import { flags } from '@oclif/command';
import { BalenaSDK } from 'balena-sdk';
import type { TransposeOptions } from 'docker-qemu-transpose';
import type { TransposeOptions } from '@balena/compose/dist/emulate';
import type * as Dockerode from 'dockerode';
import { promises as fs } from 'fs';
import jsyaml = require('js-yaml');
@ -26,8 +26,8 @@ import type {
BuildConfig,
Composition,
ImageDescriptor,
} from 'resin-compose-parse';
import type * as MultiBuild from 'resin-multibuild';
} from '@balena/compose/dist/parse';
import type * as MultiBuild from '@balena/compose/dist/multibuild';
import * as semver from 'semver';
import type { Duplex, Readable } from 'stream';
import type { Pack } from 'tar-stream';
@ -118,7 +118,7 @@ export async function loadProject(
image?: string,
imageTag?: string,
): Promise<ComposeProject> {
const compose = await import('resin-compose-parse');
const compose = await import('@balena/compose/dist/parse');
const { createProject } = await import('./compose');
let composeName: string;
let composeStr: string;
@ -262,7 +262,7 @@ export async function buildProject(
opts: BuildProjectOpts,
): Promise<BuiltImage[]> {
await checkBuildSecretsRequirements(opts.docker, opts.projectPath);
const compose = await import('resin-compose-parse');
const compose = await import('@balena/compose/dist/parse');
const imageDescriptors = compose.parse(opts.composition);
const renderer = await startRenderer({ imageDescriptors, ...opts });
let buildSummaryByService: Dictionary<string> | undefined;
@ -333,7 +333,7 @@ async function $buildProject(
logger.logDebug('Prepared tasks; building...');
const { BALENA_ENGINE_TMP_PATH } = await import('../config');
const builder = await import('resin-multibuild');
const builder = await import('@balena/compose/dist/multibuild');
const builtImages = await builder.performBuilds(
tasks,
@ -481,8 +481,9 @@ async function qemuTransposeBuildStream({
throw new Error(`No buildStream for task '${task.tag}'`);
}
const transpose = await import('docker-qemu-transpose');
const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
const transpose = await import('@balena/compose/dist/emulate');
const { toPosixPath } = (await import('@balena/compose/dist/multibuild'))
.PathUtils;
const transposeOptions: TransposeOptions = {
hostQemuPath: toPosixPath(binPath),
@ -508,9 +509,9 @@ async function setTaskProgressHooks({
inlineLogs?: boolean;
renderer: Renderer;
task: BuildTaskPlus;
transposeOptions?: import('docker-qemu-transpose').TransposeOptions;
transposeOptions?: import('@balena/compose/dist/emulate').TransposeOptions;
}) {
const transpose = await import('docker-qemu-transpose');
const transpose = await import('@balena/compose/dist/emulate');
// Get the service-specific log stream
const logStream = renderer.streams[task.serviceName];
task.logBuffer = [];
@ -724,16 +725,16 @@ export async function getServiceDirsFromComposition(
*
* The `image` argument may therefore refer to either a `build` or `image` property
* of a service in a docker-compose.yml file, which is a bit confusing but it matches
* the `ImageDescriptor.image` property as defined by `resin-compose-parse`.
* the `ImageDescriptor.image` property as defined by `@balena/compose/parse`.
*
* Note that `resin-compose-parse` "normalizes" the docker-compose.yml file such
* Note that `@balena/compose/parse` "normalizes" the docker-compose.yml file such
* that, if `services.service.build` is a string, it is converted to a BuildConfig
* object with the string value assigned to `services.service.build.context`:
* https://github.com/balena-io-modules/resin-compose-parse/blob/v2.1.3/src/compose.ts#L166-L167
* https://github.com/balena-io-modules/balena-compose/blob/v0.1.0/lib/parse/compose.ts#L166-L167
* This is why this implementation works when `services.service.build` is defined
* as a string in the docker-compose.yml file.
*
* @param image The `ImageDescriptor.image` attribute parsed with `resin-compose-parse`
* @param image The `ImageDescriptor.image` attribute parsed with `@balena/compose/parse`
*/
export function isBuildConfig(
image: string | BuildConfig,
@ -759,7 +760,8 @@ export async function tarDirectory(
}: TarDirectoryOptions,
): Promise<import('stream').Readable> {
const { filterFilesWithDockerignore } = await import('./ignore');
const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
const { toPosixPath } = (await import('@balena/compose/dist/multibuild'))
.PathUtils;
let readFile: (file: string) => Promise<Buffer>;
if (process.platform === 'win32') {
@ -941,7 +943,7 @@ async function parseRegistrySecrets(
throw new ExpectedError('Filename must end with .json, .yml or .yaml');
}
const raw = (await fs.readFile(secretsFilename)).toString();
const multiBuild = await import('resin-multibuild');
const multiBuild = await import('@balena/compose/dist/multibuild');
const registrySecrets =
new multiBuild.RegistrySecretValidator().validateRegistrySecrets(
isYaml ? require('js-yaml').load(raw) : JSON.parse(raw),
@ -970,7 +972,7 @@ export async function makeBuildTasks(
releaseHash: string = 'unavailable',
preprocessHook?: (dockerfile: string) => string,
): Promise<MultiBuild.BuildTask[]> {
const multiBuild = await import('resin-multibuild');
const multiBuild = await import('@balena/compose/dist/multibuild');
const buildTasks = await multiBuild.splitBuildStream(composition, tarStream);
logger.logDebug('Found build tasks:');
@ -1016,7 +1018,7 @@ async function performResolution(
releaseHash: string,
preprocessHook?: (dockerfile: string) => string,
): Promise<MultiBuild.BuildTask[]> {
const multiBuild = await import('resin-multibuild');
const multiBuild = await import('@balena/compose/dist/multibuild');
const resolveListeners: MultiBuild.ResolveListeners = {};
const resolvePromise = new Promise<never>((_resolve, reject) => {
resolveListeners.error = [reject];
@ -1081,7 +1083,7 @@ async function validateSpecifiedDockerfile(
dockerfilePath: string,
): Promise<string> {
const { contains, toNativePath, toPosixPath } = (
await import('resin-multibuild')
await import('@balena/compose/dist/multibuild')
).PathUtils;
const nativeProjectPath = path.normalize(projectPath);
@ -1241,7 +1243,7 @@ async function pushAndUpdateServiceImages(
token: string,
images: TaggedImage[],
afterEach: (
serviceImage: import('balena-release/build/models').ImageModel,
serviceImage: import('@balena/compose/dist/release/models').ImageModel,
props: object,
) => void,
) {
@ -1326,12 +1328,14 @@ async function pushAndUpdateServiceImages(
async function pushServiceImages(
docker: Dockerode,
logger: Logger,
pineClient: ReturnType<typeof import('balena-release').createClient>,
pineClient: ReturnType<
typeof import('@balena/compose/dist/release').createClient
>,
taggedImages: TaggedImage[],
token: string,
skipLogUpload: boolean,
): Promise<void> {
const releaseMod = await import('balena-release');
const releaseMod = await import('@balena/compose/dist/release');
logger.logInfo('Pushing images to registry...');
await pushAndUpdateServiceImages(
docker,
@ -1361,8 +1365,8 @@ export async function deployProject(
skipLogUpload: boolean,
projectPath: string,
isDraft: boolean,
): Promise<import('balena-release/build/models').ReleaseModel> {
const releaseMod = await import('balena-release');
): Promise<import('@balena/compose/dist/release/models').ReleaseModel> {
const releaseMod = await import('@balena/compose/dist/release');
const { createRelease, tagServiceImages } = await import('./compose');
const tty = (await import('./tty'))(process.stdout);
@ -1639,7 +1643,6 @@ function truncateString(str: string, len: number): string {
return str.slice(0, str.lastIndexOf('\n'));
}
// TODO: docker-compose naming
export const composeCliFlags: flags.Input<ComposeCliFlags> = {
emulated: flags.boolean({
description:
@ -1650,14 +1653,6 @@ export const composeCliFlags: flags.Input<ComposeCliFlags> = {
description:
'Alternative Dockerfile name/path, relative to the source folder',
}),
dockercompose: flags.string({
description:
'Alternative docker-compose.yml name in the source root folder',
}),
logs: flags.boolean({
description:
'No-op and deprecated since balena CLI v12.0.0. Build logs are now shown by default.',
}),
nologs: flags.boolean({
description:
'Hide the image build log output (produce less verbose output)',

View File

@ -18,13 +18,13 @@
import * as semver from 'balena-semver';
import * as Docker from 'dockerode';
import * as _ from 'lodash';
import { Composition } from 'resin-compose-parse';
import { Composition } from '@balena/compose/dist/parse';
import {
BuildTask,
getAuthConfigObj,
LocalImage,
RegistrySecrets,
} from 'resin-multibuild';
} from '@balena/compose/dist/multibuild';
import type { Readable } from 'stream';
import { BALENA_ENGINE_TMP_PATH } from '../../config';
@ -321,7 +321,7 @@ async function performBuilds(
opts: DeviceDeployOptions,
buildLogs?: Dictionary<string>,
): Promise<BuildTask[]> {
const multibuild = await import('resin-multibuild');
const multibuild = await import('@balena/compose/dist/multibuild');
const buildTasks = await makeBuildTasks(
composition,
@ -370,7 +370,7 @@ async function performBuilds(
const imagesToRemove: string[] = [];
// Now tag any external images with the correct name that they should be,
// as this won't be done by resin-multibuild
// as this won't be done by @balena/compose/multibuild
await Promise.all(
localImages.map(async (localImage) => {
if (localImage.external) {
@ -414,7 +414,7 @@ export async function rebuildSingleTask(
// this should provide the following callback
containerIdCb?: (id: string) => void,
): Promise<string> {
const multibuild = await import('resin-multibuild');
const multibuild = await import('@balena/compose/dist/multibuild');
// First we run the build task, to get the new image id
let buildLogs = '';
const logHandler = (_s: string, line: string) => {
@ -533,10 +533,17 @@ async function assignDockerBuildOpts(
await Promise.all(
buildTasks.map(async (task: BuildTask) => {
task.dockerOpts = {
cachefrom: images,
labels: {
'io.resin.local.image': '1',
'io.resin.local.service': task.serviceName,
...(task.dockerOpts || {}),
...{
cachefrom: images,
labels: {
'io.resin.local.image': '1',
'io.resin.local.service': task.serviceName,
},
t: getImageNameFromTask(task),
nocache: opts.nocache,
forcerm: true,
pull: opts.pull,
},
t: getImageNameFromTask(task),
nocache: opts.nocache,

View File

@ -21,8 +21,8 @@ import * as fs from 'fs';
import Livepush, { ContainerNotRunningError } from 'livepush';
import * as _ from 'lodash';
import * as path from 'path';
import type { Composition } from 'resin-compose-parse';
import type { BuildTask } from 'resin-multibuild';
import type { Composition } from '@balena/compose/dist/parse';
import type { BuildTask } from '@balena/compose/dist/multibuild';
import { instanceOf } from '../../errors';
import Logger = require('../logger');

View File

@ -105,7 +105,7 @@ export interface BuildOpts {
cachefrom?: string[];
nocache?: boolean;
pull?: boolean;
registryconfig?: import('resin-multibuild').RegistrySecrets;
registryconfig?: import('@balena/compose/dist/multibuild').RegistrySecrets;
squash?: boolean;
t?: string; // only the tag portion of the image name, e.g. 'abc' in 'myimg:abc'
}
@ -132,7 +132,7 @@ export function generateBuildOpts(options: {
'cache-from'?: string;
nocache: boolean;
pull?: boolean;
'registry-secrets'?: import('resin-multibuild').RegistrySecrets;
'registry-secrets'?: import('@balena/compose/dist/multibuild').RegistrySecrets;
squash: boolean;
tag?: string;
}): BuildOpts {

View File

@ -92,7 +92,6 @@ async function readDockerIgnoreFile(projectDir: string): Promise<string> {
return dockerIgnoreStr;
}
// TODO: docker-compose naming
/**
* Create an instance of '@balena/dockerignore', initialized with the contents
* of a .dockerignore file (if any) found at the given directory argument, plus

View File

@ -86,7 +86,6 @@ 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.`;
// TODO: docker-compose naming
export const dockerignoreHelp =
'DOCKERIGNORE AND GITIGNORE FILES \n' +
`By default, the balena CLI will use a single ".dockerignore" file (if any) at
@ -138,7 +137,7 @@ adding exception patterns to the applicable .dockerignore file(s), for example
- https://www.npmjs.com/package/@balena/dockerignore`;
export const applicationIdInfo = `\
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
Fleets may be specified by fleet name or slug. Fleet slugs are
the recommended option, as they are unique and unambiguous. Slugs can be
listed with the \`balena fleets\` command. Note that slugs may change if the
fleet is renamed. Fleet names are not unique and may result in "Fleet is
@ -146,9 +145,7 @@ 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 fleet, or with fleets
from other balena accounts that you may be invited to join under any role.
For this reason, fleet names are especially discouraged in scripts (e.g. CI
environments). Numeric fleet 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.`;
environments).`;
export const applicationNameNote = `\
Fleets may be specified by fleet name or slug. Slugs are recommended because

View File

@ -280,71 +280,64 @@ export function inferOrSelectDevice(preferredUuid: string) {
}
/*
* Given applicationOrDevice, which may be
* - an application name
* - an application slug
* - an application id (integer)
* Given fleetOrDevice, which may be
* - a fleet name
* - a fleet slug
* - a device uuid
* Either:
* - in case of device uuid, return uuid of device after verifying that it exists and is online.
* - in case of application, return uuid of device user selects from list of online devices.
*
* TODO: Modify this when app IDs dropped.
* - in case of fleet, return uuid of device user selects from list of online devices.
*/
export async function getOnlineTargetDeviceUuid(
sdk: BalenaSDK,
applicationOrDevice: string,
fleetOrDevice: string,
) {
const logger = (await import('../utils/logger')).getLogger();
// If looks like UUID, probably device
if (validation.validateUuid(applicationOrDevice)) {
if (validation.validateUuid(fleetOrDevice)) {
let device: Device;
try {
logger.logDebug(
`Trying to fetch device by UUID ${applicationOrDevice} (${typeof applicationOrDevice})`,
`Trying to fetch device by UUID ${fleetOrDevice} (${typeof fleetOrDevice})`,
);
device = await sdk.models.device.get(applicationOrDevice, {
device = await sdk.models.device.get(fleetOrDevice, {
$select: ['uuid', 'is_online'],
});
if (!device.is_online) {
throw new ExpectedError(
`Device with UUID ${applicationOrDevice} is offline`,
);
throw new ExpectedError(`Device with UUID ${fleetOrDevice} is offline`);
}
return device.uuid;
} catch (err) {
const { BalenaDeviceNotFound } = await import('balena-errors');
if (instanceOf(err, BalenaDeviceNotFound)) {
logger.logDebug(`Device with UUID ${applicationOrDevice} not found`);
// Now try app
logger.logDebug(`Device with UUID ${fleetOrDevice} not found`);
// Now try application
} else {
throw err;
}
}
}
// Not a device UUID, try app
let app: Application;
// Not a device UUID, try application
let application: Application;
try {
logger.logDebug(`Fetching fleet ${applicationOrDevice}`);
logger.logDebug(`Fetching fleet ${fleetOrDevice}`);
const { getApplication } = await import('./sdk');
app = await getApplication(sdk, applicationOrDevice);
application = await getApplication(sdk, fleetOrDevice);
} catch (err) {
const { BalenaApplicationNotFound } = await import('balena-errors');
if (instanceOf(err, BalenaApplicationNotFound)) {
throw new ExpectedError(
`Fleet or Device not found: ${applicationOrDevice}`,
);
throw new ExpectedError(`Fleet or Device not found: ${fleetOrDevice}`);
} else {
throw err;
}
}
// App found, load its devices
const devices = await sdk.models.device.getAllByApplication(app.id, {
const devices = await sdk.models.device.getAllByApplication(application.id, {
$select: ['device_name', 'uuid'],
$filter: { is_online: true },
});
@ -352,13 +345,13 @@ export async function getOnlineTargetDeviceUuid(
// Throw if no devices online
if (_.isEmpty(devices)) {
throw new ExpectedError(
`Fleet ${app.slug} found, but has no devices online.`,
`Fleet ${application.slug} found, but has no devices online.`,
);
}
// Ask user to select from online devices for application
// Ask user to select from online devices for fleet
return getCliForm().ask({
message: `Select a device on fleet ${app.slug}`,
message: `Select a device on fleet ${application.slug}`,
type: 'list',
default: devices[0].uuid,
choices: _.map(devices, (device) => ({

View File

@ -334,13 +334,7 @@ async function createApplication(
try {
await sdk.models.application.getDirectlyAccessible(appName, {
$filter: {
$or: [
{ slug: { $startswith: `${username!.toLowerCase()}/` } },
// TODO: do we still need the following filter? Is it for
// old openBalena instances where slugs were equal to the
// app name and did not contain the slash character?
{ $not: { slug: { $contains: '/' } } },
],
slug: { $startswith: `${username!.toLowerCase()}/` },
},
});
// TODO: This is the only example in the codebase where `printErrorMessage()`

View File

@ -21,7 +21,7 @@ import { ExpectedError } from '../errors';
import { getBalenaSdk, stripIndent } from './lazy';
import Logger = require('./logger');
export const QEMU_VERSION = 'v6.0.0+balena1';
export const QEMU_VERSION = 'v7.0.0+balena1';
export const QEMU_BIN_NAME = 'qemu-execve';
export function qemuPathInContext(context: string) {

View File

@ -17,7 +17,7 @@ import type { BalenaSDK } from 'balena-sdk';
import * as JSONStream from 'JSONStream';
import * as readline from 'readline';
import * as request from 'request';
import { RegistrySecrets } from 'resin-multibuild';
import { RegistrySecrets } from '@balena/compose/dist/multibuild';
import type * as Stream from 'stream';
import streamToPromise = require('stream-to-promise');
import type { Pack } from 'tar-stream';

View File

@ -24,54 +24,32 @@ import type {
/**
* Get a fleet object, disambiguating the fleet identifier which may be a
* a fleet slug, name or numeric database ID (as a string).
* a fleet slug or name.
* TODO: add support for fleet UUIDs.
*/
export async function getApplication(
sdk: BalenaSDK,
nameOrSlugOrId: string | number,
nameOrSlug: string,
options?: PineOptions<Application>,
): Promise<Application> {
const { looksLikeFleetSlug, looksLikeInteger } = await import('./validation');
if (
typeof nameOrSlugOrId === 'string' &&
looksLikeFleetSlug(nameOrSlugOrId)
) {
return await sdk.models.application.getDirectlyAccessible(
nameOrSlugOrId,
const { looksLikeFleetSlug } = await import('./validation');
if (!looksLikeFleetSlug(nameOrSlug)) {
// Not a slug: must be an app name.
// TODO: revisit this logic when we add support for fleet UUIDs.
return await sdk.models.application.getAppByName(
nameOrSlug,
options,
'directly_accessible',
);
}
if (typeof nameOrSlugOrId === 'number' || looksLikeInteger(nameOrSlugOrId)) {
try {
// Test for existence of app with this numerical ID
return await sdk.models.application.getDirectlyAccessible(
Number(nameOrSlugOrId),
options,
);
} catch (e) {
if (typeof nameOrSlugOrId === 'number') {
throw e;
}
const { instanceOf } = await import('../errors');
const { BalenaApplicationNotFound } = await import('balena-errors');
if (!instanceOf(e, BalenaApplicationNotFound)) {
throw e;
}
// App with this numerical ID not found, but there may be an app with this numerical name.
}
}
// Not a slug and not a numeric database ID: must be an app name.
// TODO: revisit this logic when we add support for fleet UUIDs.
return await sdk.models.application.getAppByName(
nameOrSlugOrId,
return await sdk.models.application.getDirectlyAccessible(
nameOrSlug,
options,
'directly_accessible',
);
}
/**
* Given a fleet name, slug or numeric database ID, return its slug.
* Given a fleet name or slug, return its slug.
* This function conditionally makes an async SDK/API call to retrieve the
* application object, which can be wasteful if the application object is
* required before or after the call to this function. If this is the case,
@ -79,16 +57,15 @@ export async function getApplication(
*/
export async function getFleetSlug(
sdk: BalenaSDK,
nameOrSlugOrId: string | number,
nameOrSlug: string,
): Promise<string> {
const { looksLikeFleetSlug } = await import('./validation');
if (
typeof nameOrSlugOrId === 'string' &&
looksLikeFleetSlug(nameOrSlugOrId)
) {
return nameOrSlugOrId.toLowerCase();
if (!looksLikeFleetSlug(nameOrSlug)) {
// Not a slug: must be an app name.
// TODO: revisit this logic when we add support for fleet UUIDs.
return (await getApplication(sdk, nameOrSlug)).slug;
}
return (await getApplication(sdk, nameOrSlugOrId)).slug;
return nameOrSlug.toLowerCase();
}
/**

View File

@ -21,13 +21,3 @@ import { version } from '../../package.json';
export function isVersionGTE(v: string): boolean {
return semver.gte(process.env.BALENA_CLI_VERSION_OVERRIDE || version, v);
}
let v14: boolean;
/** Feature switch for the next major version of the CLI */
export function isV14(): boolean {
if (v14 === undefined) {
v14 = isVersionGTE('14.0.0');
}
return v14;
}

1053
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "balena-cli",
"version": "13.4.1",
"version": "14.3.0",
"description": "The official balena Command Line Interface",
"main": "./build/app.js",
"homepage": "https://github.com/balena-io/balena-cli",
@ -29,7 +29,7 @@
"node_modules/balena-sdk/es2018/index.js",
"node_modules/balena-sync/build/**/*.js",
"node_modules/pinejs-client-request/node_modules/pinejs-client-core/es2018/index.js",
"node_modules/resin-compose-parse/build/schemas/*.json"
"node_modules/@balena/compose/dist/parse/schemas/*.json"
],
"assets": [
"build/auth/pages/*.ejs",
@ -127,7 +127,7 @@
"@types/chai-as-promised": "^7.1.4",
"@types/cli-truncate": "^2.0.0",
"@types/common-tags": "^1.8.1",
"@types/dockerode": "^3.3.8",
"@types/dockerode": "^3.3.9",
"@types/ejs": "^3.1.0",
"@types/express": "^4.17.13",
"@types/fs-extra": "^9.0.13",
@ -191,9 +191,10 @@
"simple-git": "^2.48.0",
"sinon": "^11.1.2",
"ts-node": "^10.4.0",
"typescript": "^4.5.4"
"typescript": "^4.6.4"
},
"dependencies": {
"@balena/compose": "^2.1.1",
"@balena/dockerignore": "^1.0.2",
"@balena/es-version": "^1.0.1",
"@oclif/command": "^1.8.16",
@ -206,10 +207,9 @@
"balena-device-init": "^6.0.0",
"balena-errors": "^4.7.1",
"balena-image-fs": "^7.0.6",
"balena-image-manager": "^7.1.1",
"balena-preload": "^12.0.0",
"balena-release": "^3.2.0",
"balena-sdk": "^16.9.0",
"balena-image-manager": "^8.0.0",
"balena-preload": "^12.1.0",
"balena-sdk": "^16.22.0",
"balena-semver": "^2.3.0",
"balena-settings-client": "^4.0.7",
"balena-settings-storage": "^7.0.0",
@ -225,8 +225,7 @@
"common-tags": "^1.7.2",
"denymount": "^2.3.0",
"docker-modem": "3.0.0",
"docker-progress": "^5.0.1",
"docker-qemu-transpose": "^1.1.1",
"docker-progress": "^5.1.3",
"dockerode": "^3.3.1",
"ejs": "^3.1.6",
"etcher-sdk": "^6.2.1",
@ -264,9 +263,7 @@
"request": "^2.88.2",
"resin-cli-form": "^2.0.2",
"resin-cli-visuals": "^1.8.0",
"resin-compose-parse": "^2.1.3",
"resin-doodles": "^0.2.0",
"resin-multibuild": "^4.12.2",
"resin-stream-logger": "^0.1.2",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
@ -288,6 +285,6 @@
"windosu": "^0.3.0"
},
"versionist": {
"publishedAt": "2022-04-11T16:10:47.566Z"
"publishedAt": "2022-08-17T11:37:13.226Z"
}
}

View File

@ -14,7 +14,7 @@ upstream:
url: 'https://github.com/balena-io-modules/balena-sync'
- repo: 'etcher-sdk'
url: 'https://github.com/balena-io-modules/etcher-sdk/'
- repo: 'resin-compose-parse'
url: 'https://github.com/balena-io-modules/resin-compose-parse'
- repo: 'balena-compose'
url: 'https://github.com/balena-io-modules/balena-compose'
- repo: 'docker-progress'
url: 'https://github.com/balena-io-modules/docker-progress'

View File

@ -6,7 +6,6 @@ const johnDoe = {
gitlab_id: 1325,
social_service_account: null,
hasPasswordSet: true,
needsPasswordReset: false,
public_key: false,
features: [],
id: 1344,
@ -21,7 +20,6 @@ const janeDoe = {
social_service_account: null,
has_disabled_newsletter: true,
hasPasswordSet: true,
needsPasswordReset: false,
public_key: false,
features: [],
intercomUserHash:

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import type { Request as ReleaseRequest } from 'balena-release';
import type { Request as ReleaseRequest } from '@balena/compose/dist/release';
import { expect } from 'chai';
import { promises as fs } from 'fs';
import * as _ from 'lodash';
@ -291,7 +291,7 @@ describe('balena deploy', function () {
statusCode: 500,
inspectRequest: (_uri, requestBody) => {
const imageBody = requestBody as Partial<
import('balena-release/build/models').ImageModel
import('@balena/compose/dist/release/models').ImageModel
>;
expect(imageBody.status).to.equal('success');
},
@ -300,7 +300,7 @@ describe('balena deploy', function () {
api.expectPatchRelease({
inspectRequest: (_uri, requestBody) => {
const releaseBody = requestBody as Partial<
import('balena-release/build/models').ReleaseModel
import('@balena/compose/dist/release/models').ReleaseModel
>;
expect(releaseBody.status).to.equal('failed');
},

View File

@ -59,6 +59,7 @@ if (process.platform !== 'win32') {
'--config-network ethernet',
'--initial-device-name testDeviceName',
'--provisioning-key-name testKey',
'--provisioning-key-expiry-date 2050-12-12',
];
const { err } = await runCommand(command.join(' '));

View File

@ -19,7 +19,7 @@ import { expect } from 'chai';
import * as _ from 'lodash';
import { promises as fs } from 'fs';
import * as path from 'path';
import { PathUtils } from 'resin-multibuild';
import { PathUtils } from '@balena/compose/dist/multibuild';
import rewire = require('rewire');
import * as sinon from 'sinon';
import { Readable } from 'stream';

View File

@ -64,6 +64,12 @@
The file must be distributed with executable as %2.
%1: node_modules/patch-package/node_modules/open/xdg-open
%2: path-to-executable/xdg-open
> Warning Cannot resolve 'path'
node_modules/@balena/compose/dist/parse/schemas/index.js
Dynamic require may fail at run time, because the requested file
is unknown at compilation time and not included into executable.
Use a string literal as an argument for 'require', or leave it
as is and specify the resolved file name in 'scripts' option.
> Warning Cannot include file %1 into executable.
The file must be distributed with executable as %2.
%1: node_modules/drivelist/build/Release/drivelist.node

View File

@ -64,6 +64,12 @@
The file must be distributed with executable as %2.
%1: node_modules/patch-package/node_modules/open/xdg-open
%2: path-to-executable/xdg-open
> Warning Cannot resolve 'path'
node_modules/@balena/compose/dist/parse/schemas/index.js
Dynamic require may fail at run time, because the requested file
is unknown at compilation time and not included into executable.
Use a string literal as an argument for 'require', or leave it
as is and specify the resolved file name in 'scripts' option.
> Warning Cannot include file %1 into executable.
The file must be distributed with executable as %2.
%1: node_modules/drivelist/build/Release/drivelist.node

View File

@ -64,6 +64,12 @@
The file must be distributed with executable as %2.
%1: node_modules\patch-package\node_modules\open\xdg-open
%2: path-to-executable/xdg-open
> Warning Cannot resolve 'path'
node_modules\@balena\compose\dist\parse\schemas\index.js
Dynamic require may fail at run time, because the requested file
is unknown at compilation time and not included into executable.
Use a string literal as an argument for 'require', or leave it
as is and specify the resolved file name in 'scripts' option.
> Warning Cannot include file %1 into executable.
The file must be distributed with executable as %2.
%1: node_modules\drivelist\build\Release\drivelist.node

View File

@ -79,7 +79,7 @@ describeSS('LivepushManager::setupFilesystemWatcher', function () {
async function createMonitors(
projectPath: string,
composition: import('resin-compose-parse').Composition,
composition: import('@balena/compose/dist/parse').Composition,
multiDockerignore: boolean,
changedPathHandler: (serviceName: string, changedPath: string) => void,
): Promise<ByService<chokidar.FSWatcher>> {

View File

@ -17,9 +17,11 @@
import { expect } from 'chai';
describe('resin-multibuild consistency', function () {
describe('@balena/compose/multibuild consistency', function () {
it('should use the same values for selected constants', async () => {
const { QEMU_BIN_NAME: MQEMU_BIN_NAME } = await import('resin-multibuild');
const { QEMU_BIN_NAME: MQEMU_BIN_NAME } = await import(
'@balena/compose/dist/multibuild'
);
const { QEMU_BIN_NAME } = await import('../../build/utils/qemu');
expect(QEMU_BIN_NAME).to.equal(MQEMU_BIN_NAME);
});

View File

@ -1,30 +0,0 @@
/**
* @license
* Copyright 2019 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.
*/
declare module 'dockerfile-template' {
/**
* Variables which define what will be replaced, and what they will be replaced with.
*/
export interface TemplateVariables {
[key: string]: string;
}
export function process(
content: string,
variables: TemplateVariables,
): string;
}