import ./make-test.nix ({ pkgs, ...} : let backend = { config, pkgs, ... }: { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; services.httpd.documentRoot = "${pkgs.valgrind.doc}/share/doc/valgrind/html"; networking.firewall.allowedTCPPorts = [ 80 ]; }; in { name = "proxy"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ eelco chaoflow ]; }; nodes = { proxy = { config, pkgs, nodes, ... }: { services.httpd.enable = true; services.httpd.adminAddr = "bar@example.org"; services.httpd.extraModules = [ "proxy_balancer" "lbmethod_byrequests" ]; services.httpd.extraConfig = '' ExtendedStatus on Require all granted SetHandler server-status Require all granted BalancerMember http://${nodes.backend1.config.networking.hostName} retry=0 BalancerMember http://${nodes.backend2.config.networking.hostName} retry=0 ProxyStatus full ProxyPass /server-status ! ProxyPass / balancer://cluster/ ProxyPassReverse / balancer://cluster/ # For testing; don't want to wait forever for dead backend servers. ProxyTimeout 5 ''; networking.firewall.allowedTCPPorts = [ 80 ]; }; backend1 = backend; backend2 = backend; client = { config, pkgs, ... }: { }; }; testScript = '' startAll; $proxy->waitForUnit("httpd"); $backend1->waitForUnit("httpd"); $backend2->waitForUnit("httpd"); # With the back-ends up, the proxy should work. $client->succeed("curl --fail http://proxy/"); $client->succeed("curl --fail http://proxy/server-status"); # Block the first back-end. $backend1->block; # The proxy should still work. $client->succeed("curl --fail http://proxy/"); $client->succeed("curl --fail http://proxy/"); # Block the second back-end. $backend2->block; # Now the proxy should fail as well. $client->fail("curl --fail http://proxy/"); # But if the second back-end comes back, the proxy should start # working again. $backend2->unblock; $client->succeed("curl --fail http://proxy/"); ''; })