diff --git a/nixos/tests/postgresql/anonymizer.nix b/nixos/tests/postgresql/anonymizer.nix index 7b9d84ca8aff5..ec971aa710253 100644 --- a/nixos/tests/postgresql/anonymizer.nix +++ b/nixos/tests/postgresql/anonymizer.nix @@ -5,16 +5,16 @@ let inherit (pkgs) lib; - makeAnonymizerTest = postgresqlPackage: + makeTestFor = package: makeTest { - name = "postgresql_anonymizer-${postgresqlPackage.name}"; + name = "postgresql_anonymizer-${package.name}"; meta.maintainers = lib.teams.flyingcircus.members; nodes.machine = { pkgs, ... }: { environment.systemPackages = [ pkgs.pg-dump-anon ]; services.postgresql = { + inherit package; enable = true; - package = postgresqlPackage; extraPlugins = ps: [ ps.anonymizer ]; settings.shared_preload_libraries = [ "anon" ]; }; @@ -102,9 +102,9 @@ let ''; }; in -pkgs.lib.recurseIntoAttrs ( - pkgs.lib.concatMapAttrs (n: p: { ${n} = makeAnonymizerTest p; }) pkgs.postgresqlVersions +lib.recurseIntoAttrs ( + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.anonymizer.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makeAnonymizerTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/pgjwt.nix b/nixos/tests/postgresql/pgjwt.nix index e8beb6cbee532..2c0b77f180ff8 100644 --- a/nixos/tests/postgresql/pgjwt.nix +++ b/nixos/tests/postgresql/pgjwt.nix @@ -5,23 +5,21 @@ let inherit (pkgs) lib; - makePgjwtTest = postgresqlPackage: + makeTestFor = package: makeTest { - name = "pgjwt-${postgresqlPackage.name}"; + name = "pgjwt-${package.name}"; meta = with lib.maintainers; { maintainers = [ spinus willibutz ]; }; - nodes = { - master = { ... }: + nodes.master = { ... }: { services.postgresql = { + inherit package; enable = true; - package = postgresqlPackage; extraPlugins = ps: with ps; [ pgjwt pgtap ]; }; }; - }; testScript = { nodes, ... }: let @@ -39,8 +37,8 @@ let }; in lib.recurseIntoAttrs ( - lib.concatMapAttrs (n: p: { ${n} = makePgjwtTest p; }) pkgs.postgresqlVersions + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.pgjwt.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makePgjwtTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/pgvecto-rs.nix b/nixos/tests/postgresql/pgvecto-rs.nix index 4d14dfdb6bb1f..8f8c3fdd84368 100644 --- a/nixos/tests/postgresql/pgvecto-rs.nix +++ b/nixos/tests/postgresql/pgvecto-rs.nix @@ -2,9 +2,9 @@ , makeTest }: -with pkgs.lib; - let + inherit (pkgs) lib; + # Test cases from https://docs.pgvecto.rs/use-cases/hybrid-search.html test-sql = pkgs.writeText "postgresql-test" '' CREATE EXTENSION vectors; @@ -22,53 +22,53 @@ let ('a thin dog sat on a mat and ate a thin rat', '[10, 11, 12]'); ''; - makePgVectorsTest = postgresqlPackage: makeTest { - name = "pgvecto-rs-${postgresqlPackage.name}"; - meta = with pkgs.lib.maintainers; { - maintainers = [ diogotcorreia ]; - }; - - nodes.machine = { ... }: - { - services.postgresql = { - enable = true; - package = postgresqlPackage; - extraPlugins = ps: with ps; [ - pgvecto-rs - ]; - settings.shared_preload_libraries = "vectors"; - }; + makeTestFor = postgresqlPackage: + makeTest { + name = "pgvecto-rs-${postgresqlPackage.name}"; + meta = with lib.maintainers; { + maintainers = [ diogotcorreia ]; }; - testScript = { nodes, ... }: - let - inherit (nodes.machine.services.postgresql.package.pkgs) pgvecto-rs; - in - '' - def check_count(statement, lines): - return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( - statement, lines - ) + nodes.machine = { ... }: + { + services.postgresql = { + enable = true; + package = postgresqlPackage; + extraPlugins = ps: with ps; [ + pgvecto-rs + ]; + settings.shared_preload_libraries = "vectors"; + }; + }; + testScript = { nodes, ... }: + let + inherit (nodes.machine.services.postgresql.package.pkgs) pgvecto-rs; + in + '' + def check_count(statement, lines): + return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( + statement, lines + ) - machine.start() - machine.wait_for_unit("postgresql") - with subtest("Postgresql with extension vectors is available just after unit start"): - machine.succeed(check_count("SELECT * FROM pg_available_extensions WHERE name = 'vectors' AND default_version = '${pgvecto-rs.version}';", 1)) + machine.start() + machine.wait_for_unit("postgresql") - machine.succeed("sudo -u postgres psql -f ${test-sql}") + with subtest("Postgresql with extension vectors is available just after unit start"): + machine.succeed(check_count("SELECT * FROM pg_available_extensions WHERE name = 'vectors' AND default_version = '${pgvecto-rs.version}';", 1)) - machine.succeed(check_count("SELECT content, embedding FROM items WHERE to_tsvector('english', content) @@ 'cat & rat'::tsquery;", 2)) + machine.succeed("sudo -u postgres psql -f ${test-sql}") - machine.shutdown() - ''; + machine.succeed(check_count("SELECT content, embedding FROM items WHERE to_tsvector('english', content) @@ 'cat & rat'::tsquery;", 2)) - }; + machine.shutdown() + ''; + }; in -recurseIntoAttrs ( - concatMapAttrs (n: p: { ${n} = makePgVectorsTest p; }) (filterAttrs (n: p: !p.pkgs.pgvecto-rs.meta.broken) pkgs.postgresqlVersions) +lib.recurseIntoAttrs ( + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.pgvecto-rs.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makePgVectorsTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/postgresql-jit.nix b/nixos/tests/postgresql/postgresql-jit.nix index 40329d038fefe..69967f091312b 100644 --- a/nixos/tests/postgresql/postgresql-jit.nix +++ b/nixos/tests/postgresql/postgresql-jit.nix @@ -5,45 +5,48 @@ let inherit (pkgs) lib; - mkJitTest = package: makeTest { - name = "postgresql-jit-${package.name}"; - meta.maintainers = with lib.maintainers; [ ma27 ]; - nodes.machine = { pkgs, lib, ... }: { - services.postgresql = { - inherit package; - enable = true; - enableJIT = true; - initialScript = pkgs.writeText "init.sql" '' - create table demo (id int); - insert into demo (id) select generate_series(1, 5); - ''; + makeTestFor = package: + makeTest { + name = "postgresql-jit-${package.name}"; + meta.maintainers = with lib.maintainers; [ ma27 ]; + + nodes.machine = { pkgs, ... }: { + services.postgresql = { + inherit package; + enable = true; + enableJIT = true; + initialScript = pkgs.writeText "init.sql" '' + create table demo (id int); + insert into demo (id) select generate_series(1, 5); + ''; + }; }; - }; - testScript = '' - machine.start() - machine.wait_for_unit("postgresql.service") - with subtest("JIT is enabled"): - machine.succeed("sudo -u postgres psql <<<'show jit;' | grep 'on'") + testScript = '' + machine.start() + machine.wait_for_unit("postgresql.service") - with subtest("Test JIT works fine"): - output = machine.succeed( - "cat ${pkgs.writeText "test.sql" '' - set jit_above_cost = 1; - EXPLAIN ANALYZE SELECT CONCAT('jit result = ', SUM(id)) FROM demo; - SELECT CONCAT('jit result = ', SUM(id)) from demo; - ''} | sudo -u postgres psql" - ) - assert "JIT:" in output - assert "jit result = 15" in output + with subtest("JIT is enabled"): + machine.succeed("sudo -u postgres psql <<<'show jit;' | grep 'on'") - machine.shutdown() - ''; - }; + with subtest("Test JIT works fine"): + output = machine.succeed( + "cat ${pkgs.writeText "test.sql" '' + set jit_above_cost = 1; + EXPLAIN ANALYZE SELECT CONCAT('jit result = ', SUM(id)) FROM demo; + SELECT CONCAT('jit result = ', SUM(id)) from demo; + ''} | sudo -u postgres psql" + ) + assert "JIT:" in output + assert "jit result = 15" in output + + machine.shutdown() + ''; + }; in lib.recurseIntoAttrs ( - lib.concatMapAttrs (n: p: { ${n} = mkJitTest p; }) (lib.filterAttrs (n: _: lib.hasSuffix "_jit" n) pkgs.postgresqlVersions) + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (n: _: lib.hasSuffix "_jit" n) pkgs.postgresqlVersions) // { - passthru.override = p: mkJitTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/postgresql-tls-client-cert.nix b/nixos/tests/postgresql/postgresql-tls-client-cert.nix index 503bc77268c20..4939c96b2b84d 100644 --- a/nixos/tests/postgresql/postgresql-tls-client-cert.nix +++ b/nixos/tests/postgresql/postgresql-tls-client-cert.nix @@ -3,43 +3,41 @@ }: let - lib = pkgs.lib; + inherit (pkgs) lib; - makePostgresqlTlsClientCertTest = pkg: - let - runWithOpenSSL = file: cmd: pkgs.runCommand file - { - buildInputs = [ pkgs.openssl ]; - } - cmd; - caKey = runWithOpenSSL "ca.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; - caCert = runWithOpenSSL - "ca.crt" - '' - openssl req -new -x509 -sha256 -key ${caKey} -out $out -subj "/CN=test.example" -days 36500 - ''; - serverKey = - runWithOpenSSL "server.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; - serverKeyPath = "/var/lib/postgresql"; - serverCert = - runWithOpenSSL "server.crt" '' - openssl req -new -sha256 -key ${serverKey} -out server.csr -subj "/CN=db.test.example" - openssl x509 -req -in server.csr -CA ${caCert} -CAkey ${caKey} \ - -CAcreateserial -out $out -days 36500 -sha256 - ''; - clientKey = - runWithOpenSSL "client.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; - clientCert = - runWithOpenSSL "client.crt" '' - openssl req -new -sha256 -key ${clientKey} -out client.csr -subj "/CN=test" - openssl x509 -req -in client.csr -CA ${caCert} -CAkey ${caKey} \ - -CAcreateserial -out $out -days 36500 -sha256 - ''; - clientKeyPath = "/root"; + runWithOpenSSL = file: cmd: pkgs.runCommand file + { + buildInputs = [ pkgs.openssl ]; + } + cmd; + caKey = runWithOpenSSL "ca.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + caCert = runWithOpenSSL + "ca.crt" + '' + openssl req -new -x509 -sha256 -key ${caKey} -out $out -subj "/CN=test.example" -days 36500 + ''; + serverKey = + runWithOpenSSL "server.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + serverKeyPath = "/var/lib/postgresql"; + serverCert = + runWithOpenSSL "server.crt" '' + openssl req -new -sha256 -key ${serverKey} -out server.csr -subj "/CN=db.test.example" + openssl x509 -req -in server.csr -CA ${caCert} -CAkey ${caKey} \ + -CAcreateserial -out $out -days 36500 -sha256 + ''; + clientKey = + runWithOpenSSL "client.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + clientCert = + runWithOpenSSL "client.crt" '' + openssl req -new -sha256 -key ${clientKey} -out client.csr -subj "/CN=test" + openssl x509 -req -in client.csr -CA ${caCert} -CAkey ${caKey} \ + -CAcreateserial -out $out -days 36500 -sha256 + ''; + clientKeyPath = "/root"; - in + makeTestFor = package: makeTest { - name = "postgresql-tls-client-cert-${pkg.name}"; + name = "postgresql-tls-client-cert-${package.name}"; meta.maintainers = with lib.maintainers; [ erictapen ]; nodes.server = { ... }: { @@ -52,7 +50,7 @@ let ''; }; services.postgresql = { - package = pkg; + inherit package; enable = true; enableTCPIP = true; ensureUsers = [ @@ -102,7 +100,7 @@ let PGSSLKEY = "${clientKeyPath}/client.key"; PGSSLROOTCERT = caCert; }; - systemPackages = [ pkg ]; + systemPackages = [ package ]; }; networking = { interfaces.eth1 = { @@ -120,11 +118,10 @@ let client.succeed("psql -c \"SELECT 1;\"") ''; }; - in lib.recurseIntoAttrs ( - lib.concatMapAttrs (n: p: { ${n} = makePostgresqlTlsClientCertTest p; }) pkgs.postgresqlVersions + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) pkgs.postgresqlVersions // { - passthru.override = p: makePostgresqlTlsClientCertTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/postgresql-wal-receiver.nix b/nixos/tests/postgresql/postgresql-wal-receiver.nix index d46b3fcbdcf30..b9d69cf00684d 100644 --- a/nixos/tests/postgresql/postgresql-wal-receiver.nix +++ b/nixos/tests/postgresql/postgresql-wal-receiver.nix @@ -3,21 +3,20 @@ }: let - lib = pkgs.lib; + inherit (pkgs) lib; - makePostgresqlWalReceiverTest = pkg: + makeTestFor = package: let - postgresqlDataDir = "/var/lib/postgresql/${pkg.psqlSchema}"; + postgresqlDataDir = "/var/lib/postgresql/${package.psqlSchema}"; replicationUser = "wal_receiver_user"; replicationSlot = "wal_receiver_slot"; replicationConn = "postgresql://${replicationUser}@localhost"; baseBackupDir = "/var/cache/wals/pg_basebackup"; walBackupDir = "/var/cache/wals/pg_wal"; - recoveryFile = pkgs.writeTextDir "recovery.signal" ""; - - in makeTest { - name = "postgresql-wal-receiver-${pkg.name}"; + in + makeTest { + name = "postgresql-wal-receiver-${package.name}"; meta.maintainers = with lib.maintainers; [ pacien ]; nodes.machine = { ... }: { @@ -26,7 +25,7 @@ let ]; services.postgresql = { - package = pkg; + inherit package; enable = true; settings = { max_replication_slots = 10; @@ -45,7 +44,7 @@ let }; services.postgresqlWalReceiver.receivers.main = { - postgresqlPackage = pkg; + postgresqlPackage = package; connection = replicationConn; slot = replicationSlot; directory = walBackupDir; @@ -64,7 +63,7 @@ let # required only for 9.4 machine.sleep(5) machine.succeed( - "${pkg}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}" + "${package}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}" ) # create a dummy table with 100 records @@ -105,8 +104,8 @@ let }; in lib.recurseIntoAttrs ( - lib.concatMapAttrs (n: p: { ${n} = makePostgresqlWalReceiverTest p; }) pkgs.postgresqlVersions + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) pkgs.postgresqlVersions // { - passthru.override = p: makePostgresqlWalReceiverTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/postgresql.nix b/nixos/tests/postgresql/postgresql.nix index 56ec43d0a3b69..13a768d9a8a9a 100644 --- a/nixos/tests/postgresql/postgresql.nix +++ b/nixos/tests/postgresql/postgresql.nix @@ -2,14 +2,14 @@ , makeTest }: -with pkgs.lib; - let - testsForPackage = package: - recurseIntoAttrs { - postgresql = make-postgresql-test package false; - postgresql-backup-all = make-postgresql-test package true; - postgresql-clauses = mk-ensure-clauses-test package; + inherit (pkgs) lib; + + makeTestFor = package: + lib.recurseIntoAttrs { + postgresql = makeTestForWithBackupAll package false; + postgresql-backup-all = makeTestForWithBackupAll package true; + postgresql-clauses = makeEnsureTestFor package; }; test-sql = pkgs.writeText "postgresql-test" '' @@ -26,207 +26,208 @@ let INSERT INTO xmltest (doc) VALUES ('ok'); -- check if libxml2 enabled ''; - make-postgresql-test = postgresql-package: backup-all: makeTest { - name = "postgresql${optionalString backup-all "-backup-all"}-${postgresql-package.name}"; - meta = with pkgs.lib.maintainers; { - maintainers = [ zagy ]; - }; + makeTestForWithBackupAll = package: backupAll: + makeTest { + name = "postgresql${lib.optionalString backupAll "-backup-all"}-${package.name}"; + meta = with lib.maintainers; { + maintainers = [ zagy ]; + }; - nodes.machine = {...}: - { - services.postgresql = { - enable = true; - package = postgresql-package; + nodes.machine = {...}: + { + services.postgresql = { + inherit (package); + enable = true; + }; + + services.postgresqlBackup = { + enable = true; + databases = lib.optional (!backupAll) "postgres"; + }; }; - services.postgresqlBackup = { - enable = true; - databases = optional (!backup-all) "postgres"; - }; - }; + testScript = let + backupName = if backupAll then "all" else "postgres"; + backupService = if backupAll then "postgresqlBackup" else "postgresqlBackup-postgres"; + backupFileBase = "/var/backup/postgresql/${backupName}"; + in '' + def check_count(statement, lines): + return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( + statement, lines + ) - testScript = let - backupName = if backup-all then "all" else "postgres"; - backupService = if backup-all then "postgresqlBackup" else "postgresqlBackup-postgres"; - backupFileBase = "/var/backup/postgresql/${backupName}"; - in '' - def check_count(statement, lines): - return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( - statement, lines - ) - - - machine.start() - machine.wait_for_unit("postgresql") - - with subtest("Postgresql is available just after unit start"): - machine.succeed( - "cat ${test-sql} | sudo -u postgres psql" - ) - - with subtest("Postgresql survives restart (bug #1735)"): - machine.shutdown() - import time - time.sleep(2) - machine.start() - machine.wait_for_unit("postgresql") - - machine.fail(check_count("SELECT * FROM sth;", 3)) - machine.succeed(check_count("SELECT * FROM sth;", 5)) - machine.fail(check_count("SELECT * FROM sth;", 4)) - machine.succeed(check_count("SELECT xpath('/test/text()', doc) FROM xmltest;", 1)) - - with subtest("Backup service works"): - machine.succeed( - "systemctl start ${backupService}.service", - "zcat ${backupFileBase}.sql.gz | grep 'ok'", - "ls -hal /var/backup/postgresql/ >/dev/console", - "stat -c '%a' ${backupFileBase}.sql.gz | grep 600", - ) - with subtest("Backup service removes prev files"): - machine.succeed( - # Create dummy prev files. - "touch ${backupFileBase}.prev.sql{,.gz,.zstd}", - "chown postgres:postgres ${backupFileBase}.prev.sql{,.gz,.zstd}", - - # Run backup. - "systemctl start ${backupService}.service", - "ls -hal /var/backup/postgresql/ >/dev/console", - - # Since nothing has changed in the database, the cur and prev files - # should match. - "zcat ${backupFileBase}.sql.gz | grep 'ok'", - "cmp ${backupFileBase}.sql.gz ${backupFileBase}.prev.sql.gz", - - # The prev files with unused suffix should be removed. - "[ ! -f '${backupFileBase}.prev.sql' ]", - "[ ! -f '${backupFileBase}.prev.sql.zstd' ]", - - # Both cur and prev file should only be accessible by the postgres user. - "stat -c '%a' ${backupFileBase}.sql.gz | grep 600", - "stat -c '%a' '${backupFileBase}.prev.sql.gz' | grep 600", - ) - with subtest("Backup service fails gracefully"): - # Sabotage the backup process - machine.succeed("rm /run/postgresql/.s.PGSQL.5432") - machine.fail( - "systemctl start ${backupService}.service", - ) - machine.succeed( - "ls -hal /var/backup/postgresql/ >/dev/console", - "zcat ${backupFileBase}.prev.sql.gz | grep 'ok'", - "stat ${backupFileBase}.in-progress.sql.gz", - ) - # In a previous version, the second run would overwrite prev.sql.gz, - # so we test a second run as well. - machine.fail( - "systemctl start ${backupService}.service", - ) - machine.succeed( - "stat ${backupFileBase}.in-progress.sql.gz", - "zcat ${backupFileBase}.prev.sql.gz | grep 'ok'", - ) - - - with subtest("Initdb works"): - machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2") - - machine.log(machine.execute("systemd-analyze security postgresql.service | grep -v ✓")[1]) - - machine.shutdown() - ''; - - }; - - mk-ensure-clauses-test = postgresql-package: makeTest { - name = "postgresql-clauses-${postgresql-package.name}"; - meta = with pkgs.lib.maintainers; { - maintainers = [ zagy ]; - }; - nodes.machine = {...}: - { - services.postgresql = { - enable = true; - package = postgresql-package; - ensureUsers = [ - { - name = "all-clauses"; - ensureClauses = { - superuser = true; - createdb = true; - createrole = true; - "inherit" = true; - login = true; - replication = true; - bypassrls = true; - }; - } - { - name = "default-clauses"; - } - ]; - }; - }; + machine.start() + machine.wait_for_unit("postgresql") + + with subtest("Postgresql is available just after unit start"): + machine.succeed( + "cat ${test-sql} | sudo -u postgres psql" + ) - testScript = let - getClausesQuery = user: pkgs.lib.concatStringsSep " " - [ - "SELECT row_to_json(row)" - "FROM (" - "SELECT" - "rolsuper," - "rolinherit," - "rolcreaterole," - "rolcreatedb," - "rolcanlogin," - "rolreplication," - "rolbypassrls" - "FROM pg_roles" - "WHERE rolname = '${user}'" - ") row;" - ]; - in '' - import json - machine.start() - machine.wait_for_unit("postgresql") - - with subtest("All user permissions are set according to the ensureClauses attr"): - clauses = json.loads( + with subtest("Postgresql survives restart (bug #1735)"): + machine.shutdown() + import time + time.sleep(2) + machine.start() + machine.wait_for_unit("postgresql") + + machine.fail(check_count("SELECT * FROM sth;", 3)) + machine.succeed(check_count("SELECT * FROM sth;", 5)) + machine.fail(check_count("SELECT * FROM sth;", 4)) + machine.succeed(check_count("SELECT xpath('/test/text()', doc) FROM xmltest;", 1)) + + with subtest("Backup service works"): + machine.succeed( + "systemctl start ${backupService}.service", + "zcat ${backupFileBase}.sql.gz | grep 'ok'", + "ls -hal /var/backup/postgresql/ >/dev/console", + "stat -c '%a' ${backupFileBase}.sql.gz | grep 600", + ) + with subtest("Backup service removes prev files"): machine.succeed( - "sudo -u postgres psql -tc \"${getClausesQuery "all-clauses"}\"" + # Create dummy prev files. + "touch ${backupFileBase}.prev.sql{,.gz,.zstd}", + "chown postgres:postgres ${backupFileBase}.prev.sql{,.gz,.zstd}", + + # Run backup. + "systemctl start ${backupService}.service", + "ls -hal /var/backup/postgresql/ >/dev/console", + + # Since nothing has changed in the database, the cur and prev files + # should match. + "zcat ${backupFileBase}.sql.gz | grep 'ok'", + "cmp ${backupFileBase}.sql.gz ${backupFileBase}.prev.sql.gz", + + # The prev files with unused suffix should be removed. + "[ ! -f '${backupFileBase}.prev.sql' ]", + "[ ! -f '${backupFileBase}.prev.sql.zstd' ]", + + # Both cur and prev file should only be accessible by the postgres user. + "stat -c '%a' ${backupFileBase}.sql.gz | grep 600", + "stat -c '%a' '${backupFileBase}.prev.sql.gz' | grep 600", + ) + with subtest("Backup service fails gracefully"): + # Sabotage the backup process + machine.succeed("rm /run/postgresql/.s.PGSQL.5432") + machine.fail( + "systemctl start ${backupService}.service", ) - ) - print(clauses) - assert clauses['rolsuper'], 'expected user with clauses to have superuser clause' - assert clauses['rolinherit'], 'expected user with clauses to have inherit clause' - assert clauses['rolcreaterole'], 'expected user with clauses to have create role clause' - assert clauses['rolcreatedb'], 'expected user with clauses to have create db clause' - assert clauses['rolcanlogin'], 'expected user with clauses to have login clause' - assert clauses['rolreplication'], 'expected user with clauses to have replication clause' - assert clauses['rolbypassrls'], 'expected user with clauses to have bypassrls clause' - - with subtest("All user permissions default when ensureClauses is not provided"): - clauses = json.loads( machine.succeed( - "sudo -u postgres psql -tc \"${getClausesQuery "default-clauses"}\"" + "ls -hal /var/backup/postgresql/ >/dev/console", + "zcat ${backupFileBase}.prev.sql.gz | grep 'ok'", + "stat ${backupFileBase}.in-progress.sql.gz", + ) + # In a previous version, the second run would overwrite prev.sql.gz, + # so we test a second run as well. + machine.fail( + "systemctl start ${backupService}.service", + ) + machine.succeed( + "stat ${backupFileBase}.in-progress.sql.gz", + "zcat ${backupFileBase}.prev.sql.gz | grep 'ok'", + ) + + + with subtest("Initdb works"): + machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2") + + machine.log(machine.execute("systemd-analyze security postgresql.service | grep -v ✓")[1]) + + machine.shutdown() + ''; + }; + + makeEnsureTestFor = package: + makeTest { + name = "postgresql-clauses-${package.name}"; + meta = with lib.maintainers; { + maintainers = [ zagy ]; + }; + + nodes.machine = {...}: + { + services.postgresql = { + inherit package; + enable = true; + ensureUsers = [ + { + name = "all-clauses"; + ensureClauses = { + superuser = true; + createdb = true; + createrole = true; + "inherit" = true; + login = true; + replication = true; + bypassrls = true; + }; + } + { + name = "default-clauses"; + } + ]; + }; + }; + + testScript = let + getClausesQuery = user: lib.concatStringsSep " " + [ + "SELECT row_to_json(row)" + "FROM (" + "SELECT" + "rolsuper," + "rolinherit," + "rolcreaterole," + "rolcreatedb," + "rolcanlogin," + "rolreplication," + "rolbypassrls" + "FROM pg_roles" + "WHERE rolname = '${user}'" + ") row;" + ]; + in '' + import json + machine.start() + machine.wait_for_unit("postgresql") + + with subtest("All user permissions are set according to the ensureClauses attr"): + clauses = json.loads( + machine.succeed( + "sudo -u postgres psql -tc \"${getClausesQuery "all-clauses"}\"" + ) ) - ) - assert not clauses['rolsuper'], 'expected user with no clauses set to have default superuser clause' - assert clauses['rolinherit'], 'expected user with no clauses set to have default inherit clause' - assert not clauses['rolcreaterole'], 'expected user with no clauses set to have default create role clause' - assert not clauses['rolcreatedb'], 'expected user with no clauses set to have default create db clause' - assert clauses['rolcanlogin'], 'expected user with no clauses set to have default login clause' - assert not clauses['rolreplication'], 'expected user with no clauses set to have default replication clause' - assert not clauses['rolbypassrls'], 'expected user with no clauses set to have default bypassrls clause' - - machine.shutdown() - ''; - }; + print(clauses) + assert clauses['rolsuper'], 'expected user with clauses to have superuser clause' + assert clauses['rolinherit'], 'expected user with clauses to have inherit clause' + assert clauses['rolcreaterole'], 'expected user with clauses to have create role clause' + assert clauses['rolcreatedb'], 'expected user with clauses to have create db clause' + assert clauses['rolcanlogin'], 'expected user with clauses to have login clause' + assert clauses['rolreplication'], 'expected user with clauses to have replication clause' + assert clauses['rolbypassrls'], 'expected user with clauses to have bypassrls clause' + + with subtest("All user permissions default when ensureClauses is not provided"): + clauses = json.loads( + machine.succeed( + "sudo -u postgres psql -tc \"${getClausesQuery "default-clauses"}\"" + ) + ) + assert not clauses['rolsuper'], 'expected user with no clauses set to have default superuser clause' + assert clauses['rolinherit'], 'expected user with no clauses set to have default inherit clause' + assert not clauses['rolcreaterole'], 'expected user with no clauses set to have default create role clause' + assert not clauses['rolcreatedb'], 'expected user with no clauses set to have default create db clause' + assert clauses['rolcanlogin'], 'expected user with no clauses set to have default login clause' + assert not clauses['rolreplication'], 'expected user with no clauses set to have default replication clause' + assert not clauses['rolbypassrls'], 'expected user with no clauses set to have default bypassrls clause' + + machine.shutdown() + ''; + }; in -recurseIntoAttrs ( - concatMapAttrs (n: p: { ${n} = testsForPackage p; }) pkgs.postgresqlVersions +lib.recurseIntoAttrs ( + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) pkgs.postgresqlVersions // { - passthru.override = p: testsForPackage p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/timescaledb.nix b/nixos/tests/postgresql/timescaledb.nix index 7f37e79bf0946..a01f890a12c6c 100644 --- a/nixos/tests/postgresql/timescaledb.nix +++ b/nixos/tests/postgresql/timescaledb.nix @@ -2,9 +2,9 @@ , makeTest }: -with pkgs.lib; - let + inherit (pkgs) lib; + test-sql = pkgs.writeText "postgresql-test" '' CREATE EXTENSION timescaledb; CREATE EXTENSION timescaledb_toolkit; @@ -38,55 +38,55 @@ let SELECT * FROM sth; ''; - makeTimescaleDbTest = postgresqlPackage: makeTest { - name = "timescaledb-${postgresqlPackage.name}"; - meta = with pkgs.lib.maintainers; { - maintainers = [ typetetris ]; - }; - - nodes.machine = { ... }: - { - services.postgresql = { - enable = true; - package = postgresqlPackage; - extraPlugins = ps: with ps; [ - timescaledb - timescaledb_toolkit - ]; - settings = { shared_preload_libraries = "timescaledb, timescaledb_toolkit"; }; - }; + makeTestFor = package: + makeTest { + name = "timescaledb-${package.name}"; + meta = with lib.maintainers; { + maintainers = [ typetetris ]; }; - testScript = '' - def check_count(statement, lines): - return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( - statement, lines - ) + nodes.machine = { ... }: + { + services.postgresql = { + inherit package; + enable = true; + extraPlugins = ps: with ps; [ + timescaledb + timescaledb_toolkit + ]; + settings = { shared_preload_libraries = "timescaledb, timescaledb_toolkit"; }; + }; + }; + testScript = '' + def check_count(statement, lines): + return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( + statement, lines + ) - machine.start() - machine.wait_for_unit("postgresql") - with subtest("Postgresql with extensions timescaledb and timescaledb_toolkit is available just after unit start"): - machine.succeed( - "sudo -u postgres psql -f ${test-sql}" - ) + machine.start() + machine.wait_for_unit("postgresql") - machine.fail(check_count("SELECT * FROM sth;", 3)) - machine.succeed(check_count("SELECT * FROM sth;", 5)) - machine.fail(check_count("SELECT * FROM sth;", 4)) + with subtest("Postgresql with extensions timescaledb and timescaledb_toolkit is available just after unit start"): + machine.succeed( + "sudo -u postgres psql -f ${test-sql}" + ) - machine.shutdown() - ''; + machine.fail(check_count("SELECT * FROM sth;", 3)) + machine.succeed(check_count("SELECT * FROM sth;", 5)) + machine.fail(check_count("SELECT * FROM sth;", 4)) - }; + machine.shutdown() + ''; + }; in # Not run by default, because this requires allowUnfree. # To run these tests: # NIXPKGS_ALLOW_UNFREE=1 nix-build -A nixosTests.postgresql.timescaledb -dontRecurseIntoAttrs ( - pkgs.lib.concatMapAttrs (n: p: { ${n} = makeTimescaleDbTest p; }) (filterAttrs (n: p: !p.pkgs.timescaledb.meta.broken) pkgs.postgresqlVersions) +lib.dontRecurseIntoAttrs ( + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.timescaledb.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makeTimescaleDbTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/tsja.nix b/nixos/tests/postgresql/tsja.nix index dedda35540ace..8d78093136df7 100644 --- a/nixos/tests/postgresql/tsja.nix +++ b/nixos/tests/postgresql/tsja.nix @@ -3,27 +3,25 @@ }: let - makeTsjaTest = postgresqlPackage: + inherit (pkgs) lib; + + makeTestFor = package: makeTest { - name = "tsja-${postgresqlPackage.name}"; + name = "tsja-${package.name}"; meta = { maintainers = with lib.maintainers; [ chayleaf ]; }; - nodes = { - master = - { config, ... }: - - { - services.postgresql = { - enable = true; - package = postgresqlPackage; - extraPlugins = ps: with ps; [ - tsja - ]; - }; + nodes.master = { ... }: + { + services.postgresql = { + inherit package; + enable = true; + extraPlugins = ps: with ps; [ + tsja + ]; }; - }; + }; testScript = '' start_all() @@ -38,9 +36,9 @@ let ''; }; in -pkgs.lib.recurseIntoAttrs ( - pkgs.lib.concatMapAttrs (n: p: { ${n} = makeTsjaTest p; }) pkgs.postgresqlVersions +lib.recurseIntoAttrs ( + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.tsja.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makeTsjaTest p; + passthru.override = p: makeTestFor p; } ) diff --git a/nixos/tests/postgresql/wal2json.nix b/nixos/tests/postgresql/wal2json.nix index 782fc5c94f66b..0333369722f0c 100644 --- a/nixos/tests/postgresql/wal2json.nix +++ b/nixos/tests/postgresql/wal2json.nix @@ -5,17 +5,16 @@ let inherit (pkgs) lib; - makePostgresqlWal2jsonTest = - postgresqlPackage: + makeTestFor = package: makeTest { - name = "wal2json-${postgresqlPackage.name}"; + name = "wal2json-${package.name}"; meta.maintainers = with pkgs.lib.maintainers; [ euank ]; nodes.machine = { services.postgresql = { - package = postgresqlPackage; + inherit package; enable = true; - extraPlugins = with postgresqlPackage.pkgs; [ wal2json ]; + extraPlugins = with package.pkgs; [ wal2json ]; settings = { wal_level = "logical"; max_replication_slots = "10"; @@ -40,11 +39,10 @@ let ) ''; }; - in lib.recurseIntoAttrs ( - lib.concatMapAttrs (n: p: { ${n} = makePostgresqlWal2jsonTest p; }) pkgs.postgresqlVersions + lib.concatMapAttrs (n: p: { ${n} = makeTestFor p; }) (lib.filterAttrs (_: p: !p.pkgs.wal2json.meta.broken) pkgs.postgresqlVersions) // { - passthru.override = p: makePostgresqlWal2jsonTest p; + passthru.override = p: makeTestFor p; } )