From c6a0bc0fba70dc6d5d702dfda4982d8608d4f0a9 Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Fri, 10 Dec 2021 00:38:56 +0000 Subject: [PATCH 1/2] os download: Don't append '.prod' if the OS version does not match regex --- lib/utils/cloud.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/utils/cloud.ts b/lib/utils/cloud.ts index a0b01a12..b5b8a4e1 100644 --- a/lib/utils/cloud.ts +++ b/lib/utils/cloud.ts @@ -202,15 +202,15 @@ async function resolveOSVersion( if (['menu', 'menu-esr'].includes(version)) { return await selectOSVersionFromMenu(deviceType, version === 'menu-esr'); } - if (version[0] === 'v') { - version = version.slice(1); - } - // The version must end with either '.dev' or '.prod', as expected - // by `balena-image-manager` and the balena SDK. Note that something - // like '2.88.4.prod' is not valid semver (https://semver.org/), - // so we don't even attempt semver parsing here. - if (!version.endsWith('.dev') && !version.endsWith('.prod')) { - version += '.prod'; + if (/^v?\d+\.\d+\.\d+/.test(version)) { + if (version[0] === 'v') { + version = version.slice(1); + } + // The version must end with either '.dev' or '.prod', as expected + // by `balena-image-manager` and the balena SDK. + if (!version.endsWith('.dev') && !version.endsWith('.prod')) { + version += '.prod'; + } } return version; } From bfc995e9486024628f3599f52b9c0fb13d815311 Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Fri, 10 Dec 2021 00:45:14 +0000 Subject: [PATCH 2/2] os download, os versions: Accept device type aliases Change-type: patch --- lib/utils/cloud.ts | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/utils/cloud.ts b/lib/utils/cloud.ts index b5b8a4e1..67242f3a 100644 --- a/lib/utils/cloud.ts +++ b/lib/utils/cloud.ts @@ -107,6 +107,16 @@ export const getDeviceAndMaybeAppFromUUID = _.memoize( (_sdk, deviceUUID) => deviceUUID, ); +/** Given a device type alias like 'nuc', return the actual slug like 'intel-nuc'. */ +export const unaliasDeviceType = _.memoize(async function ( + sdk: SDK.BalenaSDK, + deviceType: string, +): Promise { + return ( + (await sdk.models.device.getManifestBySlug(deviceType)).slug || deviceType + ); +}); + /** * Download balenaOS image for the specified `deviceType`. * `OSVersion` may be one of: @@ -244,11 +254,19 @@ export async function getFormattedOsVersions( deviceType: string, esr: boolean, ): Promise { - const versions: SDK.OsVersion[] = ( - (await getBalenaSdk().models.hostapp.getAvailableOsVersions([deviceType]))[ - deviceType - ] ?? [] - ) + const sdk = getBalenaSdk(); + let slug = deviceType; + let versionsByDT: SDK.OsVersionsByDeviceType = + await sdk.models.hostapp.getAvailableOsVersions([slug]); + // if slug is an alias, fetch the real slug + if (!versionsByDT[slug]?.length) { + // unaliasDeviceType() produces a nice error msg if slug is invalid + slug = await unaliasDeviceType(sdk, slug); + if (slug !== deviceType) { + versionsByDT = await sdk.models.hostapp.getAvailableOsVersions([slug]); + } + } + const versions: SDK.OsVersion[] = (versionsByDT[slug] || []) .filter((v: SDK.OsVersion) => v.osType === (esr ? 'esr' : 'default')) .map((v: SDK.OsVersion) => { const i = v.formattedVersion.indexOf(' '); @@ -259,9 +277,10 @@ export async function getFormattedOsVersions( 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'.`); + const vType = esr ? 'ESR versions' : 'versions'; + throw new ExpectedError( + `Error: No balenaOS ${vType} found for device type '${deviceType}'.`, + ); } return versions; }