Skip to content

Commit

Permalink
Improve getDeviceTargetStateV3/getFleetTargetStateV3 typings
Browse files Browse the repository at this point in the history
Change-type: patch
  • Loading branch information
otaviojacobi committed Sep 30, 2024
1 parent 132d840 commit 5073c7c
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 24 deletions.
20 changes: 16 additions & 4 deletions src/features/device-state/routes/fleet-state-get-v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {

import { sbvrUtils, errors } from '@balena/pinejs';
import { getConfig, readTransaction } from '../state-get-utils.js';
import type { StateV3 } from './state-get-v3.js';
import type { ExpandedRelease, StateV3 } from './state-get-v3.js';
import { buildAppFromRelease, releaseExpand } from './state-get-v3.js';
import type { OptionsToResponse } from 'pinejs-client-core';
import type { Application } from '../../../balena-model.js';
const { api } = sbvrUtils;
const { UnauthorizedError } = errors;

Expand Down Expand Up @@ -46,6 +48,16 @@ const fleetExpand = {
},
} as const;

export type ExpandedApplicationWithService = NonNullable<
OptionsToResponse<
Application['Read'],
{
$expand: typeof fleetExpand;
},
number
>
>;

const stateQuery = _.once(() =>
api.resin.prepare(
{
Expand Down Expand Up @@ -104,8 +116,8 @@ const getSuccessfulReleaseForFleetAndCommit = async (
};

const getFleetAppsForState = (
fleet: AnyObject,
release: AnyObject | undefined,
fleet: ExpandedApplicationWithService,
release: ExpandedRelease,
config: Dictionary<string>,
): FleetStateV3[string]['apps'] => {
return {
Expand All @@ -128,7 +140,7 @@ const getFleetStateV3 = async (
): Promise<FleetStateV3> => {
const fleet = await getFleet(req, uuid);
const config = getConfig(undefined, fleet);
let release: AnyObject | undefined;
let release: ExpandedRelease;
if (releaseUuid) {
release = await getSuccessfulReleaseForFleetAndCommit(
req,
Expand Down
89 changes: 69 additions & 20 deletions src/features/device-state/routes/state-get-v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,33 @@ import { sbvrUtils } from '@balena/pinejs';
import { events } from '../index.js';
import type { ResolveDeviceInfoCustomObject } from '../middleware.js';
import { getIP } from '../../../lib/utils.js';
import type { OptionsToResponse } from 'pinejs-client-core';
import type { Application } from '../../../balena-model.js';
import type { ExpandedApplicationWithService } from './fleet-state-get-v3.js';

const { api } = sbvrUtils;

type LocalStateApp = StateV3[string]['apps'][string];
type ServiceComposition = AnyObject;
type ExpandedDevice = Awaited<ReturnType<typeof getDevice>>;
type ExpandedApplication = NonNullable<
OptionsToResponse<
Application['Read'],
{
$select: typeof appSelect;
$expand: typeof appExpand;
},
number
>
>;

type TargetReleaseField =
| 'should_be_running__release'
| 'should_be_managed_by__release'
| 'should_be_operated_by__release';

export type ExpandedRelease = ExpandedDevice[TargetReleaseField][number];

export type StateV3 = {
[uuid: string]: {
name: string;
Expand Down Expand Up @@ -80,9 +102,23 @@ export type StateV3 = {
};

export function buildAppFromRelease(
device: AnyObject | undefined,
application: AnyObject,
release: AnyObject,
device: undefined,
application: ExpandedApplicationWithService,
release: ExpandedRelease,
config: Dictionary<string>,
defaultLabels?: Dictionary<string>,
): NonNullable<LocalStateApp['releases']>;
export function buildAppFromRelease(
device: ExpandedDevice,
application: ExpandedApplication,
release: ExpandedRelease,
config: Dictionary<string>,
defaultLabels?: Dictionary<string>,
): NonNullable<LocalStateApp['releases']>;
export function buildAppFromRelease(
device: ExpandedDevice | undefined,
application: ExpandedApplication | ExpandedApplicationWithService,
release: ExpandedRelease,
config: Dictionary<string>,
defaultLabels?: Dictionary<string>,
): NonNullable<LocalStateApp['releases']> {
Expand All @@ -101,25 +137,30 @@ export function buildAppFromRelease(
}
}

for (const ipr of release.contains__image as AnyObject[]) {
for (const ipr of release.contains__image) {
// extract the per-image information
const image = ipr.image[0];

const si = serviceInstallFromImage(device ?? application, image);
const si = serviceInstallFromImage(
device ?? (application as ExpandedApplicationWithService),
image,
);
if (si == null) {
throw new Error(
`Could not find service install for device or application: '${
application.uuid
}', image: '${image?.id}', service: '${JSON.stringify(
image?.is_a_build_of__service,
)}', service: '${
device
device != null
? JSON.stringify(device.service_install)
: JSON.stringify(application.service)
: JSON.stringify(
(application as ExpandedApplicationWithService).service,
)
}'`,
);
}
const svc = si.service?.[0] ?? si;
const svc = 'service' in si ? si.service[0] : si;
const environment: Dictionary<string> = {};
varListInsert(ipr.image_environment_variable, environment);
varListInsert(application.application_environment_variable, environment);
Expand All @@ -128,7 +169,7 @@ export function buildAppFromRelease(
if (device?.device_environment_variable) {
varListInsert(device.device_environment_variable, environment);
}
if (si?.device_service_environment_variable) {
if ('device_service_environment_variable' in si) {
varListInsert(si.device_service_environment_variable, environment);
}

Expand Down Expand Up @@ -211,6 +252,13 @@ export const releaseExpand = {
},
} as const;

const appSelect = [
'id',
'uuid',
'app_name',
'is_host',
'is_of__class',
] as const;
const appExpand = {
application_environment_variable: {
$select: ['name', 'value'],
Expand Down Expand Up @@ -245,7 +293,7 @@ const deviceExpand = {
},
},
belongs_to__application: {
$select: ['id', 'uuid', 'app_name', 'is_host', 'is_of__class'],
$select: appSelect,
$expand: {
...appExpand,
application_config_variable: {
Expand All @@ -258,7 +306,7 @@ const deviceExpand = {
$expand: {
...releaseExpand.$expand,
belongs_to__application: {
$select: ['id', 'uuid', 'app_name', 'is_host', 'is_of__class'],
$select: appSelect,
$expand: appExpand,
},
},
Expand All @@ -268,7 +316,7 @@ const deviceExpand = {
$expand: {
...releaseExpand.$expand,
belongs_to__application: {
$select: ['id', 'uuid', 'app_name', 'is_host', 'is_of__class'],
$select: appSelect,
$expand: appExpand,
},
},
Expand Down Expand Up @@ -363,16 +411,13 @@ const getDevice = getStateDelayingEmpty(
);

const getAppState = (
device: AnyObject,
targetReleaseField:
| 'should_be_running__release'
| 'should_be_managed_by__release'
| 'should_be_operated_by__release',
device: ExpandedDevice,
targetReleaseField: TargetReleaseField,
config: Dictionary<string>,
defaultLabels?: Dictionary<string>,
): StateV3[string]['apps'] | null => {
let application: AnyObject;
let release: AnyObject | undefined;
let application: ExpandedApplication;
let release: ExpandedRelease;
if (targetReleaseField === 'should_be_running__release') {
application = device.belongs_to__application[0];
release = device.should_be_running__release[0];
Expand All @@ -381,7 +426,11 @@ const getAppState = (
if (!release) {
return null;
}
application = release.belongs_to__application[0];
application = (
release as ExpandedDevice[
| 'should_be_managed_by__release'
| 'should_be_operated_by__release'][number]
).belongs_to__application[0];
}

return {
Expand Down
8 changes: 8 additions & 0 deletions src/features/device-state/state-get-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ export function serviceInstallFromImage(
is_a_build_of__service: number | { __id: number };
},
): ExpandedService | undefined;
export function serviceInstallFromImage(
deviceOrFleet:
| { service_install: ExpandedServiceInstall[] }
| { service: ExpandedService[] },
image?: {
is_a_build_of__service: number | { __id: number };
},
): ExpandedServiceInstall | ExpandedService | undefined;
/** @deprecated Use the strongly-typed overloads with `{ service_install }` or `{ service }` instead */
export function serviceInstallFromImage(
deviceOrFleet: AnyObject,
Expand Down

0 comments on commit 5073c7c

Please sign in to comment.