diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 41b2128e2bb4..50c27ec6da79 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -1288,7 +1288,7 @@ in
{ };
postfix-tlspol = runTest ./postfix-tlspol.nix;
postgres-websockets = runTest ./postgres-websockets.nix;
- postgresql = handleTest ./postgresql { };
+ postgresql = import ./postgresql { inherit runTest pkgs; };
postgrest = runTest ./postgrest.nix;
power-profiles-daemon = runTest ./power-profiles-daemon.nix;
powerdns = runTest ./powerdns.nix;
diff --git a/nixos/tests/postgresql/anonymizer.nix b/nixos/tests/postgresql/anonymizer.nix
index a5853e5ed533..4b37a4f8be5d 100644
--- a/nixos/tests/postgresql/anonymizer.nix
+++ b/nixos/tests/postgresql/anonymizer.nix
@@ -1,114 +1,115 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
- makeTest {
- name = "postgresql_anonymizer-${package.name}";
- meta.maintainers = [
- lib.maintainers.leona
- lib.maintainers.osnyx
- ];
+ runTest (
+ { lib, pkgs, ... }:
+ {
+ name = "postgresql_anonymizer-${package.name}";
+ meta.maintainers = [
+ lib.maintainers.leona
+ lib.maintainers.osnyx
+ ];
- nodes.machine =
- { pkgs, ... }:
- {
- environment.systemPackages = [ (pkgs.pg-dump-anon.override { postgresql = package; }) ];
- services.postgresql = {
- inherit package;
- enable = true;
- extensions = ps: [ ps.anonymizer ];
- settings.shared_preload_libraries = [ "anon" ];
+ nodes.machine =
+ { pkgs, ... }:
+ {
+ environment.systemPackages = [ (pkgs.pg-dump-anon.override { postgresql = package; }) ];
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ extensions = ps: [ ps.anonymizer ];
+ settings.shared_preload_libraries = [ "anon" ];
+ };
};
- };
- testScript = ''
- start_all()
- machine.wait_for_unit("multi-user.target")
- machine.wait_for_unit("postgresql.target")
+ testScript = ''
+ start_all()
+ machine.wait_for_unit("multi-user.target")
+ machine.wait_for_unit("postgresql.target")
- with subtest("Setup"):
- machine.succeed("sudo -u postgres psql --command 'create database demo'")
- machine.succeed(
- "sudo -u postgres psql -d demo -f ${pkgs.writeText "init.sql" ''
- create extension anon cascade;
- select anon.init();
- create table player(id serial, name text, points int);
- insert into player(id,name,points) values (1,'Foo', 23);
- insert into player(id,name,points) values (2,'Bar',42);
- security label for anon on column player.name is 'MASKED WITH FUNCTION anon.fake_last_name()';
- security label for anon on column player.points is 'MASKED WITH VALUE NULL';
- ''}"
- )
+ with subtest("Setup"):
+ machine.succeed("sudo -u postgres psql --command 'create database demo'")
+ machine.succeed(
+ "sudo -u postgres psql -d demo -f ${pkgs.writeText "init.sql" ''
+ create extension anon cascade;
+ select anon.init();
+ create table player(id serial, name text, points int);
+ insert into player(id,name,points) values (1,'Foo', 23);
+ insert into player(id,name,points) values (2,'Bar',42);
+ security label for anon on column player.name is 'MASKED WITH FUNCTION anon.fake_last_name()';
+ security label for anon on column player.points is 'MASKED WITH VALUE NULL';
+ ''}"
+ )
- def get_player_table_contents():
- return [
- x.split(',') for x in machine.succeed("sudo -u postgres psql -d demo --csv --command 'select * from player'").splitlines()[1:]
- ]
+ def get_player_table_contents():
+ return [
+ x.split(',') for x in machine.succeed("sudo -u postgres psql -d demo --csv --command 'select * from player'").splitlines()[1:]
+ ]
- def check_anonymized_row(row, id, original_name):
- t.assertEqual(row[0], id)
- t.assertNotEqual(row[1], original_name)
- t.assertFalse(bool(row[2]))
+ def check_anonymized_row(row, id, original_name):
+ t.assertEqual(row[0], id)
+ t.assertNotEqual(row[1], original_name)
+ t.assertFalse(bool(row[2]))
- def find_xsv_in_dump(dump, sep=','):
- """
- Expecting to find a CSV (for pg_dump_anon) or TSV (for pg_dump) structure, looking like
+ def find_xsv_in_dump(dump, sep=','):
+ """
+ Expecting to find a CSV (for pg_dump_anon) or TSV (for pg_dump) structure, looking like
- COPY public.player ...
- 1,Shields,
- 2,Salazar,
- \\.
+ COPY public.player ...
+ 1,Shields,
+ 2,Salazar,
+ \\.
- in the given dump (the commas are tabs in case of pg_dump).
- Extract the CSV lines and split by `sep`.
- """
+ in the given dump (the commas are tabs in case of pg_dump).
+ Extract the CSV lines and split by `sep`.
+ """
- try:
- from itertools import dropwhile, takewhile
- return [x.split(sep) for x in list(takewhile(
- lambda x: x != "\\.",
- dropwhile(
- lambda x: not x.startswith("COPY public.player"),
- dump.splitlines()
- )
- ))[1:]]
- except:
- print(f"Dump to process: {dump}")
- raise
+ try:
+ from itertools import dropwhile, takewhile
+ return [x.split(sep) for x in list(takewhile(
+ lambda x: x != "\\.",
+ dropwhile(
+ lambda x: not x.startswith("COPY public.player"),
+ dump.splitlines()
+ )
+ ))[1:]]
+ except:
+ print(f"Dump to process: {dump}")
+ raise
- def check_original_data(output):
- t.assertEqual(output[0], ["1", "Foo", "23"])
- t.assertEqual(output[1], ["2", "Bar", "42"])
+ def check_original_data(output):
+ t.assertEqual(output[0], ["1", "Foo", "23"])
+ t.assertEqual(output[1], ["2", "Bar", "42"])
- def check_anonymized_rows(output):
- check_anonymized_row(output[0], '1', 'Foo')
- check_anonymized_row(output[1], '2', 'Bar')
+ def check_anonymized_rows(output):
+ check_anonymized_row(output[0], '1', 'Foo')
+ check_anonymized_row(output[1], '2', 'Bar')
- with subtest("Check initial state"):
- check_original_data(get_player_table_contents())
+ with subtest("Check initial state"):
+ check_original_data(get_player_table_contents())
- with subtest("Anonymous dumps"):
- check_original_data(find_xsv_in_dump(
- machine.succeed("sudo -u postgres pg_dump demo"),
- sep='\t'
- ))
- check_anonymized_rows(find_xsv_in_dump(
- machine.succeed("sudo -u postgres pg_dump_anon -U postgres -h /run/postgresql -d demo"),
- sep=','
- ))
+ with subtest("Anonymous dumps"):
+ check_original_data(find_xsv_in_dump(
+ machine.succeed("sudo -u postgres pg_dump demo"),
+ sep='\t'
+ ))
+ check_anonymized_rows(find_xsv_in_dump(
+ machine.succeed("sudo -u postgres pg_dump_anon -U postgres -h /run/postgresql -d demo"),
+ sep=','
+ ))
- with subtest("Anonymize"):
- machine.succeed("sudo -u postgres psql -d demo --command 'select anon.anonymize_database();'")
- check_anonymized_rows(get_player_table_contents())
- '';
- };
+ with subtest("Anonymize"):
+ machine.succeed("sudo -u postgres psql -d demo --command 'select anon.anonymize_database();'")
+ check_anonymized_rows(get_player_table_contents())
+ '';
+ }
+ );
in
genTests {
inherit makeTestFor;
diff --git a/nixos/tests/postgresql/default.nix b/nixos/tests/postgresql/default.nix
index a8b03a29280b..a5d363a709ee 100644
--- a/nixos/tests/postgresql/default.nix
+++ b/nixos/tests/postgresql/default.nix
@@ -1,11 +1,8 @@
{
- system ? builtins.currentSystem,
- config ? { },
- pkgs ? import ../../.. { inherit system config; },
+ runTest,
+ pkgs,
}:
-with import ../../lib/testing-python.nix { inherit system pkgs; };
-
let
inherit (pkgs.lib)
recurseIntoAttrs
@@ -25,7 +22,12 @@ let
}
);
- importWithArgs = path: import path { inherit pkgs makeTest genTests; };
+ importWithArgs =
+ path:
+ import path {
+ inherit runTest genTests;
+ inherit (pkgs) lib;
+ };
in
{
# postgresql
diff --git a/nixos/tests/postgresql/pgjwt.nix b/nixos/tests/postgresql/pgjwt.nix
index 6fc43d771b92..b16efeb97ad6 100644
--- a/nixos/tests/postgresql/pgjwt.nix
+++ b/nixos/tests/postgresql/pgjwt.nix
@@ -1,51 +1,52 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
- makeTest {
- name = "pgjwt-${package.name}";
- meta = with lib.maintainers; {
- maintainers = [
- spinus
- ];
- };
-
- nodes.master =
- { ... }:
- {
- services.postgresql = {
- inherit package;
- enable = true;
- extensions =
- ps: with ps; [
- pgjwt
- pgtap
- ];
- };
+ runTest (
+ { lib, pkgs, ... }:
+ {
+ name = "pgjwt-${package.name}";
+ meta = with lib.maintainers; {
+ maintainers = [
+ spinus
+ ];
};
- testScript =
- { nodes, ... }:
- let
- sqlSU = "${nodes.master.services.postgresql.superUser}";
- pgProve = "${pkgs.perlPackages.TAPParserSourceHandlerpgTAP}";
- inherit (nodes.master.services.postgresql.package.pkgs) pgjwt;
- in
- ''
- start_all()
- master.wait_for_unit("postgresql.target")
- master.succeed(
- "${pkgs.sudo}/bin/sudo -u ${sqlSU} ${pgProve}/bin/pg_prove -d postgres -v -f ${pgjwt.src}/test.sql"
- )
- '';
- };
+ nodes.master =
+ { ... }:
+ {
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ extensions =
+ ps: with ps; [
+ pgjwt
+ pgtap
+ ];
+ };
+ };
+
+ testScript =
+ { nodes, ... }:
+ let
+ sqlSU = "${nodes.master.services.postgresql.superUser}";
+ pgProve = "${pkgs.perlPackages.TAPParserSourceHandlerpgTAP}";
+ inherit (nodes.master.services.postgresql.package.pkgs) pgjwt;
+ in
+ ''
+ start_all()
+ master.wait_for_unit("postgresql.target")
+ master.succeed(
+ "${pkgs.sudo}/bin/sudo -u ${sqlSU} ${pgProve}/bin/pg_prove -d postgres -v -f ${pgjwt.src}/test.sql"
+ )
+ '';
+ }
+ );
in
genTests {
inherit makeTestFor;
diff --git a/nixos/tests/postgresql/postgresql-jit.nix b/nixos/tests/postgresql/postgresql-jit.nix
index 347534c8bd85..de62b355d62b 100644
--- a/nixos/tests/postgresql/postgresql-jit.nix
+++ b/nixos/tests/postgresql/postgresql-jit.nix
@@ -1,53 +1,54 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
- makeTest {
- name = "postgresql-jit-${package.name}";
- meta.maintainers = with lib.maintainers; [ ma27 ];
+ runTest (
+ { lib, pkgs, ... }:
+ {
+ 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);
- '';
+ 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.target")
+ testScript = ''
+ machine.start()
+ machine.wait_for_unit("postgresql.target")
- with subtest("JIT is enabled"):
- machine.succeed("sudo -u postgres psql <<<'show jit;' | grep 'on'")
+ with subtest("JIT is enabled"):
+ machine.succeed("sudo -u postgres psql <<<'show jit;' | grep 'on'")
- 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"
- )
- t.assertIn("JIT:", output)
- t.assertIn("jit result = 15", output)
+ 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"
+ )
+ t.assertIn("JIT:", output)
+ t.assertIn("jit result = 15", output)
- machine.shutdown()
- '';
- };
+ machine.shutdown()
+ '';
+ }
+ );
in
genTests {
inherit makeTestFor;
diff --git a/nixos/tests/postgresql/postgresql-replication.nix b/nixos/tests/postgresql/postgresql-replication.nix
index b828c2d7bb49..6df0becdf115 100644
--- a/nixos/tests/postgresql/postgresql-replication.nix
+++ b/nixos/tests/postgresql/postgresql-replication.nix
@@ -1,125 +1,127 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
makeTestFor =
package:
- makeTest {
- name = "postgresql-replication-${package.name}";
- meta.maintainers = with lib.maintainers; [ bouk ];
+ runTest (
+ { lib, ... }:
+ {
+ name = "postgresql-replication-${package.name}";
+ meta.maintainers = with lib.maintainers; [ bouk ];
- nodes = {
- primary =
- { ... }:
- {
- services.postgresql = {
- inherit package;
- enable = true;
- enableTCPIP = true;
- settings = {
- wal_level = "replica";
- max_wal_senders = 10;
- max_replication_slots = 10;
+ nodes = {
+ primary =
+ { ... }:
+ {
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ enableTCPIP = true;
+ settings = {
+ wal_level = "replica";
+ max_wal_senders = 10;
+ max_replication_slots = 10;
+ };
+ authentication = ''
+ local replication postgres peer
+ host replication replication all trust
+ '';
+ ensureUsers = [
+ {
+ name = "replication";
+ ensureClauses.replication = true;
+ }
+ ];
};
- authentication = ''
- local replication postgres peer
- host replication replication all trust
- '';
- ensureUsers = [
- {
- name = "replication";
- ensureClauses.replication = true;
- }
- ];
+ networking.firewall.allowedTCPPorts = [ 5432 ];
};
- networking.firewall.allowedTCPPorts = [ 5432 ];
- };
- replica =
- { nodes, ... }:
- {
- services.postgresql = {
- inherit package;
- enable = true;
- settings = {
- hot_standby = "on";
- primary_conninfo = "host=${nodes.primary.networking.primaryIPAddress} user=replication";
- primary_slot_name = "replica_slot";
+ replica =
+ { nodes, ... }:
+ {
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ settings = {
+ hot_standby = "on";
+ primary_conninfo = "host=${nodes.primary.networking.primaryIPAddress} user=replication";
+ primary_slot_name = "replica_slot";
+ };
};
};
- };
- };
+ };
- testScript = ''
- start_all()
- primary.wait_for_unit("postgresql.target")
+ testScript = ''
+ start_all()
+ primary.wait_for_unit("postgresql.target")
- primary.succeed(
- "sudo -u postgres psql -c \"SELECT * FROM pg_create_physical_replication_slot('replica_slot');\""
- )
+ primary.succeed(
+ "sudo -u postgres psql -c \"SELECT * FROM pg_create_physical_replication_slot('replica_slot');\""
+ )
- primary.succeed(
- "sudo -u postgres pg_basebackup -D /tmp/basebackup -S replica_slot -X stream"
- )
- primary.succeed("tar -C /tmp -cf /tmp/shared/basebackup.tar basebackup")
+ primary.succeed(
+ "sudo -u postgres pg_basebackup -D /tmp/basebackup -S replica_slot -X stream"
+ )
+ primary.succeed("tar -C /tmp -cf /tmp/shared/basebackup.tar basebackup")
- replica.wait_for_unit("postgresql.target")
- replica.succeed("systemctl stop postgresql")
+ replica.wait_for_unit("postgresql.target")
+ replica.succeed("systemctl stop postgresql")
- replica_data_dir = "/var/lib/postgresql/${package.psqlSchema}"
- replica.succeed(f"rm -rf {replica_data_dir}")
- replica.succeed(f"mkdir -p {replica_data_dir}")
- replica.succeed(f"tar -C {replica_data_dir} --strip-components=1 -xf /tmp/shared/basebackup.tar")
- replica.succeed(f"touch {replica_data_dir}/standby.signal")
- replica.succeed(f"chown -R postgres:postgres {replica_data_dir}")
- replica.succeed(f"chmod 700 {replica_data_dir}")
+ replica_data_dir = "/var/lib/postgresql/${package.psqlSchema}"
+ replica.succeed(f"rm -rf {replica_data_dir}")
+ replica.succeed(f"mkdir -p {replica_data_dir}")
+ replica.succeed(f"tar -C {replica_data_dir} --strip-components=1 -xf /tmp/shared/basebackup.tar")
+ replica.succeed(f"touch {replica_data_dir}/standby.signal")
+ replica.succeed(f"chown -R postgres:postgres {replica_data_dir}")
+ replica.succeed(f"chmod 700 {replica_data_dir}")
- replica.succeed("systemctl start postgresql")
- replica.wait_for_unit("postgresql.target")
+ replica.succeed("systemctl start postgresql")
+ replica.wait_for_unit("postgresql.target")
- replica.wait_until_succeeds(
- "sudo -u postgres psql -tAc 'SELECT pg_is_in_recovery();' | grep t"
- )
+ replica.wait_until_succeeds(
+ "sudo -u postgres psql -tAc 'SELECT pg_is_in_recovery();' | grep t"
+ )
- primary.succeed(
- "sudo -u postgres psql -c 'CREATE TABLE test_replication (id serial PRIMARY KEY, data text);'"
- )
- primary.succeed(
- "sudo -u postgres psql -c \"INSERT INTO test_replication (data) VALUES ('hello');\""
- )
+ primary.succeed(
+ "sudo -u postgres psql -c 'CREATE TABLE test_replication (id serial PRIMARY KEY, data text);'"
+ )
+ primary.succeed(
+ "sudo -u postgres psql -c \"INSERT INTO test_replication (data) VALUES ('hello');\""
+ )
- replica.wait_until_succeeds(
- "sudo -u postgres psql -c 'SELECT * FROM test_replication;' | grep hello",
- timeout=30
- )
+ replica.wait_until_succeeds(
+ "sudo -u postgres psql -c 'SELECT * FROM test_replication;' | grep hello",
+ timeout=30
+ )
- with subtest("Verify replica is in recovery mode"):
- result = replica.succeed("sudo -u postgres psql -tAc 'SELECT pg_is_in_recovery();'")
- t.assertEqual(result.strip(), "t")
+ with subtest("Verify replica is in recovery mode"):
+ result = replica.succeed("sudo -u postgres psql -tAc 'SELECT pg_is_in_recovery();'")
+ t.assertEqual(result.strip(), "t")
- with subtest("Verify replication slot is active"):
- result = primary.succeed(
- "sudo -u postgres psql -tAc \"SELECT active FROM pg_replication_slots WHERE slot_name = 'replica_slot';\""
- )
- t.assertEqual(result.strip(), "t")
+ with subtest("Verify replication slot is active"):
+ result = primary.succeed(
+ "sudo -u postgres psql -tAc \"SELECT active FROM pg_replication_slots WHERE slot_name = 'replica_slot';\""
+ )
+ t.assertEqual(result.strip(), "t")
- with subtest("Insert more data and verify replication"):
- primary.succeed(
- "sudo -u postgres psql -c \"INSERT INTO test_replication (data) VALUES ('world');\""
- )
- replica.wait_until_succeeds(
- "sudo -u postgres psql -c 'SELECT * FROM test_replication;' | grep world",
- timeout=30
- )
+ with subtest("Insert more data and verify replication"):
+ primary.succeed(
+ "sudo -u postgres psql -c \"INSERT INTO test_replication (data) VALUES ('world');\""
+ )
+ replica.wait_until_succeeds(
+ "sudo -u postgres psql -c 'SELECT * FROM test_replication;' | grep world",
+ timeout=30
+ )
- primary.shutdown()
- replica.shutdown()
- '';
- };
+ primary.shutdown()
+ replica.shutdown()
+ '';
+ }
+ );
in
genTests { inherit makeTestFor; }
diff --git a/nixos/tests/postgresql/postgresql-tls-client-cert.nix b/nixos/tests/postgresql/postgresql-tls-client-cert.nix
index acb531780f76..19af512e28ff 100644
--- a/nixos/tests/postgresql/postgresql-tls-client-cert.nix
+++ b/nixos/tests/postgresql/postgresql-tls-client-cert.nix
@@ -1,145 +1,147 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
- 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";
-
makeTestFor =
package:
- makeTest {
- name = "postgresql-tls-client-cert-${package.name}";
- meta.maintainers = with lib.maintainers; [ erictapen ];
+ runTest (
+ { lib, pkgs, ... }:
+ 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";
+ in
+ {
+ name = "postgresql-tls-client-cert-${package.name}";
+ meta.maintainers = with lib.maintainers; [ erictapen ];
- nodes.server =
- { ... }:
- {
- systemd.services.create-keys = {
- wantedBy = [ "postgresql.target" ];
+ nodes.server =
+ { ... }:
+ {
+ systemd.services.create-keys = {
+ wantedBy = [ "postgresql.target" ];
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+
+ script = ''
+ mkdir -p '${serverKeyPath}'
+ cp '${serverKey}' '${serverKeyPath}/server.key'
+ chown postgres:postgres '${serverKeyPath}/server.key'
+ chmod 600 '${serverKeyPath}/server.key'
+ '';
};
-
- script = ''
- mkdir -p '${serverKeyPath}'
- cp '${serverKey}' '${serverKeyPath}/server.key'
- chown postgres:postgres '${serverKeyPath}/server.key'
- chmod 600 '${serverKeyPath}/server.key'
- '';
- };
- services.postgresql = {
- inherit package;
- enable = true;
- enableTCPIP = true;
- ensureUsers = [
- {
- name = "test";
- ensureDBOwnership = true;
- }
- ];
- ensureDatabases = [ "test" ];
- settings = {
- ssl = "on";
- ssl_ca_file = toString caCert;
- ssl_cert_file = toString serverCert;
- ssl_key_file = "${serverKeyPath}/server.key";
- };
- authentication = ''
- hostssl test test ::/0 cert clientcert=verify-full
- '';
- };
- networking = {
- interfaces.eth1 = {
- ipv6.addresses = [
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ enableTCPIP = true;
+ ensureUsers = [
{
- address = "fc00::1";
- prefixLength = 120;
+ name = "test";
+ ensureDBOwnership = true;
}
];
+ ensureDatabases = [ "test" ];
+ settings = {
+ ssl = "on";
+ ssl_ca_file = toString caCert;
+ ssl_cert_file = toString serverCert;
+ ssl_key_file = "${serverKeyPath}/server.key";
+ };
+ authentication = ''
+ hostssl test test ::/0 cert clientcert=verify-full
+ '';
};
- firewall.allowedTCPPorts = [ 5432 ];
- };
- };
-
- nodes.client =
- { ... }:
- {
- systemd.services.create-keys = {
- wantedBy = [ "multi-user.target" ];
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- };
-
- script = ''
- mkdir -p '${clientKeyPath}'
- cp '${clientKey}' '${clientKeyPath}/client.key'
- chown root:root '${clientKeyPath}/client.key'
- chmod 600 '${clientKeyPath}/client.key'
- '';
- };
- environment = {
- variables = {
- PGHOST = "db.test.example";
- PGPORT = "5432";
- PGDATABASE = "test";
- PGUSER = "test";
- PGSSLMODE = "verify-full";
- PGSSLCERT = clientCert;
- PGSSLKEY = "${clientKeyPath}/client.key";
- PGSSLROOTCERT = caCert;
- };
- systemPackages = [ package ];
- };
- networking = {
- interfaces.eth1 = {
- ipv6.addresses = [
- {
- address = "fc00::2";
- prefixLength = 120;
- }
- ];
- };
- hosts = {
- "fc00::1" = [ "db.test.example" ];
+ networking = {
+ interfaces.eth1 = {
+ ipv6.addresses = [
+ {
+ address = "fc00::1";
+ prefixLength = 120;
+ }
+ ];
+ };
+ firewall.allowedTCPPorts = [ 5432 ];
};
};
- };
- testScript = ''
- server.wait_for_unit("multi-user.target")
- client.wait_for_unit("multi-user.target")
- client.succeed("psql -c \"SELECT 1;\"")
- '';
- };
+ nodes.client =
+ { ... }:
+ {
+ systemd.services.create-keys = {
+ wantedBy = [ "multi-user.target" ];
+
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+
+ script = ''
+ mkdir -p '${clientKeyPath}'
+ cp '${clientKey}' '${clientKeyPath}/client.key'
+ chown root:root '${clientKeyPath}/client.key'
+ chmod 600 '${clientKeyPath}/client.key'
+ '';
+ };
+ environment = {
+ variables = {
+ PGHOST = "db.test.example";
+ PGPORT = "5432";
+ PGDATABASE = "test";
+ PGUSER = "test";
+ PGSSLMODE = "verify-full";
+ PGSSLCERT = clientCert;
+ PGSSLKEY = "${clientKeyPath}/client.key";
+ PGSSLROOTCERT = caCert;
+ };
+ systemPackages = [ package ];
+ };
+ networking = {
+ interfaces.eth1 = {
+ ipv6.addresses = [
+ {
+ address = "fc00::2";
+ prefixLength = 120;
+ }
+ ];
+ };
+ hosts = {
+ "fc00::1" = [ "db.test.example" ];
+ };
+ };
+ };
+
+ testScript = ''
+ server.wait_for_unit("multi-user.target")
+ client.wait_for_unit("multi-user.target")
+ client.succeed("psql -c \"SELECT 1;\"")
+ '';
+ }
+ );
in
genTests { inherit makeTestFor; }
diff --git a/nixos/tests/postgresql/postgresql-wal-receiver.nix b/nixos/tests/postgresql/postgresql-wal-receiver.nix
index c233a582546c..f929596cf614 100644
--- a/nixos/tests/postgresql/postgresql-wal-receiver.nix
+++ b/nixos/tests/postgresql/postgresql-wal-receiver.nix
@@ -1,111 +1,112 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
- let
- 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-${package.name}";
- meta.maintainers = with lib.maintainers; [ euxane ];
+ runTest (
+ { lib, pkgs, ... }:
+ let
+ 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
+ {
+ name = "postgresql-wal-receiver-${package.name}";
+ meta.maintainers = with lib.maintainers; [ euxane ];
- nodes.machine =
- { ... }:
- {
- systemd.tmpfiles.rules = [
- "d /var/cache/wals 0750 postgres postgres - -"
- ];
+ nodes.machine =
+ { ... }:
+ {
+ systemd.tmpfiles.rules = [
+ "d /var/cache/wals 0750 postgres postgres - -"
+ ];
- services.postgresql = {
- inherit package;
- enable = true;
- settings = {
- max_replication_slots = 10;
- max_wal_senders = 10;
- recovery_end_command = "touch recovery.done";
- restore_command = "cp ${walBackupDir}/%f %p";
- wal_level = "archive"; # alias for replica on pg >= 9.6
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ settings = {
+ max_replication_slots = 10;
+ max_wal_senders = 10;
+ recovery_end_command = "touch recovery.done";
+ restore_command = "cp ${walBackupDir}/%f %p";
+ wal_level = "archive"; # alias for replica on pg >= 9.6
+ };
+ authentication = ''
+ host replication ${replicationUser} all trust
+ '';
+ initialScript = pkgs.writeText "init.sql" ''
+ create user ${replicationUser} replication;
+ select * from pg_create_physical_replication_slot('${replicationSlot}');
+ '';
};
- authentication = ''
- host replication ${replicationUser} all trust
- '';
- initialScript = pkgs.writeText "init.sql" ''
- create user ${replicationUser} replication;
- select * from pg_create_physical_replication_slot('${replicationSlot}');
- '';
+
+ services.postgresqlWalReceiver.receivers.main = {
+ postgresqlPackage = package;
+ connection = replicationConn;
+ slot = replicationSlot;
+ directory = walBackupDir;
+ };
+ # This is only to speedup test, it isn't time racing. Service is set to autorestart always,
+ # default 60sec is fine for real system, but is too much for a test
+ systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
+ systemd.services.postgresql.serviceConfig.ReadWritePaths = [ "/var/cache/wals" ];
};
- services.postgresqlWalReceiver.receivers.main = {
- postgresqlPackage = package;
- connection = replicationConn;
- slot = replicationSlot;
- directory = walBackupDir;
- };
- # This is only to speedup test, it isn't time racing. Service is set to autorestart always,
- # default 60sec is fine for real system, but is too much for a test
- systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
- systemd.services.postgresql.serviceConfig.ReadWritePaths = [ "/var/cache/wals" ];
- };
+ testScript = ''
+ # make an initial base backup
+ machine.wait_for_unit("postgresql.target")
+ machine.wait_for_unit("postgresql-wal-receiver-main")
+ # WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other
+ # required only for 9.4
+ machine.sleep(5)
+ machine.succeed(
+ "${package}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}"
+ )
- testScript = ''
- # make an initial base backup
- machine.wait_for_unit("postgresql.target")
- machine.wait_for_unit("postgresql-wal-receiver-main")
- # WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other
- # required only for 9.4
- machine.sleep(5)
- machine.succeed(
- "${package}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}"
- )
+ # create a dummy table with 100 records
+ machine.succeed(
+ "sudo -u postgres psql --command='create table dummy as select * from generate_series(1, 100) as val;'"
+ )
- # create a dummy table with 100 records
- machine.succeed(
- "sudo -u postgres psql --command='create table dummy as select * from generate_series(1, 100) as val;'"
- )
+ # stop postgres and destroy data
+ machine.systemctl("stop postgresql")
+ machine.systemctl("stop postgresql-wal-receiver-main")
+ machine.succeed("rm -r ${postgresqlDataDir}/{base,global,pg_*}")
- # stop postgres and destroy data
- machine.systemctl("stop postgresql")
- machine.systemctl("stop postgresql-wal-receiver-main")
- machine.succeed("rm -r ${postgresqlDataDir}/{base,global,pg_*}")
+ # restore the base backup
+ machine.succeed(
+ "cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}"
+ )
- # restore the base backup
- machine.succeed(
- "cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}"
- )
+ # prepare WAL and recovery
+ machine.succeed("chmod a+rX -R ${walBackupDir}")
+ machine.execute(
+ "for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done"
+ ) # make use of partial segments too
+ machine.succeed(
+ "cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*"
+ )
- # prepare WAL and recovery
- machine.succeed("chmod a+rX -R ${walBackupDir}")
- machine.execute(
- "for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done"
- ) # make use of partial segments too
- machine.succeed(
- "cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*"
- )
+ # replay WAL
+ machine.systemctl("start postgresql")
+ machine.wait_for_file("${postgresqlDataDir}/recovery.done")
+ machine.systemctl("restart postgresql")
+ machine.wait_for_unit("postgresql.target")
- # replay WAL
- machine.systemctl("start postgresql")
- machine.wait_for_file("${postgresqlDataDir}/recovery.done")
- machine.systemctl("restart postgresql")
- machine.wait_for_unit("postgresql.target")
-
- # check that our records have been restored
- machine.succeed(
- "test $(sudo -u postgres psql --pset='pager=off' --tuples-only --command='select count(distinct val) from dummy;') -eq 100"
- )
- '';
- };
+ # check that our records have been restored
+ machine.succeed(
+ "test $(sudo -u postgres psql --pset='pager=off' --tuples-only --command='select count(distinct val) from dummy;') -eq 100"
+ )
+ '';
+ }
+ );
in
genTests { inherit makeTestFor; }
diff --git a/nixos/tests/postgresql/postgresql.nix b/nixos/tests/postgresql/postgresql.nix
index 32a096346445..d832f5caa4e9 100644
--- a/nixos/tests/postgresql/postgresql.nix
+++ b/nixos/tests/postgresql/postgresql.nix
@@ -1,12 +1,11 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ lib,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
lib.recurseIntoAttrs {
@@ -15,263 +14,271 @@ let
postgresql-clauses = makeEnsureTestFor package;
};
- test-sql = pkgs.writeText "postgresql-test" ''
- CREATE EXTENSION pgcrypto; -- just to check if lib loading works
- CREATE TABLE sth (
- id int
- );
- INSERT INTO sth (id) VALUES (1);
- INSERT INTO sth (id) VALUES (1);
- INSERT INTO sth (id) VALUES (1);
- INSERT INTO sth (id) VALUES (1);
- INSERT INTO sth (id) VALUES (1);
- CREATE TABLE xmltest ( doc xml );
- INSERT INTO xmltest (doc) VALUES ('ok'); -- check if libxml2 enabled
-
- -- check if hardening gets relaxed
- CREATE EXTENSION plv8;
- -- try to trigger the V8 JIT, which requires MemoryDenyWriteExecute
- DO $$
- let xs = [];
- for (let i = 0, n = 400000; i < n; i++) {
- xs.push(Math.round(Math.random() * n))
- }
- console.log(xs.reduce((acc, x) => acc + x, 0));
- $$ LANGUAGE plv8;
- '';
-
makeTestForWithBackupAll =
package: backupAll:
- makeTest {
- name = "postgresql${lib.optionalString backupAll "-backup-all"}-${package.name}";
- meta = with lib.maintainers; {
- maintainers = [ zagy ];
- };
+ runTest (
+ { lib, pkgs, ... }:
+ let
+ test-sql = pkgs.writeText "postgresql-test" ''
+ CREATE EXTENSION pgcrypto; -- just to check if lib loading works
+ CREATE TABLE sth (
+ id int
+ );
+ INSERT INTO sth (id) VALUES (1);
+ INSERT INTO sth (id) VALUES (1);
+ INSERT INTO sth (id) VALUES (1);
+ INSERT INTO sth (id) VALUES (1);
+ INSERT INTO sth (id) VALUES (1);
+ CREATE TABLE xmltest ( doc xml );
+ INSERT INTO xmltest (doc) VALUES ('ok'); -- check if libxml2 enabled
- nodes.machine =
- { config, ... }:
- {
- services.postgresql = {
- inherit package;
- enable = true;
- identMap = ''
- postgres root postgres
- '';
- # TODO(@Ma27) split this off into its own VM test and move a few other
- # extension tests to use postgresqlTestExtension.
- extensions = ps: with ps; [ plv8 ];
- };
+ -- check if hardening gets relaxed
+ CREATE EXTENSION plv8;
+ -- try to trigger the V8 JIT, which requires MemoryDenyWriteExecute
+ DO $$
+ let xs = [];
+ for (let i = 0, n = 400000; i < n; i++) {
+ xs.push(Math.round(Math.random() * n))
+ }
+ console.log(xs.reduce((acc, x) => acc + x, 0));
+ $$ LANGUAGE plv8;
+ '';
- services.postgresqlBackup = {
- enable = true;
- databases = lib.optional (!backupAll) "postgres";
- pgdumpOptions = "--restrict-key=ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- pgdumpAllOptions = "--restrict-key=ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- };
+ in
+ {
+ name = "postgresql${lib.optionalString backupAll "-backup-all"}-${package.name}";
+ meta = with lib.maintainers; {
+ maintainers = [ zagy ];
};
- 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 $(psql -U postgres postgres -tAc "{}"|wc -l) -eq {}'.format(
- statement, lines
- )
+ nodes.machine =
+ { config, ... }:
+ {
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ identMap = ''
+ postgres root postgres
+ '';
+ # TODO(@Ma27) split this off into its own VM test and move a few other
+ # extension tests to use postgresqlTestExtension.
+ extensions = ps: with ps; [ plv8 ];
+ };
+
+ services.postgresqlBackup = {
+ enable = true;
+ databases = lib.optional (!backupAll) "postgres";
+ pgdumpOptions = "--restrict-key=ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ pgdumpAllOptions = "--restrict-key=ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ };
+ };
+
+ 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 $(psql -U postgres postgres -tAc "{}"|wc -l) -eq {}'.format(
+ statement, lines
+ )
- machine.start()
- machine.wait_for_unit("postgresql.target")
+ machine.start()
+ machine.wait_for_unit("postgresql.target")
- with subtest("Postgresql is available just after unit start"):
- machine.succeed(
- "cat ${test-sql} | sudo -u postgres psql"
- )
+ 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.target")
+ with subtest("Postgresql survives restart (bug #1735)"):
+ machine.shutdown()
+ import time
+ time.sleep(2)
+ machine.start()
+ machine.wait_for_unit("postgresql.target")
- 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))
+ 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("killing postgres process should trigger an automatic restart"):
- machine.succeed("systemctl kill -s KILL postgresql")
+ with subtest("killing postgres process should trigger an automatic restart"):
+ machine.succeed("systemctl kill -s KILL postgresql")
- machine.wait_until_succeeds("systemctl is-active postgresql.service")
- machine.wait_until_succeeds("systemctl is-active postgresql.target")
+ machine.wait_until_succeeds("systemctl is-active postgresql.service")
+ machine.wait_until_succeeds("systemctl is-active postgresql.target")
- 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}",
+ 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",
+ # 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",
+ # 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' ]",
+ # 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'",
- )
+ # 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")
+ 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.log(machine.execute("systemd-analyze security postgresql.service | grep -v ✓")[1])
- machine.shutdown()
- '';
- };
+ 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;
- # SCRAM-SHA-256 hashed password for "password"
- password = "SCRAM-SHA-256$4096:SZEJF5Si4QZ6l4fedrZZWQ==$6u3PWVcz+dts+NdpByPIjKa4CaSnoXGG3M2vpo76bVU=:WSZ0iGUCmVtKYVvNX0pFOp/60IgsdJ+90Y67Eun+QE0=";
- connection_limit = 5;
- };
- }
- {
- name = "default-clauses";
- }
- ];
- };
+ runTest (
+ { lib, ... }:
+ {
+ name = "postgresql-clauses-${package.name}";
+ meta = with lib.maintainers; {
+ maintainers = [ zagy ];
};
- testScript =
- let
- getClausesQuery =
- user:
- lib.concatStringsSep " " [
- "SELECT row_to_json(row)"
- "FROM ("
- "SELECT"
- "rolsuper,"
- "rolinherit,"
- "rolcreaterole,"
- "rolcreatedb,"
- "rolcanlogin,"
- "rolreplication,"
- "rolbypassrls,"
- "rolconnlimit,"
- "rolpassword"
- "FROM pg_authid"
- "WHERE rolname = '${user}'"
- ") row;"
- ];
- in
- ''
- import json
- machine.start()
- machine.wait_for_unit("postgresql.target")
+ 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;
+ # SCRAM-SHA-256 hashed password for "password"
+ password = "SCRAM-SHA-256$4096:SZEJF5Si4QZ6l4fedrZZWQ==$6u3PWVcz+dts+NdpByPIjKa4CaSnoXGG3M2vpo76bVU=:WSZ0iGUCmVtKYVvNX0pFOp/60IgsdJ+90Y67Eun+QE0=";
+ connection_limit = 5;
+ };
+ }
+ {
+ name = "default-clauses";
+ }
+ ];
+ };
+ };
- 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"}\""
+ testScript =
+ let
+ getClausesQuery =
+ user:
+ lib.concatStringsSep " " [
+ "SELECT row_to_json(row)"
+ "FROM ("
+ "SELECT"
+ "rolsuper,"
+ "rolinherit,"
+ "rolcreaterole,"
+ "rolcreatedb,"
+ "rolcanlogin,"
+ "rolreplication,"
+ "rolbypassrls,"
+ "rolconnlimit,"
+ "rolpassword"
+ "FROM pg_authid"
+ "WHERE rolname = '${user}'"
+ ") row;"
+ ];
+ in
+ ''
+ import json
+ machine.start()
+ machine.wait_for_unit("postgresql.target")
+
+ 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"}\""
+ )
)
- )
- print(clauses)
- t.assertTrue(clauses["rolsuper"])
- t.assertTrue(clauses["rolinherit"])
- t.assertTrue(clauses["rolcreaterole"])
- t.assertTrue(clauses["rolcreatedb"])
- t.assertTrue(clauses["rolcanlogin"])
- t.assertTrue(clauses["rolreplication"])
- t.assertTrue(clauses["rolbypassrls"])
- t.assertTrue(clauses["rolconnlimit"] == 5)
- t.assertTrue(clauses["rolpassword"])
- machine.succeed(
- "PGPASSWORD='password' psql -h localhost -U all-clauses -d postgres -c \"SELECT 1\""
- )
-
- with subtest("All user permissions default when ensureClauses is not provided"):
- clauses = json.loads(
+ print(clauses)
+ t.assertTrue(clauses["rolsuper"])
+ t.assertTrue(clauses["rolinherit"])
+ t.assertTrue(clauses["rolcreaterole"])
+ t.assertTrue(clauses["rolcreatedb"])
+ t.assertTrue(clauses["rolcanlogin"])
+ t.assertTrue(clauses["rolreplication"])
+ t.assertTrue(clauses["rolbypassrls"])
+ t.assertTrue(clauses["rolconnlimit"] == 5)
+ t.assertTrue(clauses["rolpassword"])
machine.succeed(
- "sudo -u postgres psql -tc \"${getClausesQuery "default-clauses"}\""
+ "PGPASSWORD='password' psql -h localhost -U all-clauses -d postgres -c \"SELECT 1\""
)
- )
- t.assertFalse(clauses["rolsuper"])
- t.assertTrue(clauses["rolinherit"])
- t.assertFalse(clauses["rolcreaterole"])
- t.assertFalse(clauses["rolcreatedb"])
- t.assertTrue(clauses["rolcanlogin"])
- t.assertFalse(clauses["rolreplication"])
- t.assertFalse(clauses["rolbypassrls"])
- t.assertFalse(clauses["rolconnlimit"] == 5)
- t.assertFalse(clauses["rolpassword"])
- machine.shutdown()
- '';
- };
+ with subtest("All user permissions default when ensureClauses is not provided"):
+ clauses = json.loads(
+ machine.succeed(
+ "sudo -u postgres psql -tc \"${getClausesQuery "default-clauses"}\""
+ )
+ )
+ t.assertFalse(clauses["rolsuper"])
+ t.assertTrue(clauses["rolinherit"])
+ t.assertFalse(clauses["rolcreaterole"])
+ t.assertFalse(clauses["rolcreatedb"])
+ t.assertTrue(clauses["rolcanlogin"])
+ t.assertFalse(clauses["rolreplication"])
+ t.assertFalse(clauses["rolbypassrls"])
+ t.assertFalse(clauses["rolconnlimit"] == 5)
+ t.assertFalse(clauses["rolpassword"])
+
+ machine.shutdown()
+ '';
+ }
+ );
in
genTests { inherit makeTestFor; }
diff --git a/nixos/tests/postgresql/wal2json.nix b/nixos/tests/postgresql/wal2json.nix
index 708c24ebabd6..511b1a7a2e8c 100644
--- a/nixos/tests/postgresql/wal2json.nix
+++ b/nixos/tests/postgresql/wal2json.nix
@@ -1,47 +1,48 @@
{
- pkgs,
- makeTest,
+ runTest,
genTests,
+ ...
}:
let
- inherit (pkgs) lib;
-
makeTestFor =
package:
- makeTest {
- name = "wal2json-${package.name}";
- meta.maintainers = with pkgs.lib.maintainers; [ euank ];
+ runTest (
+ { lib, pkgs, ... }:
+ {
+ name = "wal2json-${package.name}";
+ meta.maintainers = with pkgs.lib.maintainers; [ euank ];
- nodes.machine = {
- services.postgresql = {
- inherit package;
- enable = true;
- extensions = with package.pkgs; [ wal2json ];
- settings = {
- wal_level = "logical";
- max_replication_slots = "10";
- max_wal_senders = "10";
+ nodes.machine = {
+ services.postgresql = {
+ inherit package;
+ enable = true;
+ extensions = with package.pkgs; [ wal2json ];
+ settings = {
+ wal_level = "logical";
+ max_replication_slots = "10";
+ max_wal_senders = "10";
+ };
};
};
- };
- testScript = ''
- machine.wait_for_unit("postgresql.target")
- machine.succeed(
- "sudo -u postgres psql -qAt -f ${./wal2json/example2.sql} postgres > /tmp/example2.out"
- )
- machine.succeed(
- "diff ${./wal2json/example2.out} /tmp/example2.out"
- )
- machine.succeed(
- "sudo -u postgres psql -qAt -f ${./wal2json/example3.sql} postgres > /tmp/example3.out"
- )
- machine.succeed(
- "diff ${./wal2json/example3.out} /tmp/example3.out"
- )
- '';
- };
+ testScript = ''
+ machine.wait_for_unit("postgresql.target")
+ machine.succeed(
+ "sudo -u postgres psql -qAt -f ${./wal2json/example2.sql} postgres > /tmp/example2.out"
+ )
+ machine.succeed(
+ "diff ${./wal2json/example2.out} /tmp/example2.out"
+ )
+ machine.succeed(
+ "sudo -u postgres psql -qAt -f ${./wal2json/example3.sql} postgres > /tmp/example3.out"
+ )
+ machine.succeed(
+ "diff ${./wal2json/example3.out} /tmp/example3.out"
+ )
+ '';
+ }
+ );
in
genTests {
inherit makeTestFor;