Add alias device ssh for ssh command

Change-type: minor
This commit is contained in:
myarmolinsky 2024-09-26 11:26:19 -04:00
parent 3f82f42652
commit 76c08b6c13
21 changed files with 142 additions and 135 deletions

View File

@ -145,7 +145,7 @@ container) in order to allow npm scripts like `postinstall` to be executed.
## Additional Dependencies ## Additional Dependencies
The `balena ssh`, `device detect`, `build`, `deploy` and `preload` commands may require The `balena device ssh`, `device detect`, `build`, `deploy` and `preload` commands may require
additional software to be installed. Check the Additional Dependencies sections for each operating additional software to be installed. Check the Additional Dependencies sections for each operating
system: system:

View File

@ -61,13 +61,13 @@ instructions](https://docs.docker.com/install/overview/) to install Docker on th
workstation as the balena CLI. The [advanced installation workstation as the balena CLI. The [advanced installation
options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities. options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities.
### balena ssh ### balena device ssh
The `balena ssh` command requires the `ssh` command-line tool to be available. Most Linux The `balena device ssh` command requires the `ssh` command-line tool to be available. Most Linux
distributions will already have it installed. Otherwise, `sudo apt-get install openssh-client` distributions will already have it installed. Otherwise, `sudo apt-get install openssh-client`
should do the trick on Debian or Ubuntu. should do the trick on Debian or Ubuntu.
The `balena ssh` command also requires an SSH key to be added to your balena account: see [SSH The `balena device ssh` command also requires an SSH key to be added to your balena account: see [SSH
Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*` Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*`
command set can also be used to list and manage SSH keys: see `balena help -v`. command set can also be used to list and manage SSH keys: see `balena help -v`.

View File

@ -19,7 +19,7 @@ Selected operating system: **macOS**
- On the terminal prompt, type `balena version` and hit Enter. It should display - On the terminal prompt, type `balena version` and hit Enter. It should display
the version of the balena CLI that you have installed. the version of the balena CLI that you have installed.
No further steps are required to run most CLI commands. The `balena ssh`, `build`, `deploy` No further steps are required to run most CLI commands. The `balena device ssh`, `build`, `deploy`
and `preload` commands may require additional software to be installed, as described and `preload` commands may require additional software to be installed, as described
in the next section. in the next section.
@ -41,9 +41,9 @@ instructions](https://docs.docker.com/install/overview/) to install Docker on th
workstation as the balena CLI. The [advanced installation workstation as the balena CLI. The [advanced installation
options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities. options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities.
### balena ssh ### balena device ssh
The `balena ssh` command requires the `ssh` command-line tool to be available. To check whether The `balena device ssh` command requires the `ssh` command-line tool to be available. To check whether
it is already installed, run `ssh` on a Terminal window. If it is not yet installed, the options it is already installed, run `ssh` on a Terminal window. If it is not yet installed, the options
include: include:
@ -52,7 +52,7 @@ include:
Components → Command Line Tools → Install. Components → Command Line Tools → Install.
* Or, install [Homebrew](https://brew.sh/), then `brew install openssh` * Or, install [Homebrew](https://brew.sh/), then `brew install openssh`
The `balena ssh` command also requires an SSH key to be added to your balena account: see [SSH The `balena device ssh` command also requires an SSH key to be added to your balena account: see [SSH
Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*` Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*`
command set can also be used to list and manage SSH keys: see `balena help -v`. command set can also be used to list and manage SSH keys: see `balena help -v`.

View File

@ -19,7 +19,7 @@ Selected operating system: **Windows**
- On the command prompt, type `balena version` and hit Enter. It should display - On the command prompt, type `balena version` and hit Enter. It should display
the version of the balena CLI that you have installed. the version of the balena CLI that you have installed.
No further steps are required to run most CLI commands. The `balena ssh`, `device detect`, `build`, No further steps are required to run most CLI commands. The `balena device ssh`, `device detect`, `build`,
`deploy` and `preload` commands may require additional software to be installed, as `deploy` and `preload` commands may require additional software to be installed, as
described below. described below.
@ -34,9 +34,9 @@ instructions](https://docs.docker.com/install/overview/) to install Docker on th
workstation as the balena CLI. The [advanced installation workstation as the balena CLI. The [advanced installation
options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities. options](./INSTALL-ADVANCED.md#additional-dependencies) document describes other possibilities.
### balena ssh ### balena device ssh
The `balena ssh` command requires the `ssh` command-line tool to be available. Microsoft started The `balena device ssh` command requires the `ssh` command-line tool to be available. Microsoft started
distributing an SSH client with Windows 10, which is automatically installed through Windows distributing an SSH client with Windows 10, which is automatically installed through Windows
Update. To check whether it is installed, run `ssh` on a Windows Command Prompt or PowerShell. It Update. To check whether it is installed, run `ssh` on a Windows Command Prompt or PowerShell. It
can also be [manually can also be [manually
@ -44,7 +44,7 @@ installed](https://docs.microsoft.com/en-us/windows-server/administration/openss
if needed. For older versions of Windows, there are several ssh/OpenSSH clients provided by 3rd if needed. For older versions of Windows, there are several ssh/OpenSSH clients provided by 3rd
parties. parties.
The `balena ssh` command also requires an SSH key to be added to your balena account: see [SSH The `balena device ssh` command also requires an SSH key to be added to your balena account: see [SSH
Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*` Access documentation](https://www.balena.io/docs/learn/manage/ssh-access/). The `balena key*`
command set can also be used to list and manage SSH keys: see `balena help -v`. command set can also be used to list and manage SSH keys: see `balena help -v`.

View File

@ -88,9 +88,9 @@ HTTP(S) proxies can be configured through any of the following methods, in prece
* The `HTTPS_PROXY` and/or `HTTP_PROXY` environment variables, in the same URL format as * The `HTTPS_PROXY` and/or `HTTP_PROXY` environment variables, in the same URL format as
`BALENARC_PROXY`. `BALENARC_PROXY`.
### Proxy setup for balena ssh ### Proxy setup for balena device ssh
In order to work behind a proxy server, the `balena ssh` command requires the In order to work behind a proxy server, the `balena device ssh` command requires the
[`proxytunnel`](http://proxytunnel.sourceforge.net/) package (command-line tool) to be installed. [`proxytunnel`](http://proxytunnel.sourceforge.net/) package (command-line tool) to be installed.
`proxytunnel` is available for Linux distributions like Ubuntu/Debian (`apt install proxytunnel`), `proxytunnel` is available for Linux distributions like Ubuntu/Debian (`apt install proxytunnel`),
and for macOS through [Homebrew](https://brew.sh/). Windows support is limited to the [Windows and for macOS through [Homebrew](https://brew.sh/). Windows support is limited to the [Windows
@ -110,7 +110,7 @@ The `BALENARC_NO_PROXY` variable may be used to exclude specified destinations f
> * This feature requires CLI version 11.30.8 or later. In the case of the npm [installation > * This feature requires CLI version 11.30.8 or later. In the case of the npm [installation
> option](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md), it also requires > option](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md), it also requires
> Node.js version 10.16.0 or later. > Node.js version 10.16.0 or later.
> * To exclude a `balena ssh` target from proxying (IP address or `.local` hostname), the > * To exclude a `balena device ssh` target from proxying (IP address or `.local` hostname), the
> `--noproxy` option should be specified in addition to the `BALENARC_NO_PROXY` variable. > `--noproxy` option should be specified in addition to the `BALENARC_NO_PROXY` variable.
By default (if `BALENARC_NO_PROXY` is not defined), all [private IPv4 By default (if `BALENARC_NO_PROXY` is not defined), all [private IPv4

View File

@ -79,10 +79,10 @@ Try resetting the ownership by running:
$ sudo chown -R <user> $HOME/.balena $ sudo chown -R <user> $HOME/.balena
``` ```
## Broken line wrapping / cursor behavior with `balena ssh` ## Broken line wrapping / cursor behavior with `balena device ssh`
Users sometimes come across broken line wrapping or cursor behavior in text terminals, for example Users sometimes come across broken line wrapping or cursor behavior in text terminals, for example
when long command lines are typed in a `balena ssh` session, or when using text editors like `vim` when long command lines are typed in a `balena device ssh` session, or when using text editors like `vim`
or `nano`. This is not something specific to the balena CLI, being also a commonly reported issue or `nano`. This is not something specific to the balena CLI, being also a commonly reported issue
with standard remote terminal tools like `ssh` or `telnet`. It is often a remote shell with standard remote terminal tools like `ssh` or `telnet`. It is often a remote shell
configuration issue (files like `/etc/profile`, `~/.bash_profile`, `~/.bash_login`, `~/.profile` configuration issue (files like `/etc/profile`, `~/.bash_profile`, `~/.bash_login`, `~/.profile`

View File

@ -61,7 +61,6 @@ const commandHeadings: { [key: string]: string } = {
organization: 'Organizations', organization: 'Organizations',
os: 'OS', os: 'OS',
util: 'Utilities', util: 'Utilities',
ssh: 'Network',
tunnel: 'Network', tunnel: 'Network',
build: 'Deploy', build: 'Deploy',
join: 'Platform', join: 'Platform',

View File

@ -8,13 +8,13 @@ _balena() {
local context state line curcontext="$curcontext" local context state line curcontext="$curcontext"
# Valid top-level completions # Valid top-level completions
main_commands=( api-key app block build config deploy device devices env fleet internal join leave local login logout notes organization os preload push release settings ssh ssh-key support tag tunnel util version whoami ) main_commands=( api-key app block build config deploy device devices env fleet internal join leave local login logout notes organization os preload push release settings ssh-key support tag tunnel util version whoami )
# Sub-completions # Sub-completions
api_key_cmds=( generate list revoke ) api_key_cmds=( generate list revoke )
app_cmds=( create ) app_cmds=( create )
block_cmds=( create ) block_cmds=( create )
config_cmds=( generate inject read reconfigure write ) config_cmds=( generate inject read reconfigure write )
device_cmds=( deactivate detect identify init list local-mode logs move os-update pin public-url purge reboot register rename restart rm shutdown start-service stop-service track-fleet ) device_cmds=( deactivate detect identify init list local-mode logs move os-update pin public-url purge reboot register rename restart rm shutdown ssh start-service stop-service track-fleet )
devices_cmds=( supported ) devices_cmds=( supported )
env_cmds=( add list rename rm ) env_cmds=( add list rename rm )
fleet_cmds=( create list pin purge rename restart rm track-latest ) fleet_cmds=( create list pin purge rename restart rm track-latest )

View File

@ -7,13 +7,13 @@ _balena_complete()
local cur prev local cur prev
# Valid top-level completions # Valid top-level completions
main_commands="api-key app block build config deploy device devices env fleet internal join leave local login logout notes organization os preload push release settings ssh ssh-key support tag tunnel util version whoami" main_commands="api-key app block build config deploy device devices env fleet internal join leave local login logout notes organization os preload push release settings ssh-key support tag tunnel util version whoami"
# Sub-completions # Sub-completions
api_key_cmds="generate list revoke" api_key_cmds="generate list revoke"
app_cmds="create" app_cmds="create"
block_cmds="create" block_cmds="create"
config_cmds="generate inject read reconfigure write" config_cmds="generate inject read reconfigure write"
device_cmds="deactivate detect identify init list local-mode logs move os-update pin public-url purge reboot register rename restart rm shutdown start-service stop-service track-fleet" device_cmds="deactivate detect identify init list local-mode logs move os-update pin public-url purge reboot register rename restart rm shutdown ssh start-service stop-service track-fleet"
devices_cmds="supported" devices_cmds="supported"
env_cmds="add list rename rm" env_cmds="add list rename rm"
fleet_cmds="create list pin purge rename restart rm track-latest" fleet_cmds="create list pin purge rename restart rm track-latest"

View File

@ -81,9 +81,9 @@ HTTP(S) proxies can be configured through any of the following methods, in prece
* The `HTTPS_PROXY` and/or `HTTP_PROXY` environment variables, in the same URL format as * The `HTTPS_PROXY` and/or `HTTP_PROXY` environment variables, in the same URL format as
`BALENARC_PROXY`. `BALENARC_PROXY`.
### Proxy setup for balena ssh ### Proxy setup for balena device ssh
In order to work behind a proxy server, the `balena ssh` command requires the In order to work behind a proxy server, the `balena device ssh` command requires the
[`proxytunnel`](http://proxytunnel.sourceforge.net/) package (command-line tool) to be installed. [`proxytunnel`](http://proxytunnel.sourceforge.net/) package (command-line tool) to be installed.
`proxytunnel` is available for Linux distributions like Ubuntu/Debian (`apt install proxytunnel`), `proxytunnel` is available for Linux distributions like Ubuntu/Debian (`apt install proxytunnel`),
and for macOS through [Homebrew](https://brew.sh/). Windows support is limited to the [Windows and for macOS through [Homebrew](https://brew.sh/). Windows support is limited to the [Windows
@ -103,7 +103,7 @@ The `BALENARC_NO_PROXY` variable may be used to exclude specified destinations f
> * This feature requires CLI version 11.30.8 or later. In the case of the npm [installation > * This feature requires CLI version 11.30.8 or later. In the case of the npm [installation
> option](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md), it also requires > option](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md), it also requires
> Node.js version 10.16.0 or later. > Node.js version 10.16.0 or later.
> * To exclude a `balena ssh` target from proxying (IP address or `.local` hostname), the > * To exclude a `balena device ssh` target from proxying (IP address or `.local` hostname), the
> `--noproxy` option should be specified in addition to the `BALENARC_NO_PROXY` variable. > `--noproxy` option should be specified in addition to the `BALENARC_NO_PROXY` variable.
By default (if `BALENARC_NO_PROXY` is not defined), all [private IPv4 By default (if `BALENARC_NO_PROXY` is not defined), all [private IPv4
@ -214,6 +214,7 @@ are encouraged to regularly update the balena CLI to the latest version.
- [device restart](#device-restart) - [device restart](#device-restart)
- [device rm](#device-rm) - [device rm](#device-rm)
- [device shutdown](#device-shutdown) - [device shutdown](#device-shutdown)
- [device ssh](#device-ssh)
- [device start-service](#device-start-service) - [device start-service](#device-start-service)
- [device stop-service](#device-stop-service) - [device stop-service](#device-stop-service)
- [device track-fleet](#device-track-fleet) - [device track-fleet](#device-track-fleet)
@ -245,7 +246,6 @@ are encouraged to regularly update the balena CLI to the latest version.
- Network - Network
- [ssh](#ssh)
- [tunnel](#tunnel) - [tunnel](#tunnel)
- Notes - Notes
@ -1903,6 +1903,80 @@ the uuid of the device to shutdown
force action if the update lock is set force action if the update lock is set
## device ssh
### Aliases
- `ssh`
To use one of the aliases, replace `device ssh` with the alias.
### Description
Start a shell on a local or remote device. If a service name is not provided,
a shell will be opened on the host OS.
If a fleet is provided, an interactive menu will be presented for the selection
of an online device. A shell will then be opened for the host OS or service
container of the chosen device.
For local devices, the IP address and .local domain name are supported.
If the device is referenced by IP or `.local` address, the connection
is initiated directly to balenaOS on port `22222` via an
openssh-compatible client. Otherwise, any connection initiated remotely
traverses the balenaCloud VPN.
Commands may be piped to the standard input for remote execution (see examples).
Note however that remote command execution on service containers (as opposed to
the host OS) is not currently possible when a device UUID is used (instead of
an IP address) because of a balenaCloud backend limitation.
Note: `balena ssh` requires an openssh-compatible client to be correctly
installed in your shell environment. For more information (including Windows
support) please check:
https://github.com/balena-io/balena-cli/blob/master/INSTALL.md#additional-dependencies,
Examples:
$ balena device ssh MyFleet
$ balena device ssh f49cefd
$ balena device ssh f49cefd my-service
$ balena device ssh f49cefd --port <port>
$ balena device ssh 192.168.0.1 --verbose
$ balena device ssh f49cefd.local my-service
$ echo "uptime; exit;" | balena device ssh f49cefd
$ echo "uptime; exit;" | balena device ssh 192.168.0.1 myService
### Arguments
#### FLEETORDEVICE
fleet name/slug, device uuid, or address of local device
#### SERVICE
service name, if connecting to a container
### Options
#### -p, --port PORT
SSH server port number (default 22222) if the target is an IP address or .local
hostname. Otherwise, port number for the balenaCloud gateway (default 22).
#### -t, --tty
force pseudo-terminal allocation (bypass TTY autodetection for stdin)
#### -v, --verbose
increase verbosity
#### --noproxy
bypass global proxy configuration for the ssh connection
## device start-service ## device start-service
### Description ### Description
@ -2635,73 +2709,6 @@ answer "yes" to all questions (non interactive use)
# Network # Network
## ssh
### Description
Start a shell on a local or remote device. If a service name is not provided,
a shell will be opened on the host OS.
If a fleet is provided, an interactive menu will be presented for the selection
of an online device. A shell will then be opened for the host OS or service
container of the chosen device.
For local devices, the IP address and .local domain name are supported.
If the device is referenced by IP or `.local` address, the connection
is initiated directly to balenaOS on port `22222` via an
openssh-compatible client. Otherwise, any connection initiated remotely
traverses the balenaCloud VPN.
Commands may be piped to the standard input for remote execution (see examples).
Note however that remote command execution on service containers (as opposed to
the host OS) is not currently possible when a device UUID is used (instead of
an IP address) because of a balenaCloud backend limitation.
Note: `balena ssh` requires an openssh-compatible client to be correctly
installed in your shell environment. For more information (including Windows
support) please check:
https://github.com/balena-io/balena-cli/blob/master/INSTALL.md#additional-dependencies,
Examples:
$ balena ssh MyFleet
$ balena ssh f49cefd
$ balena ssh f49cefd my-service
$ balena ssh f49cefd --port <port>
$ balena ssh 192.168.0.1 --verbose
$ balena ssh f49cefd.local my-service
$ echo "uptime; exit;" | balena ssh f49cefd
$ echo "uptime; exit;" | balena ssh 192.168.0.1 myService
### Arguments
#### FLEETORDEVICE
fleet name/slug, device uuid, or address of local device
#### SERVICE
service name, if connecting to a container
### Options
#### -p, --port PORT
SSH server port number (default 22222) if the target is an IP address or .local
hostname. Otherwise, port number for the balenaCloud gateway (default 22).
#### -t, --tty
force pseudo-terminal allocation (bypass TTY autodetection for stdin)
#### -v, --verbose
increase verbosity
#### --noproxy
bypass global proxy configuration for the ssh connection
## tunnel ## tunnel
### Description ### Description

View File

@ -23,7 +23,9 @@ import {
validateLocalHostnameOrIp, validateLocalHostnameOrIp,
} from '../../utils/validation'; } from '../../utils/validation';
export default class SshCmd extends Command { export default class DeviceSSHCmd extends Command {
public static aliases = ['ssh'];
public static description = stripIndent` public static description = stripIndent`
Open a SSH prompt on a device's host OS or service container. Open a SSH prompt on a device's host OS or service container.
@ -52,14 +54,14 @@ export default class SshCmd extends Command {
`; `;
public static examples = [ public static examples = [
'$ balena ssh MyFleet', '$ balena device ssh MyFleet',
'$ balena ssh f49cefd', '$ balena device ssh f49cefd',
'$ balena ssh f49cefd my-service', '$ balena device ssh f49cefd my-service',
'$ balena ssh f49cefd --port <port>', '$ balena device ssh f49cefd --port <port>',
'$ balena ssh 192.168.0.1 --verbose', '$ balena device ssh 192.168.0.1 --verbose',
'$ balena ssh f49cefd.local my-service', '$ balena device ssh f49cefd.local my-service',
'$ echo "uptime; exit;" | balena ssh f49cefd', '$ echo "uptime; exit;" | balena device ssh f49cefd',
'$ echo "uptime; exit;" | balena ssh 192.168.0.1 myService', '$ echo "uptime; exit;" | balena device ssh 192.168.0.1 myService',
]; ];
public static args = { public static args = {
@ -104,7 +106,7 @@ export default class SshCmd extends Command {
public static offlineCompatible = true; public static offlineCompatible = true;
public async run() { public async run() {
const { args: params, flags: options } = await this.parse(SshCmd); const { args: params, flags: options } = await this.parse(DeviceSSHCmd);
// Local connection // Local connection
if (validateLocalHostnameOrIp(params.fleetOrDevice)) { if (validateLocalHostnameOrIp(params.fleetOrDevice)) {

View File

@ -227,7 +227,6 @@ See: https://git.io/JRHUW#deprecation-policy`,
readonly manuallySortedPrimaryCommands = [ readonly manuallySortedPrimaryCommands = [
'login', 'login',
'push', 'push',
'ssh',
'fleet', 'fleet',
'device', 'device',
'tunnel', 'tunnel',

View File

@ -128,7 +128,7 @@ Please use "balena ${alternative}" instead.`);
throw new ExpectedError(msg); throw new ExpectedError(msg);
} }
const stopAlternative = const stopAlternative =
'Please use "balena ssh -s" to access the host OS, then use `balena-engine stop`.'; 'Please use "balena device ssh -s" to access the host OS, then use `balena-engine stop`.';
const cmds: { [cmd: string]: [(...args: any) => void, ...string[]] } = { const cmds: { [cmd: string]: [(...args: any) => void, ...string[]] } = {
sync: [replaced, 'push', 'v11.0.0', 'removed'], sync: [replaced, 'push', 'v11.0.0', 'removed'],
'local logs': [replaced, 'logs', 'v11.0.0'], 'local logs': [replaced, 'logs', 'v11.0.0'],

View File

@ -42,7 +42,7 @@ const deviceContainerEngineBinary = `$(if [ -f /usr/bin/balena ]; then echo "bal
* - Obtaining container IDs using 'dockerode' connected directly to * - Obtaining container IDs using 'dockerode' connected directly to
* balenaEngine on a device, TCP port 2375. * balenaEngine on a device, TCP port 2375.
* *
* The problem with using the supervisor API is that it means that 'balena ssh' * The problem with using the supervisor API is that it means that 'balena device ssh'
* becomes dependent on the supervisor being up an running, but sometimes ssh * becomes dependent on the supervisor being up an running, but sometimes ssh
* is needed to investigate devices issues where the supervisor has got into * is needed to investigate devices issues where the supervisor has got into
* trouble (e.g. supervisor in restart loop). This is the subject of CLI issue * trouble (e.g. supervisor in restart loop). This is the subject of CLI issue
@ -50,7 +50,7 @@ const deviceContainerEngineBinary = `$(if [ -f /usr/bin/balena ]; then echo "bal
* *
* The problem with using dockerode to connect directly to port 2375 (balenaEngine) * The problem with using dockerode to connect directly to port 2375 (balenaEngine)
* is that it only works with development variants of balenaOS. Production variants * is that it only works with development variants of balenaOS. Production variants
* block access to port 2375 for security reasons. 'balena ssh' should support * block access to port 2375 for security reasons. 'balena device ssh' should support
* production variants as well, especially after balenaOS v2.44.0 that introduced * production variants as well, especially after balenaOS v2.44.0 that introduced
* support for using the cloud account username for ssh authentication. * support for using the cloud account username for ssh authentication.
* *
@ -149,7 +149,7 @@ export async function performLocalDeviceSSH(
const shellCmd = `/bin/sh -c "if [ -e /bin/bash ]; then exec /bin/bash; else exec /bin/sh; fi"`; const shellCmd = `/bin/sh -c "if [ -e /bin/bash ]; then exec /bin/bash; else exec /bin/sh; fi"`;
// stdin (fd=0) is not a tty when data is piped in, for example // stdin (fd=0) is not a tty when data is piped in, for example
// echo 'ls -la; exit;' | balena ssh 192.168.0.20 service1 // echo 'ls -la; exit;' | balena device ssh 192.168.0.20 service1
// See https://www.balena.io/blog/balena-monthly-roundup-january-2020/#charliestipsntricks // See https://www.balena.io/blog/balena-monthly-roundup-january-2020/#charliestipsntricks
// https://assets.balena.io/newsletter/2020-01/pipe.png // https://assets.balena.io/newsletter/2020-01/pipe.png
const isTTY = !!opts.forceTTY || (await import('tty')).isatty(0); const isTTY = !!opts.forceTTY || (await import('tty')).isatty(0);

View File

@ -20,13 +20,13 @@ import * as mock from 'mock-require';
import type { Server } from 'net'; import type { Server } from 'net';
import { createServer } from 'net'; import { createServer } from 'net';
import { BalenaAPIMock } from '../nock/balena-api-mock'; import { BalenaAPIMock } from '../../nock/balena-api-mock';
import { cleanOutput, runCommand } from '../helpers'; import { cleanOutput, runCommand } from '../../helpers';
// "itSS" means "it() Skip Standalone" // "itSS" means "it() Skip Standalone"
const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it; const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it;
describe('balena ssh', function () { describe('balena device ssh', function () {
let api: BalenaAPIMock; let api: BalenaAPIMock;
let sshServer: Server | undefined; let sshServer: Server | undefined;
let sshServerPort: number; let sshServerPort: number;
@ -37,8 +37,8 @@ describe('balena ssh', function () {
const childProcessPath = 'child_process'; const childProcessPath = 'child_process';
if (revert) { if (revert) {
mock.stop(childProcessPath); mock.stop(childProcessPath);
mock.reRequire('../../build/utils/ssh'); mock.reRequire('../../../build/utils/ssh');
mock.reRequire('../../build/utils/device/ssh'); mock.reRequire('../../../build/utils/device/ssh');
return; return;
} }
const { EventEmitter } = await import('stream'); const { EventEmitter } = await import('stream');
@ -89,7 +89,7 @@ describe('balena ssh', function () {
api.expectGetDevice({ fullUUID: deviceUUID, isOnline: true }); api.expectGetDevice({ fullUUID: deviceUUID, isOnline: true });
mockedExitCode = 0; mockedExitCode = 0;
const { err, out } = await runCommand(`ssh ${deviceUUID}`); const { err, out } = await runCommand(`device ssh ${deviceUUID}`);
expect(err).to.be.empty; expect(err).to.be.empty;
expect(out).to.be.empty; expect(out).to.be.empty;
@ -97,7 +97,7 @@ describe('balena ssh', function () {
itSS('should succeed (mocked, device IP address)', async () => { itSS('should succeed (mocked, device IP address)', async () => {
mockedExitCode = 0; mockedExitCode = 0;
const { err, out } = await runCommand(`ssh 1.2.3.4`); const { err, out } = await runCommand(`device ssh 1.2.3.4`);
expect(err).to.be.empty; expect(err).to.be.empty;
expect(out).to.be.empty; expect(out).to.be.empty;
}); });
@ -113,7 +113,7 @@ describe('balena ssh', function () {
api.expectGetDevice({ fullUUID: deviceUUID, isOnline: true }); api.expectGetDevice({ fullUUID: deviceUUID, isOnline: true });
mockedExitCode = 255; mockedExitCode = 255;
const { err, out } = await runCommand(`ssh ${deviceUUID}`); const { err, out } = await runCommand(`device ssh ${deviceUUID}`);
expect(cleanOutput(err, true)).to.include.members(expectedErrLines); expect(cleanOutput(err, true)).to.include.members(expectedErrLines);
expect(out).to.be.empty; expect(out).to.be.empty;
}, },
@ -126,7 +126,7 @@ describe('balena ssh', function () {
api.expectGetDevice({ fullUUID: deviceUUID, isOnline: false }); api.expectGetDevice({ fullUUID: deviceUUID, isOnline: false });
mockedExitCode = 0; mockedExitCode = 0;
const { err, out } = await runCommand(`ssh ${deviceUUID}`); const { err, out } = await runCommand(`device ssh ${deviceUUID}`);
expect(cleanOutput(err, true)).to.include.members(expectedErrLines); expect(cleanOutput(err, true)).to.include.members(expectedErrLines);
expect(out).to.be.empty; expect(out).to.be.empty;
@ -139,7 +139,7 @@ describe('balena ssh', function () {
'SSH: Process exited with non-zero status code "255"', 'SSH: Process exited with non-zero status code "255"',
]; ];
const { err, out } = await runCommand( const { err, out } = await runCommand(
`ssh 127.0.0.1 -p ${sshServerPort} --noproxy`, `device ssh 127.0.0.1 -p ${sshServerPort} --noproxy`,
); );
expect(cleanOutput(err, true)).to.include.members(expectedErrLines); expect(cleanOutput(err, true)).to.include.members(expectedErrLines);
expect(out).to.be.empty; expect(out).to.be.empty;
@ -148,7 +148,7 @@ describe('balena ssh', function () {
/** Check whether the 'ssh' tool (executable) exists in the PATH */ /** Check whether the 'ssh' tool (executable) exists in the PATH */
async function checkSsh(): Promise<boolean> { async function checkSsh(): Promise<boolean> {
const { which } = await import('../../build/utils/which'); const { which } = await import('../../../build/utils/which');
const sshPath = await which('ssh', false); const sshPath = await which('ssh', false);
if ((sshPath || '').includes('\\Windows\\System32\\OpenSSH\\ssh')) { if ((sshPath || '').includes('\\Windows\\System32\\OpenSSH\\ssh')) {
// don't use Windows' built-in ssh tool for these test cases // don't use Windows' built-in ssh tool for these test cases

View File

@ -28,7 +28,6 @@ $ balena [COMMAND] [OPTIONS]
PRIMARY COMMANDS PRIMARY COMMANDS
login login to balena login login to balena
push <applicationOrDevice> start a remote build on the balenaCloud build servers or a local mode device push <applicationOrDevice> start a remote build on the balenaCloud build servers or a local mode device
ssh <applicationOrDevice> [service] SSH into the host or application container of a device
app <name> display information about a single application app <name> display information about a single application
device <uuid> show info about a single device device <uuid> show info about a single device
tunnel <deviceOrApplication> tunnel local ports to your balenaOS device tunnel <deviceOrApplication> tunnel local ports to your balenaOS device
@ -64,6 +63,7 @@ ADDITIONAL COMMANDS
device rename <uuid> [newName] rename a device device rename <uuid> [newName] rename a device
device rm <uuid(s)> remove one or more devices device rm <uuid(s)> remove one or more devices
device shutdown <uuid> shutdown a device device shutdown <uuid> shutdown a device
device ssh <applicationOrDevice> [service] SSH into the host or application container of a device
devices supported list the supported device types (like 'raspberrypi3' or 'intel-nuc') devices supported list the supported device types (like 'raspberrypi3' or 'intel-nuc')
env add <name> [value] add env or config variable to application(s), device(s) or service(s) env add <name> [value] add env or config variable to application(s), device(s) or service(s)
env list list the environment or config variables of an application, device or service env list list the environment or config variables of an application, device or service

View File

@ -121,6 +121,9 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/shutdown.js %2: build/commands/device/shutdown.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/device/ssh.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/start-service.js %2: build/commands/device/start-service.js
@ -238,9 +241,6 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/settings/index.js %2: build/commands/settings/index.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/ssh/index.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/ssh-key/add.js %2: build/commands/ssh-key/add.js

View File

@ -121,6 +121,9 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/shutdown.js %2: build/commands/device/shutdown.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/device/ssh.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/start-service.js %2: build/commands/device/start-service.js
@ -238,9 +241,6 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/settings/index.js %2: build/commands/settings/index.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/ssh/index.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/ssh-key/add.js %2: build/commands/ssh-key/add.js

View File

@ -121,6 +121,9 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/shutdown.js %2: build/commands/device/shutdown.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/device/ssh.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/start-service.js %2: build/commands/device/start-service.js
@ -238,9 +241,6 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/settings/index.js %2: build/commands/settings/index.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/ssh/index.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/ssh-key/add.js %2: build/commands/ssh-key/add.js

View File

@ -121,6 +121,9 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/shutdown.js %2: build/commands/device/shutdown.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/device/ssh.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/device/start-service.js %2: build/commands/device/start-service.js
@ -238,9 +241,6 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/settings/index.js %2: build/commands/settings/index.js
> Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json
%2: build/commands/ssh/index.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules/@oclif/core/package.json %1: node_modules/@oclif/core/package.json
%2: build/commands/ssh-key/add.js %2: build/commands/ssh-key/add.js

View File

@ -121,6 +121,9 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json %1: node_modules\@oclif\core\package.json
%2: build\commands\device\shutdown.js %2: build\commands\device\shutdown.js
> Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json
%2: build\commands\device\ssh.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json %1: node_modules\@oclif\core\package.json
%2: build\commands\device\start-service.js %2: build\commands\device\start-service.js
@ -238,9 +241,6 @@
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json %1: node_modules\@oclif\core\package.json
%2: build\commands\settings\index.js %2: build\commands\settings\index.js
> Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json
%2: build\commands\ssh\index.js
> Warning Entry 'main' not found in %1 > Warning Entry 'main' not found in %1
%1: node_modules\@oclif\core\package.json %1: node_modules\@oclif\core\package.json
%2: build\commands\ssh-key\add.js %2: build\commands\ssh-key\add.js