mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-29 15:44:26 +00:00
convert commands key
, keys
, key add
, key rm
to oclif.
Also: - Display keys with `name` instead of `title`. - Check for empty key before calling API. Change-type: patch Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
parent
7c9a23451b
commit
be82bcfa63
@ -68,7 +68,12 @@ const capitanoDoc = {
|
||||
},
|
||||
{
|
||||
title: 'Keys',
|
||||
files: ['build/actions/keys.js'],
|
||||
files: [
|
||||
'build/actions-oclif/keys.js',
|
||||
'build/actions-oclif/key/index.js',
|
||||
'build/actions-oclif/key/add.js',
|
||||
'build/actions-oclif/key/rm.js',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Logs',
|
||||
|
@ -190,8 +190,8 @@ If you come across any problems or would like to get in touch:
|
||||
|
||||
- [keys](#keys)
|
||||
- [key <id>](#key-id)
|
||||
- [key rm <id>](#key-rm-id)
|
||||
- [key add <name> [path]](#key-add-name-path)
|
||||
- [key rm <id>](#key-rm-id)
|
||||
|
||||
- Logs
|
||||
|
||||
@ -1063,41 +1063,33 @@ output version information in JSON format for programmatic use
|
||||
|
||||
## keys
|
||||
|
||||
Use this command to list all your SSH keys.
|
||||
List all SSH keys registered in balenaCloud for the logged in user.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena keys
|
||||
|
||||
### Options
|
||||
|
||||
## key <id>
|
||||
|
||||
Use this command to show information about a single SSH key.
|
||||
Display a single SSH key registered in balenaCloud for the logged in user.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key 17
|
||||
|
||||
## key rm <id>
|
||||
### Arguments
|
||||
|
||||
Use this command to remove a SSH key from balena.
|
||||
#### ID
|
||||
|
||||
Notice this command asks for confirmation interactively.
|
||||
You can avoid this by passing the `--yes` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key rm 17
|
||||
$ balena key rm 17 --yes
|
||||
balenaCloud ID for the SSH key
|
||||
|
||||
### Options
|
||||
|
||||
#### --yes, -y
|
||||
|
||||
confirm non interactively
|
||||
|
||||
## key add <name> [path]
|
||||
|
||||
Use this command to associate a new SSH key with your account.
|
||||
Register an SSH in balenaCloud for the logged in user.
|
||||
|
||||
If `path` is omitted, the command will attempt
|
||||
to read the SSH key from stdin.
|
||||
@ -1107,6 +1099,41 @@ Examples:
|
||||
$ balena key add Main ~/.ssh/id_rsa.pub
|
||||
$ cat ~/.ssh/id_rsa.pub | balena key add Main
|
||||
|
||||
### Arguments
|
||||
|
||||
#### NAME
|
||||
|
||||
the SSH key name
|
||||
|
||||
#### PATH
|
||||
|
||||
the path to the public key file
|
||||
|
||||
### Options
|
||||
|
||||
## key rm <id>
|
||||
|
||||
Remove a single SSH key registered in balenaCloud for the logged in user.
|
||||
|
||||
The --yes option may be used to avoid interactive confirmation.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key rm 17
|
||||
$ balena key rm 17 --yes
|
||||
|
||||
### Arguments
|
||||
|
||||
#### ID
|
||||
|
||||
balenaCloud ID for the SSH key
|
||||
|
||||
### Options
|
||||
|
||||
#### -y, --yes
|
||||
|
||||
answer "yes" to all questions (non interactive use)
|
||||
|
||||
# Logs
|
||||
|
||||
## logs <uuidOrDevice>
|
||||
|
3
lib/actions-oclif/env/rename.ts
vendored
3
lib/actions-oclif/env/rename.ts
vendored
@ -22,6 +22,7 @@ import * as cf from '../../utils/common-flags';
|
||||
import * as ec from '../../utils/env-common';
|
||||
import { getBalenaSdk } from '../../utils/lazy';
|
||||
import { CommandHelp } from '../../utils/oclif-utils';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
|
||||
type IArg<T> = import('@oclif/parser').args.IArg<T>;
|
||||
|
||||
@ -60,7 +61,7 @@ export default class EnvRenameCmd extends Command {
|
||||
name: 'id',
|
||||
required: true,
|
||||
description: "variable's numeric database ID",
|
||||
parse: input => ec.parseDbId(input),
|
||||
parse: input => parseAsInteger(input, 'id'),
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
|
3
lib/actions-oclif/env/rm.ts
vendored
3
lib/actions-oclif/env/rm.ts
vendored
@ -22,6 +22,7 @@ import Command from '../../command';
|
||||
import * as ec from '../../utils/env-common';
|
||||
import { getBalenaSdk } from '../../utils/lazy';
|
||||
import { CommandHelp } from '../../utils/oclif-utils';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
|
||||
type IArg<T> = import('@oclif/parser').args.IArg<T>;
|
||||
|
||||
@ -63,7 +64,7 @@ export default class EnvRmCmd extends Command {
|
||||
name: 'id',
|
||||
required: true,
|
||||
description: "variable's numeric database ID",
|
||||
parse: input => ec.parseDbId(input),
|
||||
parse: input => parseAsInteger(input, 'id'),
|
||||
},
|
||||
];
|
||||
|
||||
|
87
lib/actions-oclif/key/add.ts
Normal file
87
lib/actions-oclif/key/add.ts
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @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 { ExpectedError } from '../../errors';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk } from '../../utils/lazy';
|
||||
|
||||
interface FlagsDef {
|
||||
help: void;
|
||||
}
|
||||
|
||||
interface ArgsDef {
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export default class KeyAddCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Add an SSH key to balenaCloud.
|
||||
|
||||
Register an SSH in balenaCloud for the logged in user.
|
||||
|
||||
If \`path\` is omitted, the command will attempt
|
||||
to read the SSH key from stdin.
|
||||
`;
|
||||
|
||||
public static examples = [
|
||||
'$ balena key add Main ~/.ssh/id_rsa.pub',
|
||||
'$ cat ~/.ssh/id_rsa.pub | balena key add Main',
|
||||
];
|
||||
|
||||
public static args = [
|
||||
{
|
||||
name: 'name',
|
||||
description: 'the SSH key name',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: `path`,
|
||||
description: `the path to the public key file`,
|
||||
},
|
||||
];
|
||||
|
||||
public static usage = 'key add <name> [path]';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public static readStdin = true;
|
||||
|
||||
public async run() {
|
||||
const { args: params } = this.parse<FlagsDef, ArgsDef>(KeyAddCmd);
|
||||
|
||||
let key: string;
|
||||
if (params.path != null) {
|
||||
const { promisify } = await import('util');
|
||||
const readFileAsync = promisify((await import('fs')).readFile);
|
||||
key = await readFileAsync(params.path, 'utf8');
|
||||
} else if (this.stdin.length > 0) {
|
||||
key = this.stdin;
|
||||
} else {
|
||||
throw new ExpectedError('No public key file or path provided.');
|
||||
}
|
||||
|
||||
await getBalenaSdk().models.key.create(params.name, key);
|
||||
}
|
||||
}
|
79
lib/actions-oclif/key/index.ts
Normal file
79
lib/actions-oclif/key/index.ts
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @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, getVisuals } from '../../utils/lazy';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
|
||||
type IArg<T> = import('@oclif/parser').args.IArg<T>;
|
||||
|
||||
interface FlagsDef {
|
||||
help: void;
|
||||
}
|
||||
|
||||
interface ArgsDef {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export default class KeyCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Display an SSH key.
|
||||
|
||||
Display a single SSH key registered in balenaCloud for the logged in user.
|
||||
`;
|
||||
|
||||
public static examples = ['$ balena key 17'];
|
||||
|
||||
public static args: Array<IArg<any>> = [
|
||||
{
|
||||
name: 'id',
|
||||
description: 'balenaCloud ID for the SSH key',
|
||||
parse: x => parseAsInteger(x, 'id'),
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
|
||||
public static usage = 'key <id>';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public async run() {
|
||||
const { args: params } = this.parse<{}, ArgsDef>(KeyCmd);
|
||||
|
||||
const key = await getBalenaSdk().models.key.get(params.id);
|
||||
|
||||
// Use 'name' instead of 'title' to match dashboard.
|
||||
const displayKey = {
|
||||
id: key.id,
|
||||
name: key.title,
|
||||
};
|
||||
|
||||
console.log(getVisuals().table.vertical(displayKey, ['id', 'name']));
|
||||
|
||||
// Since the public key string is long, it might
|
||||
// wrap to lines below, causing the table layout to break.
|
||||
// See https://github.com/balena-io/balena-cli/issues/151
|
||||
console.log('\n' + key.public_key);
|
||||
}
|
||||
}
|
79
lib/actions-oclif/key/rm.ts
Normal file
79
lib/actions-oclif/key/rm.ts
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @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';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
|
||||
type IArg<T> = import('@oclif/parser').args.IArg<T>;
|
||||
|
||||
interface FlagsDef {
|
||||
yes: boolean;
|
||||
help: void;
|
||||
}
|
||||
|
||||
interface ArgsDef {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export default class KeyRmCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Remove an SSH key from balenaCloud.
|
||||
|
||||
Remove a single SSH key registered in balenaCloud for the logged in user.
|
||||
|
||||
The --yes option may be used to avoid interactive confirmation.
|
||||
`;
|
||||
|
||||
public static examples = ['$ balena key rm 17', '$ balena key rm 17 --yes'];
|
||||
|
||||
public static args: Array<IArg<any>> = [
|
||||
{
|
||||
name: 'id',
|
||||
description: 'balenaCloud ID for the SSH key',
|
||||
parse: x => parseAsInteger(x, 'id'),
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
|
||||
public static usage = 'key rm <id>';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
yes: cf.yes,
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public async run() {
|
||||
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
|
||||
KeyRmCmd,
|
||||
);
|
||||
|
||||
const patterns = await import('../../utils/patterns');
|
||||
|
||||
await patterns.confirm(
|
||||
options.yes ?? false,
|
||||
`Are you sure you want to delete key ${params.id}?`,
|
||||
);
|
||||
|
||||
await getBalenaSdk().models.key.remove(params.id);
|
||||
}
|
||||
}
|
56
lib/actions-oclif/keys.ts
Normal file
56
lib/actions-oclif/keys.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @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, getVisuals } from '../utils/lazy';
|
||||
|
||||
interface FlagsDef {
|
||||
help: void;
|
||||
}
|
||||
|
||||
export default class KeysCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
List the SSH keys in balenaCloud.
|
||||
|
||||
List all SSH keys registered in balenaCloud for the logged in user.
|
||||
`;
|
||||
public static examples = ['$ balena keys'];
|
||||
|
||||
public static usage = 'keys';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public async run() {
|
||||
this.parse<FlagsDef, {}>(KeysCmd);
|
||||
|
||||
const keys = await getBalenaSdk().models.key.getAll();
|
||||
|
||||
// Use 'name' instead of 'title' to match dashboard.
|
||||
const displayKeys: Array<{ id: number; name: string }> = keys.map(k => {
|
||||
return { id: k.id, name: k.title };
|
||||
});
|
||||
|
||||
console.log(getVisuals().table.horizontal(displayKeys, ['id', 'name']));
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@ module.exports =
|
||||
auth: require('./auth')
|
||||
device: require('./device')
|
||||
tags: require('./tags')
|
||||
keys: require('./keys')
|
||||
logs: require('./logs')
|
||||
local: require('./local')
|
||||
scan: require('./scan')
|
||||
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
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 { CommandDefinition } from 'capitano';
|
||||
import { ExpectedError } from '../errors';
|
||||
import { getBalenaSdk, getVisuals } from '../utils/lazy';
|
||||
import * as commandOptions from './command-options';
|
||||
|
||||
function parseId(id: string): number {
|
||||
if (/^[\d]+$/.exec(id) == null) {
|
||||
throw new ExpectedError('The key id must be an integer');
|
||||
}
|
||||
return Number(id);
|
||||
}
|
||||
|
||||
export const list: CommandDefinition = {
|
||||
signature: 'keys',
|
||||
description: 'list all ssh keys',
|
||||
help: `\
|
||||
Use this command to list all your SSH keys.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena keys\
|
||||
`,
|
||||
permission: 'user',
|
||||
async action() {
|
||||
const keys = await getBalenaSdk().models.key.getAll();
|
||||
|
||||
console.log(getVisuals().table.horizontal(keys, ['id', 'title']));
|
||||
},
|
||||
};
|
||||
|
||||
export const info: CommandDefinition<{ id: string }> = {
|
||||
signature: 'key <id>',
|
||||
description: 'list a single ssh key',
|
||||
help: `\
|
||||
Use this command to show information about a single SSH key.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key 17\
|
||||
`,
|
||||
permission: 'user',
|
||||
async action(params) {
|
||||
const key = await getBalenaSdk().models.key.get(parseId(params.id));
|
||||
|
||||
console.log(getVisuals().table.vertical(key, ['id', 'title']));
|
||||
|
||||
// Since the public key string is long, it might
|
||||
// wrap to lines below, causing the table layout to break.
|
||||
// See https://github.com/balena-io/balena-cli/issues/151
|
||||
console.log('\n' + key.public_key);
|
||||
},
|
||||
};
|
||||
|
||||
export const remove: CommandDefinition<
|
||||
{ id: string },
|
||||
commandOptions.YesOption
|
||||
> = {
|
||||
signature: 'key rm <id>',
|
||||
description: 'remove a ssh key',
|
||||
help: `\
|
||||
Use this command to remove a SSH key from balena.
|
||||
|
||||
Notice this command asks for confirmation interactively.
|
||||
You can avoid this by passing the \`--yes\` boolean option.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key rm 17
|
||||
$ balena key rm 17 --yes\
|
||||
`,
|
||||
options: [commandOptions.yes],
|
||||
permission: 'user',
|
||||
async action(params, options) {
|
||||
const patterns = await import('../utils/patterns');
|
||||
|
||||
await patterns.confirm(
|
||||
options.yes ?? false,
|
||||
'Are you sure you want to delete the key?',
|
||||
);
|
||||
|
||||
await getBalenaSdk().models.key.remove(parseId(params.id));
|
||||
},
|
||||
};
|
||||
|
||||
export const add: CommandDefinition<{ name: string; path: string }> = {
|
||||
signature: 'key add <name> [path]',
|
||||
description: 'add a SSH key to balena',
|
||||
help: `\
|
||||
Use this command to associate a new SSH key with your account.
|
||||
|
||||
If \`path\` is omitted, the command will attempt
|
||||
to read the SSH key from stdin.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena key add Main ~/.ssh/id_rsa.pub
|
||||
$ cat ~/.ssh/id_rsa.pub | balena key add Main\
|
||||
`,
|
||||
permission: 'user',
|
||||
async action(params) {
|
||||
let key: string;
|
||||
if (params.path != null) {
|
||||
const { promisify } = await import('util');
|
||||
const readFileAsync = promisify((await import('fs')).readFile);
|
||||
key = await readFileAsync(params.path, 'utf8');
|
||||
} else {
|
||||
const getStdin = await import('get-stdin');
|
||||
key = await getStdin();
|
||||
}
|
||||
|
||||
await getBalenaSdk().models.key.create(params.name, key);
|
||||
},
|
||||
};
|
@ -74,12 +74,6 @@ capitano.command(actions.device.move)
|
||||
capitano.command(actions.device.osUpdate)
|
||||
capitano.command(actions.device.info)
|
||||
|
||||
# ---------- Keys Module ----------
|
||||
capitano.command(actions.keys.list)
|
||||
capitano.command(actions.keys.add)
|
||||
capitano.command(actions.keys.info)
|
||||
capitano.command(actions.keys.remove)
|
||||
|
||||
# ---------- Tags Module ----------
|
||||
capitano.command(actions.tags.list)
|
||||
capitano.command(actions.tags.set)
|
||||
|
@ -134,6 +134,10 @@ export const convertedCommands = [
|
||||
'internal:scandevices',
|
||||
'internal:osinit',
|
||||
'join',
|
||||
'keys',
|
||||
'key',
|
||||
'key:add',
|
||||
'key:rm',
|
||||
'leave',
|
||||
'note',
|
||||
'os:configure',
|
||||
|
@ -46,3 +46,8 @@ export const verbose: IBooleanFlag<boolean> = flags.boolean({
|
||||
char: 'v',
|
||||
description: 'produce verbose output',
|
||||
});
|
||||
|
||||
export const yes: IBooleanFlag<boolean> = flags.boolean({
|
||||
char: 'y',
|
||||
description: 'answer "yes" to all questions (non interactive use)',
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016-2017 Balena
|
||||
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.
|
||||
@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import validEmail = require('@resin.io/valid-email');
|
||||
import { ExpectedError } from '../errors';
|
||||
|
||||
const APPNAME_REGEX = new RegExp(/^[a-zA-Z0-9_-]+$/);
|
||||
// An regex to detect an IP address, from https://www.regular-expressions.info/ip.html
|
||||
@ -73,3 +74,17 @@ export function validateShortUuid(input: string): boolean {
|
||||
export function validateUuid(input: string): boolean {
|
||||
return validateLongUuid(input) || validateShortUuid(input);
|
||||
}
|
||||
|
||||
export function parseAsInteger(input: string, paramName?: string) {
|
||||
// Allow only digits, no leading 0
|
||||
if (!/^(0|[1-9][0-9]*)$/.test(input)) {
|
||||
const message =
|
||||
paramName == null
|
||||
? 'The parameter must be an integer.'
|
||||
: `The parameter '${paramName}' must be an integer.`;
|
||||
|
||||
throw new ExpectedError(message);
|
||||
}
|
||||
|
||||
return Number(input);
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ Additional commands:
|
||||
env rename <id> <value> change the value of a config or env var for an app, device or service
|
||||
env rm <id> 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 <id> list a single ssh key
|
||||
key add <name> [path] add a SSH key to balena
|
||||
key rm <id> remove a ssh key
|
||||
keys list all ssh keys
|
||||
key <id> display an SSH key
|
||||
key add <name> [path] add an SSH key to balenaCloud
|
||||
key rm <id> remove an SSH key from balenaCloud
|
||||
keys list the SSH keys in balenaCloud
|
||||
local configure <target> (Re)configure a balenaOS drive or image
|
||||
local flash <image> Flash an image to a drive
|
||||
logout logout from balena
|
||||
|
54
tests/utils/validation.spec.ts
Normal file
54
tests/utils/validation.spec.ts
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @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 { expect } from 'chai';
|
||||
import { ExpectedError } from '../../build/errors';
|
||||
import { parseAsInteger } from '../../build/utils/validation';
|
||||
|
||||
describe('parseAsInteger() function', function() {
|
||||
it('should reject non-numeric characters', () => {
|
||||
expect(() => parseAsInteger('abc')).to.throw(ExpectedError);
|
||||
expect(() => parseAsInteger('1a')).to.throw(ExpectedError);
|
||||
expect(() => parseAsInteger('a1')).to.throw(ExpectedError);
|
||||
expect(() => parseAsInteger('a')).to.throw(ExpectedError);
|
||||
expect(() => parseAsInteger('1.0')).to.throw(ExpectedError);
|
||||
});
|
||||
|
||||
it('should reject leading zeros', () => {
|
||||
expect(() => parseAsInteger('01')).to.throw(ExpectedError);
|
||||
expect(() => parseAsInteger('001')).to.throw(ExpectedError);
|
||||
});
|
||||
|
||||
it('should throw with specific message when param name passed', () => {
|
||||
expect(() => parseAsInteger('abc')).to.throw(
|
||||
'The parameter must be an integer.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw with general message when no param name passed', () => {
|
||||
expect(() => parseAsInteger('abc', 'foo')).to.throw(
|
||||
"The parameter 'foo' must be an integer.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse integers to number type', () => {
|
||||
expect(parseAsInteger('100')).to.equal(100);
|
||||
expect(parseAsInteger('100')).to.be.a('number');
|
||||
expect(parseAsInteger('0')).to.equal(0);
|
||||
expect(parseAsInteger('0')).to.be.a('number');
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user