Skip to content

Commit

Permalink
Support extending the device fields populated in the "get-state" event
Browse files Browse the repository at this point in the history
Change-type: minor
  • Loading branch information
thgreasi committed Sep 26, 2023
1 parent d109280 commit 0589256
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
7 changes: 6 additions & 1 deletion src/features/device-state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type StrictEventEmitter from 'strict-event-emitter-types';

import { EventEmitter } from 'events';
import { middleware } from '../../infra/auth';
import type { Device } from '../../balena-model';

import { resolveOrDenyDevicesWithStatus } from './middleware';
import { stateV2 } from './routes/state-get-v2';
Expand All @@ -14,9 +15,10 @@ import {
statePatchV3,
} from './routes/state-patch-v3';
import { fleetStateV3 } from './routes/fleet-state-get-v3';
import { Device } from '../../balena-model';
import type { GetStateEventStoredDeviceFields } from './state-get-utils';

export {
getStateEventAdditionalFields,
getConfig,
setReadTransaction,
filterDeviceConfig,
Expand Down Expand Up @@ -74,7 +76,10 @@ export interface Events {
info: Pick<Request, 'apiKey'> & {
config?: Dictionary<string>;
ipAddress: string | undefined;
// TODO: Drop in the next major
/** @deprecated use the storedDeviceFields */
storedPublicAddress: Device['public_address'];
storedDeviceFields: GetStateEventStoredDeviceFields;
},
) => void;
}
Expand Down
5 changes: 4 additions & 1 deletion src/features/device-state/routes/state-get-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ConfigurationVarsToLabels,
getStateDelayingEmpty,
getConfig,
getStateEventAdditionalFields,
} from '../state-get-utils';
import { sbvrUtils } from '@balena/pinejs';
import { events } from '..';
Expand Down Expand Up @@ -194,7 +195,7 @@ const stateQuery = _.once(() =>
resource: 'device',
id: { uuid: { '@': 'uuid' } },
options: {
$select: ['device_name', 'public_address'],
$select: ['device_name', ...getStateEventAdditionalFields],
$expand: {
device_config_variable: {
$select: ['name', 'value'],
Expand Down Expand Up @@ -250,7 +251,9 @@ const getStateV2 = async (req: Request, uuid: string): Promise<StateV2> => {
apiKey: req.apiKey,
config,
ipAddress: getIP(req),
// TODO: Drop in the next major in favor of storedDeviceFields
storedPublicAddress: device.public_address as Device['public_address'],
storedDeviceFields: _.pick(device, getStateEventAdditionalFields),
});

const userApp = getUserAppForState(device, config);
Expand Down
5 changes: 4 additions & 1 deletion src/features/device-state/routes/state-get-v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getConfig,
getReleaseForDevice,
getStateDelayingEmpty,
getStateEventAdditionalFields,
readTransaction,
serviceInstallFromImage,
varListInsert,
Expand Down Expand Up @@ -270,7 +271,7 @@ const stateQuery = _.once(() =>
resource: 'device',
id: { uuid: { '@': 'uuid' } },
options: {
$select: ['device_name', 'public_address'],
$select: ['device_name', ...getStateEventAdditionalFields],
$expand: deviceExpand,
},
}),
Expand All @@ -287,7 +288,9 @@ const getStateV3 = async (req: Request, uuid: string): Promise<StateV3> => {
apiKey: req.apiKey,
config,
ipAddress: getIP(req),
// TODO: Drop in the next major in favor of storedDeviceFields
storedPublicAddress: device.public_address as Device['public_address'],
storedDeviceFields: _.pick(device, getStateEventAdditionalFields),
});

let apps = getUserAppState(device, config);
Expand Down
13 changes: 13 additions & 0 deletions src/features/device-state/state-get-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ import {
createMultiLevelStore,
reqPermissionNormalizer,
} from '../../infra/cache';
import type { Device } from '../../balena-model';

// eslint-disable-next-line @typescript-eslint/no-empty-interface -- This needs to be an interface so that downstream projects can extend it.
export interface GetStateEventStoredDeviceFields
extends Pick<Device, 'public_address'> {}

// We do not use "satisfies" or "as const" so that downstream projects can augment this list.
export const getStateEventAdditionalFields: Array<
keyof GetStateEventStoredDeviceFields
> = [
// TODO: Remove the public_address from this list in the next major since it's not used by oB-api and downstream projects can set it if needed.
'public_address',
];

const defaultConfigVariableFns: Array<(config: Dictionary<string>) => void> = [
function setMinPollInterval(config) {
Expand Down

0 comments on commit 0589256

Please sign in to comment.