87 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
		
		
			
		
	
	
			87 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| 
								 | 
							
								{ system ? builtins.currentSystem
							 | 
						||
| 
								 | 
							
								, config ? { }
							 | 
						||
| 
								 | 
							
								, pkgs ? import ../.. { inherit system config; } }:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								with import ../lib/testing.nix { inherit system pkgs; };
							 | 
						||
| 
								 | 
							
								with pkgs.lib;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let
							 | 
						||
| 
								 | 
							
								  postgresqlDataDir = "/var/db/postgresql/test";
							 | 
						||
| 
								 | 
							
								  replicationUser = "wal_receiver_user";
							 | 
						||
| 
								 | 
							
								  replicationSlot = "wal_receiver_slot";
							 | 
						||
| 
								 | 
							
								  replicationConn = "postgresql://${replicationUser}@localhost";
							 | 
						||
| 
								 | 
							
								  baseBackupDir = "/tmp/pg_basebackup";
							 | 
						||
| 
								 | 
							
								  walBackupDir = "/tmp/pg_wal";
							 | 
						||
| 
								 | 
							
								  recoveryConf = pkgs.writeText "recovery.conf" ''
							 | 
						||
| 
								 | 
							
								    restore_command = 'cp ${walBackupDir}/%f %p'
							 | 
						||
| 
								 | 
							
								  '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  makePostgresqlWalReceiverTest = subTestName: postgresqlPackage: makeTest {
							 | 
						||
| 
								 | 
							
								    name = "postgresql-wal-receiver-${subTestName}";
							 | 
						||
| 
								 | 
							
								    meta.maintainers = with maintainers; [ pacien ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    machine = { ... }: {
							 | 
						||
| 
								 | 
							
								      services.postgresql = {
							 | 
						||
| 
								 | 
							
								        package = postgresqlPackage;
							 | 
						||
| 
								 | 
							
								        enable = true;
							 | 
						||
| 
								 | 
							
								        dataDir = postgresqlDataDir;
							 | 
						||
| 
								 | 
							
								        extraConfig = ''
							 | 
						||
| 
								 | 
							
								          wal_level = archive # alias for replica on pg >= 9.6
							 | 
						||
| 
								 | 
							
								          max_wal_senders = 10
							 | 
						||
| 
								 | 
							
								          max_replication_slots = 10
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								        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 = {
							 | 
						||
| 
								 | 
							
								        inherit postgresqlPackage;
							 | 
						||
| 
								 | 
							
								        connection = replicationConn;
							 | 
						||
| 
								 | 
							
								        slot = replicationSlot;
							 | 
						||
| 
								 | 
							
								        directory = walBackupDir;
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    testScript = ''
							 | 
						||
| 
								 | 
							
								      # make an initial base backup
							 | 
						||
| 
								 | 
							
								      $machine->waitForUnit('postgresql');
							 | 
						||
| 
								 | 
							
								      $machine->waitForUnit('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('${postgresqlPackage}/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;"');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # 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}');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # 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 ${recoveryConf} ${postgresqlDataDir}/recovery.conf && chmod 666 ${postgresqlDataDir}/recovery.conf');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # replay WAL
							 | 
						||
| 
								 | 
							
								      $machine->systemctl('start postgresql');
							 | 
						||
| 
								 | 
							
								      $machine->waitForFile('${postgresqlDataDir}/recovery.done');
							 | 
						||
| 
								 | 
							
								      $machine->systemctl('restart postgresql');
							 | 
						||
| 
								 | 
							
								      $machine->waitForUnit('postgresql');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # 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 mapAttrs makePostgresqlWalReceiverTest (import ../../pkgs/servers/sql/postgresql pkgs)
							 |