balena-cli 13.2.1 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/build/commands/ssh.d.ts +0 -7
- package/build/commands/ssh.js +10 -73
- package/build/commands/ssh.js.map +1 -1
- package/build/utils/device/ssh.d.ts +6 -5
- package/build/utils/device/ssh.js +37 -41
- package/build/utils/device/ssh.js.map +1 -1
- package/build/utils/ssh.d.ts +2 -2
- package/build/utils/ssh.js +12 -5
- package/build/utils/ssh.js.map +1 -1
- package/lib/commands/ssh.ts +11 -113
- package/lib/utils/device/ssh.ts +91 -70
- package/lib/utils/ssh.ts +19 -14
- package/npm-shrinkwrap.json +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file
|
|
|
4
4
|
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
|
5
5
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
|
7
|
+
## 13.3.0 - 2022-02-28
|
|
8
|
+
|
|
9
|
+
* ssh: Allow ssh to service with IP address and production balenaOS image [Paulo Castro]
|
|
10
|
+
* ssh: Advise use of 'balena login' if root authentication fails [Paulo Castro]
|
|
11
|
+
|
|
7
12
|
## 13.2.1 - 2022-02-24
|
|
8
13
|
|
|
9
14
|
* Remove unnecessary fetch of device info in `balena tunnel` [Pagan Gazzard]
|
package/build/commands/ssh.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { flags } from '@oclif/command';
|
|
2
2
|
import Command from '../command';
|
|
3
|
-
import * as BalenaSdk from 'balena-sdk';
|
|
4
3
|
interface FlagsDef {
|
|
5
4
|
port?: number;
|
|
6
5
|
tty: boolean;
|
|
@@ -21,11 +20,5 @@ export default class SshCmd extends Command {
|
|
|
21
20
|
static primary: boolean;
|
|
22
21
|
static offlineCompatible: boolean;
|
|
23
22
|
run(): Promise<void>;
|
|
24
|
-
getContainerId(sdk: BalenaSdk.BalenaSDK, uuid: string, serviceName: string, sshOpts: {
|
|
25
|
-
port?: number;
|
|
26
|
-
proxyCommand?: string[];
|
|
27
|
-
proxyUrl: string;
|
|
28
|
-
username: string;
|
|
29
|
-
}, version?: string, id?: number): Promise<string>;
|
|
30
23
|
}
|
|
31
24
|
export {};
|
package/build/commands/ssh.js
CHANGED
|
@@ -11,8 +11,8 @@ class SshCmd extends command_2.default {
|
|
|
11
11
|
if ((0, validation_1.validateLocalHostnameOrIp)(params.fleetOrDevice)) {
|
|
12
12
|
const { performLocalDeviceSSH } = await Promise.resolve().then(() => require('../utils/device/ssh'));
|
|
13
13
|
return await performLocalDeviceSSH({
|
|
14
|
-
|
|
15
|
-
port: options.port,
|
|
14
|
+
hostname: params.fleetOrDevice,
|
|
15
|
+
port: options.port || 'local',
|
|
16
16
|
forceTTY: options.tty,
|
|
17
17
|
verbose: options.verbose,
|
|
18
18
|
service: params.service,
|
|
@@ -26,11 +26,6 @@ class SshCmd extends command_2.default {
|
|
|
26
26
|
await command_2.default.checkNotUsingOfflineMode();
|
|
27
27
|
await command_2.default.checkLoggedIn();
|
|
28
28
|
const deviceUuid = await getOnlineTargetDeviceUuid(sdk, params.fleetOrDevice);
|
|
29
|
-
const device = await sdk.models.device.get(deviceUuid, {
|
|
30
|
-
$select: ['id', 'supervisor_version', 'is_online'],
|
|
31
|
-
});
|
|
32
|
-
const deviceId = device.id;
|
|
33
|
-
const supervisorVersion = device.supervisor_version;
|
|
34
29
|
const { which } = await Promise.resolve().then(() => require('../utils/which'));
|
|
35
30
|
const [whichProxytunnel, username, proxyUrl] = await Promise.all([
|
|
36
31
|
useProxy ? which('proxytunnel', false) : undefined,
|
|
@@ -66,12 +61,15 @@ class SshCmd extends command_2.default {
|
|
|
66
61
|
const proxyCommand = useProxy ? getSshProxyCommand() : undefined;
|
|
67
62
|
let containerId;
|
|
68
63
|
if (params.service != null) {
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
const { getContainerIdForService } = await Promise.resolve().then(() => require('../utils/device/ssh'));
|
|
65
|
+
containerId = await getContainerIdForService({
|
|
66
|
+
deviceUuid,
|
|
67
|
+
hostname: `ssh.${proxyUrl}`,
|
|
68
|
+
port: options.port || 'cloud',
|
|
71
69
|
proxyCommand,
|
|
72
|
-
|
|
70
|
+
service: params.service,
|
|
73
71
|
username: username,
|
|
74
|
-
}
|
|
72
|
+
});
|
|
75
73
|
}
|
|
76
74
|
let accessCommand;
|
|
77
75
|
if (containerId != null) {
|
|
@@ -84,73 +82,12 @@ class SshCmd extends command_2.default {
|
|
|
84
82
|
await runRemoteCommand({
|
|
85
83
|
cmd: accessCommand,
|
|
86
84
|
hostname: `ssh.${proxyUrl}`,
|
|
87
|
-
port: options.port,
|
|
85
|
+
port: options.port || 'cloud',
|
|
88
86
|
proxyCommand,
|
|
89
87
|
username,
|
|
90
88
|
verbose: options.verbose,
|
|
91
89
|
});
|
|
92
90
|
}
|
|
93
|
-
async getContainerId(sdk, uuid, serviceName, sshOpts, version, id) {
|
|
94
|
-
const semver = await Promise.resolve().then(() => require('balena-semver'));
|
|
95
|
-
if (version == null || id == null) {
|
|
96
|
-
const device = await sdk.models.device.get(uuid, {
|
|
97
|
-
$select: ['id', 'supervisor_version'],
|
|
98
|
-
});
|
|
99
|
-
version = device.supervisor_version;
|
|
100
|
-
id = device.id;
|
|
101
|
-
}
|
|
102
|
-
let containerId;
|
|
103
|
-
if (semver.gte(version, '8.6.0')) {
|
|
104
|
-
const apiUrl = await sdk.settings.get('apiUrl');
|
|
105
|
-
const request = await sdk.request.send({
|
|
106
|
-
method: 'POST',
|
|
107
|
-
url: '/supervisor/v2/containerId',
|
|
108
|
-
baseUrl: apiUrl,
|
|
109
|
-
body: {
|
|
110
|
-
method: 'GET',
|
|
111
|
-
deviceId: id,
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
if (request.status !== 200) {
|
|
115
|
-
throw new Error(`There was an error connecting to device ${uuid}, HTTP response code: ${request.status}.`);
|
|
116
|
-
}
|
|
117
|
-
const body = request.body;
|
|
118
|
-
if (body.status !== 'success') {
|
|
119
|
-
throw new Error(`There was an error communicating with device ${uuid}.\n\tError: ${body.message}`);
|
|
120
|
-
}
|
|
121
|
-
containerId = body.services[serviceName];
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
console.error((0, lazy_1.stripIndent) `
|
|
125
|
-
Using slow legacy method to determine container IDs. To speed up
|
|
126
|
-
this process, update the device supervisor to v8.6.0 or later.
|
|
127
|
-
`);
|
|
128
|
-
const { escapeRegExp } = await Promise.resolve().then(() => require('lodash'));
|
|
129
|
-
const { deviceContainerEngineBinary } = await Promise.resolve().then(() => require('../utils/device/ssh'));
|
|
130
|
-
const { getRemoteCommandOutput } = await Promise.resolve().then(() => require('../utils/ssh'));
|
|
131
|
-
const containers = (await getRemoteCommandOutput({
|
|
132
|
-
cmd: `host ${uuid} "${deviceContainerEngineBinary}" ps --format "{{.ID}} {{.Names}}"`,
|
|
133
|
-
hostname: `ssh.${sshOpts.proxyUrl}`,
|
|
134
|
-
port: sshOpts.port,
|
|
135
|
-
proxyCommand: sshOpts.proxyCommand,
|
|
136
|
-
stderr: 'inherit',
|
|
137
|
-
username: sshOpts.username,
|
|
138
|
-
})).stdout.toString();
|
|
139
|
-
const lines = containers.split('\n');
|
|
140
|
-
const regex = new RegExp(`\\/?${escapeRegExp(serviceName)}_\\d+_\\d+`);
|
|
141
|
-
for (const container of lines) {
|
|
142
|
-
const [cId, name] = container.split(' ');
|
|
143
|
-
if (regex.test(name)) {
|
|
144
|
-
containerId = cId;
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (containerId == null) {
|
|
150
|
-
throw new Error(`Could not find a service ${serviceName} on device ${uuid}.`);
|
|
151
|
-
}
|
|
152
|
-
return containerId;
|
|
153
|
-
}
|
|
154
91
|
}
|
|
155
92
|
exports.default = SshCmd;
|
|
156
93
|
SshCmd.description = (0, lazy_1.stripIndent) `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../lib/commands/ssh.ts"],"names":[],"mappings":";;AAiBA,4CAAuC;AACvC,wCAAiC;AACjC,4CAA4C;AAC5C,wCAA0D;AAC1D,oDAAgF;
|
|
1
|
+
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../lib/commands/ssh.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
port?: number;
|
|
1
|
+
import { SshRemoteCommandOpts } from '../ssh';
|
|
2
|
+
export interface DeviceSSHOpts extends SshRemoteCommandOpts {
|
|
4
3
|
forceTTY?: boolean;
|
|
5
|
-
verbose: boolean;
|
|
6
4
|
service?: string;
|
|
7
5
|
}
|
|
8
|
-
export declare
|
|
6
|
+
export declare function getContainerIdForService(opts: SshRemoteCommandOpts & {
|
|
7
|
+
service: string;
|
|
8
|
+
deviceUuid?: string;
|
|
9
|
+
}): Promise<string>;
|
|
9
10
|
export declare function performLocalDeviceSSH(opts: DeviceSSHOpts): Promise<void>;
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.performLocalDeviceSSH = exports.
|
|
3
|
+
exports.performLocalDeviceSSH = exports.getContainerIdForService = void 0;
|
|
4
4
|
const errors_1 = require("../../errors");
|
|
5
5
|
const lazy_1 = require("../lazy");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
host
|
|
12
|
-
port: 2375,
|
|
13
|
-
});
|
|
14
|
-
const regex = new RegExp(`(^|\\/)${escapeRegExp(service)}_\\d+_\\d+`);
|
|
15
|
-
const nameRegex = /\/?([a-zA-Z0-9_-]+)_\d+_\d+/;
|
|
16
|
-
let allContainers;
|
|
17
|
-
try {
|
|
18
|
-
allContainers = await docker.listContainers();
|
|
19
|
-
}
|
|
20
|
-
catch (_e) {
|
|
21
|
-
throw new errors_1.ExpectedError((0, lazy_1.stripIndent) `
|
|
22
|
-
Could not access docker daemon on device ${deviceAddress}.
|
|
23
|
-
Please ensure the device is in local mode.`);
|
|
6
|
+
const ssh_1 = require("../ssh");
|
|
7
|
+
const deviceContainerEngineBinary = `$(if [ -f /usr/bin/balena ]; then echo "balena"; else echo "docker"; fi)`;
|
|
8
|
+
async function getContainerIdForService(opts) {
|
|
9
|
+
opts.cmd = `"${deviceContainerEngineBinary}" ps --format "{{.ID}} {{.Names}}"`;
|
|
10
|
+
if (opts.deviceUuid) {
|
|
11
|
+
opts.cmd = `host ${opts.deviceUuid} ${opts.cmd}`;
|
|
24
12
|
}
|
|
13
|
+
const psLines = (await (0, ssh_1.getRemoteCommandOutput)({ ...opts, stderr: 'inherit' })).stdout
|
|
14
|
+
.toString()
|
|
15
|
+
.split('\n')
|
|
16
|
+
.filter((l) => l);
|
|
17
|
+
const { escapeRegExp } = await Promise.resolve().then(() => require('lodash'));
|
|
18
|
+
const regex = new RegExp(`(?:^|\\/)${escapeRegExp(opts.service)}_\\d+_\\d+`);
|
|
19
|
+
const nameRegex = /(?:^|\/)([a-zA-Z0-9_-]+)_\d+_\d+(?:_.+)?$/;
|
|
25
20
|
const serviceNames = [];
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const containerNames = [];
|
|
22
|
+
let containerId;
|
|
23
|
+
for (const psLine of psLines) {
|
|
24
|
+
const [cId, name] = psLine.split(' ');
|
|
25
|
+
if (cId && name) {
|
|
29
26
|
if (regex.test(name)) {
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
containerNames.push(name);
|
|
28
|
+
containerId = cId;
|
|
32
29
|
}
|
|
33
30
|
const match = name.match(nameRegex);
|
|
34
31
|
if (match) {
|
|
@@ -36,39 +33,38 @@ async function getContainerIdForService(service, deviceAddress) {
|
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
|
-
if (
|
|
36
|
+
if (containerNames.length > 1) {
|
|
37
|
+
const [s, d] = [opts.service, opts.deviceUuid || opts.hostname];
|
|
40
38
|
throw new errors_1.ExpectedError((0, lazy_1.stripIndent) `
|
|
41
|
-
Found more than one container matching service name "${
|
|
42
|
-
${
|
|
39
|
+
Found more than one container matching service name "${s}" on device "${d}":
|
|
40
|
+
${containerNames.join(', ')}
|
|
43
41
|
Use different service names to avoid ambiguity.
|
|
44
42
|
`);
|
|
45
43
|
}
|
|
46
|
-
const containerId = containers.length ? containers[0].id : '';
|
|
47
44
|
if (!containerId) {
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const [s, d] = [opts.service, opts.deviceUuid || opts.hostname];
|
|
46
|
+
throw new errors_1.ExpectedError(`Could not find a container matching service name "${s}" on device "${d}".${serviceNames.length > 0
|
|
47
|
+
? `\nAvailable services:\n\t${serviceNames.join('\n\t')}`
|
|
50
48
|
: ''}`);
|
|
51
49
|
}
|
|
52
50
|
return containerId;
|
|
53
51
|
}
|
|
52
|
+
exports.getContainerIdForService = getContainerIdForService;
|
|
54
53
|
async function performLocalDeviceSSH(opts) {
|
|
54
|
+
const username = await (0, ssh_1.findBestUsernameForDevice)(opts.hostname, opts.port);
|
|
55
55
|
let cmd = '';
|
|
56
56
|
if (opts.service) {
|
|
57
|
-
const containerId = await getContainerIdForService(
|
|
57
|
+
const containerId = await getContainerIdForService({
|
|
58
|
+
...opts,
|
|
59
|
+
service: opts.service,
|
|
60
|
+
username,
|
|
61
|
+
});
|
|
58
62
|
const shellCmd = `/bin/sh -c "if [ -e /bin/bash ]; then exec /bin/bash; else exec /bin/sh; fi"`;
|
|
59
63
|
const isTTY = !!opts.forceTTY || (await Promise.resolve().then(() => require('tty'))).isatty(0);
|
|
60
64
|
const ttyFlag = isTTY ? '-t' : '';
|
|
61
|
-
cmd = `${
|
|
65
|
+
cmd = `${deviceContainerEngineBinary} exec -i ${ttyFlag} ${containerId} ${shellCmd}`;
|
|
62
66
|
}
|
|
63
|
-
|
|
64
|
-
const username = await findBestUsernameForDevice(opts.address);
|
|
65
|
-
await runRemoteCommand({
|
|
66
|
-
cmd,
|
|
67
|
-
hostname: opts.address,
|
|
68
|
-
port: Number(opts.port) || 'local',
|
|
69
|
-
username,
|
|
70
|
-
verbose: opts.verbose,
|
|
71
|
-
});
|
|
67
|
+
await (0, ssh_1.runRemoteCommand)({ ...opts, cmd, username });
|
|
72
68
|
}
|
|
73
69
|
exports.performLocalDeviceSSH = performLocalDeviceSSH;
|
|
74
70
|
//# sourceMappingURL=ssh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../../lib/utils/device/ssh.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../../lib/utils/device/ssh.ts"],"names":[],"mappings":"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"}
|
package/build/utils/ssh.d.ts
CHANGED
|
@@ -38,6 +38,6 @@ export declare function getRemoteCommandOutput({ cmd, hostname, port, proxyComma
|
|
|
38
38
|
stderr: Buffer;
|
|
39
39
|
}>;
|
|
40
40
|
export declare function getLocalDeviceCmdStdout(hostname: string, cmd: string, stdout?: 'capture' | 'ignore' | 'inherit' | NodeJS.WritableStream): Promise<Buffer>;
|
|
41
|
-
export declare const isRootUserGood: ((hostname: string, port
|
|
42
|
-
export declare const findBestUsernameForDevice: ((hostname: string, port
|
|
41
|
+
export declare const isRootUserGood: ((hostname: string, port: any) => Promise<boolean>) & _.MemoizedFunction;
|
|
42
|
+
export declare const findBestUsernameForDevice: ((hostname: string, port: any) => Promise<string>) & _.MemoizedFunction;
|
|
43
43
|
export declare const getDeviceOsRelease: ((hostname: string) => Promise<string>) & _.MemoizedFunction;
|
package/build/utils/ssh.js
CHANGED
|
@@ -133,17 +133,18 @@ async function getRemoteCommandOutput({ cmd, hostname, port, proxyCommand, stdin
|
|
|
133
133
|
}
|
|
134
134
|
exports.getRemoteCommandOutput = getRemoteCommandOutput;
|
|
135
135
|
async function getLocalDeviceCmdStdout(hostname, cmd, stdout = 'capture') {
|
|
136
|
+
const port = 'local';
|
|
136
137
|
return (await getRemoteCommandOutput({
|
|
137
138
|
cmd,
|
|
138
139
|
hostname,
|
|
139
|
-
port
|
|
140
|
+
port,
|
|
140
141
|
stdout,
|
|
141
142
|
stderr: 'inherit',
|
|
142
|
-
username: await (0, exports.findBestUsernameForDevice)(hostname),
|
|
143
|
+
username: await (0, exports.findBestUsernameForDevice)(hostname, port),
|
|
143
144
|
})).stdout;
|
|
144
145
|
}
|
|
145
146
|
exports.getLocalDeviceCmdStdout = getLocalDeviceCmdStdout;
|
|
146
|
-
exports.isRootUserGood = _.memoize(async (hostname, port
|
|
147
|
+
exports.isRootUserGood = _.memoize(async (hostname, port) => {
|
|
147
148
|
try {
|
|
148
149
|
await runRemoteCommand({ cmd: 'exit 0', hostname, port, ...exports.stdioIgnore });
|
|
149
150
|
}
|
|
@@ -152,7 +153,7 @@ exports.isRootUserGood = _.memoize(async (hostname, port = 'local') => {
|
|
|
152
153
|
}
|
|
153
154
|
return true;
|
|
154
155
|
});
|
|
155
|
-
exports.findBestUsernameForDevice = _.memoize(async (hostname, port
|
|
156
|
+
exports.findBestUsernameForDevice = _.memoize(async (hostname, port) => {
|
|
156
157
|
var _a;
|
|
157
158
|
let username;
|
|
158
159
|
if (await (0, exports.isRootUserGood)(hostname, port)) {
|
|
@@ -162,7 +163,13 @@ exports.findBestUsernameForDevice = _.memoize(async (hostname, port = 'local') =
|
|
|
162
163
|
const { getCachedUsername } = await Promise.resolve().then(() => require('./bootstrap'));
|
|
163
164
|
username = (_a = (await getCachedUsername())) === null || _a === void 0 ? void 0 : _a.username;
|
|
164
165
|
}
|
|
165
|
-
|
|
166
|
+
if (!username) {
|
|
167
|
+
const { stripIndent } = await Promise.resolve().then(() => require('./lazy'));
|
|
168
|
+
throw new errors_1.ExpectedError(stripIndent `
|
|
169
|
+
SSH authentication failed for 'root@${hostname}'.
|
|
170
|
+
Please login with 'balena login' for alternative authentication.`);
|
|
171
|
+
}
|
|
172
|
+
return username;
|
|
166
173
|
});
|
|
167
174
|
exports.getDeviceOsRelease = _.memoize(async (hostname) => (await getLocalDeviceCmdStdout(hostname, 'cat /etc/os-release')).toString());
|
|
168
175
|
function sshErrorMessage(cmd, exitSignal, exitCode) {
|
package/build/utils/ssh.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../lib/utils/ssh.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../lib/utils/ssh.ts"],"names":[],"mappings":"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"}
|
package/lib/commands/ssh.ts
CHANGED
|
@@ -20,7 +20,6 @@ import Command from '../command';
|
|
|
20
20
|
import * as cf from '../utils/common-flags';
|
|
21
21
|
import { getBalenaSdk, stripIndent } from '../utils/lazy';
|
|
22
22
|
import { parseAsInteger, validateLocalHostnameOrIp } from '../utils/validation';
|
|
23
|
-
import * as BalenaSdk from 'balena-sdk';
|
|
24
23
|
|
|
25
24
|
interface FlagsDef {
|
|
26
25
|
port?: number;
|
|
@@ -128,8 +127,8 @@ export default class SshCmd extends Command {
|
|
|
128
127
|
if (validateLocalHostnameOrIp(params.fleetOrDevice)) {
|
|
129
128
|
const { performLocalDeviceSSH } = await import('../utils/device/ssh');
|
|
130
129
|
return await performLocalDeviceSSH({
|
|
131
|
-
|
|
132
|
-
port: options.port,
|
|
130
|
+
hostname: params.fleetOrDevice,
|
|
131
|
+
port: options.port || 'local',
|
|
133
132
|
forceTTY: options.tty,
|
|
134
133
|
verbose: options.verbose,
|
|
135
134
|
service: params.service,
|
|
@@ -152,12 +151,6 @@ export default class SshCmd extends Command {
|
|
|
152
151
|
params.fleetOrDevice,
|
|
153
152
|
);
|
|
154
153
|
|
|
155
|
-
const device = await sdk.models.device.get(deviceUuid, {
|
|
156
|
-
$select: ['id', 'supervisor_version', 'is_online'],
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const deviceId = device.id;
|
|
160
|
-
const supervisorVersion = device.supervisor_version;
|
|
161
154
|
const { which } = await import('../utils/which');
|
|
162
155
|
|
|
163
156
|
const [whichProxytunnel, username, proxyUrl] = await Promise.all([
|
|
@@ -209,19 +202,15 @@ export default class SshCmd extends Command {
|
|
|
209
202
|
// that we know exists and is accessible
|
|
210
203
|
let containerId: string | undefined;
|
|
211
204
|
if (params.service != null) {
|
|
212
|
-
|
|
213
|
-
|
|
205
|
+
const { getContainerIdForService } = await import('../utils/device/ssh');
|
|
206
|
+
containerId = await getContainerIdForService({
|
|
214
207
|
deviceUuid,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
},
|
|
222
|
-
supervisorVersion,
|
|
223
|
-
deviceId,
|
|
224
|
-
);
|
|
208
|
+
hostname: `ssh.${proxyUrl}`,
|
|
209
|
+
port: options.port || 'cloud',
|
|
210
|
+
proxyCommand,
|
|
211
|
+
service: params.service,
|
|
212
|
+
username: username!,
|
|
213
|
+
});
|
|
225
214
|
}
|
|
226
215
|
|
|
227
216
|
let accessCommand: string;
|
|
@@ -234,101 +223,10 @@ export default class SshCmd extends Command {
|
|
|
234
223
|
await runRemoteCommand({
|
|
235
224
|
cmd: accessCommand,
|
|
236
225
|
hostname: `ssh.${proxyUrl}`,
|
|
237
|
-
port: options.port,
|
|
226
|
+
port: options.port || 'cloud',
|
|
238
227
|
proxyCommand,
|
|
239
228
|
username,
|
|
240
229
|
verbose: options.verbose,
|
|
241
230
|
});
|
|
242
231
|
}
|
|
243
|
-
|
|
244
|
-
async getContainerId(
|
|
245
|
-
sdk: BalenaSdk.BalenaSDK,
|
|
246
|
-
uuid: string,
|
|
247
|
-
serviceName: string,
|
|
248
|
-
sshOpts: {
|
|
249
|
-
port?: number;
|
|
250
|
-
proxyCommand?: string[];
|
|
251
|
-
proxyUrl: string;
|
|
252
|
-
username: string;
|
|
253
|
-
},
|
|
254
|
-
version?: string,
|
|
255
|
-
id?: number,
|
|
256
|
-
): Promise<string> {
|
|
257
|
-
const semver = await import('balena-semver');
|
|
258
|
-
|
|
259
|
-
if (version == null || id == null) {
|
|
260
|
-
const device = await sdk.models.device.get(uuid, {
|
|
261
|
-
$select: ['id', 'supervisor_version'],
|
|
262
|
-
});
|
|
263
|
-
version = device.supervisor_version;
|
|
264
|
-
id = device.id;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
let containerId: string | undefined;
|
|
268
|
-
if (semver.gte(version, '8.6.0')) {
|
|
269
|
-
const apiUrl = await sdk.settings.get('apiUrl');
|
|
270
|
-
// TODO: Move this into the SDKs device model
|
|
271
|
-
const request = await sdk.request.send({
|
|
272
|
-
method: 'POST',
|
|
273
|
-
url: '/supervisor/v2/containerId',
|
|
274
|
-
baseUrl: apiUrl,
|
|
275
|
-
body: {
|
|
276
|
-
method: 'GET',
|
|
277
|
-
deviceId: id,
|
|
278
|
-
},
|
|
279
|
-
});
|
|
280
|
-
if (request.status !== 200) {
|
|
281
|
-
throw new Error(
|
|
282
|
-
`There was an error connecting to device ${uuid}, HTTP response code: ${request.status}.`,
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
const body = request.body;
|
|
286
|
-
if (body.status !== 'success') {
|
|
287
|
-
throw new Error(
|
|
288
|
-
`There was an error communicating with device ${uuid}.\n\tError: ${body.message}`,
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
containerId = body.services[serviceName];
|
|
292
|
-
} else {
|
|
293
|
-
console.error(stripIndent`
|
|
294
|
-
Using slow legacy method to determine container IDs. To speed up
|
|
295
|
-
this process, update the device supervisor to v8.6.0 or later.
|
|
296
|
-
`);
|
|
297
|
-
// We need to execute a balena ps command on the device,
|
|
298
|
-
// and parse the output, looking for a specific
|
|
299
|
-
// container
|
|
300
|
-
const { escapeRegExp } = await import('lodash');
|
|
301
|
-
const { deviceContainerEngineBinary } = await import(
|
|
302
|
-
'../utils/device/ssh'
|
|
303
|
-
);
|
|
304
|
-
const { getRemoteCommandOutput } = await import('../utils/ssh');
|
|
305
|
-
|
|
306
|
-
const containers: string = (
|
|
307
|
-
await getRemoteCommandOutput({
|
|
308
|
-
cmd: `host ${uuid} "${deviceContainerEngineBinary}" ps --format "{{.ID}} {{.Names}}"`,
|
|
309
|
-
hostname: `ssh.${sshOpts.proxyUrl}`,
|
|
310
|
-
port: sshOpts.port,
|
|
311
|
-
proxyCommand: sshOpts.proxyCommand,
|
|
312
|
-
stderr: 'inherit',
|
|
313
|
-
username: sshOpts.username,
|
|
314
|
-
})
|
|
315
|
-
).stdout.toString();
|
|
316
|
-
const lines = containers.split('\n');
|
|
317
|
-
const regex = new RegExp(`\\/?${escapeRegExp(serviceName)}_\\d+_\\d+`);
|
|
318
|
-
for (const container of lines) {
|
|
319
|
-
const [cId, name] = container.split(' ');
|
|
320
|
-
if (regex.test(name)) {
|
|
321
|
-
containerId = cId;
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (containerId == null) {
|
|
328
|
-
throw new Error(
|
|
329
|
-
`Could not find a service ${serviceName} on device ${uuid}.`,
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
return containerId;
|
|
333
|
-
}
|
|
334
232
|
}
|