From bc6381f0e87eee39209f77c6ee4cee731025fb7f Mon Sep 17 00:00:00 2001 From: Otavio Jacobi Date: Thu, 28 Nov 2024 14:58:44 -0300 Subject: [PATCH 1/3] Rewrite service install FKs on balena model Change-type: patch --- src/balena-model.ts | 76 +++++++++++++++------------------------ src/balena.sbvr | 16 ++------- src/balena.ts | 8 +++++ src/translations/v7/v7.ts | 6 +++- 4 files changed, 45 insertions(+), 61 deletions(-) diff --git a/src/balena-model.ts b/src/balena-model.ts index 788118100..cc54e9aad 100644 --- a/src/balena-model.ts +++ b/src/balena-model.ts @@ -600,16 +600,10 @@ export interface Service { >; device__installs__service?: Array; service_install?: Array; - device__installs__application__has__service_name__has__name?: Array< + device__has__application__has__service_name__has__env_var_name?: Array< DeviceServiceEnvironmentVariable['Read'] >; - device__installs__service__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device__installs__service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - service_install__has__name?: Array< + device__has__service__has__env_var_name?: Array< DeviceServiceEnvironmentVariable['Read'] >; device_service_environment_variable?: Array< @@ -783,6 +777,15 @@ export interface Device { device_environment_variable?: Array; device__has__config_var_name?: Array; device_config_variable?: Array; + device__has__application__has__service_name__has__env_var_name?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; + device__has__service__has__env_var_name?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; + device_service_environment_variable?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; device__has__tag_key?: Array; device_tag?: Array; device__installs__image?: Array; @@ -792,21 +795,6 @@ export interface Device { >; device__installs__service?: Array; service_install?: Array; - device__installs__application__has__service_name__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device__installs__service__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device__installs__service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - service_install__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device_service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; installs__image?: Array; installs__application__has__service_name?: Array; installs__service?: Array; @@ -941,21 +929,6 @@ export interface ServiceInstall { device: { __id: Device['Read']['id'] } | [Device['Read']]; installs__service: { __id: Service['Read']['id'] } | [Service['Read']]; id: Types['Serial']['Read']; - device__installs__application__has__service_name__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device__installs__service__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device__installs__service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - service_install__has__name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - device_service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; application__has__service_name: | { __id: Service['Read']['id'] } | [Service['Read']]; @@ -964,6 +937,15 @@ export interface ServiceInstall { | { __id: Service['Read']['id'] } | [Service['Read']]; is_installed_on__device: { __id: Device['Read']['id'] } | [Device['Read']]; + is_of__device__has__application__has__service_name__has__env_var_name?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; + is_of__device__has__service__has__env_var_name?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; + is_of__device_service_environment_variable?: Array< + DeviceServiceEnvironmentVariable['Read'] + >; }; Write: { created_at: Types['Date Time']['Write']; @@ -978,14 +960,14 @@ export interface DeviceServiceEnvironmentVariable { Read: { created_at: Types['Date Time']['Read']; modified_at: Types['Date Time']['Read']; - service_install: - | { __id: ServiceInstall['Read']['id'] } - | [ServiceInstall['Read']]; + device: { __id: Device['Read']['id'] } | [Device['Read']]; + service: { __id: Service['Read']['id'] } | [Service['Read']]; name: Types['Short Text']['Read']; id: Types['Serial']['Read']; value: Types['Text']['Read']; - service: { __id: Service['Read']['id'] } | [Service['Read']]; - device: { __id: Device['Read']['id'] } | [Device['Read']]; + service_install: + | { __id: ServiceInstall['Read']['id'] } + | [ServiceInstall['Read']]; device__installs__application__has__service_name: | { __id: ServiceInstall['Read']['id'] } | [ServiceInstall['Read']]; @@ -999,12 +981,12 @@ export interface DeviceServiceEnvironmentVariable { Write: { created_at: Types['Date Time']['Write']; modified_at: Types['Date Time']['Write']; - service_install: ServiceInstall['Write']['id']; + device: Device['Write']['id']; + service: Service['Write']['id']; name: Types['Short Text']['Write']; id: Types['Serial']['Write']; value: Types['Text']['Write']; - service: Service['Write']['id']; - device: Device['Write']['id']; + service_install: ServiceInstall['Write']['id']; }; } @@ -1329,7 +1311,7 @@ export default interface $Model { device__has__config_var_name: DeviceConfigVariable; device__installs__image: ImageInstall; device__installs__application__has__service_name: ServiceInstall; - device__installs__application__has__service_name__has__name: DeviceServiceEnvironmentVariable; + device__has__application__has__service_name__has__env_var_name: DeviceServiceEnvironmentVariable; device__has__tag_key: DeviceTag; release: Release; release__has__tag_key: ReleaseTag; diff --git a/src/balena.sbvr b/src/balena.sbvr index 1ade14cf6..7bdf14d87 100644 --- a/src/balena.sbvr +++ b/src/balena.sbvr @@ -395,9 +395,7 @@ Term: device Term Form: service install Database Table Name: service install - -- Target form for this table is: - -- Fact type: device has service has env var name - Fact type: service install has name (Auth) + Fact type: device has service has env var name Term Form: device service environment variable Database Table Name: device service environment variable @@ -814,16 +812,8 @@ Fact type: image environment variable has value Fact type: device service environment variable has value Necessity: each device service environment variable has exactly one value. -Fact type: device service environment variable has service - -- This is the default name that will be given to the synonymous form - -- once the device service environment variable origin fact type changes - Synonymous form: service has device service environment variable - Necessity: each device service environment variable has exactly one service. -Fact type: device service environment variable has device - -- This is the default name that will be given to the synonymous form - -- once the device service environment variable origin fact type changes - Synonymous form: device has device service environment variable - Necessity: each device service environment variable has exactly one device. +Fact type: device service environment variable has service install + Necessity: each device service environment variable has exactly one service install. -- application tag diff --git a/src/balena.ts b/src/balena.ts index 034d31b85..b055db0cc 100644 --- a/src/balena.ts +++ b/src/balena.ts @@ -3,6 +3,7 @@ import { generateAbstractSqlModel, renameVarResourcesName, optimizeSchema, + renameField, } from './abstract-sql-utils.js'; import * as userHasDirectAccessToApplication from './features/applications/models/user__has_direct_access_to__application.js'; @@ -22,6 +23,13 @@ export const model = { abstractSql, } satisfies ConfigLoader.Model; +renameField( + abstractSql, + 'device-has-application-has-service name-has-env var name', + ['has'], + 'env var name', + 'name', +); renameVarResourcesName(abstractSql); userHasDirectAccessToApplication.addToModel(abstractSql); diff --git a/src/translations/v7/v7.ts b/src/translations/v7/v7.ts index 823543bd3..fcda71f7e 100644 --- a/src/translations/v7/v7.ts +++ b/src/translations/v7/v7.ts @@ -19,5 +19,9 @@ overrideFieldType(v7AbstractSqlModel, 'release', 'version', 'JSON'); userHasDirectAccessToApplication.addToModel(v7AbstractSqlModel); // eslint-disable-next-line @typescript-eslint/no-unused-vars -- So that the interface is already well defined. export const getV7Translations = (_abstractSqlModel = v7AbstractSqlModel) => { - return {} satisfies ConfigLoader.Model['translations']; + return { + 'device-installs-application-has-service name-has-name': { + $toResource: 'device-has-application-has-service name-has-env var name', + }, + } satisfies ConfigLoader.Model['translations']; }; From 39ab00da3aafae6f05cb5aaafbe613b1ac9f825e Mon Sep 17 00:00:00 2001 From: Otavio Jacobi Date: Fri, 29 Nov 2024 09:49:03 -0300 Subject: [PATCH 2/3] Add v7 read translation for device service environment variable service install Change-type: patch --- src/balena-model.ts | 19 ----- src/balena.sbvr | 2 - src/features/cascade-delete/hooks.ts | 33 +++++++- src/translations/v7/v7.ts | 38 +++++++++ test/25_service-installs.ts | 112 ++++++++++++++------------- 5 files changed, 125 insertions(+), 79 deletions(-) diff --git a/src/balena-model.ts b/src/balena-model.ts index cc54e9aad..34adfef5f 100644 --- a/src/balena-model.ts +++ b/src/balena-model.ts @@ -937,15 +937,6 @@ export interface ServiceInstall { | { __id: Service['Read']['id'] } | [Service['Read']]; is_installed_on__device: { __id: Device['Read']['id'] } | [Device['Read']]; - is_of__device__has__application__has__service_name__has__env_var_name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - is_of__device__has__service__has__env_var_name?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; - is_of__device_service_environment_variable?: Array< - DeviceServiceEnvironmentVariable['Read'] - >; }; Write: { created_at: Types['Date Time']['Write']; @@ -965,15 +956,6 @@ export interface DeviceServiceEnvironmentVariable { name: Types['Short Text']['Read']; id: Types['Serial']['Read']; value: Types['Text']['Read']; - service_install: - | { __id: ServiceInstall['Read']['id'] } - | [ServiceInstall['Read']]; - device__installs__application__has__service_name: - | { __id: ServiceInstall['Read']['id'] } - | [ServiceInstall['Read']]; - device__installs__service: - | { __id: ServiceInstall['Read']['id'] } - | [ServiceInstall['Read']]; application__has__service_name: | { __id: Service['Read']['id'] } | [Service['Read']]; @@ -986,7 +968,6 @@ export interface DeviceServiceEnvironmentVariable { name: Types['Short Text']['Write']; id: Types['Serial']['Write']; value: Types['Text']['Write']; - service_install: ServiceInstall['Write']['id']; }; } diff --git a/src/balena.sbvr b/src/balena.sbvr index 7bdf14d87..5961f3864 100644 --- a/src/balena.sbvr +++ b/src/balena.sbvr @@ -812,8 +812,6 @@ Fact type: image environment variable has value Fact type: device service environment variable has value Necessity: each device service environment variable has exactly one value. -Fact type: device service environment variable has service install - Necessity: each device service environment variable has exactly one service install. -- application tag diff --git a/src/features/cascade-delete/hooks.ts b/src/features/cascade-delete/hooks.ts index 9b4ac1ed8..54963c10c 100644 --- a/src/features/cascade-delete/hooks.ts +++ b/src/features/cascade-delete/hooks.ts @@ -21,6 +21,7 @@ setupDeleteCascade('device', { device_tag: 'device', image_install: 'device', service_install: 'device', + device_service_environment_variable: 'device', }); setupDeleteCascade('image', { @@ -45,11 +46,37 @@ setupDeleteCascade('service', { service_install: 'installs__service', image: 'is_a_build_of__service', service_label: 'service', + device_service_environment_variable: 'service', }); -setupDeleteCascade('service_install', { - device_service_environment_variable: 'service_install', -}); +// hooks.addPureHook('DELETE', 'resin', 'service install', { +// PRERUN: async (args) => { +// const serviceInstallIds = await getAffectedIds(args); +// if (serviceInstallIds.length === 0) { +// return; +// } + +// // Delete all device_service_environment_variable (dsev) where +// // dsev.device = service_install.device and dsev.service = service_install.installs__service +// await args.api.delete({ +// resource: 'device_service_environment_variable', +// passthrough: { +// tx: args.tx, +// req: permissions.root, +// }, +// options: { +// $filter: { + +// }, +// }, +// }); + +// }, +// }); + +// setupDeleteCascade('service_install', { +// device_service_environment_variable: 'service_install', +// }); const deleteApiKeyHooks: hooks.Hooks = { PRERUN: async (args) => { diff --git a/src/translations/v7/v7.ts b/src/translations/v7/v7.ts index fcda71f7e..b3fe07274 100644 --- a/src/translations/v7/v7.ts +++ b/src/translations/v7/v7.ts @@ -22,6 +22,44 @@ export const getV7Translations = (_abstractSqlModel = v7AbstractSqlModel) => { return { 'device-installs-application-has-service name-has-name': { $toResource: 'device-has-application-has-service name-has-env var name', + 'service install': [ + 'SelectQuery', + ['Select', [['ReferencedField', 'si', 'id']]], + [ + 'From', + [ + 'Alias', + // TODO: should this be changed from table to resource? How? + ['Table', 'device service environment variable'], + 'dsev', + ], + ], + [ + 'Join', + [ + 'Alias', + // TODO: should this be changed from table to resource? How? + ['Table', 'service install'], + 'si', + ], + [ + 'On', + [ + 'And', + [ + 'Equals', + ['ReferencedField', 'dsev', 'device'], + ['ReferencedField', 'si', 'device'], + ], + [ + 'Equals', + ['ReferencedField', 'dsev', 'service'], + ['ReferencedField', 'si', 'installs-service'], + ], + ], + ], + ], + ], }, } satisfies ConfigLoader.Model['translations']; }; diff --git a/test/25_service-installs.ts b/test/25_service-installs.ts index a2ffc8e20..4d5263ea8 100644 --- a/test/25_service-installs.ts +++ b/test/25_service-installs.ts @@ -284,68 +284,70 @@ export default () => { ); }); - it('should be able to update device_service_environment_variable service_install', async () => { - const { body: serviceInstallService1 } = await pineUser - .get({ - resource: 'service_install', - id: { - device: ctx.device.id, - installs__service: ctx.app2Service1.id, - }, - }) - .expect(200); - assertExists(serviceInstallService1); + if (versions.lte(version, 'v7')) { + it('should be able to update device_service_environment_variable service_install', async () => { + const { body: serviceInstallService1 } = await pineUser + .get({ + resource: 'service_install', + id: { + device: ctx.device.id, + installs__service: ctx.app2Service1.id, + }, + }) + .expect(200); + assertExists(serviceInstallService1); - const { body: serviceInstallService2 } = await pineUser - .get({ - resource: 'service_install', - id: { - device: ctx.device.id, - installs__service: ctx.app2Service2.id, - }, - }) - .expect(200); - assertExists(serviceInstallService2); + const { body: serviceInstallService2 } = await pineUser + .get({ + resource: 'service_install', + id: { + device: ctx.device.id, + installs__service: ctx.app2Service2.id, + }, + }) + .expect(200); + assertExists(serviceInstallService2); - const { - body: [deviceServiceEnvVar], - } = await pineUser - .get({ - resource: 'device_service_environment_variable', - options: { - $filter: { - service_install: serviceInstallService1.id, + const { + body: [deviceServiceEnvVar], + } = await pineUser + .get({ + resource: 'device_service_environment_variable', + options: { + $filter: { + service_install: serviceInstallService1.id, + }, }, - }, - }) - .expect(200); - assertExists(deviceServiceEnvVar); + }) + .expect(200); + assertExists(deviceServiceEnvVar); + + await pineUser + .patch({ + resource: 'device_service_environment_variable', + id: deviceServiceEnvVar.id, + body: { + service_install: serviceInstallService2.id, + }, + }) + .expect(200); - await pineUser - .patch({ - resource: 'device_service_environment_variable', - id: deviceServiceEnvVar.id, + const { body: { - service_install: serviceInstallService2.id, + d: [dbDeviceServiceEnvVar], }, - }) - .expect(200); - - const { - body: { - d: [dbDeviceServiceEnvVar], - }, - } = await supertest(ctx.admin) - .get( - `/resin/device_service_environment_variable(${deviceServiceEnvVar.id})?$select=device,service`, - ) - .expect(200); + } = await supertest(ctx.admin) + .get( + `/resin/device_service_environment_variable(${deviceServiceEnvVar.id})?$select=device,service`, + ) + .expect(200); - expect(dbDeviceServiceEnvVar.device.__id).to.equal(ctx.device.id); - expect(dbDeviceServiceEnvVar.service.__id).to.equal( - ctx.app2Service2.id, - ); - }); + expect(dbDeviceServiceEnvVar.device.__id).to.equal(ctx.device.id); + expect(dbDeviceServiceEnvVar.service.__id).to.equal( + ctx.app2Service2.id, + ); + }); + } }); }); }); From 3352b46a1354622a816ec27be9f364cd54b6348b Mon Sep 17 00:00:00 2001 From: Otavio Jacobi Date: Mon, 18 Nov 2024 18:28:29 -0300 Subject: [PATCH 3/3] Move backfill device service env var hook to a v7 translation hook Change-type: patch --- src/features/cascade-delete/hooks.ts | 64 +++++++++++-------- ...ill-device-service-environment-variable.ts | 35 ---------- ...rvice-install-on-device-service-env-var.ts | 58 +++++++++++++++++ src/features/service-install/hooks/index.ts | 2 +- src/translations/v7/hooks.ts | 45 +++++++++++++ src/translations/v7/v7.ts | 39 +++++------ test/25_service-installs.ts | 4 +- test/test-lib/fixtures.ts | 10 +-- 8 files changed, 163 insertions(+), 94 deletions(-) delete mode 100644 src/features/service-install/hooks/backfill-device-service-environment-variable.ts create mode 100644 src/features/service-install/hooks/backfill-service-install-on-device-service-env-var.ts diff --git a/src/features/cascade-delete/hooks.ts b/src/features/cascade-delete/hooks.ts index 54963c10c..aaec06b1a 100644 --- a/src/features/cascade-delete/hooks.ts +++ b/src/features/cascade-delete/hooks.ts @@ -49,34 +49,42 @@ setupDeleteCascade('service', { device_service_environment_variable: 'service', }); -// hooks.addPureHook('DELETE', 'resin', 'service install', { -// PRERUN: async (args) => { -// const serviceInstallIds = await getAffectedIds(args); -// if (serviceInstallIds.length === 0) { -// return; -// } - -// // Delete all device_service_environment_variable (dsev) where -// // dsev.device = service_install.device and dsev.service = service_install.installs__service -// await args.api.delete({ -// resource: 'device_service_environment_variable', -// passthrough: { -// tx: args.tx, -// req: permissions.root, -// }, -// options: { -// $filter: { - -// }, -// }, -// }); - -// }, -// }); - -// setupDeleteCascade('service_install', { -// device_service_environment_variable: 'service_install', -// }); +hooks.addPureHook('DELETE', 'resin', 'service_install', { + PRERUN: async (args) => { + const serviceInstallIds = await getAffectedIds(args); + if (serviceInstallIds.length === 0) { + return; + } + + const serviceInstalls = await api.resin.get({ + resource: 'service_install', + options: { + $filter: { + id: { $in: serviceInstallIds }, + }, + $select: ['device', 'installs__service'], + }, + }); + + const filterConditions = serviceInstalls.map((serviceInstall) => ({ + device: serviceInstall.device.__id, + service: serviceInstall.installs__service.__id, + })); + + await args.api.delete({ + resource: 'device_service_environment_variable', + passthrough: { + tx: args.tx, + req: permissions.root, + }, + options: { + $filter: { + $or: filterConditions, + }, + }, + }); + }, +}); const deleteApiKeyHooks: hooks.Hooks = { PRERUN: async (args) => { diff --git a/src/features/service-install/hooks/backfill-device-service-environment-variable.ts b/src/features/service-install/hooks/backfill-device-service-environment-variable.ts deleted file mode 100644 index ba5e9cf5d..000000000 --- a/src/features/service-install/hooks/backfill-device-service-environment-variable.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { hooks, errors, type sbvrUtils } from '@balena/pinejs'; - -async function backfillDeviceAndService({ - request, - api, -}: sbvrUtils.HookArgs<'resin'>) { - const { service_install: siId } = request.values; - - if (siId == null) { - return; - } - - const si = await api.get({ - resource: 'service_install', - id: siId, - options: { - $select: ['device', 'service'], - }, - }); - - if (si == null) { - throw new errors.UnauthorizedError(); - } - - request.values.device = si.device.__id; - request.values.service = si.service.__id; -} - -hooks.addPureHook('POST', 'resin', 'device_service_environment_variable', { - POSTPARSE: backfillDeviceAndService, -}); - -hooks.addPureHook('PATCH', 'resin', 'device_service_environment_variable', { - POSTPARSE: backfillDeviceAndService, -}); diff --git a/src/features/service-install/hooks/backfill-service-install-on-device-service-env-var.ts b/src/features/service-install/hooks/backfill-service-install-on-device-service-env-var.ts new file mode 100644 index 000000000..cf15a0dca --- /dev/null +++ b/src/features/service-install/hooks/backfill-service-install-on-device-service-env-var.ts @@ -0,0 +1,58 @@ +import { hooks, errors, type sbvrUtils } from '@balena/pinejs'; + +async function backfillServiceInstall({ + request, + api, +}: sbvrUtils.HookArgs<'resin'>) { + const { device: deviceId, service: serviceId } = request.values; + + if (deviceId == null && serviceId == null) { + return; + } + + if ( + (deviceId == null && serviceId != null) || + (deviceId != null && serviceId == null) + ) { + throw new errors.BadRequestError( + 'Both or none of device and service must be specified', + ); + } + + let si = await api.get({ + resource: 'service_install', + id: { + device: deviceId, + installs__service: serviceId, + }, + options: { + $select: ['id'], + }, + }); + + if (si == null) { + si = await api.post({ + resource: 'service_install', + body: { + device: deviceId, + installs__service: serviceId, + }, + }); + } + + if (si == null) { + throw new errors.BadRequestError( + `No service install exists for device: ${deviceId} and service ${serviceId} and one could not be created`, + ); + } + + request.values.service_install = si.id; +} + +hooks.addPureHook('POST', 'resin', 'device_service_environment_variable', { + POSTPARSE: backfillServiceInstall, +}); + +hooks.addPureHook('PATCH', 'resin', 'device_service_environment_variable', { + POSTPARSE: backfillServiceInstall, +}); diff --git a/src/features/service-install/hooks/index.ts b/src/features/service-install/hooks/index.ts index d089cbd91..740e23fb3 100644 --- a/src/features/service-install/hooks/index.ts +++ b/src/features/service-install/hooks/index.ts @@ -1 +1 @@ -import './backfill-device-service-environment-variable.js'; +import './backfill-service-install-on-device-service-env-var.js'; diff --git a/src/translations/v7/hooks.ts b/src/translations/v7/hooks.ts index e69de29bb..742ad3a6b 100644 --- a/src/translations/v7/hooks.ts +++ b/src/translations/v7/hooks.ts @@ -0,0 +1,45 @@ +import { hooks, sbvrUtils, errors } from '@balena/pinejs'; + +const addReadOnlyHook = ( + methods: Array[0]>, + resource: string, + hook: sbvrUtils.Hooks<'v7'>, +) => { + methods.map((method) => { + hooks.addHook(method, 'v7', resource, { + ...hook, + sideEffects: false, + readOnlyTx: true, + }); + }); +}; + +addReadOnlyHook( + ['POST', 'PATCH', 'PUT'], + 'device_service_environment_variable', + { + POSTPARSE: async ({ request, api }) => { + const { service_install: siId } = request.values; + + if (siId == null) { + return; + } + + const si = await sbvrUtils.api.resin.get({ + resource: 'service_install', + passthrough: api.passthrough, + id: siId, + options: { + $select: ['device', 'service'], + }, + }); + + if (si == null) { + throw new errors.UnauthorizedError(); + } + + request.values.device = si.device.__id; + request.values.service = si.service.__id; + }, + }, +); diff --git a/src/translations/v7/v7.ts b/src/translations/v7/v7.ts index b3fe07274..6d80b5d8b 100644 --- a/src/translations/v7/v7.ts +++ b/src/translations/v7/v7.ts @@ -25,37 +25,28 @@ export const getV7Translations = (_abstractSqlModel = v7AbstractSqlModel) => { 'service install': [ 'SelectQuery', ['Select', [['ReferencedField', 'si', 'id']]], + ['From', ['Alias', ['Table', 'service install'], 'si']], [ - 'From', + 'Where', [ - 'Alias', - // TODO: should this be changed from table to resource? How? - ['Table', 'device service environment variable'], - 'dsev', - ], - ], - [ - 'Join', - [ - 'Alias', - // TODO: should this be changed from table to resource? How? - ['Table', 'service install'], - 'si', - ], - [ - 'On', + 'And', [ - 'And', + 'Equals', [ - 'Equals', - ['ReferencedField', 'dsev', 'device'], - ['ReferencedField', 'si', 'device'], + 'ReferencedField', + 'device-installs-application-has-service name-has-name', + 'device', ], + ['ReferencedField', 'si', 'device'], + ], + [ + 'Equals', [ - 'Equals', - ['ReferencedField', 'dsev', 'service'], - ['ReferencedField', 'si', 'installs-service'], + 'ReferencedField', + 'device-installs-application-has-service name-has-name', + 'service', ], + ['ReferencedField', 'si', 'installs-service'], ], ], ], diff --git a/test/25_service-installs.ts b/test/25_service-installs.ts index 4d5263ea8..407c7ccb3 100644 --- a/test/25_service-installs.ts +++ b/test/25_service-installs.ts @@ -260,7 +260,9 @@ export default () => { .post({ resource: 'device_service_environment_variable', body: { - service_install: serviceInstall.id, + ...(versions.lte(version, 'v7') + ? { service_install: serviceInstall.id } + : { device: ctx.device.id, service: ctx.app2Service1.id }), name: 'test', value: '123', }, diff --git a/test/test-lib/fixtures.ts b/test/test-lib/fixtures.ts index 0ed0ca3ae..e5843dc5e 100644 --- a/test/test-lib/fixtures.ts +++ b/test/test-lib/fixtures.ts @@ -508,8 +508,8 @@ const loaders: types.Dictionary = { logErrorAndThrow(`Could not find service: ${jsonData.service}`); } - const si = await expectToEventually(async () => { - const $si = await api.resin.get({ + await expectToEventually(async () => { + const si = await api.resin.get({ resource: 'service_install', passthrough: { req: permissions.rootRead }, id: { @@ -517,14 +517,14 @@ const loaders: types.Dictionary = { installs__service: service.id, }, }); - assertExists($si); - return $si; + assertExists(si); }); return await createResource({ resource: 'device_service_environment_variable', body: { - service_install: si.id, + device: device.id, + service: service.id, name: jsonData.name, value: jsonData.value, },