mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-23 15:32:22 +00:00
Merge pull request #2334 from balena-io/2005-os-esr-versions-hostapp
os versions, os download: Add support for balenaOS ESR versions
This commit is contained in:
commit
6c29d0ae27
@ -2240,6 +2240,9 @@ device UUID
|
||||
Show the available balenaOS versions for the given device type.
|
||||
Check available types with `balena devices supported`.
|
||||
|
||||
balenaOS ESR versions can be listed with the '--esr' option. See also:
|
||||
https://www.balena.io/docs/reference/OS/extended-support-release/
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena os versions raspberrypi3
|
||||
@ -2252,23 +2255,28 @@ device type
|
||||
|
||||
### Options
|
||||
|
||||
#### --esr
|
||||
|
||||
select balenaOS ESR versions
|
||||
|
||||
## os download <type>
|
||||
|
||||
Download an unconfigured OS image for a certain device type.
|
||||
Check available types with `balena devices supported`
|
||||
Download an unconfigured OS image for the specified device type.
|
||||
Check available device types with 'balena devices supported'.
|
||||
|
||||
Note: Currently this command only works with balenaCloud, not openBalena.
|
||||
If using openBalena, please download the OS from: https://www.balena.io/os/
|
||||
|
||||
If version is not specified the newest stable (non-pre-release) version of OS
|
||||
is downloaded (if available), otherwise the newest version (if all existing
|
||||
versions for the given device type are pre-release).
|
||||
The '--version' option is used to select the balenaOS version. If omitted,
|
||||
the latest released version is downloaded (and if only pre-release versions
|
||||
exist, the latest pre-release version is downloaded).
|
||||
|
||||
You can pass `--version menu` to pick the OS version from the interactive menu
|
||||
of all available versions.
|
||||
Use '--version menu' or '--version menu-esr' to interactively select the
|
||||
OS version. The latter lists ESR versions which are only available for
|
||||
download on Production and Enterprise plans. See also:
|
||||
https://www.balena.io/docs/reference/OS/extended-support-release/
|
||||
|
||||
To download a development image append `.dev` to the version or select from
|
||||
the interactive menu.
|
||||
Development images can be selected by appending `.dev` to the version.
|
||||
|
||||
Examples:
|
||||
|
||||
@ -2294,11 +2302,13 @@ output path
|
||||
|
||||
#### --version VERSION
|
||||
|
||||
exact version number, or a valid semver range,
|
||||
version number (ESR or non-ESR versions),
|
||||
or semver range (non-ESR versions only),
|
||||
or 'latest' (includes pre-releases),
|
||||
or 'default' (excludes pre-releases if at least one stable version is available),
|
||||
or 'default' (excludes pre-releases if at least one released version is available),
|
||||
or 'recommended' (excludes pre-releases, will fail if only pre-release versions are available),
|
||||
or 'menu' (will show the interactive menu)
|
||||
or 'menu' (interactive menu, non-ESR versions),
|
||||
or 'menu-esr' (interactive menu, ESR versions)
|
||||
|
||||
## os build-config <image> <device-type>
|
||||
|
||||
|
@ -34,21 +34,22 @@ export default class OsDownloadCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Download an unconfigured OS image.
|
||||
|
||||
Download an unconfigured OS image for a certain device type.
|
||||
Check available types with \`balena devices supported\`
|
||||
Download an unconfigured OS image for the specified device type.
|
||||
Check available device types with 'balena devices supported'.
|
||||
|
||||
Note: Currently this command only works with balenaCloud, not openBalena.
|
||||
If using openBalena, please download the OS from: https://www.balena.io/os/
|
||||
|
||||
If version is not specified the newest stable (non-pre-release) version of OS
|
||||
is downloaded (if available), otherwise the newest version (if all existing
|
||||
versions for the given device type are pre-release).
|
||||
The '--version' option is used to select the balenaOS version. If omitted,
|
||||
the latest released version is downloaded (and if only pre-release versions
|
||||
exist, the latest pre-release version is downloaded).
|
||||
|
||||
You can pass \`--version menu\` to pick the OS version from the interactive menu
|
||||
of all available versions.
|
||||
Use '--version menu' or '--version menu-esr' to interactively select the
|
||||
OS version. The latter lists ESR versions which are only available for
|
||||
download on Production and Enterprise plans. See also:
|
||||
https://www.balena.io/docs/reference/OS/extended-support-release/
|
||||
|
||||
To download a development image append \`.dev\` to the version or select from
|
||||
the interactive menu.
|
||||
Development images can be selected by appending \`.dev\` to the version.
|
||||
`;
|
||||
public static examples = [
|
||||
'$ balena os download raspberrypi3 -o ../foo/bar/raspberry-pi.img',
|
||||
@ -78,11 +79,13 @@ export default class OsDownloadCmd extends Command {
|
||||
}),
|
||||
version: flags.string({
|
||||
description: stripIndent`
|
||||
exact version number, or a valid semver range,
|
||||
version number (ESR or non-ESR versions),
|
||||
or semver range (non-ESR versions only),
|
||||
or 'latest' (includes pre-releases),
|
||||
or 'default' (excludes pre-releases if at least one stable version is available),
|
||||
or 'default' (excludes pre-releases if at least one released version is available),
|
||||
or 'recommended' (excludes pre-releases, will fail if only pre-release versions are available),
|
||||
or 'menu' (will show the interactive menu)
|
||||
or 'menu' (interactive menu, non-ESR versions),
|
||||
or 'menu-esr' (interactive menu, ESR versions)
|
||||
`,
|
||||
}),
|
||||
help: cf.help,
|
||||
|
@ -18,9 +18,10 @@
|
||||
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';
|
||||
|
||||
interface FlagsDef {
|
||||
esr?: boolean;
|
||||
help: void;
|
||||
}
|
||||
|
||||
@ -34,6 +35,9 @@ export default class OsVersionsCmd extends Command {
|
||||
|
||||
Show the available balenaOS versions for the given device type.
|
||||
Check available types with \`balena devices supported\`.
|
||||
|
||||
balenaOS ESR versions can be listed with the '--esr' option. See also:
|
||||
https://www.balena.io/docs/reference/OS/extended-support-release/
|
||||
`;
|
||||
|
||||
public static examples = ['$ balena os versions raspberrypi3'];
|
||||
@ -50,16 +54,20 @@ export default class OsVersionsCmd extends Command {
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
help: cf.help,
|
||||
esr: flags.boolean({
|
||||
description: 'select balenaOS ESR versions',
|
||||
default: false,
|
||||
}),
|
||||
};
|
||||
|
||||
public async run() {
|
||||
const { args: params } = this.parse<FlagsDef, ArgsDef>(OsVersionsCmd);
|
||||
const { args: params, flags: options } = this.parse<FlagsDef, ArgsDef>(
|
||||
OsVersionsCmd,
|
||||
);
|
||||
|
||||
const { versions: vs, recommended } =
|
||||
await getBalenaSdk().models.os.getSupportedVersions(params.type);
|
||||
const { getFormattedOsVersions } = await import('../../utils/cloud');
|
||||
const vs = await getFormattedOsVersions(params.type, !!options.esr);
|
||||
|
||||
vs.forEach((v) => {
|
||||
console.log(`v${v}` + (v === recommended ? ' (recommended)' : ''));
|
||||
});
|
||||
console.log(vs.map((v) => v.formattedVersion).join('\n'));
|
||||
}
|
||||
}
|
||||
|
@ -130,15 +130,13 @@ export async function downloadOSImage(
|
||||
console.info(`Getting device operating system for ${deviceType}`);
|
||||
|
||||
if (!OSVersion) {
|
||||
console.warn('OS version not specified: using latest stable version');
|
||||
console.warn('OS version not specified: using latest released version');
|
||||
}
|
||||
|
||||
OSVersion = OSVersion
|
||||
? await resolveOSVersion(deviceType, OSVersion)
|
||||
: 'default';
|
||||
|
||||
const displayVersion = OSVersion === 'default' ? '' : ` ${OSVersion}`;
|
||||
|
||||
// Override the default zlib flush value as we've seen cases of
|
||||
// incomplete files being identified as successful downloads when using Z_SYNC_FLUSH.
|
||||
// Using Z_NO_FLUSH results in a Z_BUF_ERROR instead of a corrupt image file.
|
||||
@ -150,10 +148,17 @@ export async function downloadOSImage(
|
||||
const manager = await import('balena-image-manager');
|
||||
const stream = await manager.get(deviceType, OSVersion);
|
||||
|
||||
const displayVersion = await new Promise((resolve, reject) => {
|
||||
stream.on('error', reject);
|
||||
stream.on('balena-image-manager:resolved-version', resolve);
|
||||
});
|
||||
|
||||
const visuals = getVisuals();
|
||||
const bar = new visuals.Progress(`Downloading Device OS${displayVersion}`);
|
||||
const bar = new visuals.Progress(
|
||||
`Downloading balenaOS version ${displayVersion}`,
|
||||
);
|
||||
const spinner = new visuals.Spinner(
|
||||
`Downloading Device OS${displayVersion} (size unknown)`,
|
||||
`Downloading balenaOS version ${displayVersion} (size unknown)`,
|
||||
);
|
||||
|
||||
stream.on('progress', (state: any) => {
|
||||
@ -183,28 +188,29 @@ export async function downloadOSImage(
|
||||
const streamToPromise = await import('stream-to-promise');
|
||||
await streamToPromise(stream.pipe(output));
|
||||
|
||||
console.info('The image was downloaded successfully');
|
||||
console.info(
|
||||
`balenaOS image version ${displayVersion} downloaded successfully`,
|
||||
);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
async function resolveOSVersion(deviceType: string, version: string) {
|
||||
if (version !== 'menu') {
|
||||
async function resolveOSVersion(
|
||||
deviceType: string,
|
||||
version: string,
|
||||
): Promise<string> {
|
||||
if (!['menu', 'menu-esr'].includes(version)) {
|
||||
if (version[0] === 'v') {
|
||||
version = version.slice(1);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
const vs = (
|
||||
(await getBalenaSdk().models.hostapp.getAllOsVersions([deviceType]))[
|
||||
deviceType
|
||||
] ?? []
|
||||
).filter((v) => v.osType === 'default');
|
||||
const vs = await getFormattedOsVersions(deviceType, version === 'menu-esr');
|
||||
|
||||
const choices = vs.map((v) => ({
|
||||
value: v.rawVersion,
|
||||
name: `v${v.rawVersion}` + (v.isRecommended ? ' (recommended)' : ''),
|
||||
name: v.formattedVersion,
|
||||
}));
|
||||
|
||||
return getCliForm().ask({
|
||||
@ -214,3 +220,35 @@ async function resolveOSVersion(deviceType: string, version: string) {
|
||||
default: (vs.find((v) => v.isRecommended) ?? vs[0])?.rawVersion,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the output of sdk.models.hostapp.getAvailableOsVersions(), filtered
|
||||
* regarding ESR or non-ESR versions, and having the `formattedVersion` field
|
||||
* reformatted for compatibility with the pre-existing output format of the
|
||||
* `os versions` and `os download` commands.
|
||||
*/
|
||||
export async function getFormattedOsVersions(
|
||||
deviceType: string,
|
||||
esr: boolean,
|
||||
): Promise<SDK.OsVersion[]> {
|
||||
const versions: SDK.OsVersion[] = (
|
||||
(await getBalenaSdk().models.hostapp.getAvailableOsVersions([deviceType]))[
|
||||
deviceType
|
||||
] ?? []
|
||||
)
|
||||
.filter((v: SDK.OsVersion) => v.osType === (esr ? 'esr' : 'default'))
|
||||
.map((v: SDK.OsVersion) => {
|
||||
const i = v.formattedVersion.indexOf(' ');
|
||||
v.formattedVersion =
|
||||
i < 0
|
||||
? `v${v.rawVersion}`
|
||||
: `v${v.rawVersion}${v.formattedVersion.substring(i)}`;
|
||||
return v;
|
||||
});
|
||||
if (!versions.length) {
|
||||
throw new ExpectedError(stripIndent`
|
||||
Error: No balenaOS versions found for device type '${deviceType}'.
|
||||
Double-check the device type slug with 'balena devices supported'.`);
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
|
6
npm-shrinkwrap.json
generated
6
npm-shrinkwrap.json
generated
@ -3785,9 +3785,9 @@
|
||||
}
|
||||
},
|
||||
"balena-image-manager": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/balena-image-manager/-/balena-image-manager-7.0.3.tgz",
|
||||
"integrity": "sha512-KLb/5JksYxCR7JClq+MAuCMYPNMAXB9MgqubUvzj4mI/Yec3XD4xZ2BMITwINrl4sMKui/G7t/R5tBNFZsFe9w==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/balena-image-manager/-/balena-image-manager-7.1.0.tgz",
|
||||
"integrity": "sha512-W8Etn0PBQJUlTJ1m1rCuQQ8TTLdkBoNP2SRHQqez2HANQp+T38wFjQXVx9PhQ6J7eqOYuW87SkJiKLpnmlz79Q==",
|
||||
"requires": {
|
||||
"balena-sdk": "^15.2.1",
|
||||
"mime": "^2.4.6",
|
||||
|
@ -205,7 +205,7 @@
|
||||
"balena-device-init": "^6.0.0",
|
||||
"balena-errors": "^4.7.1",
|
||||
"balena-image-fs": "^7.0.6",
|
||||
"balena-image-manager": "^7.0.3",
|
||||
"balena-image-manager": "^7.1.0",
|
||||
"balena-preload": "^11.0.0",
|
||||
"balena-release": "^3.2.0",
|
||||
"balena-sdk": "^15.51.1",
|
||||
|
Loading…
Reference in New Issue
Block a user