nixosTests.nginx: migrate to runTest

Part of #386873
This commit is contained in:
Piotr Kwiecinski 2025-03-29 23:45:36 +01:00
parent 073a164a60
commit 389f2fb908
No known key found for this signature in database
GPG key ID: EC0DE1CB9D5258B4
2 changed files with 123 additions and 107 deletions

View file

@ -797,7 +797,7 @@ in {
nfs3 = handleTest ./nfs { version = 3; }; nfs3 = handleTest ./nfs { version = 3; };
nfs4 = handleTest ./nfs { version = 4; }; nfs4 = handleTest ./nfs { version = 4; };
nghttpx = handleTest ./nghttpx.nix {}; nghttpx = handleTest ./nghttpx.nix {};
nginx = handleTest ./nginx.nix {}; nginx = runTest ./nginx.nix;
nginx-auth = handleTest ./nginx-auth.nix {}; nginx-auth = handleTest ./nginx-auth.nix {};
nginx-etag = handleTest ./nginx-etag.nix {}; nginx-etag = handleTest ./nginx-etag.nix {};
nginx-etag-compression = handleTest ./nginx-etag-compression.nix {}; nginx-etag-compression = handleTest ./nginx-etag-compression.nix {};

View file

@ -4,134 +4,150 @@
# 2. whether the ETag header is properly generated whenever we're serving # 2. whether the ETag header is properly generated whenever we're serving
# files in Nix store paths # files in Nix store paths
# 3. nginx doesn't restart on configuration changes (only reloads) # 3. nginx doesn't restart on configuration changes (only reloads)
import ./make-test-python.nix ({ pkgs, ... }: { { pkgs, ... }:
{
name = "nginx"; name = "nginx";
meta = with pkgs.lib.maintainers; { meta = with pkgs.lib.maintainers; {
maintainers = [ mbbx6spp danbst ]; maintainers = [
mbbx6spp
danbst
];
}; };
nodes = { nodes = {
webserver = { pkgs, lib, ... }: { webserver =
services.nginx.enable = true; { pkgs, lib, ... }:
services.nginx.commonHttpConfig = '' {
log_format ceeformat '@cee: {"status":"$status",' services.nginx.enable = true;
'"request_time":$request_time,' services.nginx.commonHttpConfig = ''
'"upstream_response_time":$upstream_response_time,' log_format ceeformat '@cee: {"status":"$status",'
'"pipe":"$pipe","bytes_sent":$bytes_sent,' '"request_time":$request_time,'
'"connection":"$connection",' '"upstream_response_time":$upstream_response_time,'
'"remote_addr":"$remote_addr",' '"pipe":"$pipe","bytes_sent":$bytes_sent,'
'"host":"$host",' '"connection":"$connection",'
'"timestamp":"$time_iso8601",' '"remote_addr":"$remote_addr",'
'"request":"$request",' '"host":"$host",'
'"http_referer":"$http_referer",' '"timestamp":"$time_iso8601",'
'"upstream_addr":"$upstream_addr"}'; '"request":"$request",'
''; '"http_referer":"$http_referer",'
services.nginx.virtualHosts."0.my.test" = { '"upstream_addr":"$upstream_addr"}';
extraConfig = ''
access_log syslog:server=unix:/dev/log,facility=user,tag=mytag,severity=info ceeformat;
location /favicon.ico { allow all; access_log off; log_not_found off; }
''; '';
}; services.nginx.virtualHosts."0.my.test" = {
extraConfig = ''
access_log syslog:server=unix:/dev/log,facility=user,tag=mytag,severity=info ceeformat;
location /favicon.ico { allow all; access_log off; log_not_found off; }
'';
};
services.nginx.virtualHosts.localhost = {
root = pkgs.runCommand "testdir" {} ''
mkdir "$out"
echo hello world > "$out/index.html"
'';
};
services.nginx.enableReload = true;
specialisation.etagSystem.configuration = {
services.nginx.virtualHosts.localhost = { services.nginx.virtualHosts.localhost = {
root = lib.mkForce (pkgs.runCommand "testdir2" {} '' root = pkgs.runCommand "testdir" { } ''
mkdir "$out" mkdir "$out"
echo content changed > "$out/index.html" echo hello world > "$out/index.html"
''); '';
};
services.nginx.enableReload = true;
specialisation.etagSystem.configuration = {
services.nginx.virtualHosts.localhost = {
root = lib.mkForce (
pkgs.runCommand "testdir2" { } ''
mkdir "$out"
echo content changed > "$out/index.html"
''
);
};
};
specialisation.justReloadSystem.configuration = {
services.nginx.virtualHosts."1.my.test".listen = [
{
addr = "127.0.0.1";
port = 8080;
}
];
};
specialisation.reloadRestartSystem.configuration = {
services.nginx.package = pkgs.nginxMainline;
};
specialisation.reloadWithErrorsSystem.configuration = {
services.nginx.package = pkgs.nginxMainline;
services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
}; };
}; };
specialisation.justReloadSystem.configuration = {
services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }];
};
specialisation.reloadRestartSystem.configuration = {
services.nginx.package = pkgs.nginxMainline;
};
specialisation.reloadWithErrorsSystem.configuration = {
services.nginx.package = pkgs.nginxMainline;
services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
};
};
}; };
testScript = { nodes, ... }: let testScript =
etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etagSystem"; { nodes, ... }:
justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/justReloadSystem"; let
reloadRestartSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadRestartSystem"; etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etagSystem";
reloadWithErrorsSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadWithErrorsSystem"; justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/justReloadSystem";
in '' reloadRestartSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadRestartSystem";
url = "http://localhost/index.html" reloadWithErrorsSystem = "${nodes.webserver.system.build.toplevel}/specialisation/reloadWithErrorsSystem";
in
''
url = "http://localhost/index.html"
def check_etag(): def check_etag():
etag = webserver.succeed( etag = webserver.succeed(
f'curl -v {url} 2>&1 | sed -n -e "s/^< etag: *//ip"' f'curl -v {url} 2>&1 | sed -n -e "s/^< etag: *//ip"'
).rstrip() ).rstrip()
http_code = webserver.succeed( http_code = webserver.succeed(
f"curl -w '%{{http_code}}' --head --fail -H 'If-None-Match: {etag}' {url}" f"curl -w '%{{http_code}}' --head --fail -H 'If-None-Match: {etag}' {url}"
) )
assert http_code.split("\n")[-1] == "304" assert http_code.split("\n")[-1] == "304"
return etag return etag
def wait_for_nginx_on_port(port): def wait_for_nginx_on_port(port):
webserver.wait_for_unit("nginx") webserver.wait_for_unit("nginx")
webserver.wait_for_open_port(port) webserver.wait_for_open_port(port)
# nginx can be ready before multi-user.target, in which case switching to # nginx can be ready before multi-user.target, in which case switching to
# a different configuration might not realize it needs to restart nginx. # a different configuration might not realize it needs to restart nginx.
webserver.wait_for_unit("multi-user.target") webserver.wait_for_unit("multi-user.target")
wait_for_nginx_on_port(80) wait_for_nginx_on_port(80)
with subtest("check ETag if serving Nix store paths"): with subtest("check ETag if serving Nix store paths"):
old_etag = check_etag() old_etag = check_etag()
webserver.succeed( webserver.succeed(
"${etagSystem}/bin/switch-to-configuration test >&2" "${etagSystem}/bin/switch-to-configuration test >&2"
) )
wait_for_nginx_on_port(80) wait_for_nginx_on_port(80)
new_etag = check_etag() new_etag = check_etag()
assert old_etag != new_etag assert old_etag != new_etag
with subtest("config is reloaded on nixos-rebuild switch"): with subtest("config is reloaded on nixos-rebuild switch"):
webserver.succeed( webserver.succeed(
"${justReloadSystem}/bin/switch-to-configuration test >&2" "${justReloadSystem}/bin/switch-to-configuration test >&2"
) )
wait_for_nginx_on_port(8080) wait_for_nginx_on_port(8080)
webserver.fail("journalctl -u nginx | grep -q -i stopped") webserver.fail("journalctl -u nginx | grep -q -i stopped")
webserver.succeed("journalctl -u nginx | grep -q -i reloaded") webserver.succeed("journalctl -u nginx | grep -q -i reloaded")
with subtest("restart when nginx package changes"): with subtest("restart when nginx package changes"):
webserver.succeed( webserver.succeed(
"${reloadRestartSystem}/bin/switch-to-configuration test >&2" "${reloadRestartSystem}/bin/switch-to-configuration test >&2"
) )
wait_for_nginx_on_port(80) wait_for_nginx_on_port(80)
webserver.succeed("journalctl -u nginx | grep -q -i stopped") webserver.succeed("journalctl -u nginx | grep -q -i stopped")
with subtest("nixos-rebuild --switch should fail when there are configuration errors"): with subtest("nixos-rebuild --switch should fail when there are configuration errors"):
webserver.fail( webserver.fail(
"${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2" "${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2"
) )
webserver.succeed("[[ $(systemctl is-failed nginx-config-reload) == failed ]]") webserver.succeed("[[ $(systemctl is-failed nginx-config-reload) == failed ]]")
webserver.succeed("[[ $(systemctl is-failed nginx) == active ]]") webserver.succeed("[[ $(systemctl is-failed nginx) == active ]]")
# just to make sure operation is idempotent. During development I had a situation # just to make sure operation is idempotent. During development I had a situation
# when first time it shows error, but stops showing it on subsequent rebuilds # when first time it shows error, but stops showing it on subsequent rebuilds
webserver.fail( webserver.fail(
"${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2" "${reloadWithErrorsSystem}/bin/switch-to-configuration test >&2"
) )
''; '';
}) }