Merge pull request from balena-io/convert-settings-oclif

Convert commands `settings`, `note` to oclif
This commit is contained in:
srlowe 2020-03-30 15:41:48 +02:00 committed by GitHub
commit bc15ad6e05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 208 additions and 120 deletions

@ -84,7 +84,7 @@ const capitanoDoc = {
},
{
title: 'Notes',
files: ['build/actions/notes.js'],
files: ['build/actions-oclif/note.js'],
},
{
title: 'OS',
@ -104,7 +104,7 @@ const capitanoDoc = {
},
{
title: 'Settings',
files: ['build/actions/settings.js'],
files: ['build/actions-oclif/settings.js'],
},
{
title: 'Local',

@ -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];

@ -1252,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 <uuid>.
To view device notes, use the `balena device <uuid>` command.
Examples:
$ balena note "My useful note" --device 7cf02a6
$ cat note.txt | balena note --device 7cf02a6
### Arguments
#### NOTE
note content
### Options
#### --device, -d, --dev &#60;device&#62;
#### -d, --device DEVICE
device UUID
#### --dev DEV
#### --stdin
device uuid
# OS
@ -1817,12 +1830,14 @@ Source files are not modified.
## settings
Use this command to display detected settings
Use this command to display current balena CLI settings.
Examples:
$ balena settings
### Options
# Local
## local configure &#60;target&#62;

100
lib/actions-oclif/note.ts Normal file

@ -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 <uuid>\` 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<FlagsDef> = {
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<FlagsDef, ArgsDef>(
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);
}
}

@ -0,0 +1,52 @@
/**
* @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 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<FlagsDef> = {
help: cf.help,
};
public async run() {
this.parse<FlagsDef, {}>(SettingsCmd);
const prettyjson = await import('prettyjson');
return getBalenaSdk()
.settings.getAll()
.then(prettyjson.render)
.then(console.log);
}
}

@ -24,10 +24,8 @@ module.exports =
logs: require('./logs')
local: require('./local')
scan: require('./scan')
notes: require('./notes')
help: require('./help')
os: require('./os')
settings: require('./settings')
config: require('./config')
ssh: require('./ssh')
internal: require('./internal')

@ -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 <uuid>.
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);
},
};

@ -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);
},
};

@ -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)
@ -101,9 +98,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)

@ -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();
}
}
}

@ -131,7 +131,9 @@ export const convertedCommands = [
'env:add',
'env:rename',
'env:rm',
'note',
'os:configure',
'settings',
'version',
];