From 49b00e18aefee6759093e116b0b756dbcd3b25c9 Mon Sep 17 00:00:00 2001 From: Scott Lowe Date: Tue, 24 Mar 2020 11:44:32 +0100 Subject: [PATCH 1/2] Convert command `settings` to oclif Change-type: patch Signed-off-by: Scott Lowe --- automation/capitanodoc/capitanodoc.ts | 2 +- doc/cli.markdown | 14 -------- lib/actions-oclif/settings.ts | 52 +++++++++++++++++++++++++++ lib/actions/index.coffee | 1 - lib/actions/settings.ts | 38 -------------------- lib/app-capitano.coffee | 3 -- lib/preparser.ts | 1 + 7 files changed, 54 insertions(+), 57 deletions(-) create mode 100644 lib/actions-oclif/settings.ts delete mode 100644 lib/actions/settings.ts diff --git a/automation/capitanodoc/capitanodoc.ts b/automation/capitanodoc/capitanodoc.ts index 48a95d09..75823d26 100644 --- a/automation/capitanodoc/capitanodoc.ts +++ b/automation/capitanodoc/capitanodoc.ts @@ -104,7 +104,7 @@ const capitanoDoc = { }, { title: 'Settings', - files: ['build/actions/settings.js'], + files: ['build/actions-oclif/settings.js'], }, { title: 'Local', diff --git a/doc/cli.markdown b/doc/cli.markdown index 52788c92..eceefaa8 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -229,10 +229,6 @@ If you come across any problems or would like to get in touch: - [push <applicationOrDevice>](#push-applicationordevice) -- Settings - - - [settings](#settings) - - Local - [local configure <target>](#local-configure-target) @@ -1813,16 +1809,6 @@ left hand side of the = character will be treated as the variable name. On Windows only, convert line endings from CRLF (Windows format) to LF (Unix format). Source files are not modified. -# Settings - -## settings - -Use this command to display detected settings - -Examples: - - $ balena settings - # Local ## local configure <target> diff --git a/lib/actions-oclif/settings.ts b/lib/actions-oclif/settings.ts new file mode 100644 index 00000000..4df9d864 --- /dev/null +++ b/lib/actions-oclif/settings.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright 2020 Balena Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { flags } from '@oclif/command'; +import { stripIndent } from 'common-tags'; +import Command from '../command'; +import * as cf from '../utils/common-flags'; +import { getBalenaSdk } from '../utils/lazy'; + +interface FlagsDef { + help: void; +} + +export default class SettingsCmd extends Command { + public static description = stripIndent` + Print current settings. + + Use this command to display current balena CLI settings. +`; + public static examples = ['$ balena settings']; + + public static usage = 'settings'; + + public static flags: flags.Input = { + help: cf.help, + }; + + public async run() { + this.parse(SettingsCmd); + + const prettyjson = await import('prettyjson'); + + return getBalenaSdk() + .settings.getAll() + .then(prettyjson.render) + .then(console.log); + } +} diff --git a/lib/actions/index.coffee b/lib/actions/index.coffee index 85504045..23a2ffed 100644 --- a/lib/actions/index.coffee +++ b/lib/actions/index.coffee @@ -27,7 +27,6 @@ module.exports = notes: require('./notes') help: require('./help') os: require('./os') - settings: require('./settings') config: require('./config') ssh: require('./ssh') internal: require('./internal') diff --git a/lib/actions/settings.ts b/lib/actions/settings.ts deleted file mode 100644 index 66a27957..00000000 --- a/lib/actions/settings.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2016-2017 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 { CommandDefinition } from 'capitano'; -import { getBalenaSdk } from '../utils/lazy'; - -export const list: CommandDefinition = { - signature: 'settings', - description: 'print current settings', - help: `\ -Use this command to display detected settings - -Examples: - - $ balena settings\ -`, - async action() { - const prettyjson = await import('prettyjson'); - - return getBalenaSdk() - .settings.getAll() - .then(prettyjson.render) - .then(console.log); - }, -}; diff --git a/lib/app-capitano.coffee b/lib/app-capitano.coffee index f1ec4561..5f6c57e3 100644 --- a/lib/app-capitano.coffee +++ b/lib/app-capitano.coffee @@ -101,9 +101,6 @@ capitano.command(actions.config.inject) capitano.command(actions.config.reconfigure) capitano.command(actions.config.generate) -# ---------- Settings Module ---------- -capitano.command(actions.settings.list) - # ---------- Logs Module ---------- capitano.command(actions.logs.logs) diff --git a/lib/preparser.ts b/lib/preparser.ts index 5e890065..8b6c3e8c 100644 --- a/lib/preparser.ts +++ b/lib/preparser.ts @@ -133,6 +133,7 @@ export const convertedCommands = [ 'env:rm', 'os:configure', 'version', + 'settings', ]; /** From fcad35402aa7cfc43ea16f6c0e620fe7281a318f Mon Sep 17 00:00:00 2001 From: Scott Lowe Date: Wed, 25 Mar 2020 18:07:17 +0100 Subject: [PATCH 2/2] Convert command `note` to oclif Add oclif support for piped input Change-type: patch Signed-off-by: Scott Lowe --- automation/capitanodoc/capitanodoc.ts | 2 +- automation/capitanodoc/index.ts | 3 + doc/cli.markdown | 41 +++++++++-- lib/actions-oclif/note.ts | 100 ++++++++++++++++++++++++++ lib/actions-oclif/settings.ts | 2 +- lib/actions/index.coffee | 1 - lib/actions/notes.ts | 58 --------------- lib/app-capitano.coffee | 3 - lib/command.ts | 34 +++++++-- lib/preparser.ts | 3 +- 10 files changed, 169 insertions(+), 78 deletions(-) create mode 100644 lib/actions-oclif/note.ts delete mode 100644 lib/actions/notes.ts diff --git a/automation/capitanodoc/capitanodoc.ts b/automation/capitanodoc/capitanodoc.ts index 75823d26..3013e4e2 100644 --- a/automation/capitanodoc/capitanodoc.ts +++ b/automation/capitanodoc/capitanodoc.ts @@ -84,7 +84,7 @@ const capitanoDoc = { }, { title: 'Notes', - files: ['build/actions/notes.js'], + files: ['build/actions-oclif/note.js'], }, { title: 'OS', diff --git a/automation/capitanodoc/index.ts b/automation/capitanodoc/index.ts index aec8ca9f..f1a2e220 100644 --- a/automation/capitanodoc/index.ts +++ b/automation/capitanodoc/index.ts @@ -68,6 +68,9 @@ function importCapitanoCommands(jsFilename: string): CapitanoCommand[] { } function importOclifCommands(jsFilename: string): OclifCommand[] { + // TODO: Currently oclif commands with no `usage` overridden will cause + // an error when parsed. This should be improved so that `usage` does not have + // to be overridden if not necessary. const command: OclifCommand = require(path.join(process.cwd(), jsFilename)) .default as OclifCommand; return [command]; diff --git a/doc/cli.markdown b/doc/cli.markdown index eceefaa8..429d09e3 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -229,6 +229,10 @@ If you come across any problems or would like to get in touch: - [push <applicationOrDevice>](#push-applicationordevice) +- Settings + + - [settings](#settings) + - Local - [local configure <target>](#local-configure-target) @@ -1248,22 +1252,35 @@ The mapping of remote to local ports. ## note <|note> -Use this command to set or update a device note. +Set or update a device note. If the note argument is not provided, +it will be read from stdin. -If note command isn't passed, the tool attempts to read from `stdin`. - -To view the notes, use $ balena device . +To view device notes, use the `balena device ` command. Examples: $ balena note "My useful note" --device 7cf02a6 $ cat note.txt | balena note --device 7cf02a6 +### Arguments + +#### NOTE + +note content + ### Options -#### --device, -d, --dev <device> +#### -d, --device DEVICE + +device UUID + +#### --dev DEV + + + +#### --stdin + -device uuid # OS @@ -1809,6 +1826,18 @@ left hand side of the = character will be treated as the variable name. On Windows only, convert line endings from CRLF (Windows format) to LF (Unix format). Source files are not modified. +# Settings + +## settings + +Use this command to display current balena CLI settings. + +Examples: + + $ balena settings + +### Options + # Local ## local configure <target> diff --git a/lib/actions-oclif/note.ts b/lib/actions-oclif/note.ts new file mode 100644 index 00000000..082d3fcd --- /dev/null +++ b/lib/actions-oclif/note.ts @@ -0,0 +1,100 @@ +/** + * @license + * Copyright 2016-2020 Balena Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { flags } from '@oclif/command'; +import { stripIndent } from 'common-tags'; +import * as _ from 'lodash'; +import Command from '../command'; +import { ExpectedError } from '../errors'; +import * as cf from '../utils/common-flags'; +import { getBalenaSdk } from '../utils/lazy'; + +interface FlagsDef { + device?: string; // device UUID + dev?: string; // Alias for device. + stdin: boolean; + help: void; +} + +interface ArgsDef { + note: string; +} + +export default class NoteCmd extends Command { + public static description = stripIndent` + Set a device note. + + Set or update a device note. If the note argument is not provided, + it will be read from stdin. + + To view device notes, use the \`balena device \` command. +`; + public static examples = [ + '$ balena note "My useful note" --device 7cf02a6', + '$ cat note.txt | balena note --device 7cf02a6', + ]; + + public static args = [ + { + name: 'note', + // required: true, + description: 'note content', + }, + ]; + + public static usage = 'note <|note>'; + + public static flags: flags.Input = { + device: { exclusive: ['dev'], ...cf.device }, + dev: flags.string({ + exclusive: ['device'], + hidden: true, + }), + // Hack to read stdin with oclif + stdin: flags.boolean({ + hidden: true, + }), + help: cf.help, + }; + + public static authenticated = true; + + public static readStdin = true; + + public async run() { + const { args: params, flags: options } = this.parse( + NoteCmd, + ); + + params.note = params.note || this.stdin; + + if (_.isEmpty(params.note)) { + throw new ExpectedError('Missing note content'); + } + + options.device = options.device || options.dev; + delete options.dev; + + if (_.isEmpty(options.device)) { + throw new ExpectedError('Missing device UUID (--device)'); + } + + const balena = getBalenaSdk(); + + return balena.models.device.note(options.device!, params.note); + } +} diff --git a/lib/actions-oclif/settings.ts b/lib/actions-oclif/settings.ts index 4df9d864..dd1207ae 100644 --- a/lib/actions-oclif/settings.ts +++ b/lib/actions-oclif/settings.ts @@ -1,6 +1,6 @@ /** * @license - * Copyright 2020 Balena Ltd. + * Copyright 2016-2020 Balena Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/lib/actions/index.coffee b/lib/actions/index.coffee index 23a2ffed..1cdbfff1 100644 --- a/lib/actions/index.coffee +++ b/lib/actions/index.coffee @@ -24,7 +24,6 @@ module.exports = logs: require('./logs') local: require('./local') scan: require('./scan') - notes: require('./notes') help: require('./help') os: require('./os') config: require('./config') diff --git a/lib/actions/notes.ts b/lib/actions/notes.ts deleted file mode 100644 index ff2b80e8..00000000 --- a/lib/actions/notes.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2016-2017 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 { CommandDefinition } from 'capitano'; -import { getBalenaSdk } from '../utils/lazy'; - -export const set: CommandDefinition<{ note: string }, { device: string }> = { - signature: 'note <|note>', - description: 'set a device note', - help: `\ -Use this command to set or update a device note. - -If note command isn't passed, the tool attempts to read from \`stdin\`. - -To view the notes, use $ balena device . - -Examples: - - $ balena note "My useful note" --device 7cf02a6 - $ cat note.txt | balena note --device 7cf02a6\ -`, - options: [ - { - signature: 'device', - parameter: 'device', - description: 'device uuid', - alias: ['d', 'dev'], - required: 'You have to specify a device', - }, - ], - permission: 'user', - async action(params, options) { - const { normalizeUuidProp } = await import('../utils/normalization'); - normalizeUuidProp(options, 'device'); - const _ = await import('lodash'); - const balena = getBalenaSdk(); - - if (_.isEmpty(params.note)) { - const { exitWithExpectedError } = await import('../utils/patterns'); - exitWithExpectedError('Missing note content'); - } - - return balena.models.device.note(options.device!, params.note); - }, -}; diff --git a/lib/app-capitano.coffee b/lib/app-capitano.coffee index 5f6c57e3..82be2dc2 100644 --- a/lib/app-capitano.coffee +++ b/lib/app-capitano.coffee @@ -74,9 +74,6 @@ capitano.command(actions.device.move) capitano.command(actions.device.osUpdate) capitano.command(actions.device.info) -# ---------- Notes Module ---------- -capitano.command(actions.notes.set) - # ---------- Keys Module ---------- capitano.command(actions.keys.list) capitano.command(actions.keys.add) diff --git a/lib/command.ts b/lib/command.ts index 0f428395..57be66f6 100644 --- a/lib/command.ts +++ b/lib/command.ts @@ -40,6 +40,15 @@ export default abstract class BalenaCommand extends Command { */ public static authenticated = false; + /** + * Accept piped input. + * When set to true, command will read from stdin during init + * and make contents available on member `stdin`. + */ + public static readStdin = false; + + public stdin: string; + /** * Throw InsufficientPrivilegesError if not root on Mac/Linux * or non-Administrator on Windows. @@ -74,18 +83,29 @@ export default abstract class BalenaCommand extends Command { await (await import('./utils/patterns')).checkLoggedIn(); } - protected async init() { - const requireElevatedPrivileges = (this.constructor as typeof BalenaCommand) - .root; - const requireAuthentication = (this.constructor as typeof BalenaCommand) - .authenticated; + /** + * Read stdin contents and make available to command. + * + * This approach could be improved in the future to automatically set argument + * values from stdin based in configuration, minimising command implementation. + */ + protected async getStdin() { + this.stdin = await (await import('get-stdin'))(); + } - if (requireElevatedPrivileges) { + protected async init() { + const ctr = this.constructor as typeof BalenaCommand; + + if (ctr.root) { await BalenaCommand.checkElevatedPrivileges(); } - if (requireAuthentication) { + if (ctr.authenticated) { await BalenaCommand.checkLoggedIn(); } + + if (ctr.readStdin) { + await this.getStdin(); + } } } diff --git a/lib/preparser.ts b/lib/preparser.ts index 8b6c3e8c..a5e588c4 100644 --- a/lib/preparser.ts +++ b/lib/preparser.ts @@ -131,9 +131,10 @@ export const convertedCommands = [ 'env:add', 'env:rename', 'env:rm', + 'note', 'os:configure', - 'version', 'settings', + 'version', ]; /**