Merge pull request #2148 from balena-io/remove-internal-scandevices

Refactor out command internal scandevices
This commit is contained in:
bulldozer-balena[bot] 2021-01-06 15:29:10 +00:00 committed by GitHub
commit f45fac6138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 106 deletions

View File

@ -3191,8 +3191,8 @@ To move a device between applications on the same server, use the
If you don't specify a device hostname or IP, this command will automatically
scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This requires root privileges. Likewise, if
the application flag is not provided then a picker will be shown.
from an interactive picker. This may require administrator/root privileges.
Likewise, if the application flag is not provided then a picker will be shown.
Applications may be specified by app name, slug, or numeric ID. App slugs
are the recommended option, as they are unique and unambiguous. Slugs
@ -3243,7 +3243,7 @@ so the device can subsequently re-join the server if needed.
If you don't specify a device hostname or IP, this command will automatically
scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This usually requires root privileges.
from an interactive picker. This may require administrator/root privileges.
Examples:

View File

@ -1,55 +0,0 @@
/**
* @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 Command from '../../command';
import { stripIndent } from '../../utils/lazy';
// 'Internal' commands are called during the execution of other commands.
// `scandevices` is called during by `join`,`leave'.
// TODO: These should be refactored to modules/functions, and removed
// See previous `internal sudo` refactor:
// - https://github.com/balena-io/balena-cli/pull/1455/files
// - https://github.com/balena-io/balena-cli/pull/1455#discussion_r334308357
// - https://github.com/balena-io/balena-cli/pull/1455#discussion_r334308526
export default class ScandevicesCmd extends Command {
public static description = stripIndent`
Scan for local balena-enabled devices and show a picker to choose one.
Don't use this command directly!
`;
public static usage = 'internal scandevices';
public static root = true;
public static hidden = true;
public async run() {
const { forms } = await import('balena-sync');
try {
const hostnameOrIp = await forms.selectLocalBalenaOsDevice();
return console.error(`==> Selected device: ${hostnameOrIp}`);
} catch (e) {
if (e.message.toLowerCase().includes('could not find any')) {
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(e);
} else {
throw e;
}
}
}
}

View File

@ -48,8 +48,8 @@ export default class JoinCmd extends Command {
If you don't specify a device hostname or IP, this command will automatically
scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This requires root privileges. Likewise, if
the application flag is not provided then a picker will be shown.
from an interactive picker. This may require administrator/root privileges.
Likewise, if the application flag is not provided then a picker will be shown.
${applicationIdInfo.split('\n').join('\n\t\t')}
`;

View File

@ -18,7 +18,7 @@
import { flags } from '@oclif/command';
import Command from '../command';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../utils/lazy';
import { stripIndent } from '../utils/lazy';
import { parseAsLocalHostnameOrIp } from '../utils/validation';
interface FlagsDef {
@ -42,7 +42,7 @@ export default class LeaveCmd extends Command {
If you don't specify a device hostname or IP, this command will automatically
scan the local network for balenaOS devices and prompt you to select one
from an interactive picker. This usually requires root privileges.
from an interactive picker. This may require administrator/root privileges.
`;
public static examples = [
@ -72,8 +72,7 @@ export default class LeaveCmd extends Command {
const { args: params } = this.parse<FlagsDef, ArgsDef>(LeaveCmd);
const promote = await import('../utils/promote');
const sdk = getBalenaSdk();
const logger = await Command.getLogger();
return promote.leave(logger, sdk, params.deviceIpOrHostname);
return promote.leave(logger, params.deviceIpOrHostname);
}
}

View File

@ -31,12 +31,12 @@ export async function join(
appUpdatePollInterval?: number,
): Promise<void> {
logger.logDebug('Determining device...');
const deviceIp = await getOrSelectLocalDevice(deviceHostnameOrIp);
await assertDeviceIsCompatible(deviceIp);
logger.logDebug(`Using device: ${deviceIp}`);
deviceHostnameOrIp = deviceHostnameOrIp || (await selectLocalDevice());
await assertDeviceIsCompatible(deviceHostnameOrIp);
logger.logDebug(`Using device: ${deviceHostnameOrIp}`);
logger.logDebug('Determining device type...');
const deviceType = await getDeviceType(deviceIp);
const deviceType = await getDeviceType(deviceHostnameOrIp);
logger.logDebug(`Device type: ${deviceType}`);
logger.logDebug('Determining application...');
@ -50,7 +50,7 @@ export async function join(
}
logger.logDebug('Determining device OS version...');
const deviceOsVersion = await getOsVersion(deviceIp);
const deviceOsVersion = await getOsVersion(deviceHostnameOrIp);
logger.logDebug(`Device OS version: ${deviceOsVersion}`);
logger.logDebug('Generating application config...');
@ -61,8 +61,7 @@ export async function join(
logger.logDebug(`Using config: ${JSON.stringify(config, null, 2)}`);
logger.logDebug('Configuring...');
await configure(deviceIp, config);
logger.logDebug('All done.');
await configure(deviceHostnameOrIp, config);
const platformUrl = await sdk.settings.get('balenaUrl');
logger.logSuccess(`Device successfully joined ${platformUrl}!`);
@ -70,17 +69,15 @@ export async function join(
export async function leave(
logger: Logger,
_sdk: BalenaSdk.BalenaSDK,
deviceHostnameOrIp?: string,
): Promise<void> {
logger.logDebug('Determining device...');
const deviceIp = await getOrSelectLocalDevice(deviceHostnameOrIp);
await assertDeviceIsCompatible(deviceIp);
logger.logDebug(`Using device: ${deviceIp}`);
deviceHostnameOrIp = deviceHostnameOrIp || (await selectLocalDevice());
await assertDeviceIsCompatible(deviceHostnameOrIp);
logger.logDebug(`Using device: ${deviceHostnameOrIp}`);
logger.logDebug('Deconfiguring...');
await deconfigure(deviceIp);
logger.logDebug('All done.');
await deconfigure(deviceHostnameOrIp);
logger.logSuccess('Device successfully left the platform.');
}
@ -155,39 +152,21 @@ async function getOsVersion(deviceIp: string): Promise<string> {
return match[1];
}
async function getOrSelectLocalDevice(deviceIp?: string): Promise<string> {
if (deviceIp) {
return deviceIp;
}
const through = await import('through2');
let ip: string | null = null;
const stream = through(function (data, _enc, cb) {
const match = /^==> Selected device: (.*)$/m.exec(data.toString());
if (match) {
ip = match[1];
cb();
async function selectLocalDevice(): Promise<string> {
const { forms } = await import('balena-sync');
let hostnameOrIp;
try {
hostnameOrIp = await forms.selectLocalBalenaOsDevice();
console.error(`==> Selected device: ${hostnameOrIp}`);
} catch (e) {
if (e.message.toLowerCase().includes('could not find any')) {
throw new ExpectedError(e);
} else {
cb(null, data);
throw e;
}
});
stream.pipe(process.stderr);
const { sudo } = await import('../utils/helpers');
const command = ['internal', 'scandevices'];
await sudo(command, {
stderr: stream,
msg:
'Scanning for local devices. If asked, please type your computer password.',
});
if (!ip) {
throw new ExpectedError('No device selected');
}
return ip;
return hostnameOrIp;
}
async function selectAppFromList(