2020-06-17 13:46:25 +00:00
|
|
|
/**
|
|
|
|
* @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 { IArg } from '@oclif/parser/lib/args';
|
|
|
|
import Command from '../../command';
|
|
|
|
import * as cf from '../../utils/common-flags';
|
|
|
|
import { expandForAppName } from '../../utils/helpers';
|
2020-05-04 14:57:23 +00:00
|
|
|
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
2021-07-15 13:41:38 +00:00
|
|
|
|
2020-07-31 14:35:20 +00:00
|
|
|
import type { Application, Release } from 'balena-sdk';
|
2020-06-17 13:46:25 +00:00
|
|
|
|
2020-07-31 14:35:20 +00:00
|
|
|
interface ExtendedDevice extends DeviceWithDeviceType {
|
2020-06-17 13:46:25 +00:00
|
|
|
dashboard_url?: string;
|
2021-12-20 01:13:50 +00:00
|
|
|
fleet: string; // 'org/name' slug
|
2020-07-31 14:35:20 +00:00
|
|
|
device_type?: string;
|
2020-06-17 13:46:25 +00:00
|
|
|
commit?: string;
|
2020-07-09 13:10:20 +00:00
|
|
|
last_seen?: string;
|
2020-09-03 15:09:31 +00:00
|
|
|
memory_usage_mb: number | null;
|
|
|
|
memory_total_mb: number | null;
|
|
|
|
memory_usage_percent?: number;
|
|
|
|
storage_usage_mb: number | null;
|
|
|
|
storage_total_mb: number | null;
|
|
|
|
storage_usage_percent?: number;
|
|
|
|
cpu_temp_c: number | null;
|
|
|
|
cpu_usage_percent: number | null;
|
|
|
|
undervoltage_detected?: boolean;
|
2020-06-17 13:46:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface FlagsDef {
|
|
|
|
help: void;
|
2022-07-14 18:56:51 +00:00
|
|
|
view: boolean;
|
2020-06-17 13:46:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface ArgsDef {
|
|
|
|
uuid: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default class DeviceCmd extends Command {
|
|
|
|
public static description = stripIndent`
|
|
|
|
Show info about a single device.
|
|
|
|
|
|
|
|
Show information about a single device.
|
|
|
|
`;
|
2022-07-14 18:56:51 +00:00
|
|
|
public static examples = [
|
|
|
|
'$ balena device 7cf02a6',
|
|
|
|
'$ balena device 7cf02a6 --view',
|
|
|
|
];
|
2020-06-17 13:46:25 +00:00
|
|
|
|
|
|
|
public static args: Array<IArg<any>> = [
|
|
|
|
{
|
|
|
|
name: 'uuid',
|
|
|
|
description: 'the device uuid',
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
public static usage = 'device <uuid>';
|
|
|
|
|
|
|
|
public static flags: flags.Input<FlagsDef> = {
|
|
|
|
help: cf.help,
|
2022-07-14 18:56:51 +00:00
|
|
|
view: flags.boolean({
|
|
|
|
default: false,
|
|
|
|
description: 'open device dashboard page',
|
|
|
|
}),
|
2020-06-17 13:46:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public static authenticated = true;
|
|
|
|
public static primary = true;
|
|
|
|
|
|
|
|
public async run() {
|
2022-07-14 18:56:51 +00:00
|
|
|
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
|
|
|
|
DeviceCmd,
|
|
|
|
);
|
2020-06-17 13:46:25 +00:00
|
|
|
|
|
|
|
const balena = getBalenaSdk();
|
|
|
|
|
2020-07-31 14:35:20 +00:00
|
|
|
const device = (await balena.models.device.get(params.uuid, {
|
2020-07-09 13:50:11 +00:00
|
|
|
$select: [
|
|
|
|
'device_name',
|
|
|
|
'id',
|
|
|
|
'overall_status',
|
|
|
|
'is_online',
|
|
|
|
'ip_address',
|
|
|
|
'mac_address',
|
|
|
|
'last_connectivity_event',
|
|
|
|
'uuid',
|
|
|
|
'supervisor_version',
|
|
|
|
'is_web_accessible',
|
|
|
|
'note',
|
|
|
|
'os_version',
|
2020-09-03 15:09:31 +00:00
|
|
|
'memory_usage',
|
|
|
|
'memory_total',
|
2021-03-18 20:00:10 +00:00
|
|
|
'public_address',
|
2020-09-03 15:09:31 +00:00
|
|
|
'storage_block_device',
|
|
|
|
'storage_usage',
|
|
|
|
'storage_total',
|
|
|
|
'cpu_usage',
|
|
|
|
'cpu_temp',
|
|
|
|
'cpu_id',
|
|
|
|
'is_undervolted',
|
2020-07-09 13:50:11 +00:00
|
|
|
],
|
|
|
|
...expandForAppName,
|
2020-07-31 14:35:20 +00:00
|
|
|
})) as ExtendedDevice;
|
2022-07-14 18:56:51 +00:00
|
|
|
|
|
|
|
if (options.view) {
|
|
|
|
const open = await import('open');
|
|
|
|
const dashboardUrl = balena.models.device.getDashboardUrl(device.uuid);
|
|
|
|
await open(dashboardUrl, { wait: false });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-09 13:50:11 +00:00
|
|
|
device.status = device.overall_status;
|
2020-06-17 13:46:25 +00:00
|
|
|
|
|
|
|
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid);
|
|
|
|
|
2021-07-20 13:57:00 +00:00
|
|
|
const belongsToApplication =
|
|
|
|
device.belongs_to__application as Application[];
|
2021-12-20 01:13:50 +00:00
|
|
|
device.fleet = belongsToApplication?.[0]
|
|
|
|
? belongsToApplication[0].slug
|
2020-06-17 13:46:25 +00:00
|
|
|
: 'N/a';
|
|
|
|
|
2020-07-31 14:35:20 +00:00
|
|
|
device.device_type = device.is_of__device_type[0].slug;
|
2020-09-08 12:13:30 +00:00
|
|
|
|
|
|
|
const isRunningRelease = device.is_running__release as Release[];
|
|
|
|
device.commit = isRunningRelease?.[0] ? isRunningRelease[0].commit : 'N/a';
|
|
|
|
|
2020-07-31 14:35:20 +00:00
|
|
|
device.last_seen = device.last_connectivity_event ?? undefined;
|
2020-06-17 13:46:25 +00:00
|
|
|
|
2020-09-03 15:09:31 +00:00
|
|
|
// Memory/Storage are really MiB
|
|
|
|
// Consider changing headings to MiB once we can do lowercase
|
|
|
|
|
|
|
|
device.memory_usage_mb = device.memory_usage;
|
|
|
|
device.memory_total_mb = device.memory_total;
|
|
|
|
|
|
|
|
device.storage_usage_mb = device.storage_usage;
|
|
|
|
device.storage_total_mb = device.storage_total;
|
|
|
|
|
|
|
|
device.cpu_temp_c = device.cpu_temp;
|
|
|
|
device.cpu_usage_percent = device.cpu_usage;
|
2020-09-04 08:32:40 +00:00
|
|
|
|
|
|
|
// Only show undervoltage status if true
|
|
|
|
// API sends false even for devices which are not detecting this.
|
|
|
|
if (device.is_undervolted) {
|
|
|
|
device.undervoltage_detected = device.is_undervolted;
|
|
|
|
}
|
2020-09-03 15:09:31 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
device.memory_usage != null &&
|
|
|
|
device.memory_total != null &&
|
|
|
|
device.memory_total !== 0
|
|
|
|
) {
|
|
|
|
device.memory_usage_percent = Math.round(
|
|
|
|
(device.memory_usage / device.memory_total) * 100,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
device.storage_usage != null &&
|
|
|
|
device.storage_total != null &&
|
|
|
|
device.storage_total !== 0
|
|
|
|
) {
|
|
|
|
device.storage_usage_percent = Math.round(
|
|
|
|
(device.storage_usage / device.storage_total) * 100,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-06-17 13:46:25 +00:00
|
|
|
console.log(
|
|
|
|
getVisuals().table.vertical(device, [
|
|
|
|
`$${device.device_name}$`,
|
|
|
|
'id',
|
|
|
|
'device_type',
|
|
|
|
'status',
|
|
|
|
'is_online',
|
|
|
|
'ip_address',
|
2021-03-18 20:00:10 +00:00
|
|
|
'public_address',
|
2020-06-29 13:04:37 +00:00
|
|
|
'mac_address',
|
2021-12-20 01:13:50 +00:00
|
|
|
'fleet',
|
2020-06-17 13:46:25 +00:00
|
|
|
'last_seen',
|
|
|
|
'uuid',
|
|
|
|
'commit',
|
|
|
|
'supervisor_version',
|
|
|
|
'is_web_accessible',
|
|
|
|
'note',
|
|
|
|
'os_version',
|
|
|
|
'dashboard_url',
|
2020-09-03 15:09:31 +00:00
|
|
|
'cpu_usage_percent',
|
|
|
|
'cpu_temp_c',
|
|
|
|
'cpu_id',
|
|
|
|
'memory_usage_mb',
|
|
|
|
'memory_total_mb',
|
|
|
|
'memory_usage_percent',
|
|
|
|
'storage_block_device',
|
|
|
|
'storage_usage_mb',
|
|
|
|
'storage_total_mb',
|
|
|
|
'storage_usage_percent',
|
|
|
|
'undervoltage_detected',
|
2020-06-17 13:46:25 +00:00
|
|
|
]),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|