diff --git a/capitanodoc.ts b/capitanodoc.ts index 5388394b..650651a5 100644 --- a/capitanodoc.ts +++ b/capitanodoc.ts @@ -83,6 +83,10 @@ environment variable (in the same standard URL format).\ title: 'Environment Variables', files: ['build/actions/environment-variables.js'], }, + { + title: 'Tags', + files: ['build/actions/tags.js'], + }, { title: 'Help', files: ['build/actions/help.js'], diff --git a/doc/cli.markdown b/doc/cli.markdown index 2f8c733b..771847e5 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -106,6 +106,12 @@ environment variable (in the same standard URL format). - [env add <key> [value]](#env-add-key-value-) - [env rename <id> <value>](#env-rename-id-value-) +- Tags + + - [tags](#tags) + - [tag set <tagKey> [value]](#tag-set-tagkey-value-) + - [tag rm <tagKey>](#tag-rm-tagkey-) + - Help - [help [command...]](#help-command-) @@ -672,6 +678,89 @@ Examples: device +# Tags + +## tags + +Use this command to list all tags for +a particular application, device or release. + +This command lists all application/device/release tags. + +Example: + + $ balena tags --application MyApp + $ balena tags --device 7cf02a6 + $ balena tags --release 1234 + +### Options + +#### --application, -a, --app <application> + +application name + +#### --device, -d <device> + +device uuid + +#### --release, -r <release> + +release id + +## tag set <tagKey> [value] + +Use this command to set a tag to an application, device or release. + +You can optionally provide a value to be associated with the created +tag, as an extra argument after the tag key. When the value isn't +provided, a tag with an empty value is created. + +Examples: + + $ balena tag set mySimpleTag --application MyApp + $ balena tag set myCompositeTag myTagValue --application MyApp + $ balena tag set myCompositeTag myTagValue --device 7cf02a6 + $ balena tag set myCompositeTag myTagValue --release 1234 + $ balena tag set myCompositeTag "my tag value with whitespaces" --release 1234 + +### Options + +#### --application, -a, --app <application> + +application name + +#### --device, -d <device> + +device uuid + +#### --release, -r <release> + +release id + +## tag rm <tagKey> + +Use this command to remove a tag from an application, device or release. + +Examples: + + $ balena tag rm myTagKey --application MyApp + $ balena tag rm myTagKey --device 7cf02a6 + $ balena tag rm myTagKey --release 1234 + +### Options + +#### --application, -a, --app <application> + +application name + +#### --device, -d <device> + +device uuid + +#### --release, -r <release> + +release id + # Help ## help [command...] diff --git a/lib/actions/command-options.ts b/lib/actions/command-options.ts index 562138d0..dfb68e4c 100644 --- a/lib/actions/command-options.ts +++ b/lib/actions/command-options.ts @@ -35,6 +35,13 @@ export const application = _.defaults( optionalApplication, ); +export const optionalRelease = { + signature: 'release', + parameter: 'release', + description: 'release id', + alias: 'r', +}; + export const optionalDevice = { signature: 'device', parameter: 'device', diff --git a/lib/actions/index.coffee b/lib/actions/index.coffee index 14c8ee69..160f3d69 100644 --- a/lib/actions/index.coffee +++ b/lib/actions/index.coffee @@ -22,6 +22,7 @@ module.exports = info: require('./info') device: require('./device') env: require('./environment-variables') + tags: require('./tags') keys: require('./keys') logs: require('./logs') local: require('./local') diff --git a/lib/actions/tags.ts b/lib/actions/tags.ts new file mode 100644 index 00000000..c8be2653 --- /dev/null +++ b/lib/actions/tags.ts @@ -0,0 +1,277 @@ +/* +Copyright 2016-2018 Balena + +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 { ApplicationTag, DeviceTag, ReleaseTag } from 'balena-sdk'; +import { CommandDefinition } from 'capitano'; +import { stripIndent } from 'common-tags'; +import { normalizeUuidProp } from '../utils/normalization'; +import * as commandOptions from './command-options'; + +export const list: CommandDefinition< + {}, + { + application?: string; + device?: string; + release?: number; + } +> = { + signature: 'tags', + description: 'list all resource tags', + help: stripIndent` + Use this command to list all tags for + a particular application, device or release. + + This command lists all application/device/release tags. + + Example: + + $ balena tags --application MyApp + $ balena tags --device 7cf02a6 + $ balena tags --release 1234 + `, + options: [ + commandOptions.optionalApplication, + commandOptions.optionalDevice, + commandOptions.optionalRelease, + ], + permission: 'user', + async action(_params, options, done) { + normalizeUuidProp(options, 'device'); + const Bluebird = await import('bluebird'); + const _ = await import('lodash'); + const balena = (await import('balena-sdk')).fromSharedOptions(); + const visuals = await import('resin-cli-visuals'); + + const { exitWithExpectedError } = await import('../utils/patterns'); + + return Bluebird.try(() => { + const wrongParametersError = stripIndent` + To list resource tags, you must provide exactly one of: + + * An application, with --application + * A device, with --device + * A release, with --release + + See the help page for examples: + + $ balena help tags + `; + + if ( + _.filter([options.application, options.device, options.release]) + .length !== 1 + ) { + return exitWithExpectedError(wrongParametersError); + } + + if (options.application) { + return balena.models.application.tags.getAllByApplication( + options.application, + ); + } + if (options.device) { + return balena.models.device.tags.getAllByDevice(options.device); + } + if (options.release) { + return balena.models.release.tags.getAllByRelease(options.release); + } + + // return never, so that TS typings are happy + return exitWithExpectedError(wrongParametersError); + }) + .tap(function(environmentVariables) { + if (_.isEmpty(environmentVariables)) { + exitWithExpectedError('No tags found'); + } + + console.log( + visuals.table.horizontal(environmentVariables, [ + 'id', + 'tag_key', + 'value', + ]), + ); + }) + .nodeify(done); + }, +}; + +export const set: CommandDefinition< + { + tagKey: string; + value?: string; + }, + { + application?: string; + device?: string; + release?: number; + } +> = { + signature: 'tag set [value]', + description: 'set a resource tag', + help: stripIndent` + Use this command to set a tag to an application, device or release. + + You can optionally provide a value to be associated with the created + tag, as an extra argument after the tag key. When the value isn't + provided, a tag with an empty value is created. + + Examples: + + $ balena tag set mySimpleTag --application MyApp + $ balena tag set myCompositeTag myTagValue --application MyApp + $ balena tag set myCompositeTag myTagValue --device 7cf02a6 + $ balena tag set myCompositeTag myTagValue --release 1234 + $ balena tag set myCompositeTag "my tag value with whitespaces" --release 1234 + `, + options: [ + commandOptions.optionalApplication, + commandOptions.optionalDevice, + commandOptions.optionalRelease, + ], + permission: 'user', + async action(params, options, done) { + normalizeUuidProp(options, 'device'); + const Bluebird = await import('bluebird'); + const _ = await import('lodash'); + const balena = (await import('balena-sdk')).fromSharedOptions(); + + const { exitWithExpectedError } = await import('../utils/patterns'); + + return Bluebird.try(() => { + if (_.isEmpty(params.tagKey)) { + return exitWithExpectedError('No tag key was provided'); + } + + if ( + _.filter([options.application, options.device, options.release]) + .length !== 1 + ) { + return exitWithExpectedError(stripIndent` + To set a resource tag, you must provide exactly one of: + + * An application, with --application + * A device, with --device + * A release, with --release + + See the help page for examples: + + $ balena help tag set + `); + } + + if (params.value == null) { + params.value = ''; + } + + if (options.application) { + return balena.models.application.tags.set( + options.application, + params.tagKey, + params.value, + ); + } + if (options.device) { + return balena.models.device.tags.set( + options.device, + params.tagKey, + params.value, + ); + } + if (options.release) { + return balena.models.release.tags.set( + options.release, + params.tagKey, + params.value, + ); + } + }).nodeify(done); + }, +}; + +export const remove: CommandDefinition< + { + tagKey: string; + }, + { + application?: string; + device?: string; + release?: number; + } +> = { + signature: 'tag rm ', + description: 'remove a resource tag', + help: stripIndent` + Use this command to remove a tag from an application, device or release. + + Examples: + + $ balena tag rm myTagKey --application MyApp + $ balena tag rm myTagKey --device 7cf02a6 + $ balena tag rm myTagKey --release 1234 + `, + options: [ + commandOptions.optionalApplication, + commandOptions.optionalDevice, + commandOptions.optionalRelease, + ], + permission: 'user', + async action(params, options, done) { + const Bluebird = await import('bluebird'); + const _ = await import('lodash'); + const balena = (await import('balena-sdk')).fromSharedOptions(); + const { exitWithExpectedError } = await import('../utils/patterns'); + + return Bluebird.try(() => { + if (_.isEmpty(params.tagKey)) { + return exitWithExpectedError('No tag key was provided'); + } + + if ( + _.filter([options.application, options.device, options.release]) + .length !== 1 + ) { + return exitWithExpectedError(stripIndent` + To remove a resource tag, you must provide exactly one of: + + * An application, with --application + * A device, with --device + * A release, with --release + + See the help page for examples: + + $ balena help tag rm + `); + } + + if (options.application) { + return balena.models.application.tags.remove( + options.application, + params.tagKey, + ); + } + if (options.device) { + return balena.models.device.tags.remove(options.device, params.tagKey); + } + if (options.release) { + return balena.models.release.tags.remove( + options.release, + params.tagKey, + ); + } + }).nodeify(done); + }, +}; diff --git a/lib/app.coffee b/lib/app.coffee index a0c976fc..84aa8700 100644 --- a/lib/app.coffee +++ b/lib/app.coffee @@ -164,6 +164,11 @@ capitano.command(actions.env.add) capitano.command(actions.env.rename) capitano.command(actions.env.remove) +# ---------- Tags Module ---------- +capitano.command(actions.tags.list) +capitano.command(actions.tags.set) +capitano.command(actions.tags.remove) + # ---------- OS Module ---------- capitano.command(actions.os.versions) capitano.command(actions.os.download)