Skip to content

Commit 532aefb

Browse files
committed
feat: multiple versions for the pg_tle extension
Build multiple versions of the pg_tle extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
1 parent 24430ee commit 532aefb

File tree

5 files changed

+284
-26
lines changed

5 files changed

+284
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ result*
1919
.history
2020
.envrc
2121
.direnv
22+
.nixos-test-history
2223

2324

2425
#IDE

nix/checks.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@
309309
;
310310
}
311311
// pkgs.lib.optionalAttrs (system == "x86_64-linux") {
312+
pg_tle = import ./ext/tests/pg_tle.nix {
313+
inherit self;
314+
inherit pkgs;
315+
};
312316
wrappers = import ./ext/tests/wrappers.nix {
313317
inherit self;
314318
inherit pkgs;

nix/ext/pg_tle.nix

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,108 @@
11
{
22
lib,
33
stdenv,
4+
buildEnv,
45
fetchFromGitHub,
56
postgresql,
67
flex,
78
openssl,
89
libkrb5,
910
}:
10-
11-
stdenv.mkDerivation rec {
11+
let
1212
pname = "pg_tle";
13-
version = "1.4.0";
13+
build =
14+
version: hash:
15+
stdenv.mkDerivation rec {
16+
inherit pname version;
1417

15-
nativeBuildInputs = [ flex ];
16-
buildInputs = [
17-
openssl
18-
postgresql
19-
libkrb5
20-
];
18+
nativeBuildInputs = [ flex ];
19+
buildInputs = [
20+
openssl
21+
postgresql
22+
libkrb5
23+
];
2124

22-
src = fetchFromGitHub {
23-
owner = "aws";
24-
repo = pname;
25-
rev = "refs/tags/v${version}";
26-
hash = "sha256-crxj5R9jblIv0h8lpqddAoYe2UqgUlnvbOajKTzVces=";
27-
};
25+
src = fetchFromGitHub {
26+
owner = "aws";
27+
repo = pname;
28+
rev = "refs/tags/v${version}";
29+
inherit hash;
30+
};
31+
32+
makeFlags = [ "FLEX=flex" ];
33+
34+
installPhase = ''
2835
29-
makeFlags = [ "FLEX=flex" ];
36+
mkdir -p $out/{lib,share/postgresql/extension}
3037
31-
installPhase = ''
32-
mkdir -p $out/{lib,share/postgresql/extension}
38+
mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
3339
34-
cp *${postgresql.dlSuffix} $out/lib
35-
cp *.sql $out/share/postgresql/extension
36-
cp *.control $out/share/postgresql/extension
40+
create_sql_files() {
41+
if test -f ${pname}--${version}.sql; then
42+
cp ${pname}--${version}.sql $out/share/postgresql/extension
43+
fi
44+
echo "Creating SQL files for previous versions..."
45+
if [[ "${version}" == "${latestVersion}" ]]; then
46+
cp *.sql $out/share/postgresql/extension
47+
fi
48+
}
49+
50+
create_control_files() {
51+
sed -e "/^default_version =/d" \
52+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
53+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
54+
55+
if [[ "${version}" == "${latestVersion}" ]]; then
56+
{
57+
echo "default_version = '${latestVersion}'"
58+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
59+
} > $out/share/postgresql/extension/${pname}.control
60+
ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
61+
fi
62+
}
63+
64+
create_sql_files
65+
create_control_files
66+
'';
67+
68+
meta = with lib; {
69+
description = "Framework for 'Trusted Language Extensions' in PostgreSQL";
70+
homepage = "https://github.com/aws/${pname}";
71+
license = licenses.postgresql;
72+
inherit (postgresql.meta) platforms;
73+
};
74+
};
75+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
76+
supportedVersions = lib.filterAttrs (
77+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
78+
) allVersions;
79+
versions = lib.naturalSort (lib.attrNames supportedVersions);
80+
latestVersion = lib.last versions;
81+
numberOfVersions = builtins.length versions;
82+
packages = builtins.attrValues (
83+
lib.mapAttrs (name: value: build name value.hash) supportedVersions
84+
);
85+
in
86+
buildEnv {
87+
name = pname;
88+
paths = packages;
89+
pathsToLink = [
90+
"/lib"
91+
"/share/postgresql/extension"
92+
];
93+
postBuild = ''
94+
# checks
95+
(set -x
96+
test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${
97+
toString (numberOfVersions + 1)
98+
}"
99+
)
37100
'';
38101

39-
meta = with lib; {
40-
description = "Framework for 'Trusted Language Extensions' in PostgreSQL";
41-
homepage = "https://github.com/aws/${pname}";
42-
platforms = postgresql.meta.platforms;
43-
license = licenses.postgresql;
102+
passthru = {
103+
inherit versions numberOfVersions;
104+
pname = "${pname}-all";
105+
version =
106+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
44107
};
45108
}

nix/ext/tests/pg_tle.nix

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{ self, pkgs }:
2+
let
3+
pname = "pg_tle";
4+
inherit (pkgs) lib;
5+
installedExtension =
6+
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
7+
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
8+
postgresqlWithExtension =
9+
postgresql:
10+
let
11+
majorVersion = lib.versions.major postgresql.version;
12+
pkg = pkgs.buildEnv {
13+
name = "postgresql-${majorVersion}-${pname}";
14+
paths = [
15+
postgresql
16+
postgresql.lib
17+
(installedExtension majorVersion)
18+
];
19+
passthru = {
20+
inherit (postgresql) version psqlSchema;
21+
lib = pkg;
22+
withPackages = _: pkg;
23+
};
24+
nativeBuildInputs = [ pkgs.makeWrapper ];
25+
pathsToLink = [
26+
"/"
27+
"/bin"
28+
"/lib"
29+
];
30+
postBuild = ''
31+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
32+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
33+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
34+
'';
35+
};
36+
in
37+
pkg;
38+
in
39+
self.inputs.nixpkgs.lib.nixos.runTest {
40+
name = pname;
41+
hostPkgs = pkgs;
42+
nodes.server =
43+
{ config, ... }:
44+
{
45+
virtualisation = {
46+
forwardPorts = [
47+
{
48+
from = "host";
49+
host.port = 13022;
50+
guest.port = 22;
51+
}
52+
];
53+
};
54+
services.openssh = {
55+
enable = true;
56+
};
57+
users.users.root.openssh.authorizedKeys.keys = [
58+
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIo+ulCUfJjnCVgfM4946Ih5Nm8DeZZiayYeABHGPEl7 jfroche"
59+
];
60+
61+
services.postgresql = {
62+
enable = true;
63+
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
64+
settings = {
65+
shared_preload_libraries = "pg_tle";
66+
};
67+
};
68+
69+
specialisation.postgresql17.configuration = {
70+
services.postgresql = {
71+
package = lib.mkForce (postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
72+
};
73+
74+
systemd.services.postgresql-migrate = {
75+
serviceConfig = {
76+
Type = "oneshot";
77+
RemainAfterExit = true;
78+
User = "postgres";
79+
Group = "postgres";
80+
StateDirectory = "postgresql";
81+
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
82+
};
83+
script =
84+
let
85+
oldPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
86+
newPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
87+
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
88+
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
89+
in
90+
''
91+
if [[ ! -d ${newDataDir} ]]; then
92+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
93+
${newPostgresql}/bin/initdb -D "${newDataDir}"
94+
echo "shared_preload_libraries = 'pg_tle'" >> "${newDataDir}/postgresql.conf"
95+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
96+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
97+
else
98+
echo "${newDataDir} already exists"
99+
fi
100+
'';
101+
};
102+
103+
systemd.services.postgresql = {
104+
after = [ "postgresql-migrate.service" ];
105+
requires = [ "postgresql-migrate.service" ];
106+
};
107+
};
108+
};
109+
testScript =
110+
{ nodes, ... }:
111+
let
112+
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
113+
in
114+
''
115+
versions = {
116+
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
117+
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
118+
}
119+
120+
def run_sql(query):
121+
return server.succeed(f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """).strip()
122+
123+
def check_upgrade_path(pg_version):
124+
with subtest("Check ${pname} upgrade path"):
125+
firstVersion = versions[pg_version][0]
126+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION IF EXISTS ${pname};'")
127+
run_sql(f"""CREATE EXTENSION ${pname} WITH VERSION '{firstVersion}';""")
128+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
129+
assert installed_version == firstVersion, f"Expected ${pname} version {firstVersion}, but found {installed_version}"
130+
for version in versions[pg_version][1:]:
131+
run_sql(f"""ALTER EXTENSION ${pname} UPDATE TO '{version}';""")
132+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
133+
assert installed_version == version, f"Expected ${pname} version {version}, but found {installed_version}"
134+
135+
start_all()
136+
137+
server.wait_for_unit("multi-user.target")
138+
server.wait_for_unit("postgresql.service")
139+
140+
check_upgrade_path("15")
141+
142+
with subtest("Check ${pname} latest extension version"):
143+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION ${pname};'")
144+
server.succeed("sudo -u postgres psql -c 'CREATE EXTENSION ${pname};'")
145+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
146+
latestVersion = versions["15"][-1]
147+
assert f"${pname},{latestVersion}" in installed_extensions
148+
149+
with subtest("switch to postgresql 17"):
150+
server.succeed(
151+
"${pg17-configuration}/bin/switch-to-configuration test >&2"
152+
)
153+
154+
with subtest("Check ${pname} latest extension version"):
155+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
156+
latestVersion = versions["17"][-1]
157+
assert f"${pname},{latestVersion}" in installed_extensions
158+
159+
check_upgrade_path("17")
160+
'';
161+
}

nix/ext/versions.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,34 @@
2020
],
2121
"hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs="
2222
}
23+
},
24+
"pg_tle": {
25+
"1.0.1": {
26+
"postgresql": [
27+
"15"
28+
],
29+
"hash": "sha256-yAe37nIgObjs0kZY1A0QBGMP/s45sC1HVRwxVRaXwXs="
30+
},
31+
"1.0.4": {
32+
"postgresql": [
33+
"15",
34+
"17"
35+
],
36+
"hash": "sha256-W/7pLy/27VatCdzUh1NZ4K2FRMD1erfHiFV2eY2x2W0="
37+
},
38+
"1.3.0": {
39+
"postgresql": [
40+
"15",
41+
"17"
42+
],
43+
"hash": "sha256-Q4D4+eYPBONd8IKlDVfQa8wI4PJyKHkMPPqONqEWFLE="
44+
},
45+
"1.4.0": {
46+
"postgresql": [
47+
"15",
48+
"17"
49+
],
50+
"hash": "sha256-crxj5R9jblIv0h8lpqddAoYe2UqgUlnvbOajKTzVces="
51+
}
2352
}
2453
}

0 commit comments

Comments
 (0)