feature: every write of an instance's variable files is kept as a revision with the schema version of their layout and the application that wrote them.
Release / release (push) Successful in 1m8s

This commit is contained in:
slawek committed 2026-11-06 22:22:35 +01:00
1 parent 7c335c7ed2
commit 5e62e143b6
11 files changed
+286 -37

No files matched your search

+58 -2
View File
@@ -1,6 +1,7 @@
-- The store of Terraform modules, their instances and the instances' variable files: the tables tf_modules,
-- tf_instances and tf_variable_files, and the functions and procedures the store calls. The store applies the file on
-- its first use in the schema its connection's search path names; every statement can run again.
-- tf_instances, tf_variable_files and tf_variable_revisions, and the functions and procedures the store calls. The
-- store applies the file on its first use in the schema its connection's search path names; every statement can run
-- again.
CREATE TABLE IF NOT EXISTS tf_modules (
name text PRIMARY KEY CHECK (name ~ '^[a-z][a-z0-9-]*$'),
@@ -28,6 +29,28 @@ CREATE TABLE IF NOT EXISTS tf_variable_files (
FOREIGN KEY (module, instance) REFERENCES tf_instances (module, name) ON DELETE CASCADE
);
-- Every write of an instance's variable files: all its files after the write, by name, the schema version of their
-- layout, null when not known, and the application that wrote them.
CREATE TABLE IF NOT EXISTS tf_variable_revisions (
module text NOT NULL,
instance text NOT NULL,
revision integer NOT NULL CHECK (revision > 0),
files jsonb NOT NULL CHECK (jsonb_typeof(files) = 'object'),
schema integer CHECK (schema > 0),
producer text NOT NULL CHECK (producer <> ''),
saved timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (module, instance, revision),
FOREIGN KEY (module, instance) REFERENCES tf_instances (module, name) ON DELETE CASCADE
);
-- The files of an instance that has no revision are its revision 1, of an unknown schema and producer.
INSERT INTO tf_variable_revisions (module, instance, revision, files, schema, producer, saved)
SELECT f.module, f.instance, 1, jsonb_object_agg(f.name, f.content), NULL, 'unknown', max(f.updated)
FROM tf_variable_files f
WHERE NOT EXISTS (SELECT 1 FROM tf_variable_revisions r WHERE r.module = f.module AND r.instance = f.instance)
GROUP BY f.module, f.instance
ON CONFLICT DO NOTHING;
-- The modules, by name.
CREATE OR REPLACE FUNCTION tf_modules_list()
RETURNS TABLE (name text, root text, description text, configurator_url text)
@@ -115,3 +138,36 @@ SET search_path FROM CURRENT
AS $$
DELETE FROM tf_variable_files WHERE module = module_name AND instance = instance_name AND name = file_name
$$;
-- Records the variable files of an instance as its next revision, with the schema of their layout and their producer;
-- called with the lock of tf_variable_files_lock held.
CREATE OR REPLACE PROCEDURE tf_variable_revision_add(module_name text, instance_name text, revision_schema integer, revision_producer text)
LANGUAGE sql
SET search_path FROM CURRENT
AS $$
INSERT INTO tf_variable_revisions (module, instance, revision, files, schema, producer)
SELECT module_name, instance_name,
(SELECT coalesce(max(r.revision), 0) + 1 FROM tf_variable_revisions r WHERE r.module = module_name AND r.instance = instance_name),
(SELECT coalesce(jsonb_object_agg(f.name, f.content), '{}'::jsonb) FROM tf_variable_files f WHERE f.module = module_name AND f.instance = instance_name),
revision_schema, revision_producer
$$;
-- The revisions of an instance, newest first, with the names of their files.
CREATE OR REPLACE FUNCTION tf_variable_revisions_list(module_name text, instance_name text)
RETURNS TABLE (revision integer, schema integer, producer text, saved timestamptz, names text[])
LANGUAGE sql STABLE
SET search_path FROM CURRENT
AS $$
SELECT r.revision, r.schema, r.producer, r.saved, ARRAY(SELECT jsonb_object_keys(r.files) ORDER BY 1)
FROM tf_variable_revisions r WHERE r.module = module_name AND r.instance = instance_name ORDER BY r.revision DESC
$$;
-- A revision of an instance with its files.
CREATE OR REPLACE FUNCTION tf_variable_revision_get(module_name text, instance_name text, revision_number integer)
RETURNS TABLE (revision integer, schema integer, producer text, saved timestamptz, files jsonb)
LANGUAGE sql STABLE
SET search_path FROM CURRENT
AS $$
SELECT r.revision, r.schema, r.producer, r.saved, r.files
FROM tf_variable_revisions r WHERE r.module = module_name AND r.instance = instance_name AND r.revision = revision_number
$$;