Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

device management 1: Add 'is pinned on-release' column and synchronize values from 'should be running release' #1639

Merged
merged 1 commit into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/balena-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ 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
-- TODO: remove device_should_be_running_release_application_idx as soon as the is_pinned_on_release migration is ended
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
CREATE INDEX IF NOT EXISTS "device_is_pinned_on_release_application_idx"
ON "device" ("is pinned on-release", "belongs to-application");
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
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_to__device?: Device[];
should_operate__device?: Device[];
should_manage__device?: Device[];
provides__device__installs__image?: ImageInstall[];
Expand Down
3 changes: 3 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
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_application_idx"
ON "device" ("is pinned on-release", "belongs to-application");

-- 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;
$$;
Loading