os configure, config generate: Add '--dev' option for OS developmentMode

Change-type: minor
This commit is contained in:
Paulo Castro 2021-12-24 15:10:59 +00:00
parent 851301a336
commit 7d58b8c120
6 changed files with 116 additions and 23 deletions

View File

@ -2126,10 +2126,21 @@ following sources, in precedence order:
2. A given `config.json` file specified with the `--config` option. 2. A given `config.json` file specified with the `--config` option.
3. User input through interactive prompts (text menus). 3. User input through interactive prompts (text menus).
The --device-type option may be used to override the fleet's default device The --device-type option is used to override the fleet's default device type,
type, in case of a fleet with mixed device types. in case of a fleet with mixed device types.
The --system-connection (-c) option can be used to inject NetworkManager connection The '--dev' option is used to configure balenaOS to operate in development mode,
allowing anauthenticated root ssh access and exposing network ports such as
balenaEngine's 2375 (unencrypted). This option causes `"developmentMode": true`
to be inserted in the 'config.json' file in the image's boot partion. Development
mode (as a configurable option) is applicable to balenaOS releases from early
2022. Older releases have separate development and production balenaOS images
that cannot be reconfigured through 'config.json' or the '--dev' option. Do not
confuse the balenaOS "development mode" with a device's "local mode", the latter
being a supervisor feature that allows the "balena push" command to push a user's
application directly to a device in the local network.
The --system-connection (-c) option is used to inject NetworkManager connection
profiles for additional network interfaces, such as cellular/GSM or additional profiles for additional network interfaces, such as cellular/GSM or additional
WiFi or ethernet connections. This option may be passed multiple times in case there WiFi or ethernet connections. This option may be passed multiple times in case there
are multiple files to inject. See connection profile examples and reference at: are multiple files to inject. See connection profile examples and reference at:
@ -2197,6 +2208,10 @@ WiFi key (password) (non-interactive configuration)
WiFi SSID (network name) (non-interactive configuration) WiFi SSID (network name) (non-interactive configuration)
#### --dev
Configure balenaOS to operate in development mode
#### -d, --device DEVICE #### -d, --device DEVICE
device UUID device UUID
@ -2264,6 +2279,17 @@ Generate a config.json file for a device or fleet.
The target balenaOS version must be specified with the --version option. The target balenaOS version must be specified with the --version option.
The '--dev' option is used to configure balenaOS to operate in development mode,
allowing anauthenticated root ssh access and exposing network ports such as
balenaEngine's 2375 (unencrypted). This option causes `"developmentMode": true`
to be inserted in the 'config.json' file in the image's boot partion. Development
mode (as a configurable option) is applicable to balenaOS releases from early
2022. Older releases have separate development and production balenaOS images
that cannot be reconfigured through 'config.json' or the '--dev' option. Do not
confuse the balenaOS "development mode" with a device's "local mode", the latter
being a supervisor feature that allows the "balena push" command to push a user's
application directly to a device in the local network.
To configure an image for a fleet of mixed device types, use the --fleet option To configure an image for a fleet of mixed device types, use the --fleet option
alongside the --deviceType option to specify the target device type. alongside the --deviceType option to specify the target device type.
@ -2288,11 +2314,10 @@ Examples:
$ balena config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key $ balena config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key
$ balena config generate --device 7cf02a6 --version 2.12.7 --deviceApiKey <existingDeviceKey> $ balena config generate --device 7cf02a6 --version 2.12.7 --deviceApiKey <existingDeviceKey>
$ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json $ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json
$ balena config generate --fleet MyFleet --version 2.12.7 $ balena config generate --fleet myorg/fleet --version 2.12.7 --dev
$ balena config generate --fleet myorg/myfleet --version 2.12.7 $ balena config generate --fleet myorg/fleet --version 2.12.7 --deviceType fincm3
$ balena config generate --fleet MyFleet --version 2.12.7 --deviceType fincm3 $ balena config generate --fleet myorg/fleet --version 2.12.7 --output config.json
$ balena config generate --fleet MyFleet --version 2.12.7 --output config.json $ balena config generate --fleet myorg/fleet --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 15
$ balena config generate --fleet MyFleet --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 15
### Options ### Options
@ -2304,6 +2329,10 @@ a balenaOS version
fleet name, slug (preferred), or numeric ID (deprecated) fleet name, slug (preferred), or numeric ID (deprecated)
#### --dev
Configure balenaOS to operate in development mode
#### -d, --device DEVICE #### -d, --device DEVICE
device UUID device UUID

View File

@ -19,12 +19,13 @@ import { flags } from '@oclif/command';
import Command from '../../command'; import Command from '../../command';
import * as cf from '../../utils/common-flags'; import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy'; import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages'; import { applicationIdInfo, devModeInfo } from '../../utils/messages';
import type { PineDeferred } from 'balena-sdk'; import type { PineDeferred } from 'balena-sdk';
interface FlagsDef { interface FlagsDef {
version: string; // OS version version: string; // OS version
fleet?: string; fleet?: string;
dev?: boolean; // balenaOS development variant
device?: string; device?: string;
deviceApiKey?: string; deviceApiKey?: string;
deviceType?: string; deviceType?: string;
@ -47,6 +48,8 @@ export default class ConfigGenerateCmd extends Command {
The target balenaOS version must be specified with the --version option. The target balenaOS version must be specified with the --version option.
${devModeInfo.split('\n').join('\n\t\t')}
To configure an image for a fleet of mixed device types, use the --fleet option To configure an image for a fleet of mixed device types, use the --fleet option
alongside the --deviceType option to specify the target device type. alongside the --deviceType option to specify the target device type.
@ -61,11 +64,10 @@ export default class ConfigGenerateCmd extends Command {
'$ balena config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key', '$ balena config generate --device 7cf02a6 --version 2.12.7 --generate-device-api-key',
'$ balena config generate --device 7cf02a6 --version 2.12.7 --deviceApiKey <existingDeviceKey>', '$ balena config generate --device 7cf02a6 --version 2.12.7 --deviceApiKey <existingDeviceKey>',
'$ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json', '$ balena config generate --device 7cf02a6 --version 2.12.7 --output config.json',
'$ balena config generate --fleet MyFleet --version 2.12.7', '$ balena config generate --fleet myorg/fleet --version 2.12.7 --dev',
'$ balena config generate --fleet myorg/myfleet --version 2.12.7', '$ balena config generate --fleet myorg/fleet --version 2.12.7 --deviceType fincm3',
'$ balena config generate --fleet MyFleet --version 2.12.7 --deviceType fincm3', '$ balena config generate --fleet myorg/fleet --version 2.12.7 --output config.json',
'$ balena config generate --fleet MyFleet --version 2.12.7 --output config.json', '$ balena config generate --fleet myorg/fleet --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 15',
'$ balena config generate --fleet MyFleet --version 2.12.7 --network wifi --wifiSsid mySsid --wifiKey abcdefgh --appUpdatePollInterval 15',
]; ];
public static usage = 'config generate'; public static usage = 'config generate';
@ -76,6 +78,7 @@ export default class ConfigGenerateCmd extends Command {
required: true, required: true,
}), }),
fleet: { ...cf.fleet, exclusive: ['device'] }, fleet: { ...cf.fleet, exclusive: ['device'] },
dev: cf.dev,
device: { device: {
...cf.device, ...cf.device,
exclusive: ['fleet', 'provisioning-key-name'], exclusive: ['fleet', 'provisioning-key-name'],
@ -191,6 +194,7 @@ export default class ConfigGenerateCmd extends Command {
override: { ...options, app: options.fleet, application: options.fleet }, override: { ...options, app: options.fleet, application: options.fleet },
}); });
answers.version = options.version; answers.version = options.version;
answers.developmentMode = options.dev;
answers.provisioningKeyName = options['provisioning-key-name']; answers.provisioningKeyName = options['provisioning-key-name'];
// Generate config // Generate config
@ -241,5 +245,7 @@ export default class ConfigGenerateCmd extends Command {
if (!options.fleet && options.deviceType) { if (!options.fleet && options.deviceType) {
throw new ExpectedError(this.deviceTypeNotAllowedMessage); throw new ExpectedError(this.deviceTypeNotAllowedMessage);
} }
const { validateDevOptionAndWarn } = await import('../../utils/config');
await validateDevOptionAndWarn(options.dev, options.version);
} }
} }

View File

@ -23,7 +23,7 @@ import Command from '../../command';
import { ExpectedError } from '../../errors'; import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags'; import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy'; import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages'; import { applicationIdInfo, devModeInfo } from '../../utils/messages';
const CONNECTIONS_FOLDER = '/system-connections'; const CONNECTIONS_FOLDER = '/system-connections';
@ -35,6 +35,7 @@ interface FlagsDef {
'config-network'?: string; 'config-network'?: string;
'config-wifi-key'?: string; 'config-wifi-key'?: string;
'config-wifi-ssid'?: string; 'config-wifi-ssid'?: string;
dev?: boolean; // balenaOS development variant
device?: string; // device UUID device?: string; // device UUID
'device-type'?: string; 'device-type'?: string;
help?: void; help?: void;
@ -50,6 +51,7 @@ interface ArgsDef {
interface Answers { interface Answers {
appUpdatePollInterval: number; // in minutes appUpdatePollInterval: number; // in minutes
developmentMode?: boolean; // balenaOS development variant
deviceType: string; // e.g. "raspberrypi3" deviceType: string; // e.g. "raspberrypi3"
network: 'ethernet' | 'wifi'; network: 'ethernet' | 'wifi';
version: string; // e.g. "2.32.0+rev1" version: string; // e.g. "2.32.0+rev1"
@ -71,10 +73,12 @@ export default class OsConfigureCmd extends Command {
2. A given \`config.json\` file specified with the \`--config\` option. 2. A given \`config.json\` file specified with the \`--config\` option.
3. User input through interactive prompts (text menus). 3. User input through interactive prompts (text menus).
The --device-type option may be used to override the fleet's default device The --device-type option is used to override the fleet's default device type,
type, in case of a fleet with mixed device types. in case of a fleet with mixed device types.
The --system-connection (-c) option can be used to inject NetworkManager connection ${devModeInfo.split('\n').join('\n\t\t')}
The --system-connection (-c) option is used to inject NetworkManager connection
profiles for additional network interfaces, such as cellular/GSM or additional profiles for additional network interfaces, such as cellular/GSM or additional
WiFi or ethernet connections. This option may be passed multiple times in case there WiFi or ethernet connections. This option may be passed multiple times in case there
are multiple files to inject. See connection profile examples and reference at: are multiple files to inject. See connection profile examples and reference at:
@ -133,6 +137,7 @@ export default class OsConfigureCmd extends Command {
'config-wifi-ssid': flags.string({ 'config-wifi-ssid': flags.string({
description: 'WiFi SSID (network name) (non-interactive configuration)', description: 'WiFi SSID (network name) (non-interactive configuration)',
}), }),
dev: cf.dev,
device: { ...cf.device, exclusive: ['fleet', 'provisioning-key-name'] }, device: { ...cf.device, exclusive: ['fleet', 'provisioning-key-name'] },
'device-type': flags.string({ 'device-type': flags.string({
description: description:
@ -212,6 +217,13 @@ export default class OsConfigureCmd extends Command {
configJson = JSON.parse(rawConfig); configJson = JSON.parse(rawConfig);
} }
const osVersion =
options.version ||
(await getOsVersionFromImage(params.image, deviceTypeManifest, devInit));
const { validateDevOptionAndWarn } = await import('../../utils/config');
await validateDevOptionAndWarn(options.dev, osVersion);
const answers: Answers = await askQuestionsForDeviceType( const answers: Answers = await askQuestionsForDeviceType(
deviceTypeManifest, deviceTypeManifest,
options, options,
@ -220,10 +232,8 @@ export default class OsConfigureCmd extends Command {
if (options.fleet) { if (options.fleet) {
answers.deviceType = deviceTypeSlug; answers.deviceType = deviceTypeSlug;
} }
answers.version = answers.version = osVersion;
options.version || answers.developmentMode = options.dev;
(await getOsVersionFromImage(params.image, deviceTypeManifest, devInit));
answers.provisioningKeyName = options['provisioning-key-name']; answers.provisioningKeyName = options['provisioning-key-name'];
if (_.isEmpty(configJson)) { if (_.isEmpty(configJson)) {

View File

@ -70,6 +70,11 @@ export const force: IBooleanFlag<boolean> = flags.boolean({
default: false, default: false,
}); });
export const dev: IBooleanFlag<boolean> = flags.boolean({
description: 'Configure balenaOS to operate in development mode',
default: false,
});
export const drive = flags.string({ export const drive = flags.string({
char: 'd', char: 'd',
description: stripIndent` description: stripIndent`

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import * as semver from 'balena-semver'; import * as semver from 'balena-semver';
import { getBalenaSdk } from './lazy'; import { getBalenaSdk, stripIndent } from './lazy';
export interface ImgConfig { export interface ImgConfig {
applicationName: string; applicationName: string;
@ -134,3 +134,34 @@ export function generateDeviceConfig(
return config; return config;
}); });
} }
/**
* Chech whether the `--dev` option of commands related to OS configuration
* such as `os configure` and `config generate` is compatible with a given
* balenaOS version, and print a warning regarding the consequences of using
* that option.
*/
export async function validateDevOptionAndWarn(
dev?: boolean,
version?: string,
logger?: import('./logger'),
) {
if (!dev) {
return;
}
if (version && /\bprod\b/.test(version)) {
const { ExpectedError } = await import('../errors');
throw new ExpectedError(
`Error: The '--dev' option conflicts with production balenaOS version '${version}'`,
);
}
if (!logger) {
const Logger = await import('./logger');
logger = Logger.getLogger();
}
logger.logInfo(stripIndent`
The '--dev' option is being used to configure a balenaOS image in development mode.
Please note that development mode allows unauthenticated, passwordless root ssh access
and exposes network ports such as 2375 that allows unencrypted access to balenaEngine.
Therefore, development mode should only be used in private, trusted local networks.`);
}

View File

@ -159,6 +159,18 @@ created public/open fleet, or with fleets from other balena accounts that you
may be invited to join under any role. For this reason, fleet names are may be invited to join under any role. For this reason, fleet names are
especially discouraged in scripts (e.g. CI environments).`; especially discouraged in scripts (e.g. CI environments).`;
export const devModeInfo = `\
The '--dev' option is used to configure balenaOS to operate in development mode,
allowing anauthenticated root ssh access and exposing network ports such as
balenaEngine's 2375 (unencrypted). This option causes \`"developmentMode": true\`
to be inserted in the 'config.json' file in the image's boot partion. Development
mode (as a configurable option) is applicable to balenaOS releases from early
2022. Older releases have separate development and production balenaOS images
that cannot be reconfigured through 'config.json' or the '--dev' option. Do not
confuse the balenaOS "development mode" with a device's "local mode", the latter
being a supervisor feature that allows the "balena push" command to push a user's
application directly to a device in the local network.`;
export const jsonInfo = `\ export const jsonInfo = `\
The --json option is recommended when scripting the output of this command, The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it because field names are less likely to change in JSON format and because it