os initialize: Deprecate the --type parameter

Change-type: patch
This commit is contained in:
Thodoris Greasidis 2024-12-31 18:49:27 +02:00
parent d9f21b4c3f
commit 06133c789e
7 changed files with 69 additions and 46 deletions

View File

@ -3048,6 +3048,7 @@ because we need to access the raw devices directly.
Examples: Examples:
$ balena os initialize ../path/rpi.img
$ balena os initialize ../path/rpi.img --type raspberry-pi $ balena os initialize ../path/rpi.img --type raspberry-pi
### Arguments ### Arguments

View File

@ -38,9 +38,6 @@ export default class OsinitCmd extends Command {
image: Args.string({ image: Args.string({
required: true, required: true,
}), }),
type: Args.string({
required: true,
}),
config: Args.string({ config: Args.string({
required: true, required: true,
}), }),
@ -58,7 +55,7 @@ export default class OsinitCmd extends Command {
const { getManifest, osProgressHandler } = await import( const { getManifest, osProgressHandler } = await import(
'../../utils/helpers' '../../utils/helpers'
); );
const manifest = await getManifest(params.image, params.type); const manifest = await getManifest(params.image);
const { initialize } = await import('balena-device-init'); const { initialize } = await import('balena-device-init');
const initializeEmitter = await initialize(params.image, manifest, config); const initializeEmitter = await initialize(params.image, manifest, config);

View File

@ -197,6 +197,7 @@ export default class OsConfigureCmd extends Command {
const deviceTypeManifest = await helpers.getManifest( const deviceTypeManifest = await helpers.getManifest(
params.image, params.image,
// TODO: Drop this in the next major in favor of calling checkManifestMatchesDeviceType() directly
deviceTypeSlug, deviceTypeSlug,
); );

View File

@ -37,6 +37,7 @@ export default class OsInitializeCmd extends Command {
`; `;
public static examples = [ public static examples = [
'$ balena os initialize ../path/rpi.img',
'$ balena os initialize ../path/rpi.img --type raspberry-pi', '$ balena os initialize ../path/rpi.img --type raspberry-pi',
]; ];
@ -63,6 +64,11 @@ export default class OsInitializeCmd extends Command {
console.info(`Initializing device ${INIT_WARNING_MESSAGE}`); console.info(`Initializing device ${INIT_WARNING_MESSAGE}`);
const manifest = await getManifest(params.image, options.type); const manifest = await getManifest(params.image, options.type);
// the "type" arg will be removed on the next major - warn user
if (options.type != null) {
const { deviceTypeArgDeprecation } = await import('../../utils/messages');
console.log(deviceTypeArgDeprecation('type'));
}
const answers = await getCliForm().run(manifest.initialization?.options, { const answers = await getCliForm().run(manifest.initialization?.options, {
override: { override: {
@ -81,13 +87,7 @@ export default class OsInitializeCmd extends Command {
await safeUmount(answers.drive); await safeUmount(answers.drive);
} }
await sudo([ await sudo(['internal', 'osinit', params.image, JSON.stringify(answers)]);
'internal',
'osinit',
params.image,
options.type,
JSON.stringify(answers),
]);
if (answers.drive != null) { if (answers.drive != null) {
const { safeUmount } = await import('../../utils/umount'); const { safeUmount } = await import('../../utils/umount');

View File

@ -94,7 +94,6 @@ export const deviceType = Flags.string({
description: description:
'device type (Check available types with `balena device-type list`)', 'device type (Check available types with `balena device-type list`)',
char: 't', char: 't',
required: true,
}); });
export const json = Flags.boolean({ export const json = Flags.boolean({

View File

@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
@ -103,48 +103,67 @@ export async function runCommand<T>(commandArgs: string[]): Promise<T> {
return run(commandArgs) as Promise<T>; return run(commandArgs) as Promise<T>;
} }
export async function getManifest( export async function checkManifestMatchesDeviceType(
image: string, manifest: BalenaSdk.DeviceTypeJson.DeviceType,
deviceType: string, deviceType: string,
): Promise<BalenaSdk.DeviceTypeJson.DeviceType> { ) {
const init = await import('balena-device-init');
const sdk = getBalenaSdk();
const manifest = await init.getImageManifest(image);
if (manifest != null) {
const config = manifest.configuration?.config;
if (config?.partition != null) {
const { getBootPartition } = await import('balena-config-json');
// Find the device-type.json property that holds the boot partition number for
// this device type (config.partition or config.partition.primary) and overwrite it
// with the boot partition number that was found by inspecting the image.
// since it's deprecated & no longer updated for newer releases.
if (typeof config.partition === 'number') {
config.partition = await getBootPartition(image);
} else if (config.partition.primary != null) {
config.partition.primary = await getBootPartition(image);
}
// TODO: Add handling for when we no longer include a `config.partition` at all.
}
} else {
// TODO: Change this in the next major to throw, after confirming that this works for all supported OS versions.
console.error(
`[warn] Error while finding a device-type.json on the provided image path. Attempting to fetch from the API.`,
);
}
if ( if (
manifest != null &&
manifest.slug !== deviceType && manifest.slug !== deviceType &&
manifest.slug !== (await sdk.models.deviceType.get(deviceType)).slug manifest.slug !==
(await getBalenaSdk().models.deviceType.get(deviceType)).slug
) { ) {
const { ExpectedError } = await import('../errors'); const { ExpectedError } = await import('../errors');
throw new ExpectedError( throw new ExpectedError(
`The device type of the provided OS image ${manifest.slug}, does not match the expected device type ${deviceType}`, `The device type of the provided OS image ${manifest.slug}, does not match the expected device type ${deviceType}`,
); );
} }
return ( }
manifest ??
(await sdk.models.config.getDeviceTypeManifestBySlug(deviceType)) export async function getManifest(
); image: string,
// TODO: Drop this parameter in the next major
fallbackDeviceType?: string,
): Promise<BalenaSdk.DeviceTypeJson.DeviceType> {
const init = await import('balena-device-init');
const manifest = await init.getImageManifest(image);
if (manifest == null) {
// TODO: Change this in the next major to throw when not being able to find the manifest
// on the provided image, after confirming that this works for all supported OS versions.
if (fallbackDeviceType != null) {
console.error(
`[warn] Error while finding a device-type.json on the provided image path. Attempting to fetch from the API.`,
);
const sdk = getBalenaSdk();
return await sdk.models.config.getDeviceTypeManifestBySlug(
fallbackDeviceType,
);
}
const { ExpectedError } = await import('../errors');
throw new ExpectedError(
`Could not find the manifest on the provided image path '${image}'. Please double check that this is a valid balenaOS image.`,
);
}
const config = manifest.configuration?.config;
if (config?.partition != null) {
const { getBootPartition } = await import('balena-config-json');
// Find the device-type.json property that holds the boot partition number for
// this device type (config.partition or config.partition.primary) and overwrite it
// with the boot partition number that was found by inspecting the image.
// since it's deprecated & no longer updated for newer releases.
if (typeof config.partition === 'number') {
config.partition = await getBootPartition(image);
} else if (config.partition.primary != null) {
config.partition.primary = await getBootPartition(image);
}
// TODO: Add handling for when we no longer include a `config.partition` at all.
}
// TODO: Drop this in the next major along with the fallbackDeviceType argument
// and move the checkManifestMatchesDeviceType() to the caller side when still necessary.
if (fallbackDeviceType != null) {
await checkManifestMatchesDeviceType(manifest, fallbackDeviceType);
}
return manifest;
} }
export const areDeviceTypesCompatible = async ( export const areDeviceTypesCompatible = async (

View File

@ -189,6 +189,12 @@ If you have a particular use for buildArg, which is not satisfied by build-time
secrets, please contact us via support or the forums: https://forums.balena.io/ secrets, please contact us via support or the forums: https://forums.balena.io/
\n`; \n`;
export const deviceTypeArgDeprecation = (paramName: string) => `\
WARNING: You have specified a '--${paramName}' option, which is now deprecated, and
may be removed in the future. The balena-cli will now try to auto-detect
the device type of the provided balenaOS image.
\n`;
export function getNodeEngineVersionWarn( export function getNodeEngineVersionWarn(
version: string, version: string,
validVersions: string, validVersions: string,