mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-18 21:27:51 +00:00
Add balena envs '-j' option to produce JSON output
Change-type: minor Signed-off-by: Paulo Castro <paulo@balena.io>
This commit is contained in:
parent
630d53311a
commit
df58ac7673
@ -615,6 +615,10 @@ show config variables
|
||||
|
||||
device UUID
|
||||
|
||||
#### -j, --json
|
||||
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
#### -v, --verbose
|
||||
|
||||
produce verbose output
|
||||
|
@ -15,7 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Command, flags } from '@oclif/command';
|
||||
import { ApplicationVariable, DeviceVariable } from 'balena-sdk';
|
||||
import {
|
||||
ApplicationVariable,
|
||||
DeviceVariable,
|
||||
EnvironmentVariableBase,
|
||||
} from 'balena-sdk';
|
||||
import { stripIndent } from 'common-tags';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@ -27,6 +31,7 @@ interface FlagsDef {
|
||||
application?: string;
|
||||
config: boolean;
|
||||
device?: string;
|
||||
json: boolean;
|
||||
help: void;
|
||||
verbose: boolean;
|
||||
}
|
||||
@ -62,6 +67,10 @@ export default class EnvsCmd extends Command {
|
||||
}),
|
||||
device: _.assign({ exclusive: ['application'] }, cf.device),
|
||||
help: cf.help,
|
||||
json: flags.boolean({
|
||||
char: 'j',
|
||||
description: 'produce JSON output instead of tabular output',
|
||||
}),
|
||||
verbose: cf.verbose,
|
||||
};
|
||||
|
||||
@ -91,8 +100,37 @@ export default class EnvsCmd extends Command {
|
||||
throw new ExpectedError('No environment variables found');
|
||||
}
|
||||
|
||||
cmd.log(
|
||||
visuals.table.horizontal(environmentVariables, ['id', 'name', 'value']),
|
||||
);
|
||||
const fields = ['id', 'name', 'value'];
|
||||
|
||||
if (options.json) {
|
||||
cmd.log(
|
||||
stringifyVarArray<EnvironmentVariableBase>(
|
||||
environmentVariables,
|
||||
fields,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
cmd.log(visuals.table.horizontal(environmentVariables, fields));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stringifyVarArray<T = Dictionary<any>>(
|
||||
varArray: T[],
|
||||
fields: string[],
|
||||
): string {
|
||||
// Transform each object (item) of varArray to preserve
|
||||
// only the fields (keys) listed in the fields argument.
|
||||
const transformed = _.map(varArray, (o: Dictionary<any>) =>
|
||||
_.transform(
|
||||
o,
|
||||
(result, value, key) => {
|
||||
if (fields.includes(key)) {
|
||||
result[key] = value;
|
||||
}
|
||||
},
|
||||
{},
|
||||
),
|
||||
);
|
||||
return JSON.stringify(transformed, null, 4);
|
||||
}
|
||||
|
@ -112,6 +112,16 @@ export function configureBluebird() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Addresses the console warning:
|
||||
* (node:49500) MaxListenersExceededWarning: Possible EventEmitter memory
|
||||
* leak detected. 11 error listeners added. Use emitter.setMaxListeners() to
|
||||
* increase limit
|
||||
*/
|
||||
export function setMaxListeners(maxListeners: number) {
|
||||
require('events').EventEmitter.defaultMaxListeners = maxListeners;
|
||||
}
|
||||
|
||||
export function globalInit() {
|
||||
setupRaven();
|
||||
checkNodeVersion();
|
||||
|
@ -51,15 +51,75 @@ class BalenaAPIMock {
|
||||
nock.restore();
|
||||
}
|
||||
|
||||
public expectTestApp() {
|
||||
this.scope
|
||||
.get(/^\/v\d+\/application($|\?)/)
|
||||
.reply(200, { d: [{ id: 1234567 }] });
|
||||
}
|
||||
|
||||
public expectTestDevice() {
|
||||
this.scope.get(/\/v\d+\/device($|\?)/).reply(200, { d: [{ id: 7654321 }] });
|
||||
this.scope
|
||||
.get(/^\/v\d+\/device($|\?)/)
|
||||
.reply(200, { d: [{ id: 7654321 }] });
|
||||
}
|
||||
|
||||
public expectAppEnvVars() {
|
||||
this.scope
|
||||
.get(/^\/v\d+\/application_environment_variable($|\?)/)
|
||||
.reply(200, {
|
||||
d: [
|
||||
{
|
||||
id: 120101,
|
||||
name: 'var1',
|
||||
value: 'var1-val',
|
||||
},
|
||||
{
|
||||
id: 120102,
|
||||
name: 'var2',
|
||||
value: '22',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
public expectDeviceEnvVars() {
|
||||
this.scope.post(/\/v\d+\/device_environment_variable($|\?)/).reply(201, {
|
||||
id: 120203,
|
||||
name: 'var3',
|
||||
value: 'var3-val',
|
||||
this.scope.get(/^\/v\d+\/device_environment_variable($|\?)/).reply(200, {
|
||||
d: [
|
||||
{
|
||||
id: 120203,
|
||||
name: 'var3',
|
||||
value: 'var3-val',
|
||||
},
|
||||
{
|
||||
id: 120204,
|
||||
name: 'var4',
|
||||
value: '44',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
public expectAppConfigVars() {
|
||||
this.scope.get(/^\/v\d+\/application_config_variable($|\?)/).reply(200, {
|
||||
d: [
|
||||
{
|
||||
id: 120300,
|
||||
name: 'RESIN_SUPERVISOR_NATIVE_LOGGER',
|
||||
value: 'false',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
public expectDeviceConfigVars() {
|
||||
this.scope.get(/^\/v\d+\/device_config_variable($|\?)/).reply(200, {
|
||||
d: [
|
||||
{
|
||||
id: 120400,
|
||||
name: 'RESIN_SUPERVISOR_POLL_INTERVAL',
|
||||
value: '900900',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@ -92,6 +152,7 @@ class BalenaAPIMock {
|
||||
const get = this.scope.get(/^\/mixpanel\/track/);
|
||||
(optional ? get.optionally() : get).reply(200, {});
|
||||
}
|
||||
|
||||
protected handleUnexpectedRequest(req: any) {
|
||||
console.error(`Unexpected http request!: ${req.path}`);
|
||||
// Errors thrown here are not causing the tests to fail for some reason.
|
||||
|
4
tests/commands/env/add.spec.ts
vendored
4
tests/commands/env/add.spec.ts
vendored
@ -38,7 +38,9 @@ describe('balena env add', function() {
|
||||
const deviceId = 'f63fd7d7812c34c4c14ae023fdff05f5';
|
||||
api.expectTestDevice();
|
||||
api.expectConfigVars();
|
||||
api.expectDeviceEnvVars();
|
||||
api.scope
|
||||
.post(/^\/v\d+\/device_environment_variable($|\?)/)
|
||||
.reply(200, 'OK');
|
||||
|
||||
const { out, err } = await runCommand(`env add TEST 1 -d ${deviceId}`);
|
||||
|
||||
|
138
tests/commands/env/envs.spec.ts
vendored
Normal file
138
tests/commands/env/envs.spec.ts
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @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 { expect } from 'chai';
|
||||
import { stripIndent } from 'common-tags';
|
||||
|
||||
import { BalenaAPIMock } from '../../balena-api-mock';
|
||||
import { runCommand } from '../../helpers';
|
||||
|
||||
describe('balena envs', function() {
|
||||
const appName = 'test';
|
||||
const deviceUUID = 'f63fd7d7812c34c4c14ae023fdff05f5';
|
||||
let api: BalenaAPIMock;
|
||||
|
||||
beforeEach(() => {
|
||||
api = new BalenaAPIMock();
|
||||
api.expectOptionalWhoAmI(true);
|
||||
api.expectMixpanel(true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Check all expected api calls have been made and clean up.
|
||||
api.done();
|
||||
});
|
||||
|
||||
it('should successfully list env vars for a test app', async () => {
|
||||
api.expectTestApp();
|
||||
api.expectAppEnvVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -a ${appName}`);
|
||||
|
||||
expect(out.join('')).to.equal(
|
||||
stripIndent`
|
||||
ID NAME VALUE
|
||||
120101 var1 var1-val
|
||||
120102 var2 22
|
||||
` + '\n',
|
||||
);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
|
||||
it('should successfully list env vars for a test device', async () => {
|
||||
api.expectTestDevice();
|
||||
api.expectDeviceEnvVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -d ${deviceUUID}`);
|
||||
|
||||
expect(out.join('')).to.equal(
|
||||
stripIndent`
|
||||
ID NAME VALUE
|
||||
120203 var3 var3-val
|
||||
120204 var4 44
|
||||
` + '\n',
|
||||
);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
|
||||
it('should successfully list env vars for a test device (JSON output)', async () => {
|
||||
api.expectTestDevice();
|
||||
api.expectDeviceEnvVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -jd ${deviceUUID}`);
|
||||
|
||||
expect(JSON.parse(out.join(''))).to.deep.equal([
|
||||
{
|
||||
id: 120203,
|
||||
name: 'var3',
|
||||
value: 'var3-val',
|
||||
},
|
||||
{
|
||||
id: 120204,
|
||||
name: 'var4',
|
||||
value: '44',
|
||||
},
|
||||
]);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
|
||||
it('should successfully list config vars for a test app', async () => {
|
||||
api.expectTestApp();
|
||||
api.expectAppConfigVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -a ${appName} --config`);
|
||||
|
||||
expect(out.join('')).to.equal(
|
||||
stripIndent`
|
||||
ID NAME VALUE
|
||||
120300 RESIN_SUPERVISOR_NATIVE_LOGGER false
|
||||
` + '\n',
|
||||
);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
|
||||
it('should successfully list config vars for a test app (JSON output)', async () => {
|
||||
api.expectTestApp();
|
||||
api.expectAppConfigVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -cja ${appName}`);
|
||||
|
||||
expect(JSON.parse(out.join(''))).to.deep.equal([
|
||||
{
|
||||
id: 120300,
|
||||
name: 'RESIN_SUPERVISOR_NATIVE_LOGGER',
|
||||
value: 'false',
|
||||
},
|
||||
]);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
|
||||
it('should successfully list config vars for a test device', async () => {
|
||||
api.expectTestDevice();
|
||||
api.expectDeviceConfigVars();
|
||||
|
||||
const { out, err } = await runCommand(`envs -d ${deviceUUID} --config`);
|
||||
|
||||
expect(out.join('')).to.equal(
|
||||
stripIndent`
|
||||
ID NAME VALUE
|
||||
120400 RESIN_SUPERVISOR_POLL_INTERVAL 900900
|
||||
` + '\n',
|
||||
);
|
||||
expect(err.join('')).to.equal('');
|
||||
});
|
||||
});
|
@ -21,9 +21,10 @@ import * as nock from 'nock';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as balenaCLI from '../build/app';
|
||||
import { configureBluebird } from '../build/app-common';
|
||||
import { configureBluebird, setMaxListeners } from '../build/app-common';
|
||||
|
||||
configureBluebird();
|
||||
setMaxListeners(15); // it appears that using nock adds some listeners
|
||||
|
||||
export const runCommand = async (cmd: string) => {
|
||||
const preArgs = [process.argv[0], path.join(process.cwd(), 'bin', 'balena')];
|
||||
|
Loading…
Reference in New Issue
Block a user