100 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ system ? builtins.currentSystem
 | 
						|
, config ? { }
 | 
						|
, pkgs ? import ../.. { inherit system config; } }:
 | 
						|
 | 
						|
with import ../lib/testing.nix { inherit system pkgs; };
 | 
						|
with pkgs.lib;
 | 
						|
 | 
						|
let
 | 
						|
  makePostgresqlWalReceiverTest = subTestName: postgresqlPackage: 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";
 | 
						|
  atLeast12 = versionAtLeast postgresqlPackage.version "12.0";
 | 
						|
  restoreCommand = ''
 | 
						|
    restore_command = 'cp ${walBackupDir}/%f %p'
 | 
						|
  '';
 | 
						|
 | 
						|
  recoveryFile = if atLeast12
 | 
						|
      then pkgs.writeTextDir "recovery.signal" ""
 | 
						|
      else pkgs.writeTextDir "recovery.conf" "${restoreCommand}";
 | 
						|
 | 
						|
  in 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
 | 
						|
        '' + optionalString atLeast12 ''
 | 
						|
          ${restoreCommand}
 | 
						|
          recovery_end_command = 'touch recovery.done'
 | 
						|
        '';
 | 
						|
        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;
 | 
						|
      };
 | 
						|
      # 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 = mkForce 5;
 | 
						|
    };
 | 
						|
 | 
						|
    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 ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*');
 | 
						|
 | 
						|
      # 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)
 |