From b011af89ad7b4f43199be9666009155a8c6371b7 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Wed, 19 Jul 2023 19:22:17 +0300 Subject: [PATCH] move: Include fleets of discontinued device types in the fleet selection Change-type: patch --- lib/commands/device/move.ts | 62 +++++++++++++++++-------------------- lib/utils/patterns.ts | 14 ++++++--- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/lib/commands/device/move.ts b/lib/commands/device/move.ts index 5c533f2a..b670ac5f 100644 --- a/lib/commands/device/move.ts +++ b/lib/commands/device/move.ts @@ -20,7 +20,6 @@ import type { IArg } from '@oclif/parser/lib/args'; import type { BalenaSDK, Device, - DeviceType, PineOptions, PineTypedResult, } from 'balena-sdk'; @@ -138,7 +137,6 @@ export default class DeviceMoveCmd extends Command { balena: BalenaSDK, devices: Awaited>, ) { - const { getExpandedProp } = await import('../../utils/pine'); // deduplicate the slugs const deviceCpuArchs = Array.from( new Set( @@ -148,48 +146,44 @@ export default class DeviceMoveCmd extends Command { ), ); - const deviceTypeOptions = { - $select: 'slug', - $expand: { - is_of__cpu_architecture: { - $select: 'slug', - }, + const allCpuArches = await balena.pine.get({ + resource: 'cpu_architecture', + options: { + $select: ['id', 'slug'], }, - } satisfies PineOptions; - const deviceTypes = (await balena.models.deviceType.getAllSupported( - deviceTypeOptions, - )) as Array>; + }); - const compatibleDeviceTypeSlugs = new Set( - deviceTypes - .filter((deviceType) => { - const deviceTypeArch = getExpandedProp( - deviceType.is_of__cpu_architecture, - 'slug', - )!; - return deviceCpuArchs.every((deviceCpuArch) => - balena.models.os.isArchitectureCompatibleWith( - deviceCpuArch, - deviceTypeArch, - ), - ); - }) - .map((deviceType) => deviceType.slug), - ); + const compatibleCpuArchIds = allCpuArches + .filter((cpuArch) => { + return deviceCpuArchs.every((deviceCpuArch) => + balena.models.os.isArchitectureCompatibleWith( + deviceCpuArch, + cpuArch.slug, + ), + ); + }) + .map((deviceType) => deviceType.id); const patterns = await import('../../utils/patterns'); try { const application = await patterns.selectApplication( - (app) => - compatibleDeviceTypeSlugs.has(app.is_for__device_type[0].slug) && - devices.some( - (device) => device.belongs_to__application.__id !== app.id, - ), + { + is_for__device_type: { + $any: { + $alias: 'dt', + $expr: { + dt: { + is_of__cpu_architecture: { $in: compatibleCpuArchIds }, + }, + }, + }, + }, + }, true, ); return application; } catch (err) { - if (!compatibleDeviceTypeSlugs.size) { + if (!compatibleCpuArchIds.length) { throw new ExpectedError( `${err.message}\nDo all devices have a compatible architecture?`, ); diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index 01c99c94..2d94d92d 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -19,6 +19,7 @@ import type { BalenaSDK, Device, Organization, + PineFilter, PineOptions, PineTypedResult, } from 'balena-sdk'; @@ -178,19 +179,22 @@ type SelectApplicationResult = PineTypedResult< >; export async function selectApplication( - filter?: (app: SelectApplicationResult) => boolean, + filter?: + | PineFilter + | ((app: SelectApplicationResult) => boolean), errorOnEmptySelection = false, ) { const balena = getBalenaSdk(); - let apps = (await balena.models.application.getAllDirectlyAccessible( - selectApplicationPineOptions, - )) as SelectApplicationResult[]; + let apps = (await balena.models.application.getAllDirectlyAccessible({ + ...selectApplicationPineOptions, + ...(filter != null && typeof filter === 'object' && { $filter: filter }), + })) as SelectApplicationResult[]; if (!apps.length) { throw new ExpectedError('No fleets found'); } - if (filter != null) { + if (filter != null && typeof filter === 'function') { apps = apps.filter(filter); }