diff --git a/ansible/vars.yml b/ansible/vars.yml index b05651fd3..e76b72c4e 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -10,9 +10,9 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: 17.5.1.036-orioledb - postgres17: 17.6.1.015 - postgres15: 15.14.1.015 + postgresorioledb-17: 17.5.1.036-orioledb-pgaudit-1 + postgres17: 17.6.1.015-pgaudit-1 + postgres15: 15.14.1.015-pgaudit-1 # Non Postgres Extensions pgbouncer_release: 1.19.0 diff --git a/nix/ext/pgaudit.nix b/nix/ext/pgaudit.nix index 3535447a7..7e68db1ca 100644 --- a/nix/ext/pgaudit.nix +++ b/nix/ext/pgaudit.nix @@ -1,6 +1,7 @@ { lib, stdenv, + buildEnv, fetchFromGitHub, libkrb5, openssl, @@ -8,54 +9,127 @@ }: #adapted from https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/sql/postgresql/ext/pgaudit.nix let - source = - { - "17" = { - version = "17.0"; - hash = "sha256-3ksq09wiudQPuBQI3dhEQi8IkXKLVIsPFgBnwLiicro="; - }; - "16" = { - version = "16.0"; - hash = "sha256-8+tGOl1U5y9Zgu+9O5UDDE4bec4B0JC/BQ6GLhHzQzc="; - }; - "15" = { - version = "1.7.0"; - hash = "sha256-8pShPr4HJaJQPjW1iPJIpj3CutTx8Tgr+rOqoXtgCcw="; - }; - } - .${lib.versions.major postgresql.version} - or (throw "Source for pgaudit is not available for ${postgresql.version}"); -in -stdenv.mkDerivation { pname = "pgaudit"; - inherit (source) version; + # Load version configuration from external file + allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname}; - src = fetchFromGitHub { - owner = "pgaudit"; - repo = "pgaudit"; - rev = source.version; - hash = source.hash; - }; + # Filter versions compatible with current PostgreSQL version + supportedVersions = lib.filterAttrs ( + _: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql + ) allVersions; + + # Derived version information + versions = lib.naturalSort (lib.attrNames supportedVersions); + latestVersion = lib.last versions; + numberOfVersions = builtins.length versions; + packages = builtins.attrValues ( + lib.mapAttrs (name: value: build name value.hash) supportedVersions + ); + + # Build function for individual pgaudit versions + build = + version: hash: + stdenv.mkDerivation { + inherit pname version; + + src = fetchFromGitHub { + owner = "pgaudit"; + repo = "pgaudit"; + rev = version; + inherit hash; + }; + + buildInputs = [ + libkrb5 + openssl + postgresql + ]; + + makeFlags = [ "USE_PGXS=1" ]; - buildInputs = [ - libkrb5 - openssl - postgresql + postBuild = + lib.optionalString (version == "1.7.0") '' + mv ${pname}--1.7.sql ${pname}--1.7.0.sql + cp ${pname}--1.7.0.sql ${pname}--1.6.1--1.7.0.sql + '' + + lib.optionalString (version == "1.7.1") '' + mv ${pname}--1.7--1.7.1.sql ${pname}--1.7.0--1.7.1.sql + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{lib,share/postgresql/extension} + + # Install shared library with version suffix + mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix} + + # Install SQL files + sed -i '1s/^/DROP EVENT TRIGGER IF EXISTS pgaudit_ddl_command_end; \n/' *.sql + sed -i '1s/^/DROP EVENT TRIGGER IF EXISTS pgaudit_sql_drop; \n/' *.sql + sed -i 's/CREATE FUNCTION/CREATE OR REPLACE FUNCTION/' *.sql + cp *.sql $out/share/postgresql/extension + + # Create version-specific control file + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \ + ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control + + # For the latest version, create default control file and symlink + if [[ "${version}" == "${latestVersion}" ]]; then + { + echo "default_version = '${latestVersion}'" + cat $out/share/postgresql/extension/${pname}--${latestVersion}.control + } > $out/share/postgresql/extension/${pname}.control + ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + fi + + runHook postInstall + ''; + + meta = with lib; { + description = "Open Source PostgreSQL Audit Logging"; + homepage = "https://github.com/pgaudit/pgaudit"; + changelog = "https://github.com/pgaudit/pgaudit/releases/tag/${source.version}"; + license = licenses.postgresql; + inherit (postgresql.meta) platforms; + }; + }; +in +buildEnv { + name = pname; + paths = packages; + pathsToLink = [ + "/lib" + "/share/postgresql/extension" ]; + postBuild = '' + # checks + (set -x + test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ + toString (numberOfVersions + 1) + }" + ) - makeFlags = [ "USE_PGXS=1" ]; + # Verify all expected library files are present + expectedFiles=${toString (numberOfVersions + 1)} + actualFiles=$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) - installPhase = '' - install -D -t $out/lib pgaudit${postgresql.dlSuffix} - install -D -t $out/share/postgresql/extension *.sql - install -D -t $out/share/postgresql/extension *.control + if [[ "$actualFiles" != "$expectedFiles" ]]; then + echo "Error: Expected $expectedFiles library files, found $actualFiles" + echo "Files found:" + ls -la $out/lib/${pname}*${postgresql.dlSuffix} || true + exit 1 + fi ''; - meta = with lib; { - description = "Open Source PostgreSQL Audit Logging"; - homepage = "https://github.com/pgaudit/pgaudit"; - changelog = "https://github.com/pgaudit/pgaudit/releases/tag/${source.version}"; - platforms = postgresql.meta.platforms; - license = licenses.postgresql; + passthru = { + inherit versions numberOfVersions; + pname = "${pname}-all"; + version = + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + defaultSettings = { + "shared_preload_libraries" = pname; + }; }; } diff --git a/nix/ext/tests/pgaudit.nix b/nix/ext/tests/pgaudit.nix new file mode 100644 index 000000000..3689641bf --- /dev/null +++ b/nix/ext/tests/pgaudit.nix @@ -0,0 +1,162 @@ +{ self, pkgs }: +let + pname = "pgaudit"; + inherit (pkgs) lib; + installedExtension = + postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; + postgresqlWithExtension = + postgresql: + let + majorVersion = lib.versions.major postgresql.version; + pkg = pkgs.buildEnv { + name = "postgresql-${majorVersion}-${pname}"; + paths = [ + postgresql + postgresql.lib + (installedExtension majorVersion) + ]; + passthru = { + inherit (postgresql) version psqlSchema; + lib = pkg; + withPackages = _: pkg; + }; + nativeBuildInputs = [ pkgs.makeWrapper ]; + pathsToLink = [ + "/" + "/bin" + "/lib" + ]; + postBuild = '' + wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib + wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib + wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib + ''; + }; + in + pkg; + psql_15 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15; + psql_17 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17; +in +self.inputs.nixpkgs.lib.nixos.runTest { + name = pname; + hostPkgs = pkgs; + nodes.server = + { config, ... }: + { + virtualisation = { + forwardPorts = [ + { + from = "host"; + host.port = 13022; + guest.port = 22; + } + ]; + }; + + services.postgresql = { + enable = true; + package = psql_15; + settings = { + "shared_preload_libraries" = pname; + }; + }; + + specialisation.postgresql17.configuration = { + services.postgresql = { + package = lib.mkForce psql_17; + settings = { + "shared_preload_libraries" = pname; + }; + }; + + systemd.services.postgresql-migrate = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = "postgres"; + Group = "postgres"; + StateDirectory = "postgresql"; + WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}"; + }; + script = + let + oldPostgresql = psql_15; + newPostgresql = psql_17; + oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}"; + newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}"; + in + '' + if [[ ! -d ${newDataDir} ]]; then + install -d -m 0700 -o postgres -g postgres "${newDataDir}" + ${newPostgresql}/bin/initdb -D "${newDataDir}" + ${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \ + --old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin" \ + --old-options="-c shared_preload_libraries='pgaudit'" \ + --new-options="-c shared_preload_libraries='pgaudit'" + else + echo "${newDataDir} already exists" + fi + ''; + }; + + systemd.services.postgresql = { + after = [ "postgresql-migrate.service" ]; + requires = [ "postgresql-migrate.service" ]; + }; + }; + }; + testScript = + { nodes, ... }: + let + pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17"; + in + '' + from pathlib import Path + versions = { + "15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}], + "17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}], + } + extension_name = "${pname}" + support_upgrade = True + pg17_configuration = "${pg17-configuration}" + ext_has_background_worker = ${ + if (installedExtension "15") ? hasBackgroundWorker then "True" else "False" + } + sql_test_directory = Path("${../../tests}") + pg_regress_test_name = "${(installedExtension "15").pgRegressTestName or pname}" + + ${builtins.readFile ./lib.py} + + start_all() + + server.wait_for_unit("multi-user.target") + server.wait_for_unit("postgresql.service") + + test = PostgresExtensionTest(server, extension_name, versions, sql_test_directory, support_upgrade) + + with subtest("Check upgrade path with postgresql 15"): + test.check_upgrade_path("15") + + with subtest("Check pg_regress with postgresql 15"): + test.check_pg_regress(Path("${psql_15}/lib/pgxs/src/test/regress/pg_regress"), "15", pg_regress_test_name) + + last_version = None + with subtest("Check the install of the last version of the extension"): + last_version = test.check_install_last_version("15") + + with subtest("switch to postgresql 17"): + server.succeed( + f"{pg17_configuration}/bin/switch-to-configuration test >&2" + ) + + with subtest("Check last version of the extension after upgrade"): + test.assert_version_matches(last_version) + + with subtest("Check upgrade path with postgresql 17"): + test.check_upgrade_path("17") + + with subtest("Check pg_regress with postgresql 17"): + test.check_pg_regress(Path("${psql_17}/lib/pgxs/src/test/regress/pg_regress"), "17", pg_regress_test_name) + ''; +} diff --git a/nix/ext/versions.json b/nix/ext/versions.json index 3068b857b..760cfe0f8 100644 --- a/nix/ext/versions.json +++ b/nix/ext/versions.json @@ -278,6 +278,38 @@ "hash": "sha256-Cpi2iASi1QJoED0Qs1dANqg/BNZTsz5S+pw8iYyW03Y=" } }, + "pgaudit": { + "1.6.1": { + "postgresql": [ + "15" + ], + "hash": "sha256-vxUDVq7nWkq7Qugy7HJLOXk4B61MSBIYQkzcbU6wSG8=" + }, + "1.7.0": { + "postgresql": [ + "15" + ], + "hash": "sha256-8pShPr4HJaJQPjW1iPJIpj3CutTx8Tgr+rOqoXtgCcw=" + }, + "1.7.1": { + "postgresql": [ + "15" + ], + "hash": "sha256-emwoTowT7WKFX0RQDqJXjIblrzqaUIUkzqSqBCHVKQ8=" + }, + "17.0": { + "postgresql": [ + "17" + ], + "hash": "sha256-3ksq09wiudQPuBQI3dhEQi8IkXKLVIsPFgBnwLiicro=" + }, + "17.1": { + "postgresql": [ + "17" + ], + "hash": "sha256-9St/ESPiFq2NiPKqbwHLwkIyATKUkOGxFcUrWgT+Iqo=" + } + }, "pgrouting": { "3.4.1": { "postgresql": [