at 23.11-pre 5.2 kB view raw
1# verifies: 2# 1. nginx generates config file with shared http context definitions above 3# generated virtual hosts config. 4# 2. whether the ETag header is properly generated whenever we're serving 5# files in Nix store paths 6# 3. nginx doesn't restart on configuration changes (only reloads) 7import ./make-test-python.nix ({ pkgs, ... }: { 8 name = "nginx"; 9 meta = with pkgs.lib.maintainers; { 10 maintainers = [ mbbx6spp danbst ]; 11 }; 12 13 nodes = { 14 webserver = { pkgs, lib, ... }: { 15 services.nginx.enable = true; 16 services.nginx.commonHttpConfig = '' 17 log_format ceeformat '@cee: {"status":"$status",' 18 '"request_time":$request_time,' 19 '"upstream_response_time":$upstream_response_time,' 20 '"pipe":"$pipe","bytes_sent":$bytes_sent,' 21 '"connection":"$connection",' 22 '"remote_addr":"$remote_addr",' 23 '"host":"$host",' 24 '"timestamp":"$time_iso8601",' 25 '"request":"$request",' 26 '"http_referer":"$http_referer",' 27 '"upstream_addr":"$upstream_addr"}'; 28 ''; 29 services.nginx.virtualHosts."0.my.test" = { 30 extraConfig = '' 31 access_log syslog:server=unix:/dev/log,facility=user,tag=mytag,severity=info ceeformat; 32 location /favicon.ico { allow all; access_log off; log_not_found off; } 33 ''; 34 }; 35 36 services.nginx.virtualHosts.localhost = { 37 root = pkgs.runCommand "testdir" {} '' 38 mkdir "$out" 39 echo hello world > "$out/index.html" 40 ''; 41 }; 42 43 services.nginx.enableReload = true; 44 45 specialisation.etagSystem.configuration = { 46 services.nginx.virtualHosts.localhost = { 47 root = lib.mkForce (pkgs.runCommand "testdir2" {} '' 48 mkdir "$out" 49 echo content changed > "$out/index.html" 50 ''); 51 }; 52 }; 53 54 specialisation.justReloadSystem.configuration = { 55 services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }]; 56 }; 57 58 specialisation.reloadRestartSystem.configuration = { 59 services.nginx.package = pkgs.nginxMainline; 60 }; 61 62 specialisation.reloadWithErrorsSystem.configuration = { 63 services.nginx.package = pkgs.nginxMainline; 64 services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;"; 65 }; 66 }; 67 }; 68 69 testScript = { nodes, ... }: let 70 etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etagSystem"; 71 justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/justReloadSystem"; 72 reloadRestartSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadRestartSystem"; 73 reloadWithErrorsSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadWithErrorsSystem"; 74 in '' 75 url = "http://localhost/index.html" 76 77 78 def check_etag(): 79 etag = webserver.succeed( 80 f'curl -v {url} 2>&1 | sed -n -e "s/^< etag: *//ip"' 81 ).rstrip() 82 http_code = webserver.succeed( 83 f"curl -w '%{{http_code}}' --head --fail -H 'If-None-Match: {etag}' {url}" 84 ) 85 assert http_code.split("\n")[-1] == "304" 86 87 return etag 88 89 90 def wait_for_nginx_on_port(port): 91 webserver.wait_for_unit("nginx") 92 webserver.wait_for_open_port(port) 93 94 95 # nginx can be ready before multi-user.target, in which case switching to 96 # a different configuration might not realize it needs to restart nginx. 97 webserver.wait_for_unit("multi-user.target") 98 99 wait_for_nginx_on_port(80) 100 101 with subtest("check ETag if serving Nix store paths"): 102 old_etag = check_etag() 103 webserver.succeed( 104 "${etagSystem}/bin/switch-to-configuration test >&2" 105 ) 106 wait_for_nginx_on_port(80) 107 new_etag = check_etag() 108 assert old_etag != new_etag 109 110 with subtest("config is reloaded on nixos-rebuild switch"): 111 webserver.succeed( 112 "${justReloadSystem}/bin/switch-to-configuration test >&2" 113 ) 114 wait_for_nginx_on_port(8080) 115 webserver.fail("journalctl -u nginx | grep -q -i stopped") 116 webserver.succeed("journalctl -u nginx | grep -q -i reloaded") 117 118 with subtest("restart when nginx package changes"): 119 webserver.succeed( 120 "${reloadRestartSystem}/bin/switch-to-configuration test >&2" 121 ) 122 wait_for_nginx_on_port(80) 123 webserver.succeed("journalctl -u nginx | grep -q -i stopped") 124 125 with subtest("nixos-rebuild --switch should fail when there are configuration errors"): 126 webserver.fail( 127 "${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2" 128 ) 129 webserver.succeed("[[ $(systemctl is-failed nginx-config-reload) == failed ]]") 130 webserver.succeed("[[ $(systemctl is-failed nginx) == active ]]") 131 # just to make sure operation is idempotent. During development I had a situation 132 # when first time it shows error, but stops showing it on subsequent rebuilds 133 webserver.fail( 134 "${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2" 135 ) 136 ''; 137})