at 23.05-pre 4.7 kB view raw
1{ system ? builtins.currentSystem, 2 config ? {}, 3 pkgs ? import ../.. { inherit system config; } 4}: 5 6with import ../lib/testing-python.nix { inherit system pkgs; }; 7 8let 9 lib = pkgs.lib; 10 11 # Makes a test for a PostgreSQL package, given by name and looked up from `pkgs`. 12 makePostgresqlWalReceiverTest = postgresqlPackage: 13 { 14 name = postgresqlPackage; 15 value = 16 let 17 pkg = pkgs."${postgresqlPackage}"; 18 postgresqlDataDir = "/var/lib/postgresql/${pkg.psqlSchema}"; 19 replicationUser = "wal_receiver_user"; 20 replicationSlot = "wal_receiver_slot"; 21 replicationConn = "postgresql://${replicationUser}@localhost"; 22 baseBackupDir = "/tmp/pg_basebackup"; 23 walBackupDir = "/tmp/pg_wal"; 24 atLeast12 = lib.versionAtLeast pkg.version "12.0"; 25 26 recoveryFile = if atLeast12 27 then pkgs.writeTextDir "recovery.signal" "" 28 else pkgs.writeTextDir "recovery.conf" "restore_command = 'cp ${walBackupDir}/%f %p'"; 29 30 in makeTest { 31 name = "postgresql-wal-receiver-${postgresqlPackage}"; 32 meta.maintainers = with lib.maintainers; [ pacien ]; 33 34 nodes.machine = { ... }: { 35 services.postgresql = { 36 package = pkg; 37 enable = true; 38 settings = lib.mkMerge [ 39 { 40 wal_level = "archive"; # alias for replica on pg >= 9.6 41 max_wal_senders = 10; 42 max_replication_slots = 10; 43 } 44 (lib.mkIf atLeast12 { 45 restore_command = "cp ${walBackupDir}/%f %p"; 46 recovery_end_command = "touch recovery.done"; 47 }) 48 ]; 49 authentication = '' 50 host replication ${replicationUser} all trust 51 ''; 52 initialScript = pkgs.writeText "init.sql" '' 53 create user ${replicationUser} replication; 54 select * from pg_create_physical_replication_slot('${replicationSlot}'); 55 ''; 56 }; 57 58 services.postgresqlWalReceiver.receivers.main = { 59 postgresqlPackage = pkg; 60 connection = replicationConn; 61 slot = replicationSlot; 62 directory = walBackupDir; 63 }; 64 # This is only to speedup test, it isn't time racing. Service is set to autorestart always, 65 # default 60sec is fine for real system, but is too much for a test 66 systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5; 67 }; 68 69 testScript = '' 70 # make an initial base backup 71 machine.wait_for_unit("postgresql") 72 machine.wait_for_unit("postgresql-wal-receiver-main") 73 # WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other 74 # required only for 9.4 75 machine.sleep(5) 76 machine.succeed( 77 "${pkg}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}" 78 ) 79 80 # create a dummy table with 100 records 81 machine.succeed( 82 "sudo -u postgres psql --command='create table dummy as select * from generate_series(1, 100) as val;'" 83 ) 84 85 # stop postgres and destroy data 86 machine.systemctl("stop postgresql") 87 machine.systemctl("stop postgresql-wal-receiver-main") 88 machine.succeed("rm -r ${postgresqlDataDir}/{base,global,pg_*}") 89 90 # restore the base backup 91 machine.succeed( 92 "cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}" 93 ) 94 95 # prepare WAL and recovery 96 machine.succeed("chmod a+rX -R ${walBackupDir}") 97 machine.execute( 98 "for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done" 99 ) # make use of partial segments too 100 machine.succeed( 101 "cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*" 102 ) 103 104 # replay WAL 105 machine.systemctl("start postgresql") 106 machine.wait_for_file("${postgresqlDataDir}/recovery.done") 107 machine.systemctl("restart postgresql") 108 machine.wait_for_unit("postgresql") 109 110 # check that our records have been restored 111 machine.succeed( 112 "test $(sudo -u postgres psql --pset='pager=off' --tuples-only --command='select count(distinct val) from dummy;') -eq 100" 113 ) 114 ''; 115 }; 116 }; 117 118# Maps the generic function over all attributes of PostgreSQL packages 119in builtins.listToAttrs (map makePostgresqlWalReceiverTest (builtins.attrNames (import ../../pkgs/servers/sql/postgresql { })))