Stop relying on device-type.json for resolving the device type aliases

Resolves: #2541
Change-type: patch
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
This commit is contained in:
Thodoris Greasidis 2022-10-17 17:01:33 +03:00
parent 57b0dccc7d
commit a20d2a04a8
4 changed files with 648 additions and 36 deletions

View File

@ -15,6 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { flags } from '@oclif/command'; import { flags } from '@oclif/command';
import type * as BalenaSdk from 'balena-sdk';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Command from '../../command'; import Command from '../../command';
@ -59,36 +60,38 @@ export default class DevicesSupportedCmd extends Command {
public async run() { public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(DevicesSupportedCmd); const { flags: options } = this.parse<FlagsDef, {}>(DevicesSupportedCmd);
const [dts, configDTs] = await Promise.all([ const pineOptions = {
getBalenaSdk().models.deviceType.getAllSupported({ $select: (['slug', 'name'] as const).slice(),
$expand: { is_of__cpu_architecture: { $select: 'slug' } }, $expand: {
$select: ['slug', 'name'], is_of__cpu_architecture: { $select: 'slug' },
}), device_type_alias: {
getBalenaSdk().models.config.getDeviceTypes(), $select: 'is_referenced_by__alias',
]); $orderby: 'is_referenced_by__alias asc',
const dtsBySlug = _.keyBy(dts, (dt) => dt.slug); },
const configDTsBySlug = _.keyBy(configDTs, (dt) => dt.slug); },
} as const;
const dts = (await getBalenaSdk().models.deviceType.getAllSupported(
pineOptions,
)) as Array<
BalenaSdk.PineTypedResult<BalenaSdk.DeviceType, typeof pineOptions>
>;
interface DT { interface DT {
slug: string; slug: string;
aliases: string[]; aliases: string[];
arch: string; arch: string;
name: string; name: string;
} }
let deviceTypes: DT[] = []; let deviceTypes = dts.map((dt): DT => {
for (const slug of Object.keys(dtsBySlug)) { const aliases = dt.device_type_alias
const configDT: Partial<typeof configDTs[0]> = .map((dta) => dta.is_referenced_by__alias)
configDTsBySlug[slug] || {}; .filter((alias) => alias !== dt.slug);
const aliases = (configDT.aliases || []).filter( return {
(alias) => alias !== slug, slug: dt.slug,
);
const dt: Partial<typeof dts[0]> = dtsBySlug[slug] || {};
deviceTypes.push({
slug,
aliases: options.json ? aliases : [aliases.join(', ')], aliases: options.json ? aliases : [aliases.join(', ')],
arch: (dt.is_of__cpu_architecture as any)?.[0]?.slug || 'n/a', arch: dt.is_of__cpu_architecture[0]?.slug || 'n/a',
name: dt.name || 'N/A', name: dt.name || 'N/A',
}); };
} });
const fields = ['slug', 'aliases', 'arch', 'name']; const fields = ['slug', 'aliases', 'arch', 'name'];
deviceTypes = _.sortBy(deviceTypes, fields); deviceTypes = _.sortBy(deviceTypes, fields);
if (options.json) { if (options.json) {

View File

@ -107,16 +107,6 @@ export const getDeviceAndMaybeAppFromUUID = _.memoize(
(_sdk, deviceUUID) => deviceUUID, (_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<string> {
return (
(await sdk.models.device.getManifestBySlug(deviceType)).slug || deviceType
);
});
/** /**
* Download balenaOS image for the specified `deviceType`. * Download balenaOS image for the specified `deviceType`.
* `OSVersion` may be one of: * `OSVersion` may be one of:
@ -255,8 +245,8 @@ export async function getOsVersions(
); );
// if slug is an alias, fetch the real slug // if slug is an alias, fetch the real slug
if (!versions.length) { if (!versions.length) {
// unaliasDeviceType() produces a nice error msg if slug is invalid // unalias device type slug
slug = await unaliasDeviceType(sdk, slug); slug = (await sdk.models.deviceType.get(slug, { $select: 'slug' })).slug;
if (slug !== deviceType) { if (slug !== deviceType) {
versions = await sdk.models.os.getAvailableOsVersions(slug); versions = await sdk.models.os.getAvailableOsVersions(slug);
} }

View File

@ -44,7 +44,6 @@ describe('balena devices supported', function () {
it('should list currently supported devices, with correct filtering', async () => { it('should list currently supported devices, with correct filtering', async () => {
api.expectGetDeviceTypes(); api.expectGetDeviceTypes();
api.expectGetConfigDeviceTypes();
const { out, err } = await runCommand('devices supported'); const { out, err } = await runCommand('devices supported');
@ -54,7 +53,7 @@ describe('balena devices supported', function () {
expect(lines).to.have.lengthOf.at.least(2); expect(lines).to.have.lengthOf.at.least(2);
expect(lines).to.contain('intel-nuc nuc amd64 Intel NUC'); expect(lines).to.contain('intel-nuc nuc amd64 Intel NUC');
expect(lines).to.contain( expect(lines).to.contain(
'odroid-xu4 odroid-ux3, odroid-u3+ armv7hf ODROID-XU4', 'odroid-xu4 odroid-u3+, odroid-ux3 armv7hf ODROID-XU4',
); );
expect(err).to.eql([]); expect(err).to.eql([]);
}); });

File diff suppressed because it is too large Load Diff