Remove deprecated '--app' and '--application' options (renamed to '--fleet')

Change-type: major
This commit is contained in:
Paulo Castro 2021-12-19 20:50:03 +00:00
parent 580ca0d584
commit 1ed39d1d37
22 changed files with 220 additions and 651 deletions

View File

@ -684,11 +684,6 @@ fleet name, slug (preferred), or numeric ID (deprecated)
produce JSON output instead of tabular output
#### --v13
enable selected balena CLI v13 pre-release features, like the renaming
from "application" to "fleet" in command output
## devices supported
List the supported device types (like 'raspberrypi3' or 'intel-nuc').
@ -735,11 +730,6 @@ the device uuid
### Options
#### --v13
enable selected balena CLI v13 pre-release features, like the renaming
from "application" to "fleet" in command output
## device deactivate <uuid>
Deactivate a device.
@ -1296,13 +1286,6 @@ 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.
Renaming notice: The 'app' or 'application' words in table headers
or in JSON object keys/properties will be replaced with 'fleet' in
the next major version of the CLI (v13). The --v13 option may be used
to enable the new names already now, and suppress a warning message.
(The --v13 option will be silently ignored in CLI v13.)
Find out more at: https://git.io/JRuZr
Examples:
$ balena envs --fleet myorg/myfleet
@ -1333,19 +1316,10 @@ device UUID
produce JSON output instead of tabular output
#### -v, --verbose
produce verbose output
#### -s, --service SERVICE
service name
#### --v13
enable selected balena CLI v13 pre-release features, like the renaming
from "application" to "fleet" in command output
## env rm <id>
Remove a configuration or environment variable from a fleet, device
@ -2413,7 +2387,7 @@ the wifi key to use (used only if --network is set to wifi)
#### --appUpdatePollInterval APPUPDATEPOLLINTERVAL
supervisor cloud polling interval in minutes (e.g. for variable updates)
supervisor cloud polling interval in minutes (e.g. for device variables)
#### --provisioning-key-name PROVISIONING-KEY-NAME

View File

@ -22,22 +22,18 @@ import * as cf from '../utils/common-flags';
import * as compose from '../utils/compose';
import type { Application, ApplicationType, BalenaSDK } from 'balena-sdk';
import {
appToFleetFlagMsg,
buildArgDeprecation,
dockerignoreHelp,
registrySecretsHelp,
warnify,
} from '../utils/messages';
import type { ComposeCliFlags, ComposeOpts } from '../utils/compose-types';
import { buildProject, composeCliFlags } from '../utils/compose_ts';
import type { BuildOpts, DockerCliFlags } from '../utils/docker';
import { dockerCliFlags } from '../utils/docker';
import { isV13 } from '../utils/version';
interface FlagsDef extends ComposeCliFlags, DockerCliFlags {
arch?: string;
deviceType?: string;
application?: string;
fleet?: string;
source?: string; // Not part of command profile - source param copied here.
help: void;
@ -96,7 +92,6 @@ ${dockerignoreHelp}
description: 'the type of device this build is for',
char: 'd',
}),
...(isV13() ? {} : { application: cf.application }),
fleet: cf.fleet,
...composeCliFlags,
...dockerCliFlags,
@ -112,12 +107,7 @@ ${dockerignoreHelp}
BuildCmd,
);
if (options.application && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.fleet;
await Command.checkLoggedInIf(!!options.application);
await Command.checkLoggedInIf(!!options.fleet);
(await import('events')).defaultMaxListeners = 1000;
@ -161,10 +151,8 @@ ${dockerignoreHelp}
protected async validateOptions(opts: FlagsDef, sdk: BalenaSDK) {
// Validate option combinations
if (
(opts.application == null &&
(opts.arch == null || opts.deviceType == null)) ||
(opts.application != null &&
(opts.arch != null || opts.deviceType != null))
(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(
@ -189,9 +177,9 @@ ${dockerignoreHelp}
}
protected async getAppAndResolveArch(opts: FlagsDef) {
if (opts.application) {
if (opts.fleet) {
const { getAppWithArch } = await import('../utils/helpers');
const app = await getAppWithArch(opts.application);
const app = await getAppWithArch(opts.fleet);
opts.arch = app.arch;
opts.deviceType = app.is_for__device_type[0].slug;
return app;

View File

@ -19,18 +19,11 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
import type { PineDeferred } from 'balena-sdk';
interface FlagsDef {
version: string; // OS version
application?: string;
app?: string; // application alias
fleet?: string;
device?: string;
deviceApiKey?: string;
@ -82,22 +75,10 @@ export default class ConfigGenerateCmd extends Command {
description: 'a balenaOS version',
required: true,
}),
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'device'],
},
app: { ...cf.app, exclusive: ['application', 'fleet', 'device'] },
appUpdatePollInterval: flags.string({
description: 'DEPRECATED alias for --updatePollInterval',
}),
}),
fleet: { ...cf.fleet, exclusive: ['application', 'app', 'device'] },
fleet: { ...cf.fleet, exclusive: ['device'] },
device: {
...cf.device,
exclusive: ['application', 'app', 'fleet', 'provisioning-key-name'],
exclusive: ['fleet', 'provisioning-key-name'],
},
deviceApiKey: flags.string({
description:
@ -130,7 +111,7 @@ export default class ConfigGenerateCmd extends Command {
}),
appUpdatePollInterval: flags.string({
description:
'supervisor cloud polling interval in minutes (e.g. for variable updates)',
'supervisor cloud polling interval in minutes (e.g. for device variables)',
}),
'provisioning-key-name': flags.string({
description: 'custom key name assigned to generated provisioning api key',
@ -173,7 +154,7 @@ export default class ConfigGenerateCmd extends Command {
resourceDeviceType = device.is_of__device_type[0].slug;
} else {
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
application = (await getApplication(balena, options.application!, {
application = (await getApplication(balena, options.fleet!, {
$expand: {
is_for__device_type: { $select: 'slug' },
},
@ -188,7 +169,7 @@ export default class ConfigGenerateCmd extends Command {
);
// Check compatibility if application and deviceType provided
if (options.application && options.deviceType) {
if (options.fleet && options.deviceType) {
const appDeviceManifest = await balena.models.device.getManifestBySlug(
resourceDeviceType,
);
@ -198,7 +179,7 @@ export default class ConfigGenerateCmd extends Command {
!helpers.areDeviceTypesCompatible(appDeviceManifest, deviceManifest)
) {
throw new balena.errors.BalenaInvalidDeviceType(
`Device type ${options.deviceType} is incompatible with fleet ${options.application}`,
`Device type ${options.deviceType} is incompatible with fleet ${options.fleet}`,
);
}
}
@ -207,7 +188,7 @@ export default class ConfigGenerateCmd extends Command {
// Pass params as an override: if there is any param with exactly the same name as a
// required option, that value is used (and the corresponding question is not asked)
const answers = await getCliForm().run(deviceManifest.options, {
override: options,
override: { ...options, app: options.fleet, application: options.fleet },
});
answers.version = options.version;
answers.provisioningKeyName = options['provisioning-key-name'];
@ -253,18 +234,11 @@ export default class ConfigGenerateCmd extends Command {
protected async validateOptions(options: FlagsDef) {
const { ExpectedError } = await import('../../errors');
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
// Prefer options.application over options.app
delete options.app;
if (options.device == null && options.application == null) {
if (options.device == null && options.fleet == null) {
throw new ExpectedError(this.missingDeviceOrAppMessage);
}
if (!options.application && options.deviceType) {
if (!options.fleet && options.deviceType) {
throw new ExpectedError(this.deviceTypeNotAllowedMessage);
}
}

View File

@ -21,9 +21,7 @@ import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { appToFleetOutputMsg, warnify } from '../../utils/messages';
import { tryAsInteger } from '../../utils/validation';
import { isV13 } from '../../utils/version';
import type { Application, Release } from 'balena-sdk';
@ -46,7 +44,6 @@ interface ExtendedDevice extends DeviceWithDeviceType {
interface FlagsDef {
help: void;
v13: boolean;
}
interface ArgsDef {
@ -74,17 +71,13 @@ export default class DeviceCmd extends Command {
public static flags: flags.Input<FlagsDef> = {
help: cf.help,
v13: cf.v13,
};
public static authenticated = true;
public static primary = true;
public async run() {
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
DeviceCmd,
);
const useAppWord = !options.v13 && !isV13();
const { args: params } = this.parse<FlagsDef, ArgsDef>(DeviceCmd);
const balena = getBalenaSdk();
@ -170,10 +163,6 @@ export default class DeviceCmd extends Command {
);
}
if (useAppWord && process.stderr.isTTY) {
console.error(warnify(appToFleetOutputMsg));
}
console.log(
getVisuals().table.vertical(device, [
`$${device.device_name}$`,
@ -184,7 +173,7 @@ export default class DeviceCmd extends Command {
'ip_address',
'public_address',
'mac_address',
useAppWord ? 'application_name' : 'application_name => FLEET',
'application_name => FLEET',
'last_seen',
'uuid',
'commit',

View File

@ -19,17 +19,10 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { applicationIdInfo } from '../../utils/messages';
import { runCommand } from '../../utils/helpers';
import { isV13 } from '../../utils/version';
interface FlagsDef {
application?: string;
app?: string;
fleet?: string;
yes: boolean;
advanced: boolean;
@ -82,12 +75,6 @@ export default class DeviceInitCmd extends Command {
public static usage = 'device init';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
application: cf.application,
app: cf.app,
}),
fleet: cf.fleet,
yes: cf.yes,
advanced: flags.boolean({
@ -130,17 +117,10 @@ export default class DeviceInitCmd extends Command {
const logger = await Command.getLogger();
const balena = getBalenaSdk();
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
// Consolidate application options
options.application ||= options.app || options.fleet;
delete options.app;
// Get application and
const application = (await getApplication(
balena,
options['application'] ||
options.fleet ||
(
await (await import('../../utils/patterns')).selectApplication()
).id,

View File

@ -27,12 +27,7 @@ import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
type ExtendedDevice = PineTypedResult<
Device,
@ -42,8 +37,6 @@ type ExtendedDevice = PineTypedResult<
};
interface FlagsDef {
application?: string;
app?: string;
fleet?: string;
help: void;
}
@ -82,7 +75,6 @@ export default class DeviceMoveCmd extends Command {
public static usage = 'device move <uuid(s)>';
public static flags: flags.Input<FlagsDef> = {
...(isV13() ? {} : { app: cf.app, application: cf.application }),
fleet: cf.fleet,
help: cf.help,
};
@ -94,11 +86,6 @@ export default class DeviceMoveCmd extends Command {
DeviceMoveCmd,
);
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
const balena = getBalenaSdk();
const { tryAsInteger } = await import('../../utils/validation');
@ -132,8 +119,8 @@ export default class DeviceMoveCmd extends Command {
const { getApplication } = await import('../../utils/sdk');
// Get destination application
const application = options.application
? await getApplication(balena, options.application)
const application = options.fleet
? await getApplication(balena, options.fleet)
: await this.interactivelySelectApplication(balena, devices);
// Move each device

View File

@ -20,14 +20,7 @@ import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
appToFleetOutputMsg,
jsonInfo,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo, jsonInfo } from '../../utils/messages';
import type { Application } from 'balena-sdk';
@ -38,12 +31,9 @@ interface ExtendedDevice extends DeviceWithDeviceType {
}
interface FlagsDef {
application?: string;
app?: string;
fleet?: string;
help: void;
json: boolean;
v13: boolean;
}
export default class DevicesCmd extends Command {
@ -67,50 +57,25 @@ export default class DevicesCmd extends Command {
public static usage = 'devices';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'v13'],
},
app: { ...cf.app, exclusive: ['application', 'fleet', 'v13'] },
}),
fleet: { ...cf.fleet, exclusive: ['app', 'application'] },
fleet: cf.fleet,
json: cf.json,
help: cf.help,
v13: cf.v13,
};
public static primary = true;
public static authenticated = true;
protected useAppWord = false;
protected hasWarned = false;
public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(DevicesCmd);
this.useAppWord = !options.fleet && !options.v13 && !isV13();
const balena = getBalenaSdk();
if (
(options.application || options.app) &&
!options.json &&
process.stderr.isTTY
) {
this.hasWarned = true;
console.error(warnify(appToFleetFlagMsg));
}
// Consolidate application options
options.application ||= options.app || options.fleet;
let devices;
if (options.application != null) {
if (options.fleet != null) {
const { getApplication } = await import('../../utils/sdk');
const application = await getApplication(balena, options.application);
const application = await getApplication(balena, options.fleet);
devices = (await balena.models.device.getAllByApplication(
application.id,
expandForAppName,
@ -134,16 +99,14 @@ export default class DevicesCmd extends Command {
return device;
});
const jName = this.useAppWord ? 'application_name' : 'fleet_name';
const tName = this.useAppWord ? 'APPLICATION NAME' : 'FLEET';
const fields = [
'id',
'uuid',
'device_name',
'device_type',
options.json
? `application_name => ${jName}`
: `application_name => ${tName}`,
? `application_name => fleet_name`
: `application_name => FLEET`,
'status',
'is_online',
'supervisor_version',
@ -156,9 +119,6 @@ export default class DevicesCmd extends Command {
const mapped = devices.map((device) => pickAndRename(device, fields));
console.log(JSON.stringify(mapped, null, 4));
} else {
if (!this.hasWarned && this.useAppWord && process.stderr.isTTY) {
console.error(warnify(appToFleetOutputMsg));
}
const _ = await import('lodash');
console.log(
getVisuals().table.horizontal(

View File

@ -21,15 +21,9 @@ import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
application?: string;
fleet?: string;
device?: string; // device UUID
help: void;
@ -101,11 +95,8 @@ export default class EnvAddCmd extends Command {
public static usage = 'env add <name> [value]';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: { application: { ...cf.application, exclusive: ['fleet', 'device'] } }),
fleet: { ...cf.fleet, exclusive: ['application', 'device'] },
device: { ...cf.device, exclusive: ['application', 'fleet'] },
fleet: { ...cf.fleet, exclusive: ['device'] },
device: { ...cf.device, exclusive: ['fleet'] },
help: cf.help,
quiet: cf.quiet,
service: cf.service,
@ -117,11 +108,7 @@ export default class EnvAddCmd extends Command {
);
const cmd = this;
if (options.application && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.fleet;
if (!options.application && !options.device) {
if (!options.fleet && !options.device) {
throw new ExpectedError(
'Either the --fleet or the --device option must be specified',
);
@ -163,8 +150,8 @@ export default class EnvAddCmd extends Command {
}
const varType = isConfigVar ? 'configVar' : 'envVar';
if (options.application) {
for (const app of options.application.split(',')) {
if (options.fleet) {
for (const app of options.fleet.split(',')) {
try {
await balena.models.application[varType].set(
app,
@ -201,8 +188,8 @@ async function setServiceVars(
params: ArgsDef,
options: FlagsDef,
) {
if (options.application) {
for (const app of options.application.split(',')) {
if (options.fleet) {
for (const app of options.fleet.split(',')) {
for (const service of options.service!.split(',')) {
try {
const serviceId = await getServiceIdForApp(sdk, app, service);

View File

@ -21,24 +21,15 @@ import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
appToFleetOutputMsg,
warnify,
} from '../utils/messages';
import { isV13 } from '../utils/version';
import { applicationIdInfo } from '../utils/messages';
interface FlagsDef {
application?: string;
fleet?: string;
config: boolean;
device?: string; // device UUID
json: boolean;
help: void;
service?: string; // service name
verbose: boolean;
v13: boolean;
}
interface EnvironmentVariableInfo extends SDK.EnvironmentVariableBase {
@ -96,8 +87,6 @@ export default class EnvsCmd extends Command {
in case the current user was removed from the fleet by the fleet's owner).
${applicationIdInfo.split('\n').join('\n\t\t')}
${appToFleetOutputMsg.split('\n').join('\n\t\t')}
`;
public static examples = [
@ -115,57 +104,35 @@ export default class EnvsCmd extends Command {
public static usage = 'envs';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
all: flags.boolean({
default: false,
description: 'No-op since balena CLI v12.0.0.',
hidden: true,
}),
application: {
exclusive: ['device', 'fleet', 'v13'],
...cf.application,
},
}),
fleet: { exclusive: ['device', 'application'], ...cf.fleet },
fleet: { ...cf.fleet, exclusive: ['device'] },
config: flags.boolean({
default: false,
char: 'c',
description: 'show configuration variables only',
exclusive: ['service'],
}),
device: { exclusive: ['fleet', 'application'], ...cf.device },
device: { ...cf.device, exclusive: ['fleet'] },
help: cf.help,
json: cf.json,
verbose: cf.verbose,
service: { exclusive: ['config'], ...cf.service },
v13: cf.v13,
service: { ...cf.service, exclusive: ['config'] },
};
protected useAppWord = false;
protected hasWarned = false;
public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(EnvsCmd);
this.useAppWord = !options.fleet && !options.v13 && !isV13();
const variables: EnvironmentVariableInfo[] = [];
await Command.checkLoggedIn();
if (options.application && !options.json && process.stderr.isTTY) {
this.hasWarned = true;
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.fleet;
if (!options.application && !options.device) {
if (!options.fleet && !options.device) {
throw new ExpectedError('Missing --fleet or --device option');
}
const balena = getBalenaSdk();
let appNameOrSlug = options.application;
let fleetSlug: string | undefined = options.fleet
? await (await import('../utils/sdk')).getFleetSlug(balena, options.fleet)
: undefined;
let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID
if (options.device) {
@ -178,23 +145,23 @@ export default class EnvsCmd extends Command {
);
fullUUID = device.uuid;
if (app) {
appNameOrSlug = app.slug;
fleetSlug = app.slug;
}
}
if (appNameOrSlug && options.service) {
await validateServiceName(balena, options.service, appNameOrSlug);
if (fleetSlug && options.service) {
await validateServiceName(balena, options.service, fleetSlug);
}
variables.push(...(await getAppVars(balena, appNameOrSlug, options)));
variables.push(...(await getAppVars(balena, fleetSlug, options)));
if (fullUUID) {
variables.push(
...(await getDeviceVars(balena, fullUUID, appNameOrSlug, options)),
...(await getDeviceVars(balena, fullUUID, fleetSlug, options)),
);
}
if (!options.json && variables.length === 0) {
const target =
(options.service ? `service "${options.service}" of ` : '') +
(options.application
? `fleet "${options.application}"`
(options.fleet
? `fleet "${options.fleet}"`
: `device "${options.device}"`);
throw new ExpectedError(`No environment variables found for ${target}`);
}
@ -210,20 +177,11 @@ export default class EnvsCmd extends Command {
// Replace undefined app names with 'N/A' or null
varArray = varArray.map((i: EnvironmentVariableInfo) => {
if (i.appName) {
// use slug in v13, app name in v12 for compatibility
i.appName = isV13()
? i.appName
: i.appName.substring(i.appName.indexOf('/') + 1);
} else {
i.appName = options.json ? null : 'N/A';
}
i.appName ||= options.json ? null : 'N/A';
return i;
});
const jName = this.useAppWord ? 'appName' : 'fleetName';
const tName = this.useAppWord ? 'APPLICATION' : 'FLEET';
fields.push(options.json ? `appName => ${jName}` : `appName => ${tName}`);
fields.push(options.json ? `appName => fleetName` : `appName => FLEET`);
if (options.device) {
fields.push(options.json ? 'deviceUUID' : 'deviceUUID => DEVICE');
}
@ -236,9 +194,6 @@ export default class EnvsCmd extends Command {
const mapped = varArray.map((o) => pickAndRename(o, fields));
this.log(JSON.stringify(mapped, null, 4));
} else {
if (!this.hasWarned && this.useAppWord && process.stderr.isTTY) {
console.error(warnify(appToFleetOutputMsg));
}
this.log(
getVisuals().table.horizontal(
_.sortBy(varArray, (v: SDK.EnvironmentVariableBase) => v.name),
@ -252,14 +207,14 @@ export default class EnvsCmd extends Command {
async function validateServiceName(
sdk: SDK.BalenaSDK,
serviceName: string,
appName: string,
fleetSlug: string,
) {
const services = await sdk.models.service.getAllByApplication(appName, {
const services = await sdk.models.service.getAllByApplication(fleetSlug, {
$filter: { service_name: serviceName },
});
if (services.length === 0) {
throw new ExpectedError(
`Service "${serviceName}" not found for fleet "${appName}"`,
`Service "${serviceName}" not found for fleet "${fleetSlug}"`,
);
}
}
@ -273,17 +228,17 @@ async function validateServiceName(
*/
async function getAppVars(
sdk: SDK.BalenaSDK,
appNameOrSlug: string | undefined,
fleetSlug: string | undefined,
options: FlagsDef,
): Promise<EnvironmentVariableInfo[]> {
const appVars: EnvironmentVariableInfo[] = [];
if (!appNameOrSlug) {
if (!fleetSlug) {
return appVars;
}
const vars = await sdk.models.application[
options.config ? 'configVar' : 'envVar'
].getAllByApplication(appNameOrSlug);
fillInInfoFields(vars, appNameOrSlug);
].getAllByApplication(fleetSlug);
fillInInfoFields(vars, fleetSlug);
appVars.push(...vars);
if (!options.config) {
const pineOpts: SDK.PineOptions<SDK.ServiceEnvironmentVariable> = {
@ -299,10 +254,10 @@ async function getAppVars(
};
}
const serviceVars = await sdk.models.service.var.getAllByApplication(
appNameOrSlug,
fleetSlug,
pineOpts,
);
fillInInfoFields(serviceVars, appNameOrSlug);
fillInInfoFields(serviceVars, fleetSlug);
appVars.push(...serviceVars);
}
return appVars;
@ -315,7 +270,7 @@ async function getAppVars(
async function getDeviceVars(
sdk: SDK.BalenaSDK,
fullUUID: string,
appNameOrSlug: string | undefined,
fleetSlug: string | undefined,
options: FlagsDef,
): Promise<EnvironmentVariableInfo[]> {
const printedUUID = options.json ? fullUUID : options.device!;
@ -324,7 +279,7 @@ async function getDeviceVars(
const deviceConfigVars = await sdk.models.device.configVar.getAllByDevice(
fullUUID,
);
fillInInfoFields(deviceConfigVars, appNameOrSlug, printedUUID);
fillInInfoFields(deviceConfigVars, fleetSlug, printedUUID);
deviceVars.push(...deviceConfigVars);
} else {
const pineOpts: SDK.PineOptions<SDK.DeviceServiceEnvironmentVariable> = {
@ -345,13 +300,13 @@ async function getDeviceVars(
fullUUID,
pineOpts,
);
fillInInfoFields(deviceServiceVars, appNameOrSlug, printedUUID);
fillInInfoFields(deviceServiceVars, fleetSlug, printedUUID);
deviceVars.push(...deviceServiceVars);
const deviceEnvVars = await sdk.models.device.envVar.getAllByDevice(
fullUUID,
);
fillInInfoFields(deviceEnvVars, appNameOrSlug, printedUUID);
fillInInfoFields(deviceEnvVars, fleetSlug, printedUUID);
deviceVars.push(...deviceEnvVars);
}
return deviceVars;
@ -367,7 +322,7 @@ function fillInInfoFields(
| EnvironmentVariableInfo[]
| DeviceServiceEnvironmentVariableInfo[]
| ServiceEnvironmentVariableInfo[],
appNameOrSlug?: string,
fleetSlug?: string,
deviceUUID?: string,
) {
for (const envVar of varArray) {
@ -381,7 +336,7 @@ function fillInInfoFields(
?.installs__service as SDK.Service[]
)[0]?.service_name;
}
envVar.appName = appNameOrSlug;
envVar.appName = fleetSlug;
envVar.serviceName = envVar.serviceName || '*';
envVar.deviceUUID = deviceUUID || '*';
}

View File

@ -21,10 +21,8 @@ import * as cf from '../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
import { parseAsLocalHostnameOrIp } from '../utils/validation';
import { isV13 } from '../utils/version';
interface FlagsDef {
application?: string;
fleet?: string;
pollInterval?: number;
help?: void;
@ -77,7 +75,6 @@ export default class JoinCmd extends Command {
public static usage = 'join [deviceIpOrHostname]';
public static flags: flags.Input<FlagsDef> = {
...(isV13() ? {} : { application: cf.application }),
fleet: cf.fleet,
pollInterval: flags.integer({
description: 'the interval in minutes to check for updates',
@ -101,7 +98,7 @@ export default class JoinCmd extends Command {
logger,
sdk,
params.deviceIpOrHostname,
options.application || options.fleet,
options.fleet,
options.pollInterval,
);
}

View File

@ -23,19 +23,12 @@ import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
const CONNECTIONS_FOLDER = '/system-connections';
interface FlagsDef {
advanced?: boolean;
application?: string;
app?: string;
fleet?: string;
config?: string;
'config-app-update-poll-interval'?: number;
@ -128,22 +121,7 @@ export default class OsConfigureCmd extends Command {
description:
'ask advanced configuration questions (when in interactive mode)',
}),
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'device'],
},
app: {
...cf.app,
exclusive: ['application', 'fleet', 'device'],
},
}),
fleet: {
...cf.fleet,
exclusive: ['app', 'application', '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',
@ -163,10 +141,7 @@ export default class OsConfigureCmd extends Command {
'config-wifi-ssid': flags.string({
description: 'WiFi SSID (network name) (non-interactive configuration)',
}),
device: {
exclusive: ['app', 'application', 'fleet', 'provisioning-key-name'],
...cf.device,
},
device: { ...cf.device, exclusive: ['fleet', 'provisioning-key-name'] },
'device-api-key': flags.string({
char: 'k',
description:
@ -203,10 +178,6 @@ export default class OsConfigureCmd extends Command {
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
OsConfigureCmd,
);
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
await validateOptions(options);
@ -233,7 +204,7 @@ export default class OsConfigureCmd extends Command {
};
deviceTypeSlug = device.is_of__device_type[0].slug;
} else {
app = (await getApplication(balena, options.application!, {
app = (await getApplication(balena, options.fleet!, {
$expand: {
is_for__device_type: { $select: 'slug' },
},
@ -259,7 +230,7 @@ export default class OsConfigureCmd extends Command {
options,
configJson,
);
if (options.application) {
if (options.fleet) {
answers.deviceType = deviceTypeSlug;
}
answers.version =
@ -335,12 +306,12 @@ export default class OsConfigureCmd extends Command {
async function validateOptions(options: FlagsDef) {
// The 'device' and 'application' options are declared "exclusive" in the oclif
// flag definitions above, so oclif will enforce that they are not both used together.
if (!options.device && !options.application) {
if (!options.device && !options.fleet) {
throw new ExpectedError(
"Either the '--device' or the '--fleet' option must be provided",
);
}
if (!options.application && options['device-type']) {
if (!options.fleet && options['device-type']) {
throw new ExpectedError(
"The '--device-type' option can only be used in conjunction with the '--fleet' option",
);
@ -401,7 +372,7 @@ async function checkDeviceTypeCompatibility(
const helpers = await import('../../utils/helpers');
if (!helpers.areDeviceTypesCompatible(appDeviceType, optionDeviceType)) {
throw new ExpectedError(
`Device type ${options['device-type']} is incompatible with fleet ${options.application}`,
`Device type ${options['device-type']} is incompatible with fleet ${options.fleet}`,
);
}
}
@ -426,7 +397,13 @@ async function askQuestionsForDeviceType(
options: FlagsDef,
configJson?: import('../../utils/config').ImgConfig,
): Promise<Answers> {
const answerSources: any[] = [camelifyConfigOptions(options)];
const answerSources: any[] = [
{
...camelifyConfigOptions(options),
app: options.fleet,
application: options.fleet,
},
];
const defaultAnswers: Partial<Answers> = {};
const questions: any = deviceType.options;
let extraOpts: { override: object } | undefined;

View File

@ -24,15 +24,10 @@ import {
getVisuals,
stripIndent,
} from '../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../utils/messages';
import { applicationIdInfo } from '../utils/messages';
import type { DockerConnectionCliFlags } from '../utils/docker';
import { dockerConnectionCliFlags } from '../utils/docker';
import { parseAsInteger } from '../utils/validation';
import { isV13 } from '../utils/version';
import { flags } from '@oclif/command';
import * as _ from 'lodash';
@ -40,7 +35,6 @@ import type { Application, BalenaSDK, PineExpand, Release } from 'balena-sdk';
import type { Preloader } from 'balena-preload';
interface FlagsDef extends DockerConnectionCliFlags {
app?: string;
fleet?: string;
commit?: string;
'splash-image'?: string;
@ -99,7 +93,6 @@ export default class PreloadCmd extends Command {
public static usage = 'preload <image>';
public static flags: flags.Input<FlagsDef> = {
...(isV13() ? {} : { app: cf.application }),
fleet: cf.fleet,
commit: flags.string({
description: `\
@ -163,11 +156,6 @@ Can be repeated to add multiple certificates.\
PreloadCmd,
);
if (options.app && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.app ||= options.fleet;
const balena = getBalenaSdk();
const balenaPreload = await import('balena-preload');
const visuals = getVisuals();
@ -194,15 +182,9 @@ Can be repeated to add multiple certificates.\
// balena-preload currently does not work with numerical app IDs
// Load app here, and use app slug from hereon
if (options.app && !options.app.includes('/')) {
// Disambiguate application (if is a number, it could either be an ID or a numerical name)
const { getApplication } = await import('../utils/sdk');
const application = await getApplication(balena, options.app);
if (!application) {
throw new ExpectedError(`Fleet not found: ${options.app}`);
}
options.app = application.slug;
}
const fleetSlug: string | undefined = options.fleet
? await (await import('../utils/sdk')).getFleetSlug(balena, options.fleet)
: undefined;
const progressBars: {
[key: string]: ReturnType<typeof getVisuals>['Progress'];
@ -238,15 +220,12 @@ Can be repeated to add multiple certificates.\
? 'latest'
: options.commit;
const image = params.image;
const appId = options.app;
const splashImage = options['splash-image'];
const additionalSpace = options['additional-space'];
const dontCheckArch = options['dont-check-arch'] || false;
const pinDevice = options['pin-device-to-release'] || false;
if (dontCheckArch && !appId) {
if (dontCheckArch && !fleetSlug) {
throw new ExpectedError(
'You need to specify a fleet if you disable the architecture check.',
);
@ -265,7 +244,7 @@ Can be repeated to add multiple certificates.\
const preloader = new balenaPreload.Preloader(
null,
docker,
appId,
fleetSlug,
commit,
image,
splashImage,
@ -309,7 +288,7 @@ Can be repeated to add multiple certificates.\
preloader.on('error', reject);
resolve(
this.prepareAndPreload(preloader, balena, {
appId,
appId: fleetSlug,
commit,
pinDevice,
}),

View File

@ -20,15 +20,9 @@ import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getCliUx, stripIndent } from '../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../utils/messages';
import { isV13 } from '../utils/version';
import { applicationIdInfo } from '../utils/messages';
interface FlagsDef {
application?: string;
fleet?: string;
device?: string;
duration?: string;
@ -77,7 +71,6 @@ export default class SupportCmd extends Command {
description: 'comma-separated list (no spaces) of device UUIDs',
char: 'd',
}),
...(isV13() ? {} : { application: cf.application }),
fleet: {
...cf.fleet,
description:
@ -98,18 +91,13 @@ export default class SupportCmd extends Command {
SupportCmd,
);
if (options.application && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.fleet;
const balena = getBalenaSdk();
const ux = getCliUx();
const enabling = params.action === 'enable';
// Validation
if (!options.device && !options.application) {
if (!options.device && !options.fleet) {
throw new ExpectedError('At least one device or fleet must be specified');
}
@ -125,7 +113,7 @@ export default class SupportCmd extends Command {
const expiryTs = Date.now() + this.parseDuration(duration);
const deviceUuids = options.device?.split(',') || [];
const appNames = options.application?.split(',') || [];
const appNames = options.fleet?.split(',') || [];
const enablingMessage = 'Enabling support access for';
const disablingMessage = 'Disabling support access for';

View File

@ -19,16 +19,9 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
app?: string;
application?: string;
fleet?: string;
device?: string;
release?: string;
@ -67,29 +60,17 @@ export default class TagRmCmd extends Command {
public static usage = 'tag rm <tagKey>';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'fleet', 'device', 'release'],
},
}),
fleet: {
...cf.fleet,
exclusive: ['app', 'application', 'device', 'release'],
exclusive: ['device', 'release'],
},
device: {
...cf.device,
exclusive: ['app', 'application', 'fleet', 'release'],
exclusive: ['fleet', 'release'],
},
release: {
...cf.release,
exclusive: ['app', 'application', 'fleet', 'device'],
exclusive: ['fleet', 'device'],
},
help: cf.help,
};
@ -101,25 +82,20 @@ export default class TagRmCmd extends Command {
TagRmCmd,
);
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
const balena = getBalenaSdk();
// Check user has specified one of application/device/release
if (!options.application && !options.device && !options.release) {
if (!options.fleet && !options.device && !options.release) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(TagRmCmd.missingResourceMessage);
}
const { tryAsInteger } = await import('../../utils/validation');
if (options.application) {
if (options.fleet) {
const { getTypedApplicationIdentifier } = await import('../../utils/sdk');
return balena.models.application.tags.remove(
await getTypedApplicationIdentifier(balena, options.application),
await getTypedApplicationIdentifier(balena, options.fleet),
params.tagKey,
);
}

View File

@ -19,16 +19,9 @@ import { flags } from '@oclif/command';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../../utils/messages';
import { isV13 } from '../../utils/version';
import { applicationIdInfo } from '../../utils/messages';
interface FlagsDef {
app?: string;
application?: string;
fleet?: string;
device?: string;
release?: string;
@ -80,18 +73,6 @@ export default class TagSetCmd extends Command {
public static usage = 'tag set <tagKey> [value]';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'fleet', 'device', 'release'],
},
}),
fleet: {
...cf.fleet,
exclusive: ['app', 'application', 'device', 'release'],
@ -114,15 +95,10 @@ export default class TagSetCmd extends Command {
TagSetCmd,
);
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
const balena = getBalenaSdk();
// Check user has specified one of application/device/release
if (!options.application && !options.device && !options.release) {
if (!options.fleet && !options.device && !options.release) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(TagSetCmd.missingResourceMessage);
}
@ -131,10 +107,10 @@ export default class TagSetCmd extends Command {
const { tryAsInteger } = await import('../../utils/validation');
if (options.application) {
if (options.fleet) {
const { getTypedApplicationIdentifier } = await import('../../utils/sdk');
return balena.models.application.tags.set(
await getTypedApplicationIdentifier(balena, options.application),
await getTypedApplicationIdentifier(balena, options.fleet),
params.tagKey,
params.value,
);

View File

@ -20,16 +20,9 @@ import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import {
applicationIdInfo,
appToFleetFlagMsg,
warnify,
} from '../utils/messages';
import { isV13 } from '../utils/version';
import { applicationIdInfo } from '../utils/messages';
interface FlagsDef {
app?: string;
application?: string;
fleet?: string;
device?: string;
release?: string;
@ -56,29 +49,17 @@ export default class TagsCmd extends Command {
public static usage = 'tags';
public static flags: flags.Input<FlagsDef> = {
...(isV13()
? {}
: {
application: {
...cf.application,
exclusive: ['app', 'fleet', 'device', 'release'],
},
app: {
...cf.app,
exclusive: ['application', 'fleet', 'device', 'release'],
},
}),
fleet: {
...cf.fleet,
exclusive: ['app', 'application', 'device', 'release'],
exclusive: ['device', 'release'],
},
device: {
...cf.device,
exclusive: ['app', 'application', 'fleet', 'release'],
exclusive: ['fleet', 'release'],
},
release: {
...cf.release,
exclusive: ['app', 'application', 'fleet', 'device'],
exclusive: ['fleet', 'device'],
},
help: cf.help,
};
@ -88,15 +69,10 @@ export default class TagsCmd extends Command {
public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(TagsCmd);
if ((options.application || options.app) && process.stderr.isTTY) {
console.error(warnify(appToFleetFlagMsg));
}
options.application ||= options.app || options.fleet;
const balena = getBalenaSdk();
// Check user has specified one of application/device/release
if (!options.application && !options.device && !options.release) {
if (!options.fleet && !options.device && !options.release) {
throw new ExpectedError(this.missingResourceMessage);
}
@ -104,10 +80,10 @@ export default class TagsCmd extends Command {
let tags;
if (options.application) {
if (options.fleet) {
const { getTypedApplicationIdentifier } = await import('../utils/sdk');
tags = await balena.models.application.tags.getAllByApplication(
await getTypedApplicationIdentifier(balena, options.application),
await getTypedApplicationIdentifier(balena, options.fleet),
);
}
if (options.device) {

View File

@ -23,31 +23,9 @@ import { isV13 } from './version';
import type { IBooleanFlag } from '@oclif/parser/lib/flags';
import type { DataOutputOptions, DataSetOutputOptions } from '../framework';
export const v13: IBooleanFlag<boolean> = flags.boolean({
description: stripIndent`\
enable selected balena CLI v13 pre-release features, like the renaming
from "application" to "fleet" in command output`,
default: false,
});
export const application = flags.string({
char: 'a',
description: 'DEPRECATED alias for -f, --fleet',
parse: lowercaseIfSlug,
});
// TODO: Consider remove second alias 'app' when we can, to simplify.
export const app = flags.string({
description: 'DEPRECATED alias for -f, --fleet',
parse: lowercaseIfSlug,
});
export const fleet = flags.string({
char: 'f',
description: isV13()
? 'fleet name, slug (preferred), or numeric ID (deprecated)'
: // avoid the '(deprecated)' remark in v12 while cf.application and
// cf.app are also described as deprecated, to avoid the impression
// that cf.fleet is deprecated as well.
'fleet name, slug (preferred), or numeric ID',
description: 'fleet name, slug (preferred), or numeric ID (deprecated)',
parse: lowercaseIfSlug,
});

View File

@ -175,21 +175,6 @@ If you have a particular use for buildArg, which is not satisfied by build-time
secrets, please contact us via support or the forums: https://forums.balena.io/
\n`;
export const appToFleetFlagMsg = `\
Renaming notice: The '-a', '--app' or '--application' options are now
aliases for the '-f' or '--fleet' options. THE ALIASES WILL BE REMOVED
in the next major version of the balena CLI (so that a different '--app'
option can be implemented in the future). Use '-f' or '--fleet' instead.
Find out more at: https://git.io/JRuZr`;
export const appToFleetOutputMsg = `\
Renaming notice: The 'app' or 'application' words in table headers
or in JSON object keys/properties will be replaced with 'fleet' in
the next major version of the CLI (v13). The --v13 option may be used
to enable the new names already now, and suppress a warning message.
(The --v13 option will be silently ignored in CLI v13.)
Find out more at: https://git.io/JRuZr`;
export function getNodeEngineVersionWarn(
version: string,
validVersions: string,

View File

@ -49,6 +49,23 @@ export async function getApplication(
return sdk.models.application.get(nameOrSlugOrId, options);
}
/**
* Given a fleet name, slug or numeric ID, return its slug.
* This function conditionally makes an async SDK/API call to retrieve the
* application object, which can be wasteful is the application object is
* required before or after the call to this function. If this is the case,
* consider calling `getApplication()` and reusing the application object.
*/
export async function getFleetSlug(
sdk: BalenaSDK,
nameOrSlugOrId: string | number,
): Promise<string> {
if (typeof nameOrSlugOrId === 'string' && nameOrSlugOrId.includes('/')) {
return nameOrSlugOrId;
}
return (await getApplication(sdk, nameOrSlugOrId)).slug;
}
/**
* Given an string representation of an application identifier,
* which could be one of:

View File

@ -21,9 +21,6 @@ import * as path from 'path';
import { apiResponsePath, BalenaAPIMock } from '../../nock/balena-api-mock';
import { cleanOutput, runCommand } from '../../helpers';
import { appToFleetOutputMsg, warnify } from '../../../build/utils/messages';
import { isV13 } from '../../../build/utils/version';
describe('balena device', function () {
let api: BalenaAPIMock;
@ -38,13 +35,6 @@ describe('balena device', function () {
api.done();
});
const expectedWarn =
!isV13() &&
process.stderr.isTTY &&
process.env.BALENA_CLI_TEST_TYPE !== 'standalone'
? warnify(appToFleetOutputMsg) + '\n'
: '';
it('should error if uuid not provided', async () => {
const { out, err } = await runCommand('device');
const errLines = cleanOutput(err);
@ -63,15 +53,13 @@ describe('balena device', function () {
'Content-Type': 'application/json',
});
const { out, err } = await runCommand('device 27fda508c');
const { out } = await runCommand('device 27fda508c');
const lines = cleanOutput(out);
expect(lines).to.have.lengthOf(25);
expect(lines[0]).to.equal('== SPARKLING WOOD');
expect(lines[6].split(':')[1].trim()).to.equal('test app');
expect(err.join('')).to.eql(expectedWarn);
});
it.skip('correctly handles devices with missing fields', async () => {
@ -87,15 +75,13 @@ describe('balena device', function () {
},
);
const { out, err } = await runCommand('device 27fda508c');
const { out } = await runCommand('device 27fda508c');
const lines = cleanOutput(out);
expect(lines).to.have.lengthOf(14);
expect(lines[0]).to.equal('== SPARKLING WOOD');
expect(lines[6].split(':')[1].trim()).to.equal('test app');
expect(err.join('')).to.eql(expectedWarn);
});
it('correctly handles devices with missing application', async () => {
@ -113,14 +99,12 @@ describe('balena device', function () {
},
);
const { out, err } = await runCommand('device 27fda508c');
const { out } = await runCommand('device 27fda508c');
const lines = cleanOutput(out);
expect(lines).to.have.lengthOf(25);
expect(lines[0]).to.equal('== SPARKLING WOOD');
expect(lines[6].split(':')[1].trim()).to.equal('N/a');
expect(err.join('')).to.eql(expectedWarn);
});
});

View File

@ -21,9 +21,6 @@ import * as path from 'path';
import { apiResponsePath, BalenaAPIMock } from '../../nock/balena-api-mock';
import { cleanOutput, runCommand } from '../../helpers';
import { appToFleetOutputMsg, warnify } from '../../../build/utils/messages';
import { isV13 } from '../../../build/utils/version';
describe('balena devices', function () {
let api: BalenaAPIMock;
@ -38,13 +35,6 @@ describe('balena devices', function () {
api.done();
});
const expectedWarn =
!isV13() &&
process.stderr.isTTY &&
process.env.BALENA_CLI_TEST_TYPE !== 'standalone'
? warnify(appToFleetOutputMsg) + '\n'
: '';
it('should list devices from own and collaborator apps', async () => {
api.scope
.get(
@ -54,14 +44,12 @@ describe('balena devices', function () {
'Content-Type': 'application/json',
});
const { out, err } = await runCommand('devices');
const { out } = await runCommand('devices');
const lines = cleanOutput(out);
expect(lines[0].replace(/ +/g, ' ')).to.equal(
isV13()
? 'ID UUID DEVICE NAME DEVICE TYPE FLEET STATUS IS ONLINE SUPERVISOR VERSION OS VERSION DASHBOARD URL'
: 'ID UUID DEVICE NAME DEVICE TYPE APPLICATION NAME STATUS IS ONLINE SUPERVISOR VERSION OS VERSION DASHBOARD URL',
'ID UUID DEVICE NAME DEVICE TYPE FLEET STATUS IS ONLINE SUPERVISOR VERSION OS VERSION DASHBOARD URL',
);
expect(lines).to.have.lengthOf.at.least(2);
@ -70,7 +58,5 @@ describe('balena devices', function () {
// Devices with missing applications will have application name set to `N/a`.
// e.g. When user has a device associated with app that user is no longer a collaborator of.
expect(lines.some((l) => l.includes('N/a'))).to.be.true;
expect(err.join('')).to.eql(expectedWarn);
});
});

View File

@ -21,9 +21,6 @@ import { stripIndent } from '../../../build/utils/lazy';
import { BalenaAPIMock } from '../../nock/balena-api-mock';
import { runCommand } from '../../helpers';
import { appToFleetOutputMsg, warnify } from '../../../build/utils/messages';
import { isV13 } from '../../../build/utils/version';
describe('balena envs', function () {
const appName = 'test';
let fullUUID: string;
@ -44,13 +41,6 @@ describe('balena envs', function () {
api.done();
});
const appToFleetOutputWarn =
!isV13() &&
process.stderr.isTTY &&
process.env.BALENA_CLI_TEST_TYPE !== 'standalone'
? warnify(appToFleetOutputMsg) + '\n'
: '';
it('should successfully list env vars for a test fleet', async () => {
api.expectGetApplication();
api.expectGetAppEnvVars();
@ -60,11 +50,11 @@ describe('balena envs', function () {
expect(out.join('')).to.equal(
stripIndent`
ID NAME VALUE FLEET SERVICE
120110 svar1 svar1-value test service1
120111 svar2 svar2-value test service2
120101 var1 var1-val test *
120102 var2 22 test *
ID NAME VALUE FLEET SERVICE
120110 svar1 svar1-value gh_user/testApp service1
120111 svar2 svar2-value gh_user/testApp service2
120101 var1 var1-val gh_user/testApp *
120102 var2 22 gh_user/testApp *
` + '\n',
);
expect(err.join('')).to.equal('');
@ -79,7 +69,7 @@ describe('balena envs', function () {
expect(out.join('')).to.equal(
stripIndent`
ID NAME VALUE FLEET
120300 RESIN_SUPERVISOR_NATIVE_LOGGER false test
120300 RESIN_SUPERVISOR_NATIVE_LOGGER false gh_user/testApp
` + '\n',
);
@ -94,7 +84,7 @@ describe('balena envs', function () {
expect(JSON.parse(out.join(''))).to.deep.equal([
{
fleetName: 'test',
fleetName: 'gh_user/testApp',
id: 120300,
name: 'RESIN_SUPERVISOR_NATIVE_LOGGER',
value: 'false',
@ -116,10 +106,10 @@ describe('balena envs', function () {
expect(out.join('')).to.equal(
stripIndent`
ID NAME VALUE FLEET SERVICE
120111 svar2 svar2-value test service2
120101 var1 var1-val test *
120102 var2 22 test *
ID NAME VALUE FLEET SERVICE
120111 svar2 svar2-value gh_user/testApp service2
120101 var1 var1-val gh_user/testApp *
120102 var2 22 gh_user/testApp *
` + '\n',
);
expect(err.join('')).to.equal('');
@ -138,10 +128,10 @@ describe('balena envs', function () {
expect(out.join('')).to.equal(
stripIndent`
ID NAME VALUE FLEET SERVICE
120110 svar1 svar1-value test ${serviceName}
120101 var1 var1-val test *
120102 var2 22 test *
ID NAME VALUE FLEET SERVICE
120110 svar1 svar1-value gh_user/testApp ${serviceName}
120101 var1 var1-val gh_user/testApp *
120102 var2 22 gh_user/testApp *
` + '\n',
);
expect(err.join('')).to.equal('');
@ -157,29 +147,24 @@ describe('balena envs', function () {
const uuid = shortUUID;
const result = await runCommand(`envs -d ${uuid}`);
const { err } = result;
let { out } = result;
let expected =
stripIndent`
ID NAME VALUE APPLICATION DEVICE SERVICE
120110 svar1 svar1-value test * service1
120111 svar2 svar2-value test * service2
120120 svar3 svar3-value test ${uuid} service1
120121 svar4 svar4-value test ${uuid} service2
120101 var1 var1-val test * *
120102 var2 22 test * *
120203 var3 var3-val test ${uuid} *
120204 var4 44 test ${uuid} *
ID NAME VALUE FLEET DEVICE SERVICE
120110 svar1 svar1-value org/test * service1
120111 svar2 svar2-value org/test * service2
120120 svar3 svar3-value org/test ${uuid} service1
120121 svar4 svar4-value org/test ${uuid} service2
120101 var1 var1-val org/test * *
120102 var2 22 org/test * *
120203 var3 var3-val org/test ${uuid} *
120204 var4 44 org/test ${uuid} *
` + '\n';
if (isV13()) {
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected
.replace(/ +/g, ' ')
.replace(' APPLICATION ', ' FLEET ')
.replace(/ test /g, ' org/test ');
}
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected.replace(/ +/g, ' ');
expect(out.join('')).to.equal(expected);
expect(err.join('')).to.equal(appToFleetOutputWarn);
});
it('should successfully list env variables for a test device (JSON output)', async () => {
@ -191,22 +176,17 @@ describe('balena envs', function () {
api.expectGetDeviceServiceVars();
const { out, err } = await runCommand(`envs -jd ${shortUUID}`);
let expected = `[
{ "id": 120101, "appName": "test", "deviceUUID": "*", "name": "var1", "value": "var1-val", "serviceName": "*" },
{ "id": 120102, "appName": "test", "deviceUUID": "*", "name": "var2", "value": "22", "serviceName": "*" },
{ "id": 120110, "appName": "test", "deviceUUID": "*", "name": "svar1", "value": "svar1-value", "serviceName": "service1" },
{ "id": 120111, "appName": "test", "deviceUUID": "*", "name": "svar2", "value": "svar2-value", "serviceName": "service2" },
{ "id": 120120, "appName": "test", "deviceUUID": "${fullUUID}", "name": "svar3", "value": "svar3-value", "serviceName": "service1" },
{ "id": 120121, "appName": "test", "deviceUUID": "${fullUUID}", "name": "svar4", "value": "svar4-value", "serviceName": "service2" },
{ "id": 120203, "appName": "test", "deviceUUID": "${fullUUID}", "name": "var3", "value": "var3-val", "serviceName": "*" },
{ "id": 120204, "appName": "test", "deviceUUID": "${fullUUID}", "name": "var4", "value": "44", "serviceName": "*" }
const expected = `[
{ "id": 120101, "fleetName": "org/test", "deviceUUID": "*", "name": "var1", "value": "var1-val", "serviceName": "*" },
{ "id": 120102, "fleetName": "org/test", "deviceUUID": "*", "name": "var2", "value": "22", "serviceName": "*" },
{ "id": 120110, "fleetName": "org/test", "deviceUUID": "*", "name": "svar1", "value": "svar1-value", "serviceName": "service1" },
{ "id": 120111, "fleetName": "org/test", "deviceUUID": "*", "name": "svar2", "value": "svar2-value", "serviceName": "service2" },
{ "id": 120120, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "svar3", "value": "svar3-value", "serviceName": "service1" },
{ "id": 120121, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "svar4", "value": "svar4-value", "serviceName": "service2" },
{ "id": 120203, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "var3", "value": "var3-val", "serviceName": "*" },
{ "id": 120204, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "var4", "value": "44", "serviceName": "*" }
]`;
if (isV13()) {
expected = expected.replace(
/"appName": "test"/g,
'"fleetName": "org/test"',
);
}
expect(JSON.parse(out.join(''))).to.deep.equal(JSON.parse(expected));
expect(err.join('')).to.equal('');
});
@ -218,23 +198,18 @@ describe('balena envs', function () {
api.expectGetAppConfigVars();
const result = await runCommand(`envs -d ${shortUUID} --config`);
const { err } = result;
let { out } = result;
let expected =
stripIndent`
ID NAME VALUE APPLICATION DEVICE
120300 RESIN_SUPERVISOR_NATIVE_LOGGER false test *
120400 RESIN_SUPERVISOR_POLL_INTERVAL 900900 test ${shortUUID}
ID NAME VALUE FLEET DEVICE
120300 RESIN_SUPERVISOR_NATIVE_LOGGER false org/test *
120400 RESIN_SUPERVISOR_POLL_INTERVAL 900900 org/test ${shortUUID}
` + '\n';
if (isV13()) {
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected
.replace(/ +/g, ' ')
.replace(' APPLICATION ', ' FLEET ')
.replace(/ test /g, ' org/test ');
}
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected.replace(/ +/g, ' ');
expect(out.join('')).to.equal(expected);
expect(err.join('')).to.equal(appToFleetOutputWarn);
});
it('should successfully list service variables for a test device (-s flag)', async () => {
@ -249,27 +224,22 @@ describe('balena envs', function () {
const uuid = shortUUID;
const result = await runCommand(`envs -d ${uuid} -s ${serviceName}`);
const { err } = result;
let { out } = result;
let expected =
stripIndent`
ID NAME VALUE APPLICATION DEVICE SERVICE
120111 svar2 svar2-value test * service2
120121 svar4 svar4-value test ${uuid} service2
120101 var1 var1-val test * *
120102 var2 22 test * *
120203 var3 var3-val test ${uuid} *
120204 var4 44 test ${uuid} *
ID NAME VALUE FLEET DEVICE SERVICE
120111 svar2 svar2-value org/test * service2
120121 svar4 svar4-value org/test ${uuid} service2
120101 var1 var1-val org/test * *
120102 var2 22 org/test * *
120203 var3 var3-val org/test ${uuid} *
120204 var4 44 org/test ${uuid} *
` + '\n';
if (isV13()) {
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected
.replace(/ +/g, ' ')
.replace(' APPLICATION ', ' FLEET ')
.replace(/ test /g, ' org/test ');
}
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected.replace(/ +/g, ' ');
expect(out.join('')).to.equal(expected);
expect(err.join('')).to.equal(appToFleetOutputWarn);
});
it('should successfully list env and service variables for a test device (unknown fleet)', async () => {
@ -279,24 +249,20 @@ describe('balena envs', function () {
const uuid = shortUUID;
const result = await runCommand(`envs -d ${uuid}`);
const { err } = result;
let { out } = result;
let expected =
stripIndent`
ID NAME VALUE APPLICATION DEVICE SERVICE
120120 svar3 svar3-value N/A ${uuid} service1
120121 svar4 svar4-value N/A ${uuid} service2
120203 var3 var3-val N/A ${uuid} *
120204 var4 44 N/A ${uuid} *
ID NAME VALUE FLEET DEVICE SERVICE
120120 svar3 svar3-value N/A ${uuid} service1
120121 svar4 svar4-value N/A ${uuid} service2
120203 var3 var3-val N/A ${uuid} *
120204 var4 44 N/A ${uuid} *
` + '\n';
if (isV13()) {
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected
.replace(/ +/g, ' ')
.replace(' APPLICATION ', ' FLEET ');
}
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected.replace(/ +/g, ' ');
expect(out.join('')).to.equal(expected);
expect(err.join('')).to.equal(appToFleetOutputWarn);
});
it('should successfully list env and service vars for a test device (-s flags)', async () => {
@ -311,27 +277,22 @@ describe('balena envs', function () {
const uuid = shortUUID;
const result = await runCommand(`envs -d ${uuid} -s ${serviceName}`);
const { err } = result;
let { out } = result;
let expected =
stripIndent`
ID NAME VALUE APPLICATION DEVICE SERVICE
120110 svar1 svar1-value test * ${serviceName}
120120 svar3 svar3-value test ${uuid} ${serviceName}
120101 var1 var1-val test * *
120102 var2 22 test * *
120203 var3 var3-val test ${uuid} *
120204 var4 44 test ${uuid} *
ID NAME VALUE FLEET DEVICE SERVICE
120110 svar1 svar1-value org/test * ${serviceName}
120120 svar3 svar3-value org/test ${uuid} ${serviceName}
120101 var1 var1-val org/test * *
120102 var2 22 org/test * *
120203 var3 var3-val org/test ${uuid} *
120204 var4 44 org/test ${uuid} *
` + '\n';
if (isV13()) {
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected
.replace(/ +/g, ' ')
.replace(' APPLICATION ', ' FLEET ')
.replace(/ test /g, ' org/test ');
}
out = out.map((l) => l.replace(/ +/g, ' '));
expected = expected.replace(/ +/g, ' ');
expect(out.join('')).to.equal(expected);
expect(err.join('')).to.equal(appToFleetOutputWarn);
});
it('should successfully list env and service vars for a test device (-js flags)', async () => {
@ -347,20 +308,15 @@ describe('balena envs', function () {
const { out, err } = await runCommand(
`envs -d ${shortUUID} -js ${serviceName}`,
);
let expected = `[
{ "id": 120101, "appName": "test", "deviceUUID": "*", "name": "var1", "value": "var1-val", "serviceName": "*" },
{ "id": 120102, "appName": "test", "deviceUUID": "*", "name": "var2", "value": "22", "serviceName": "*" },
{ "id": 120110, "appName": "test", "deviceUUID": "*", "name": "svar1", "value": "svar1-value", "serviceName": "${serviceName}" },
{ "id": 120120, "appName": "test", "deviceUUID": "${fullUUID}", "name": "svar3", "value": "svar3-value", "serviceName": "${serviceName}" },
{ "id": 120203, "appName": "test", "deviceUUID": "${fullUUID}", "name": "var3", "value": "var3-val", "serviceName": "*" },
{ "id": 120204, "appName": "test", "deviceUUID": "${fullUUID}", "name": "var4", "value": "44", "serviceName": "*" }
const expected = `[
{ "id": 120101, "fleetName": "org/test", "deviceUUID": "*", "name": "var1", "value": "var1-val", "serviceName": "*" },
{ "id": 120102, "fleetName": "org/test", "deviceUUID": "*", "name": "var2", "value": "22", "serviceName": "*" },
{ "id": 120110, "fleetName": "org/test", "deviceUUID": "*", "name": "svar1", "value": "svar1-value", "serviceName": "${serviceName}" },
{ "id": 120120, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "svar3", "value": "svar3-value", "serviceName": "${serviceName}" },
{ "id": 120203, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "var3", "value": "var3-val", "serviceName": "*" },
{ "id": 120204, "fleetName": "org/test", "deviceUUID": "${fullUUID}", "name": "var4", "value": "44", "serviceName": "*" }
]`;
if (isV13()) {
expected = expected.replace(
/"appName": "test"/g,
'"fleetName": "org/test"',
);
}
expect(JSON.parse(out.join(''))).to.deep.equal(JSON.parse(expected));
expect(err.join('')).to.equal('');
});