Skip to content

Commit

Permalink
Move backfill device service env var hook to a v7 translation hook
Browse files Browse the repository at this point in the history
Change-type: patch
  • Loading branch information
otaviojacobi committed Nov 29, 2024
1 parent 39ab00d commit d2f9fce
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 94 deletions.
64 changes: 36 additions & 28 deletions src/features/cascade-delete/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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,
});
2 changes: 1 addition & 1 deletion src/features/service-install/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import './backfill-device-service-environment-variable.js';
import './backfill-service-install-on-device-service-env-var.js';
45 changes: 45 additions & 0 deletions src/translations/v7/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { hooks, sbvrUtils, errors } from '@balena/pinejs';

const addReadOnlyHook = (
methods: Array<Parameters<typeof hooks.addHook>[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;
},
},
);
39 changes: 15 additions & 24 deletions src/translations/v7/v7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
],
],
],
Expand Down
4 changes: 3 additions & 1 deletion test/25_service-installs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
Expand Down
10 changes: 5 additions & 5 deletions test/test-lib/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,23 +508,23 @@ const loaders: types.Dictionary<LoaderFunc> = {
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: {
device: device.id,
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,
},
Expand Down

0 comments on commit d2f9fce

Please sign in to comment.