diff --git a/doc/cli.markdown b/doc/cli.markdown index bc9f416a..5c05a936 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -662,45 +662,70 @@ service name ## env rm ID -Remove a configuration or environment variable from an application or device, -as selected by command-line options. +Remove a configuration or environment variable from an application, device +or service, as selected by command-line options. -Note that this command asks for confirmation interactively. -You can avoid this by passing the `--yes` boolean option. +Variables are selected by their database ID (as reported by the 'balena envs' +command) and one of six database "resource types": -The --device option selects a device instead of an application. -The --config option selects a config var instead of an env var. +- application (fleet) environment variable +- application (fleet) configuration variable (--config) +- application (fleet) service variable (--service) +- device environment variable (--device) +- device configuration variable (--device --config) +- device service variable (--device --service) -Service-specific variables are not currently supported. The following -examples remove variables that apply to all services in an app or device. +The --device option selects a device-specific variable instead of an application +(fleet) variable. + +The --config option selects a configuration variable. Configuration variable +names typically start with the 'BALENA_' or 'RESIN_' prefixes and are used to +configure balena platform features. + +The --service option selects a service variable, which is an environment variable +that applies to a specifc service (application container) in a microservices +(multicontainer) application. + +The --service and --config options cannot be used together, but they can be +used alongside the --device option to select a device-specific service or +configuration variable. + +Interactive confirmation is normally asked before the variable is deleted. +The --yes option disables this behaviour. Examples: - $ balena env rm 215 - $ balena env rm 215 --yes - $ balena env rm 215 --config - $ balena env rm 215 --device - $ balena env rm 215 --device --config + $ balena env rm 123123 + $ balena env rm 234234 --yes + $ balena env rm 345345 --config + $ balena env rm 456456 --service + $ balena env rm 567567 --device + $ balena env rm 678678 --device --config + $ balena env rm 789789 --device --service --yes ### Arguments #### ID -environment variable numeric database ID +variable's numeric database ID ### Options -#### -d, --device - -Selects a device environment variable instead of an application environment variable - #### -c, --config -Selects a configuration variable instead of an environment variable +select a configuration variable (may be used together with the --device option) + +#### -d, --device + +select a device-specific variable instead of an application (fleet) variable + +#### -s, --service + +select a service variable (may be used together with the --device option) #### -y, --yes -Run in non-interactive mode +do not prompt for confirmation before deleting the variable ## env add NAME [VALUE] diff --git a/lib/actions-oclif/env/rm.ts b/lib/actions-oclif/env/rm.ts index 1f40c62c..7a48ae87 100644 --- a/lib/actions-oclif/env/rm.ts +++ b/lib/actions-oclif/env/rm.ts @@ -18,12 +18,15 @@ import { Command, flags } from '@oclif/command'; import { stripIndent } from 'common-tags'; -import { ExpectedError } from '../../errors'; +import * as ec from '../../utils/env-common'; import { CommandHelp } from '../../utils/oclif-utils'; +type IArg = import('@oclif/parser').args.IArg; + interface FlagsDef { config: boolean; device: boolean; + service: boolean; yes: boolean; } @@ -33,62 +36,53 @@ interface ArgsDef { export default class EnvRmCmd extends Command { public static description = stripIndent` - Remove an environment variable from an application or device. + Remove a config or env var from an application, device or service. - Remove a configuration or environment variable from an application or device, - as selected by command-line options. + Remove a configuration or environment variable from an application, device + or service, as selected by command-line options. - Note that this command asks for confirmation interactively. - You can avoid this by passing the \`--yes\` boolean option. + ${ec.rmRenameHelp.split('\n').join('\n\t\t')} - The --device option selects a device instead of an application. - The --config option selects a config var instead of an env var. - - Service-specific variables are not currently supported. The following - examples remove variables that apply to all services in an app or device. + Interactive confirmation is normally asked before the variable is deleted. + The --yes option disables this behaviour. `; public static examples = [ - '$ balena env rm 215', - '$ balena env rm 215 --yes', - '$ balena env rm 215 --config', - '$ balena env rm 215 --device', - '$ balena env rm 215 --device --config', + '$ balena env rm 123123', + '$ balena env rm 234234 --yes', + '$ balena env rm 345345 --config', + '$ balena env rm 456456 --service', + '$ balena env rm 567567 --device', + '$ balena env rm 678678 --device --config', + '$ balena env rm 789789 --device --service --yes', ]; - public static args = [ + public static args: Array> = [ { name: 'id', required: true, - description: 'environment variable numeric database ID', + description: "variable's numeric database ID", + parse: input => ec.parseDbId(input), }, ]; - // hardcoded 'env add' to avoid oclif's 'env:add' topic syntax + // hardcoded 'env rm' to avoid oclif's 'env:rm' topic syntax public static usage = 'env rm ' + new CommandHelp({ args: EnvRmCmd.args }).defaultUsage(); public static flags: flags.Input = { - device: flags.boolean({ - char: 'd', - description: - 'Selects a device environment variable instead of an application environment variable', - default: false, - }), - config: flags.boolean({ - char: 'c', - description: - 'Selects a configuration variable instead of an environment variable', - default: false, - }), + config: ec.booleanConfig, + device: ec.booleanDevice, + service: ec.booleanService, yes: flags.boolean({ char: 'y', - description: 'Run in non-interactive mode', + description: + 'do not prompt for confirmation before deleting the variable', default: false, }), }; public async run() { - const { args: params, flags: options } = this.parse( + const { args: params, flags: opt } = this.parse( EnvRmCmd, ); const balena = (await import('balena-sdk')).fromSharedOptions(); @@ -96,25 +90,15 @@ export default class EnvRmCmd extends Command { await checkLoggedIn(); - if (isNaN(params.id) || !Number.isInteger(Number(params.id))) { - throw new ExpectedError('The environment variable id must be an integer'); - } - await confirm( - options.yes || false, + opt.yes || false, 'Are you sure you want to delete the environment variable?', undefined, true, ); await balena.pine.delete({ - resource: options.device - ? options.config - ? 'device_config_variable' - : 'device_environment_variable' - : options.config - ? 'application_config_variable' - : 'application_environment_variable', + resource: ec.getVarResourceName(opt.config, opt.device, opt.service), id: params.id, }); } diff --git a/lib/utils/env-common.ts b/lib/utils/env-common.ts new file mode 100644 index 00000000..2c2e0836 --- /dev/null +++ b/lib/utils/env-common.ts @@ -0,0 +1,110 @@ +/** + * @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. + */ + +import { flags } from '@oclif/command'; +import { stripIndent } from 'common-tags'; +import * as _ from 'lodash'; + +import { ExpectedError } from '../errors'; + +type IBooleanFlag = import('@oclif/parser/lib/flags').IBooleanFlag; + +export const booleanConfig: IBooleanFlag = flags.boolean({ + char: 'c', + description: + 'select a configuration variable (may be used together with the --device option)', + default: false, + exclusive: ['service'], +}); + +export const booleanDevice: IBooleanFlag = flags.boolean({ + char: 'd', + description: + 'select a device-specific variable instead of an application (fleet) variable', + default: false, +}); + +export const booleanService: IBooleanFlag = flags.boolean({ + char: 's', + description: + 'select a service variable (may be used together with the --device option)', + default: false, + exclusive: ['config'], +}); + +export const rmRenameHelp = stripIndent` + Variables are selected by their database ID (as reported by the 'balena envs' + command) and one of six database "resource types": + + - application (fleet) environment variable + - application (fleet) configuration variable (--config) + - application (fleet) service variable (--service) + - device environment variable (--device) + - device configuration variable (--device --config) + - device service variable (--device --service) + + The --device option selects a device-specific variable instead of an application + (fleet) variable. + + The --config option selects a configuration variable. Configuration variable + names typically start with the 'BALENA_' or 'RESIN_' prefixes and are used to + configure balena platform features. + + The --service option selects a service variable, which is an environment variable + that applies to a specifc service (application container) in a microservices + (multicontainer) application. + + The --service and --config options cannot be used together, but they can be + used alongside the --device option to select a device-specific service or + configuration variable. +`; + +/** + * Return an API database resource name like 'device_config_variable' or + * 'service_environment_variable' given three boolean arguments. + * @param isConfig Whether the resource is a configuration variable + * @param isDevice Whether the resource is a device variable + * @param isService Whether the resource is a service variable + */ +export function getVarResourceName( + isConfig: boolean, + isDevice: boolean, + isService: boolean, +): string { + return isDevice + ? isConfig + ? 'device_config_variable' + : isService + ? 'device_service_environment_variable' + : 'device_environment_variable' + : isConfig + ? 'application_config_variable' + : isService + ? 'service_environment_variable' + : 'application_environment_variable'; +} + +/** + * Check that the given string looks like and parses like a decimal integer, + * and return the parsed value. + */ +export function parseDbId(id: string): number { + if (/^[\d]+$/.exec(id) == null) { + throw new ExpectedError("The variable's ID must be an integer"); + } + return Number(id); +} diff --git a/tests/commands/help.spec.ts b/tests/commands/help.spec.ts index aca380a6..ed9b156c 100644 --- a/tests/commands/help.spec.ts +++ b/tests/commands/help.spec.ts @@ -60,7 +60,7 @@ Additional commands: devices supported list all supported devices env add [value] add an environment or config variable to an application, device or service env rename change the value of an environment variable for an app or device - env rm remove an environment variable from an application or device + env rm remove a config or env var from an application, device or service envs list the environment or config variables of an application, device or service key list a single ssh key key add [path] add a SSH key to balena