1 { system ? builtins.currentSystem,
3 pkgs ? import ../.. { inherit system config; },
7 with import ../lib/testing-python.nix { inherit system pkgs; };
12 # Makes a test for a PostgreSQL package, given by name and looked up from `pkgs`.
13 makeTestAttribute = name:
16 value = makePostgresqlWalReceiverTest pkgs."${name}";
19 makePostgresqlWalReceiverTest = pkg:
21 postgresqlDataDir = "/var/lib/postgresql/${pkg.psqlSchema}";
22 replicationUser = "wal_receiver_user";
23 replicationSlot = "wal_receiver_slot";
24 replicationConn = "postgresql://${replicationUser}@localhost";
25 baseBackupDir = "/tmp/pg_basebackup";
26 walBackupDir = "/tmp/pg_wal";
28 recoveryFile = pkgs.writeTextDir "recovery.signal" "";
31 name = "postgresql-wal-receiver-${pkg.name}";
32 meta.maintainers = with lib.maintainers; [ pacien ];
34 nodes.machine = { ... }: {
35 services.postgresql = {
39 max_replication_slots = 10;
41 recovery_end_command = "touch recovery.done";
42 restore_command = "cp ${walBackupDir}/%f %p";
43 wal_level = "archive"; # alias for replica on pg >= 9.6
46 host replication ${replicationUser} all trust
48 initialScript = pkgs.writeText "init.sql" ''
49 create user ${replicationUser} replication;
50 select * from pg_create_physical_replication_slot('${replicationSlot}');
54 services.postgresqlWalReceiver.receivers.main = {
55 postgresqlPackage = pkg;
56 connection = replicationConn;
57 slot = replicationSlot;
58 directory = walBackupDir;
60 # This is only to speedup test, it isn't time racing. Service is set to autorestart always,
61 # default 60sec is fine for real system, but is too much for a test
62 systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
66 # make an initial base backup
67 machine.wait_for_unit("postgresql")
68 machine.wait_for_unit("postgresql-wal-receiver-main")
69 # WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other
70 # required only for 9.4
73 "${pkg}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}"
76 # create a dummy table with 100 records
78 "sudo -u postgres psql --command='create table dummy as select * from generate_series(1, 100) as val;'"
81 # stop postgres and destroy data
82 machine.systemctl("stop postgresql")
83 machine.systemctl("stop postgresql-wal-receiver-main")
84 machine.succeed("rm -r ${postgresqlDataDir}/{base,global,pg_*}")
86 # restore the base backup
88 "cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}"
91 # prepare WAL and recovery
92 machine.succeed("chmod a+rX -R ${walBackupDir}")
94 "for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done"
95 ) # make use of partial segments too
97 "cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*"
101 machine.systemctl("start postgresql")
102 machine.wait_for_file("${postgresqlDataDir}/recovery.done")
103 machine.systemctl("restart postgresql")
104 machine.wait_for_unit("postgresql")
106 # check that our records have been restored
108 "test $(sudo -u postgres psql --pset='pager=off' --tuples-only --command='select count(distinct val) from dummy;') -eq 100"
114 if package == null then
115 # all-tests.nix: Maps the generic function over all attributes of PostgreSQL packages
116 builtins.listToAttrs (map makeTestAttribute (builtins.attrNames (import ../../pkgs/servers/sql/postgresql pkgs)))
118 # Called directly from <package>.tests
119 makePostgresqlWalReceiverTest package