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