Skip to content

Commit

Permalink
device management 1: Add 'is pinned on-release' column and synchroniz…
Browse files Browse the repository at this point in the history
…e values from 'should be running release'

Change-type: minor
  • Loading branch information
Andrea Rosci authored and Andrea Rosci committed May 29, 2024
1 parent 162c8ff commit d71661e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/balena-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,20 @@ CREATE INDEX IF NOT EXISTS "device_device_type_idx"
ON "device" ("is of-device type");
CREATE INDEX IF NOT EXISTS "device_is_running_release_idx"
ON "device" ("is running-release");
-- Also optimizes should be running succesful release rule
-- Also optimizes should be running successful release rule
CREATE INDEX IF NOT EXISTS "device_should_be_running_release_application_idx"
ON "device" ("should be running-release", "belongs to-application");
-- Also optimizes is pinned on successful release rule
-- TODO: remove as soon as the is_pinned_on__release migration is completed
CREATE INDEX IF NOT EXISTS "device_is_pinned_on_release_idx"
ON "device" ("is pinned on-release");
CREATE INDEX IF NOT EXISTS "device_should_be_operated_by_release_device_type_idx"
ON "device" ("should be operated by-release", "is of-device type");
-- Also optimizes the supervisor cpu arch should match device cpu arch rule
CREATE INDEX IF NOT EXISTS "device_should_be_managed_by__release_device_type_idx"
ON "device" ("should be managed by-release", "is of-device type");


-- "device config variable"."device" is the first part of an automated unique index

-- "device environment variable"."device" is the first part of an automated unique index
Expand Down
2 changes: 2 additions & 0 deletions src/balena-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export interface Device {
| [ServiceInstance?]
| null;
should_be_running__release: { __id: Release['id'] } | [Release?] | null;
is_pinned_on__release: { __id: Release['id'] } | [Release?] | null;
should_be_operated_by__release: { __id: Release['id'] } | [Release?] | null;
should_be_managed_by__release: { __id: Release['id'] } | [Release?] | null;
is_web_accessible: boolean | null;
Expand Down Expand Up @@ -519,6 +520,7 @@ export interface Release {
should_be_running_on__application?: Application[];
should_be_running_on__device?: Device[];
is_running_on__device?: Device[];
is_pinned_on__device?: Device[];
should_operate__device?: Device[];
should_manage__device?: Device[];
provides__device__installs__image?: ImageInstall[];
Expand Down
4 changes: 4 additions & 0 deletions src/balena.sbvr
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,9 @@ Fact type: device is managed by service instance
Fact type: device should be running release
Synonymous Form: release should be running on device
Necessity: each device should be running at most one release
Fact type: device is pinned on release
Synonymous Form: release is pinned to device
Necessity: each device is pinned on at most one release
Fact type: device should be operated by release
Synonymous Form: release should operate device
Necessity: each device should be operated by at most one release
Expand Down Expand Up @@ -860,6 +863,7 @@ Rule: It is necessary that each image that has a status that is equal to "succes
Rule: It is necessary that each application that owns a release1 that has a status that is equal to "success" and has a commit1, owns at most one release2 that has a status that is equal to "success" and has a commit2 that is equal to the commit1.
Rule: It is necessary that each application that owns a release1 that has a revision, owns at most one release2 that has a semver major that is of the release1 and has a semver minor that is of the release1 and has a semver patch that is of the release1 and has a semver prerelease that is of the release1 and has a variant that is of the release1 and has a revision that is of the release1.
Rule: It is necessary that each release that should be running on a device, has a status that is equal to "success" and belongs to an application1 that the device belongs to.
Rule: It is necessary that each release that is pinned on a device, has a status that is equal to "success" and belongs to an application1 that the device belongs to.
Rule: It is necessary that each release that should be running on an application, has a status that is equal to "success" and belongs to the application.
Rule: It is necessary that each application that owns a release that contains at least 2 images, has an application type that supports multicontainer.
Rule: It is necessary that each release that should operate a device, has a status that is equal to "success".
Expand Down
20 changes: 19 additions & 1 deletion src/features/devices/hooks/defaults-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,20 @@ hooks.addPureHook('POST', 'resin', 'device', {
'Device UUID must be a 32 or 62 character long lower case hex string.',
);
}

// TODO[device management next step]: Drop this after re-migrating all data on step 2:
if (request.values.should_be_running__release !== undefined) {
// Add an async boundary so that value updates,
// and doesn't remove the properties that we add.
await null;
request.values.is_pinned_on__release =
request.values.should_be_running__release;
}
},
});

hooks.addPureHook('PATCH', 'resin', 'device', {
POSTPARSE: ({ request }) => {
POSTPARSE: async ({ request }) => {
// Check for extra whitespace characters
if (
request.values.device_name != null &&
Expand Down Expand Up @@ -73,5 +82,14 @@ hooks.addPureHook('PATCH', 'resin', 'device', {
if (request.values.is_online != null) {
request.values.last_connectivity_event = new Date();
}

// TODO[device management next step]: Drop this after re-migrating all data on step 2:
if (request.values.should_be_running__release !== undefined) {
// Add an async boundary so that value updates,
// and doesn't remove the properties that we add.
await null;
request.values.is_pinned_on__release =
request.values.should_be_running__release;
}
},
});
25 changes: 25 additions & 0 deletions src/migrations/00087-add-device-pinned-on-release.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- Add the column if it does not exist
ALTER TABLE "device"
ADD COLUMN IF NOT EXISTS "is pinned on-release" INTEGER NULL;

-- Add an index for optimization if it does not exist
CREATE INDEX IF NOT EXISTS "device_is_pinned_on_release_idx"
ON "device" ("is pinned on-release");

-- Check and add the foreign key constraint conditionally
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
WHERE tc.constraint_type = 'FOREIGN KEY'
AND tc.table_schema = CURRENT_SCHEMA()
AND tc.table_name = 'device'
AND kcu.column_name = 'is pinned on-release'
) THEN
ALTER TABLE "device"
ADD CONSTRAINT "device_is_pinned_on_release_fkey" FOREIGN KEY ("is pinned on-release") REFERENCES "release" ("id");
END IF;
END;
$$;

0 comments on commit d71661e

Please sign in to comment.