From 1565d51a4cf7d2e7a9553a1c1a64a003e3a17e91 Mon Sep 17 00:00:00 2001 From: myarmolinsky Date: Mon, 4 Nov 2024 16:42:41 -0500 Subject: [PATCH 1/5] `balena build` Change-type: patch --- src/commands/api-key/list.ts | 2 +- src/commands/build/index.ts | 16 ++++------------ src/commands/config/generate.ts | 2 +- src/commands/device/init.ts | 2 +- src/commands/device/list.ts | 2 +- src/commands/device/move.ts | 2 +- src/commands/env/list.ts | 2 +- src/commands/env/set.ts | 2 +- src/commands/join/index.ts | 2 +- src/commands/os/configure.ts | 2 +- src/commands/preload/index.ts | 2 +- src/commands/support/index.ts | 2 +- src/commands/tag/list.ts | 2 +- src/commands/tag/rm.ts | 2 +- src/commands/tag/set.ts | 2 +- src/utils/common-flags.ts | 13 ++++++++----- 16 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/commands/api-key/list.ts b/src/commands/api-key/list.ts index 8f802ff7f3..d7b8fa33e6 100644 --- a/src/commands/api-key/list.ts +++ b/src/commands/api-key/list.ts @@ -37,7 +37,7 @@ export default class APIKeyListCmd extends Command { char: 'u', description: 'show API keys for your user', }), - fleet: cf.fleet, + fleet: cf.fleet(), }; public static authenticated = true; diff --git a/src/commands/build/index.ts b/src/commands/build/index.ts index 66a8944fff..da2e0b6aee 100644 --- a/src/commands/build/index.ts +++ b/src/commands/build/index.ts @@ -86,12 +86,15 @@ ${dockerignoreHelp} arch: Flags.string({ description: 'the architecture to build for', char: 'A', + exclusive: ['fleet'], + dependsOn: ['deviceType'], }), deviceType: Flags.string({ description: 'the type of device this build is for', char: 'd', + exclusive: ['fleet'], }), - fleet: cf.fleet, + fleet: cf.fleet({ exclusive: ['deviceType', 'arch'] }), ...composeCliFlags, ...dockerCliFlags, }; @@ -148,17 +151,6 @@ ${dockerignoreHelp} } protected async validateOptions(opts: FlagsDef, sdk: BalenaSDK) { - // Validate option combinations - if ( - (opts.fleet == null && (opts.arch == null || opts.deviceType == null)) || - (opts.fleet != null && (opts.arch != null || opts.deviceType != null)) - ) { - const { ExpectedError } = await import('../../errors'); - throw new ExpectedError( - 'You must specify either a fleet (-f), or the device type (-d) and optionally the architecture (-A)', - ); - } - // Validate project directory const { validateProjectDirectory } = await import('../../utils/compose_ts'); const { dockerfilePath, registrySecrets } = await validateProjectDirectory( diff --git a/src/commands/config/generate.ts b/src/commands/config/generate.ts index 4376b53f24..a2002853d1 100644 --- a/src/commands/config/generate.ts +++ b/src/commands/config/generate.ts @@ -64,7 +64,7 @@ export default class ConfigGenerateCmd extends Command { description: 'a balenaOS version', required: true, }), - fleet: { ...cf.fleet, exclusive: ['device'] }, + fleet: { ...cf.fleet(), exclusive: ['device'] }, dev: cf.dev, secureBoot: cf.secureBoot, device: { diff --git a/src/commands/device/init.ts b/src/commands/device/init.ts index 81b907f4d7..077effffb6 100644 --- a/src/commands/device/init.ts +++ b/src/commands/device/init.ts @@ -73,7 +73,7 @@ export default class DeviceInitCmd extends Command { ]; public static flags = { - fleet: cf.fleet, + fleet: cf.fleet(), yes: cf.yes, advanced: Flags.boolean({ char: 'v', diff --git a/src/commands/device/list.ts b/src/commands/device/list.ts index 7eea1c1ed4..58a7bad758 100644 --- a/src/commands/device/list.ts +++ b/src/commands/device/list.ts @@ -57,7 +57,7 @@ export default class DeviceListCmd extends Command { ]; public static flags = { - fleet: cf.fleet, + fleet: cf.fleet(), json: cf.json, }; diff --git a/src/commands/device/move.ts b/src/commands/device/move.ts index 0300fe7045..17be42d0e0 100644 --- a/src/commands/device/move.ts +++ b/src/commands/device/move.ts @@ -54,7 +54,7 @@ export default class DeviceMoveCmd extends Command { }; public static flags = { - fleet: cf.fleet, + fleet: cf.fleet(), }; public static authenticated = true; diff --git a/src/commands/env/list.ts b/src/commands/env/list.ts index 42c122d564..0c3112c17d 100644 --- a/src/commands/env/list.ts +++ b/src/commands/env/list.ts @@ -97,7 +97,7 @@ export default class EnvListCmd extends Command { ]; public static flags = { - fleet: { ...cf.fleet, exclusive: ['device'] }, + fleet: { ...cf.fleet(), exclusive: ['device'] }, config: Flags.boolean({ default: false, char: 'c', diff --git a/src/commands/env/set.ts b/src/commands/env/set.ts index 6ad8d6a044..1c2a6a34ad 100644 --- a/src/commands/env/set.ts +++ b/src/commands/env/set.ts @@ -95,7 +95,7 @@ export default class EnvSetCmd extends Command { public static strict = false; public static flags = { - fleet: { ...cf.fleet, exclusive: ['device'] }, + fleet: { ...cf.fleet(), exclusive: ['device'] }, device: { ...cf.device, exclusive: ['fleet'] }, quiet: cf.quiet, service: cf.service, diff --git a/src/commands/join/index.ts b/src/commands/join/index.ts index 5427cb5762..c3d7d28675 100644 --- a/src/commands/join/index.ts +++ b/src/commands/join/index.ts @@ -60,7 +60,7 @@ export default class JoinCmd extends Command { }; public static flags = { - fleet: cf.fleet, + fleet: cf.fleet(), pollInterval: Flags.integer({ description: 'the interval in minutes to check for updates', char: 'i', diff --git a/src/commands/os/configure.ts b/src/commands/os/configure.ts index da497c361b..c051b040cf 100644 --- a/src/commands/os/configure.ts +++ b/src/commands/os/configure.ts @@ -97,7 +97,7 @@ export default class OsConfigureCmd extends Command { description: 'ask advanced configuration questions (when in interactive mode)', }), - fleet: { ...cf.fleet, exclusive: ['device'] }, + fleet: { ...cf.fleet(), exclusive: ['device'] }, config: Flags.string({ description: 'path to a pre-generated config.json file to be injected in the OS image', diff --git a/src/commands/preload/index.ts b/src/commands/preload/index.ts index 0cdfc63b72..fe691c393a 100644 --- a/src/commands/preload/index.ts +++ b/src/commands/preload/index.ts @@ -79,7 +79,7 @@ export default class PreloadCmd extends Command { }; public static flags = { - fleet: cf.fleet, + fleet: cf.fleet(), commit: Flags.string({ description: `\ The commit hash of the release to preload. Use "current" to specify the current diff --git a/src/commands/support/index.ts b/src/commands/support/index.ts index 6c100a2472..b5b40dc2ef 100644 --- a/src/commands/support/index.ts +++ b/src/commands/support/index.ts @@ -57,7 +57,7 @@ export default class SupportCmd extends Command { char: 'd', }), fleet: { - ...cf.fleet, + ...cf.fleet(), description: 'comma-separated list (no spaces) of fleet names or slugs (preferred)', }, diff --git a/src/commands/tag/list.ts b/src/commands/tag/list.ts index 40ca940ef4..0cc847b2f8 100644 --- a/src/commands/tag/list.ts +++ b/src/commands/tag/list.ts @@ -43,7 +43,7 @@ export default class TagListCmd extends Command { public static flags = { fleet: { - ...cf.fleet, + ...cf.fleet(), exclusive: ['device', 'release'], }, device: { diff --git a/src/commands/tag/rm.ts b/src/commands/tag/rm.ts index 622b6f35a3..af2e863b6d 100644 --- a/src/commands/tag/rm.ts +++ b/src/commands/tag/rm.ts @@ -46,7 +46,7 @@ export default class TagRmCmd extends Command { public static flags = { fleet: { - ...cf.fleet, + ...cf.fleet(), exclusive: ['device', 'release'], }, device: { diff --git a/src/commands/tag/set.ts b/src/commands/tag/set.ts index adb79a1eff..9793667b91 100644 --- a/src/commands/tag/set.ts +++ b/src/commands/tag/set.ts @@ -60,7 +60,7 @@ export default class TagSetCmd extends Command { public static flags = { fleet: { - ...cf.fleet, + ...cf.fleet(), exclusive: ['device', 'release'], }, device: { diff --git a/src/utils/common-flags.ts b/src/utils/common-flags.ts index ba84db1390..e44e64e49c 100644 --- a/src/utils/common-flags.ts +++ b/src/utils/common-flags.ts @@ -19,11 +19,14 @@ import { Flags } from '@oclif/core'; import { stripIndent } from './lazy'; import { lowercaseIfSlug } from './normalization'; -export const fleet = Flags.string({ - char: 'f', - description: 'fleet name or slug (preferred)', - parse: lowercaseIfSlug, -}); +// eslint-disable-next-line id-denylist +export const fleet = (extraOpts?: Partial) => + Flags.string({ + char: 'f', + description: 'fleet name or slug (preferred)', + parse: lowercaseIfSlug, + ...extraOpts, + }); export const device = Flags.string({ char: 'd', From 0acf3eb53fd85b29a7a0dd699ab9966adeca4195 Mon Sep 17 00:00:00 2001 From: myarmolinsky Date: Tue, 5 Nov 2024 07:08:53 -0500 Subject: [PATCH 2/5] `balena config generate` Change-type: patch --- src/commands/config/generate.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/commands/config/generate.ts b/src/commands/config/generate.ts index a2002853d1..202607c1ae 100644 --- a/src/commands/config/generate.ts +++ b/src/commands/config/generate.ts @@ -64,7 +64,7 @@ export default class ConfigGenerateCmd extends Command { description: 'a balenaOS version', required: true, }), - fleet: { ...cf.fleet(), exclusive: ['device'] }, + fleet: cf.fleet({ exclusive: ['device'] }), dev: cf.dev, secureBoot: cf.secureBoot, device: { @@ -83,6 +83,7 @@ export default class ConfigGenerateCmd extends Command { deviceType: Flags.string({ description: "device type slug (run 'balena device-type list' for possible values)", + dependsOn: ['fleet'], }), 'generate-device-api-key': Flags.boolean({ description: 'generate a fresh device key for the device', @@ -240,9 +241,6 @@ export default class ConfigGenerateCmd extends Command { $ balena help config generate `; - protected readonly deviceTypeNotAllowedMessage = - 'The --deviceType option can only be used alongside the --fleet option'; - protected async validateOptions( options: Interfaces.InferredFlags, ) { @@ -252,9 +250,6 @@ export default class ConfigGenerateCmd extends Command { throw new ExpectedError(this.missingDeviceOrAppMessage); } - if (!options.fleet && options.deviceType) { - throw new ExpectedError(this.deviceTypeNotAllowedMessage); - } const { normalizeOsVersion } = await import('../../utils/normalization'); options.version = normalizeOsVersion(options.version); const { validateDevOptionAndWarn } = await import('../../utils/config'); From 01a81b355120167e2c61e6c544ad208b691a2d77 Mon Sep 17 00:00:00 2001 From: myarmolinsky Date: Tue, 5 Nov 2024 07:27:13 -0500 Subject: [PATCH 3/5] `balena device deactivate` nit Change-type: patch --- src/commands/device/deactivate.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commands/device/deactivate.ts b/src/commands/device/deactivate.ts index f0a81631d2..51450f558c 100644 --- a/src/commands/device/deactivate.ts +++ b/src/commands/device/deactivate.ts @@ -47,13 +47,14 @@ export default class DeviceDeactivateCmd extends Command { public static authenticated = true; public async run() { - const { args: params, flags: options } = - await this.parse(DeviceDeactivateCmd); + const { + args: { uuid }, + flags: options, + } = await this.parse(DeviceDeactivateCmd); const balena = getBalenaSdk(); const patterns = await import('../../utils/patterns'); - const uuid = params.uuid; const deactivationWarning = ` Warning! Deactivating a device will charge a fee equivalent to the normal monthly cost for the device (e.g. $1 for an essentials device); From ef6d37f0737a6b1e76f5cc3dd33339f42c956b2a Mon Sep 17 00:00:00 2001 From: myarmolinsky Date: Tue, 5 Nov 2024 07:57:30 -0500 Subject: [PATCH 4/5] `balena device note` Change-type: patch --- docs/balena-cli.md | 4 ---- src/commands/config/generate.ts | 2 +- src/commands/device/note.ts | 28 ++++++++-------------------- src/commands/env/list.ts | 2 +- src/commands/env/set.ts | 2 +- src/commands/os/configure.ts | 2 +- src/commands/tag/list.ts | 2 +- src/commands/tag/rm.ts | 2 +- src/commands/tag/set.ts | 2 +- src/utils/common-flags.ts | 11 +++++++---- 10 files changed, 22 insertions(+), 35 deletions(-) diff --git a/docs/balena-cli.md b/docs/balena-cli.md index 3d5c2f4964..36cfafba84 100644 --- a/docs/balena-cli.md +++ b/docs/balena-cli.md @@ -1678,10 +1678,6 @@ note content device UUID -#### --dev DEV - - - ## device os-update ### Description diff --git a/src/commands/config/generate.ts b/src/commands/config/generate.ts index 202607c1ae..9e368922fd 100644 --- a/src/commands/config/generate.ts +++ b/src/commands/config/generate.ts @@ -68,7 +68,7 @@ export default class ConfigGenerateCmd extends Command { dev: cf.dev, secureBoot: cf.secureBoot, device: { - ...cf.device, + ...cf.device(), exclusive: [ 'fleet', 'provisioning-key-name', diff --git a/src/commands/device/note.ts b/src/commands/device/note.ts index cedbdb8113..10dc08c064 100644 --- a/src/commands/device/note.ts +++ b/src/commands/device/note.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { Flags, Args, Command } from '@oclif/core'; -import { ExpectedError } from '../../errors'; +import { Args, Command } from '@oclif/core'; import * as cf from '../../utils/common-flags'; import { getBalenaSdk, stripIndent } from '../../utils/lazy'; @@ -41,35 +40,24 @@ export default class DeviceNoteCmd extends Command { public static args = { note: Args.string({ description: 'note content', + required: true, }), }; public static flags = { - device: { exclusive: ['dev'], ...cf.device }, - dev: Flags.string({ - exclusive: ['device'], - hidden: true, - }), + device: cf.device({ required: true }), }; public static authenticated = true; public async run() { - const { args: params, flags: options } = await this.parse(DeviceNoteCmd); - - if (params.note?.length === 0) { - throw new ExpectedError('Missing note content'); - } - - options.device = options.device || options.dev; - delete options.dev; - - if (options.device == null || options.device.length === 0) { - throw new ExpectedError('Missing device UUID (--device)'); - } + const { + args: params, + flags: { device }, + } = await this.parse(DeviceNoteCmd); const balena = getBalenaSdk(); - return balena.models.device.setNote(options.device, params.note ?? ''); + return balena.models.device.setNote(device!, params.note!); } } diff --git a/src/commands/env/list.ts b/src/commands/env/list.ts index 0c3112c17d..5aa3c2ac52 100644 --- a/src/commands/env/list.ts +++ b/src/commands/env/list.ts @@ -104,7 +104,7 @@ export default class EnvListCmd extends Command { description: 'show configuration variables only', exclusive: ['service'], }), - device: { ...cf.device, exclusive: ['fleet'] }, + device: { ...cf.device(), exclusive: ['fleet'] }, json: cf.json, service: { ...cf.service, exclusive: ['config'] }, }; diff --git a/src/commands/env/set.ts b/src/commands/env/set.ts index 1c2a6a34ad..6d2780c511 100644 --- a/src/commands/env/set.ts +++ b/src/commands/env/set.ts @@ -96,7 +96,7 @@ export default class EnvSetCmd extends Command { public static flags = { fleet: { ...cf.fleet(), exclusive: ['device'] }, - device: { ...cf.device, exclusive: ['fleet'] }, + device: { ...cf.device(), exclusive: ['fleet'] }, quiet: cf.quiet, service: cf.service, }; diff --git a/src/commands/os/configure.ts b/src/commands/os/configure.ts index c051b040cf..7573949a1c 100644 --- a/src/commands/os/configure.ts +++ b/src/commands/os/configure.ts @@ -120,7 +120,7 @@ export default class OsConfigureCmd extends Command { dev: cf.dev, secureBoot: cf.secureBoot, device: { - ...cf.device, + ...cf.device(), exclusive: [ 'fleet', 'provisioning-key-name', diff --git a/src/commands/tag/list.ts b/src/commands/tag/list.ts index 0cc847b2f8..22dc9e8c22 100644 --- a/src/commands/tag/list.ts +++ b/src/commands/tag/list.ts @@ -47,7 +47,7 @@ export default class TagListCmd extends Command { exclusive: ['device', 'release'], }, device: { - ...cf.device, + ...cf.device(), exclusive: ['fleet', 'release'], }, release: { diff --git a/src/commands/tag/rm.ts b/src/commands/tag/rm.ts index af2e863b6d..959c9db89d 100644 --- a/src/commands/tag/rm.ts +++ b/src/commands/tag/rm.ts @@ -50,7 +50,7 @@ export default class TagRmCmd extends Command { exclusive: ['device', 'release'], }, device: { - ...cf.device, + ...cf.device(), exclusive: ['fleet', 'release'], }, release: { diff --git a/src/commands/tag/set.ts b/src/commands/tag/set.ts index 9793667b91..eb1fe11cd8 100644 --- a/src/commands/tag/set.ts +++ b/src/commands/tag/set.ts @@ -64,7 +64,7 @@ export default class TagSetCmd extends Command { exclusive: ['device', 'release'], }, device: { - ...cf.device, + ...cf.device(), exclusive: ['fleet', 'release'], }, release: { diff --git a/src/utils/common-flags.ts b/src/utils/common-flags.ts index e44e64e49c..8f3fbbf452 100644 --- a/src/utils/common-flags.ts +++ b/src/utils/common-flags.ts @@ -28,10 +28,13 @@ export const fleet = (extraOpts?: Partial) => ...extraOpts, }); -export const device = Flags.string({ - char: 'd', - description: 'device UUID', -}); +// eslint-disable-next-line id-denylist +export const device = (extraOpts?: Partial) => + Flags.string({ + char: 'd', + description: 'device UUID', + ...extraOpts, + }); export const quiet = Flags.boolean({ char: 'q', From ed1946ec3622997f2ceb9e9d4a979a132875c002 Mon Sep 17 00:00:00 2001 From: myarmolinsky Date: Tue, 5 Nov 2024 08:04:38 -0500 Subject: [PATCH 5/5] `balena device tunnel` Change-type: patch --- src/commands/device/tunnel.ts | 11 ++--------- src/errors.ts | 6 ------ 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/commands/device/tunnel.ts b/src/commands/device/tunnel.ts index 38d877ea85..63f59aa166 100644 --- a/src/commands/device/tunnel.ts +++ b/src/commands/device/tunnel.ts @@ -16,11 +16,7 @@ */ import { Flags, Args, Command } from '@oclif/core'; -import { - NoPortsDefinedError, - InvalidPortMappingError, - ExpectedError, -} from '../../errors'; +import { InvalidPortMappingError, ExpectedError } from '../../errors'; import { getBalenaSdk, stripIndent } from '../../utils/lazy'; import { lowercaseIfSlug } from '../../utils/normalization'; @@ -85,6 +81,7 @@ export default class DeviceTunnelCmd extends Command { 'port mapping in the format [:[localIP:]localPort]', char: 'p', multiple: true, + required: true, }), }; @@ -117,10 +114,6 @@ export default class DeviceTunnelCmd extends Command { } }; - if (options.port === undefined) { - throw new NoPortsDefinedError(); - } - // Ascertain device uuid const { getOnlineTargetDeviceUuid } = await import('../../utils/patterns'); const uuid = await getOnlineTargetDeviceUuid(sdk, params.deviceOrFleet); diff --git a/src/errors.ts b/src/errors.ts index f099305f91..871f6f96a1 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -39,12 +39,6 @@ export class InvalidPortMappingError extends ExpectedError { } } -export class NoPortsDefinedError extends ExpectedError { - constructor() { - super('No ports have been provided.'); - } -} - export class SIGINTError extends ExpectedError {} /**