diff options
Diffstat (limited to 'nixos/tests')
26 files changed, 1001 insertions, 128 deletions
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix index c6d393d91963..99dd8ec6fd3c 100644 --- a/nixos/tests/acme.nix +++ b/nixos/tests/acme.nix @@ -253,7 +253,7 @@ in import ./make-test-python.nix ({ lib, ... }: { def check_connection(node, domain, retries=3): - assert retries >= 0 + assert retries >= 0, f"Failed to connect to https://{domain}" result = node.succeed( "openssl s_client -brief -verify 2 -CAfile /tmp/ca.crt" @@ -262,12 +262,12 @@ in import ./make-test-python.nix ({ lib, ... }: { for line in result.lower().split("\n"): if "verification" in line and "error" in line: - time.sleep(1) + time.sleep(3) return check_connection(node, domain, retries - 1) def check_connection_key_bits(node, domain, bits, retries=3): - assert retries >= 0 + assert retries >= 0, f"Did not find expected number of bits ({bits}) in key" result = node.succeed( "openssl s_client -CAfile /tmp/ca.crt" @@ -277,12 +277,12 @@ in import ./make-test-python.nix ({ lib, ... }: { print("Key type:", result) if bits not in result: - time.sleep(1) + time.sleep(3) return check_connection_key_bits(node, domain, bits, retries - 1) def check_stapling(node, domain, retries=3): - assert retries >= 0 + assert retries >= 0, "OCSP Stapling check failed" # Pebble doesn't provide a full OCSP responder, so just check the URL result = node.succeed( @@ -293,10 +293,23 @@ in import ./make-test-python.nix ({ lib, ... }: { print("OCSP Responder URL:", result) if "${caDomain}:4002" not in result.lower(): - time.sleep(1) + time.sleep(3) return check_stapling(node, domain, retries - 1) + def download_ca_certs(node, retries=5): + assert retries >= 0, "Failed to connect to pebble to download root CA certs" + + exit_code, _ = node.execute("curl https://${caDomain}:15000/roots/0 > /tmp/ca.crt") + exit_code_2, _ = node.execute( + "curl https://${caDomain}:15000/intermediate-keys/0 >> /tmp/ca.crt" + ) + + if exit_code + exit_code_2 > 0: + time.sleep(3) + return download_ca_certs(node, retries - 1) + + client.start() dnsserver.start() @@ -313,8 +326,7 @@ in import ./make-test-python.nix ({ lib, ... }: { acme.wait_for_unit("network-online.target") acme.wait_for_unit("pebble.service") - client.succeed("curl https://${caDomain}:15000/roots/0 > /tmp/ca.crt") - client.succeed("curl https://${caDomain}:15000/intermediate-keys/0 >> /tmp/ca.crt") + download_ca_certs(client) with subtest("Can request certificate with HTTPS-01 challenge"): webserver.wait_for_unit("acme-finished-a.example.test.target") @@ -322,6 +334,21 @@ in import ./make-test-python.nix ({ lib, ... }: { check_issuer(webserver, "a.example.test", "pebble") check_connection(client, "a.example.test") + with subtest("Certificates and accounts have safe + valid permissions"): + group = "${nodes.webserver.config.security.acme.certs."a.example.test".group}" + webserver.succeed( + f"test $(stat -L -c \"%a %U %G\" /var/lib/acme/a.example.test/* | tee /dev/stderr | grep '640 acme {group}' | wc -l) -eq 5" + ) + webserver.succeed( + f"test $(stat -L -c \"%a %U %G\" /var/lib/acme/.lego/a.example.test/**/* | tee /dev/stderr | grep '640 acme {group}' | wc -l) -eq 5" + ) + webserver.succeed( + f"test $(stat -L -c \"%a %U %G\" /var/lib/acme/a.example.test | tee /dev/stderr | grep '750 acme {group}' | wc -l) -eq 1" + ) + webserver.succeed( + f"test $(find /var/lib/acme/accounts -type f -exec stat -L -c \"%a %U %G\" {{}} \\; | tee /dev/stderr | grep -v '600 acme {group}' | wc -l) -eq 0" + ) + with subtest("Can generate valid selfsigned certs"): webserver.succeed("systemctl clean acme-a.example.test.service --what=state") webserver.succeed("systemctl start acme-selfsigned-a.example.test.service") @@ -375,8 +402,15 @@ in import ./make-test-python.nix ({ lib, ... }: { assert keyhash_old == keyhash_new with subtest("Can request certificates for vhost + aliases (apache-httpd)"): - switch_to(webserver, "httpd-aliases") - webserver.wait_for_unit("acme-finished-c.example.test.target") + try: + switch_to(webserver, "httpd-aliases") + webserver.wait_for_unit("acme-finished-c.example.test.target") + except Exception as err: + _, output = webserver.execute( + "cat /var/log/httpd/*.log && ls -al /var/lib/acme/acme-challenge" + ) + print(output) + raise err check_issuer(webserver, "c.example.test", "pebble") check_connection(client, "c.example.test") check_connection(client, "d.example.test") diff --git a/nixos/tests/agda.nix b/nixos/tests/agda.nix index 3773907cff55..f282788519c8 100644 --- a/nixos/tests/agda.nix +++ b/nixos/tests/agda.nix @@ -3,8 +3,9 @@ import ./make-test-python.nix ({ pkgs, ... }: let hello-world = pkgs.writeText "hello-world" '' open import IO + open import Level - main = run(putStrLn "Hello World!") + main = run {0ℓ} (putStrLn "Hello World!") ''; in { diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 3ce71b0abe6d..62188ddf9e8d 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -49,6 +49,7 @@ in cadvisor = handleTestOn ["x86_64-linux"] ./cadvisor.nix {}; cage = handleTest ./cage.nix {}; cagebreak = handleTest ./cagebreak.nix {}; + calibre-web = handleTest ./calibre-web.nix {}; cassandra_2_1 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_2_1; }; cassandra_2_2 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_2_2; }; cassandra_3_0 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_3_0; }; @@ -110,6 +111,7 @@ in ergo = handleTest ./ergo.nix {}; etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {}; etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {}; + etebase-server = handleTest ./etebase-server.nix {}; etesync-dav = handleTest ./etesync-dav.nix {}; fancontrol = handleTest ./fancontrol.nix {}; fcitx = handleTest ./fcitx {}; @@ -176,6 +178,7 @@ in initrd-network-ssh = handleTest ./initrd-network-ssh {}; initrdNetwork = handleTest ./initrd-network.nix {}; initrd-secrets = handleTest ./initrd-secrets.nix {}; + inspircd = handleTest ./inspircd.nix {}; installer = handleTest ./installer.nix {}; iodine = handleTest ./iodine.nix {}; ipfs = handleTest ./ipfs.nix {}; @@ -224,6 +227,7 @@ in mariadb-galera-mariabackup = handleTest ./mysql/mariadb-galera-mariabackup.nix {}; mariadb-galera-rsync = handleTest ./mysql/mariadb-galera-rsync.nix {}; matomo = handleTest ./matomo.nix {}; + matrix-appservice-irc = handleTest ./matrix-appservice-irc.nix {}; matrix-synapse = handleTest ./matrix-synapse.nix {}; mediawiki = handleTest ./mediawiki.nix {}; memcached = handleTest ./memcached.nix {}; @@ -286,6 +290,7 @@ in nzbget = handleTest ./nzbget.nix {}; nzbhydra2 = handleTest ./nzbhydra2.nix {}; oh-my-zsh = handleTest ./oh-my-zsh.nix {}; + ombi = handleTest ./ombi.nix {}; openarena = handleTest ./openarena.nix {}; openldap = handleTest ./openldap.nix {}; opensmtpd = handleTest ./opensmtpd.nix {}; @@ -317,6 +322,7 @@ in plikd = handleTest ./plikd.nix {}; plotinus = handleTest ./plotinus.nix {}; podman = handleTestOn ["x86_64-linux"] ./podman.nix {}; + pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {}; postfix = handleTest ./postfix.nix {}; postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {}; postgis = handleTest ./postgis.nix {}; @@ -393,6 +399,7 @@ in systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {}; systemd-nspawn = handleTest ./systemd-nspawn.nix {}; systemd-timesyncd = handleTest ./systemd-timesyncd.nix {}; + systemd-unit-path = handleTest ./systemd-unit-path.nix {}; taskserver = handleTest ./taskserver.nix {}; telegraf = handleTest ./telegraf.nix {}; tiddlywiki = handleTest ./tiddlywiki.nix {}; @@ -424,6 +431,7 @@ in virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {}; vscodium = handleTest ./vscodium.nix {}; wasabibackend = handleTest ./wasabibackend.nix {}; + wiki-js = handleTest ./wiki-js.nix {}; wireguard = handleTest ./wireguard {}; wordpress = handleTest ./wordpress.nix {}; xandikos = handleTest ./xandikos.nix {}; diff --git a/nixos/tests/bitwarden.nix b/nixos/tests/bitwarden.nix index 5345c7245d00..3813a1f70f96 100644 --- a/nixos/tests/bitwarden.nix +++ b/nixos/tests/bitwarden.nix @@ -113,6 +113,7 @@ let driver.find_element_by_css_selector('input#masterPasswordRetype').send_keys( '${userPassword}' ) + driver.find_element_by_css_selector('input#acceptPolicies').click() driver.find_element_by_xpath("//button[contains(., 'Submit')]").click() diff --git a/nixos/tests/calibre-web.nix b/nixos/tests/calibre-web.nix new file mode 100644 index 000000000000..4f73b3311124 --- /dev/null +++ b/nixos/tests/calibre-web.nix @@ -0,0 +1,53 @@ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + + let + port = 3142; + defaultPort = 8083; + in + with lib; + { + name = "calibre-web"; + meta.maintainers = with pkgs.lib.maintainers; [ pborzenkov ]; + + nodes = { + default = { ... }: { + services.calibre-web.enable = true; + }; + + customized = { pkgs, ... }: { + services.calibre-web = { + enable = true; + listen.port = port; + options = { + calibreLibrary = "/tmp/books"; + reverseProxyAuth = { + enable = true; + header = "X-User"; + }; + }; + }; + environment.systemPackages = [ pkgs.calibre ]; + }; + }; + testScript = '' + start_all() + + default.wait_for_unit("calibre-web.service") + default.wait_for_open_port(${toString defaultPort}) + default.succeed( + "curl --fail 'http://localhost:${toString defaultPort}/basicconfig' | grep -q 'Basic Configuration'" + ) + + customized.succeed( + "mkdir /tmp/books && calibredb --library-path /tmp/books add -e --title test-book" + ) + customized.succeed("systemctl restart calibre-web") + customized.wait_for_unit("calibre-web.service") + customized.wait_for_open_port(${toString port}) + customized.succeed( + "curl --fail -H X-User:admin 'http://localhost:${toString port}' | grep -q test-book" + ) + ''; + } +) diff --git a/nixos/tests/croc.nix b/nixos/tests/croc.nix index c1b6fc7232d7..75a8fc991d47 100644 --- a/nixos/tests/croc.nix +++ b/nixos/tests/croc.nix @@ -6,7 +6,7 @@ let pass = pkgs.writeText "pass" "PassRelay"; in { name = "croc"; - meta = with pkgs.stdenv.lib.maintainers; { + meta = with pkgs.lib.maintainers; { maintainers = [ hax404 julm ]; }; diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index a71cf79c5a78..80d527b453fa 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -161,12 +161,18 @@ import ./make-test-python.nix ({ pkgs, ... }: { "docker run --rm ${examples.layered-image.imageName} cat extraCommands", ) - with subtest("Ensure building an image on top of a layered Docker images work"): + with subtest("Ensure images built on top of layered Docker images work"): docker.succeed( "docker load --input='${examples.layered-on-top}'", "docker run --rm ${examples.layered-on-top.imageName}", ) + with subtest("Ensure layered images built on top of layered Docker images work"): + docker.succeed( + "docker load --input='${examples.layered-on-top-layered}'", + "docker run --rm ${examples.layered-on-top-layered.imageName}", + ) + def set_of_layers(image_name): return set( @@ -205,6 +211,31 @@ import ./make-test-python.nix ({ pkgs, ... }: { assert "FROM_CHILD=true" in env, "envvars from the child should be preserved" assert "LAST_LAYER=child" in env, "envvars from the child should take priority" + with subtest("Ensure environment variables of layered images are correctly inherited"): + docker.succeed( + "docker load --input='${examples.environmentVariablesLayered}'" + ) + out = docker.succeed("docker run --rm ${examples.environmentVariablesLayered.imageName} env") + env = out.splitlines() + assert "FROM_PARENT=true" in env, "envvars from the parent should be preserved" + assert "FROM_CHILD=true" in env, "envvars from the child should be preserved" + assert "LAST_LAYER=child" in env, "envvars from the child should take priority" + + with subtest( + "Ensure inherited environment variables of layered images are correctly resolved" + ): + # Read environment variables as stored in image config + config = docker.succeed( + "tar -xOf ${examples.environmentVariablesLayered} manifest.json | ${pkgs.jq}/bin/jq -r .[].Config" + ).strip() + out = docker.succeed( + f"tar -xOf ${examples.environmentVariablesLayered} {config} | ${pkgs.jq}/bin/jq -r '.config.Env | .[]'" + ) + env = out.splitlines() + assert ( + sum(entry.startswith("LAST_LAYER") for entry in env) == 1 + ), "envvars overridden by child should be unique" + with subtest("Ensure image with only 2 layers can be loaded"): docker.succeed( "docker load --input='${examples.two-layered-image}'" @@ -219,6 +250,18 @@ import ./make-test-python.nix ({ pkgs, ... }: { "docker run bulk-layer ls /bin/hello", ) + with subtest( + "Ensure the bulk layer with a base image respects the number of maxLayers" + ): + docker.succeed( + "docker load --input='${pkgs.dockerTools.examples.layered-bulk-layer}'", + # Ensure the image runs correctly + "docker run layered-bulk-layer ls /bin/hello", + ) + + # Ensure the image has the correct number of layers + assert len(set_of_layers("layered-bulk-layer")) == 4 + with subtest("Ensure correct behavior when no store is needed"): # This check tests that buildLayeredImage can build images that don't need a store. docker.succeed( diff --git a/nixos/tests/dokuwiki.nix b/nixos/tests/dokuwiki.nix index 40475d789d47..2664e1500ea4 100644 --- a/nixos/tests/dokuwiki.nix +++ b/nixos/tests/dokuwiki.nix @@ -9,7 +9,7 @@ let sha256 = "4de5ff31d54dd61bbccaf092c9e74c1af3a4c53e07aa59f60457a8f00cfb23a6"; }; # We need unzip to build this package - buildInputs = [ pkgs.unzip ]; + nativeBuildInputs = [ pkgs.unzip ]; # Installing simply means copying all files to the output directory installPhase = "mkdir -p $out; cp -R * $out/"; }; @@ -24,7 +24,7 @@ let sha256 = "e40ed7dd6bbe7fe3363bbbecb4de481d5e42385b5a0f62f6a6ce6bf3a1f9dfa8"; }; # We need unzip to build this package - buildInputs = [ pkgs.unzip ]; + nativeBuildInputs = [ pkgs.unzip ]; sourceRoot = "."; # Installing simply means copying all files to the output directory installPhase = "mkdir -p $out; cp -R * $out/"; diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix index 8488c97c01e8..fee350de65b5 100644 --- a/nixos/tests/elk.nix +++ b/nixos/tests/elk.nix @@ -120,6 +120,7 @@ let }; }; + passthru.elkPackages = elk; testScript = '' import json diff --git a/nixos/tests/etebase-server.nix b/nixos/tests/etebase-server.nix new file mode 100644 index 000000000000..4fc3c1f6392f --- /dev/null +++ b/nixos/tests/etebase-server.nix @@ -0,0 +1,50 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +let + dataDir = "/var/lib/foobar"; + +in { + name = "etebase-server"; + meta = with pkgs.lib.maintainers; { + maintainers = [ felschr ]; + }; + + machine = { pkgs, ... }: + { + services.etebase-server = { + inherit dataDir; + enable = true; + settings.global.secret_file = + toString (pkgs.writeText "secret" "123456"); + }; + }; + + testScript = '' + machine.wait_for_unit("etebase-server.service") + machine.wait_for_open_port(8001) + + with subtest("Database & src-version were created"): + machine.wait_for_file("${dataDir}/src-version") + assert ( + "${pkgs.etebase-server}" + in machine.succeed("cat ${dataDir}/src-version") + ) + machine.wait_for_file("${dataDir}/db.sqlite3") + machine.wait_for_file("${dataDir}/static") + + with subtest("Only allow access from allowed_hosts"): + machine.succeed("curl -sSfL http://0.0.0.0:8001/") + machine.fail("curl -sSfL http://127.0.0.1:8001/") + machine.fail("curl -sSfL http://localhost:8001/") + + with subtest("Run tests"): + machine.succeed("etebase-server check") + machine.succeed("etebase-server test") + + with subtest("Create superuser"): + machine.succeed( + "etebase-server createsuperuser --no-input --username admin --email root@localhost" + ) + ''; + } +) diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index baad675229cc..582f5faf9bc0 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -34,6 +34,8 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { enableImap = true; }; + systemd.services.gitlab-backup.environment.BACKUP = "dump"; + services.gitlab = { enable = true; databasePasswordFile = pkgs.writeText "dbPassword" "xo0daiF4"; @@ -64,60 +66,89 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { }; }; - testScript = - let - auth = pkgs.writeText "auth.json" (builtins.toJSON { - grant_type = "password"; - username = "root"; - password = initialRootPassword; - }); + testScript = { nodes, ... }: + let + auth = pkgs.writeText "auth.json" (builtins.toJSON { + grant_type = "password"; + username = "root"; + password = initialRootPassword; + }); + + createProject = pkgs.writeText "create-project.json" (builtins.toJSON { + name = "test"; + }); - createProject = pkgs.writeText "create-project.json" (builtins.toJSON { - name = "test"; - }); + putFile = pkgs.writeText "put-file.json" (builtins.toJSON { + branch = "master"; + author_email = "author@example.com"; + author_name = "Firstname Lastname"; + content = "some content"; + commit_message = "create a new file"; + }); - putFile = pkgs.writeText "put-file.json" (builtins.toJSON { - branch = "master"; - author_email = "author@example.com"; - author_name = "Firstname Lastname"; - content = "some content"; - commit_message = "create a new file"; - }); - in - '' - gitlab.start() + # Wait for all GitLab services to be fully started. + waitForServices = '' + gitlab.wait_for_unit("gitaly.service") + gitlab.wait_for_unit("gitlab-workhorse.service") + gitlab.wait_for_unit("gitlab-pages.service") + gitlab.wait_for_unit("gitlab-mailroom.service") + gitlab.wait_for_unit("gitlab.service") + gitlab.wait_for_unit("gitlab-sidekiq.service") + gitlab.wait_for_file("${nodes.gitlab.config.services.gitlab.statePath}/tmp/sockets/gitlab.socket") + gitlab.wait_until_succeeds("curl -sSf http://gitlab/users/sign_in") + ''; - gitlab.wait_for_unit("gitaly.service") - gitlab.wait_for_unit("gitlab-workhorse.service") - gitlab.wait_for_unit("gitlab-pages.service") - gitlab.wait_for_unit("gitlab-mailroom.service") - gitlab.wait_for_unit("gitlab.service") - gitlab.wait_for_unit("gitlab-sidekiq.service") - gitlab.wait_for_file("/var/gitlab/state/tmp/sockets/gitlab.socket") - gitlab.wait_until_succeeds("curl -sSf http://gitlab/users/sign_in") + # The actual test of GitLab. Only push data to GitLab if + # `doSetup` is is true. + test = doSetup: '' + gitlab.succeed( + "curl -isSf http://gitlab | grep -i location | grep -q http://gitlab/users/sign_in" + ) + gitlab.succeed( + "${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2" + ) + gitlab.succeed( + "echo \"Authorization: Bearer \$(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers" + ) + '' + optionalString doSetup '' + gitlab.succeed( + "curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects" + ) + gitlab.succeed( + "curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/1/repository/files/some-file.txt" + ) + '' + '' + gitlab.succeed( + "curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.gz > /tmp/archive.tar.gz" + ) + gitlab.succeed( + "curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.bz2 > /tmp/archive.tar.bz2" + ) + gitlab.succeed("test -s /tmp/archive.tar.gz") + gitlab.succeed("test -s /tmp/archive.tar.bz2") + ''; - gitlab.succeed( - "curl -isSf http://gitlab | grep -i location | grep -q http://gitlab/users/sign_in" - ) - gitlab.succeed( - "${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2" - ) - gitlab.succeed( - "echo \"Authorization: Bearer \$(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers" - ) - gitlab.succeed( - "curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects" - ) - gitlab.succeed( - "curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/1/repository/files/some-file.txt" - ) - gitlab.succeed( - "curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.gz > /tmp/archive.tar.gz" - ) - gitlab.succeed( - "curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.bz2 > /tmp/archive.tar.bz2" - ) - gitlab.succeed("test -s /tmp/archive.tar.gz") - gitlab.succeed("test -s /tmp/archive.tar.bz2") - ''; + in '' + gitlab.start() + '' + + waitForServices + + test true + + '' + gitlab.systemctl("start gitlab-backup.service") + gitlab.wait_for_unit("gitlab-backup.service") + gitlab.wait_for_file("${nodes.gitlab.config.services.gitlab.statePath}/backup/dump_gitlab_backup.tar") + gitlab.systemctl("stop postgresql.service gitlab.target") + gitlab.succeed( + "find ${nodes.gitlab.config.services.gitlab.statePath} -mindepth 1 -maxdepth 1 -not -name backup -execdir rm -r {} +" + ) + gitlab.succeed("systemd-tmpfiles --create") + gitlab.succeed("rm -rf ${nodes.gitlab.config.services.postgresql.dataDir}") + gitlab.systemctl("start gitlab-config.service gitlab-postgresql.service") + gitlab.succeed( + "sudo -u gitlab -H gitlab-rake gitlab:backup:restore RAILS_ENV=production BACKUP=dump force=yes" + ) + gitlab.systemctl("start gitlab.target") + '' + + waitForServices + + test false; }) diff --git a/nixos/tests/hledger-web.nix b/nixos/tests/hledger-web.nix index 378d819437db..f8919f7d4bd0 100644 --- a/nixos/tests/hledger-web.nix +++ b/nixos/tests/hledger-web.nix @@ -13,25 +13,22 @@ rec { name = "hledger-web"; meta.maintainers = with lib.maintainers; [ marijanp ]; - nodes = { - server = { config, pkgs, ... }: rec { + nodes = rec { + server = { config, pkgs, ... }: { services.hledger-web = { host = "127.0.0.1"; port = 5000; enable = true; - journalFile = journal; + capabilities.manage = true; }; - networking.firewall.allowedTCPPorts = [ services.hledger-web.port ]; + networking.firewall.allowedTCPPorts = [ config.services.hledger-web.port ]; + systemd.services.hledger-web.preStart = '' + ln -s ${journal} /var/lib/hledger-web/.hledger.journal + ''; }; - apiserver = { config, pkgs, ... }: rec { - services.hledger-web = { - host = "127.0.0.1"; - port = 5000; - enable = true; - serveApi = true; - journalFile = journal; - }; - networking.firewall.allowedTCPPorts = [ services.hledger-web.port ]; + apiserver = { ... }: { + imports = [ server ]; + services.hledger-web.serveApi = true; }; }; @@ -42,7 +39,7 @@ rec { server.wait_for_open_port(5000) with subtest("Check if web UI is accessible"): page = server.succeed("curl -L http://127.0.0.1:5000") - assert "test.journal" in page + assert ".hledger.journal" in page apiserver.wait_for_unit("hledger-web.service") apiserver.wait_for_open_port(5000) diff --git a/nixos/tests/inspircd.nix b/nixos/tests/inspircd.nix new file mode 100644 index 000000000000..f4d82054011c --- /dev/null +++ b/nixos/tests/inspircd.nix @@ -0,0 +1,93 @@ +let + clients = [ + "ircclient1" + "ircclient2" + ]; + server = "inspircd"; + ircPort = 6667; + channel = "nixos-cat"; + iiDir = "/tmp/irc"; +in + +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "inspircd"; + nodes = { + "${server}" = { + networking.firewall.allowedTCPPorts = [ ircPort ]; + services.inspircd = { + enable = true; + package = pkgs.inspircdMinimal; + config = '' + <bind address="" port="${toString ircPort}" type="clients"> + <connect name="main" allow="*" pingfreq="15"> + ''; + }; + }; + } // lib.listToAttrs (builtins.map (client: lib.nameValuePair client { + imports = [ + ./common/user-account.nix + ]; + + systemd.services.ii = { + requires = [ "network.target" ]; + wantedBy = [ "default.target" ]; + + serviceConfig = { + Type = "simple"; + ExecPreStartPre = "mkdir -p ${iiDir}"; + ExecStart = '' + ${lib.getBin pkgs.ii}/bin/ii -n ${client} -s ${server} -i ${iiDir} + ''; + User = "alice"; + }; + }; + }) clients); + + testScript = + let + msg = client: "Hello, my name is ${client}"; + clientScript = client: [ + '' + ${client}.wait_for_unit("network.target") + ${client}.systemctl("start ii") + ${client}.wait_for_unit("ii") + ${client}.wait_for_file("${iiDir}/${server}/out") + '' + # wait until first PING from server arrives before joining, + # so we don't try it too early + '' + ${client}.wait_until_succeeds("grep 'PING' ${iiDir}/${server}/out") + '' + # join ${channel} + '' + ${client}.succeed("echo '/j #${channel}' > ${iiDir}/${server}/in") + ${client}.wait_for_file("${iiDir}/${server}/#${channel}/in") + '' + # send a greeting + '' + ${client}.succeed( + "echo '${msg client}' > ${iiDir}/${server}/#${channel}/in" + ) + '' + # check that all greetings arrived on all clients + ] ++ builtins.map (other: '' + ${client}.succeed( + "grep '${msg other}$' ${iiDir}/${server}/#${channel}/out" + ) + '') clients; + + # foldl', but requires a non-empty list instead of a start value + reduce = f: list: + builtins.foldl' f (builtins.head list) (builtins.tail list); + in '' + start_all() + ${server}.wait_for_open_port(${toString ircPort}) + + # run clientScript for all clients so that every list + # entry is executed by every client before advancing + # to the next one. + '' + lib.concatStrings + (reduce + (lib.zipListsWith (cs: c: cs + c)) + (builtins.map clientScript clients)); +}) diff --git a/nixos/tests/matrix-appservice-irc.nix b/nixos/tests/matrix-appservice-irc.nix new file mode 100644 index 000000000000..79b07ef83c57 --- /dev/null +++ b/nixos/tests/matrix-appservice-irc.nix @@ -0,0 +1,162 @@ +import ./make-test-python.nix ({ pkgs, ... }: + let + homeserverUrl = "http://homeserver:8448"; + in + { + name = "matrix-appservice-irc"; + meta = { + maintainers = pkgs.matrix-appservice-irc.meta.maintainers; + }; + + nodes = { + homeserver = { pkgs, ... }: { + # We'll switch to this once the config is copied into place + specialisation.running.configuration = { + services.matrix-synapse = { + enable = true; + database_type = "sqlite3"; + app_service_config_files = [ "/registration.yml" ]; + + enable_registration = true; + + listeners = [ + # The default but tls=false + { + "bind_address" = ""; + "port" = 8448; + "resources" = [ + { "compress" = true; "names" = [ "client" "webclient" ]; } + { "compress" = false; "names" = [ "federation" ]; } + ]; + "tls" = false; + "type" = "http"; + "x_forwarded" = false; + } + ]; + }; + + networking.firewall.allowedTCPPorts = [ 8448 ]; + }; + }; + + ircd = { pkgs, ... }: { + services.ngircd = { + enable = true; + config = '' + [Global] + Name = ircd.ircd + Info = Server Info Text + AdminInfo1 = _ + + [Channel] + Name = #test + Topic = a cool place + + [Options] + PAM = no + ''; + }; + networking.firewall.allowedTCPPorts = [ 6667 ]; + }; + + appservice = { pkgs, ... }: { + services.matrix-appservice-irc = { + enable = true; + registrationUrl = "http://appservice:8009"; + + settings = { + homeserver.url = homeserverUrl; + homeserver.domain = "homeserver"; + + ircService.servers."ircd" = { + name = "IRCd"; + port = 6667; + dynamicChannels = { + enabled = true; + aliasTemplate = "#irc_$CHANNEL"; + }; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8009 ]; + }; + + client = { pkgs, ... }: { + environment.systemPackages = [ + (pkgs.writers.writePython3Bin "do_test" + { libraries = [ pkgs.python3Packages.matrix-client ]; } '' + import socket + from matrix_client.client import MatrixClient + from time import sleep + + matrix = MatrixClient("${homeserverUrl}") + matrix.register_with_password(username="alice", password="foobar") + + irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + irc.connect(("ircd", 6667)) + irc.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + irc.send(b"USER bob bob bob :bob\n") + irc.send(b"NICK bob\n") + + m_room = matrix.join_room("#irc_#test:homeserver") + irc.send(b"JOIN #test\n") + + # plenty of time for the joins to happen + sleep(10) + + m_room.send_text("hi from matrix") + irc.send(b"PRIVMSG #test :hi from irc \r\n") + + print("Waiting for irc message...") + while True: + buf = irc.recv(10000) + if b"hi from matrix" in buf: + break + + print("Waiting for matrix message...") + + + def callback(room, e): + if "hi from irc" in e['content']['body']: + exit(0) + + + m_room.add_listener(callback, "m.room.message") + matrix.listen_forever() + '' + ) + ]; + }; + }; + + testScript = '' + start_all() + + ircd.wait_for_unit("ngircd.service") + ircd.wait_for_open_port(6667) + + with subtest("start the appservice"): + appservice.wait_for_unit("matrix-appservice-irc.service") + appservice.wait_for_open_port(8009) + + with subtest("copy the registration file"): + appservice.copy_from_vm("/var/lib/matrix-appservice-irc/registration.yml") + homeserver.copy_from_host( + pathlib.Path(os.environ.get("out", os.getcwd())) / "registration.yml", "/" + ) + homeserver.succeed("chmod 444 /registration.yml") + + with subtest("start the homeserver"): + homeserver.succeed( + "/run/current-system/specialisation/running/bin/switch-to-configuration test >&2" + ) + + homeserver.wait_for_unit("matrix-synapse.service") + homeserver.wait_for_open_port(8448) + + with subtest("ensure messages can be exchanged"): + client.succeed("do_test") + ''; + + }) diff --git a/nixos/tests/mysql/mariadb-galera-mariabackup.nix b/nixos/tests/mysql/mariadb-galera-mariabackup.nix index a4b893a9f33a..0a40c010a471 100644 --- a/nixos/tests/mysql/mariadb-galera-mariabackup.nix +++ b/nixos/tests/mysql/mariadb-galera-mariabackup.nix @@ -2,7 +2,7 @@ import ./../make-test-python.nix ({ pkgs, ...} : let mysqlenv-common = pkgs.buildEnv { name = "mysql-path-env-common"; pathsToLink = [ "/bin" ]; paths = with pkgs; [ bash gawk gnutar inetutils which ]; }; - mysqlenv-mariabackup = pkgs.buildEnv { name = "mysql-path-env-mariabackup"; pathsToLink = [ "/bin" ]; paths = with pkgs; [ gzip iproute netcat procps pv socat ]; }; + mysqlenv-mariabackup = pkgs.buildEnv { name = "mysql-path-env-mariabackup"; pathsToLink = [ "/bin" ]; paths = with pkgs; [ gzip iproute2 netcat procps pv socat ]; }; in { name = "mariadb-galera-mariabackup"; diff --git a/nixos/tests/ombi.nix b/nixos/tests/ombi.nix new file mode 100644 index 000000000000..bfca86af8175 --- /dev/null +++ b/nixos/tests/ombi.nix @@ -0,0 +1,18 @@ +import ./make-test-python.nix ({ lib, ... }: + +with lib; + +{ + name = "ombi"; + meta.maintainers = with maintainers; [ woky ]; + + nodes.machine = + { pkgs, ... }: + { services.ombi.enable = true; }; + + testScript = '' + machine.wait_for_unit("ombi.service") + machine.wait_for_open_port("5000") + machine.succeed("curl --fail http://localhost:5000/") + ''; +}) diff --git a/nixos/tests/podman.nix b/nixos/tests/podman.nix index 4985ff60365c..6078a936edea 100644 --- a/nixos/tests/podman.nix +++ b/nixos/tests/podman.nix @@ -96,6 +96,15 @@ import ./make-test-python.nix ( podman.succeed(su_cmd("podman ps | grep sleeping")) podman.succeed(su_cmd("podman stop sleeping")) podman.succeed(su_cmd("podman rm sleeping")) + + with subtest("Run container with init"): + podman.succeed( + "tar cv -C ${pkgs.pkgsStatic.busybox} . | podman import - busybox" + ) + pid = podman.succeed("podman run --rm busybox readlink /proc/self").strip() + assert pid == "1" + pid = podman.succeed("podman run --rm --init busybox readlink /proc/self").strip() + assert pid == "2" ''; } ) diff --git a/nixos/tests/pomerium.nix b/nixos/tests/pomerium.nix new file mode 100644 index 000000000000..531b6212711f --- /dev/null +++ b/nixos/tests/pomerium.nix @@ -0,0 +1,102 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "pomerium"; + meta = with lib.maintainers; { + maintainers = [ lukegb ]; + }; + + nodes = let base = myIP: { pkgs, lib, ... }: { + virtualisation.vlans = [ 1 ]; + networking = { + dhcpcd.enable = false; + firewall.allowedTCPPorts = [ 80 443 ]; + hosts = { + "192.168.1.1" = [ "pomerium" "pom-auth" ]; + "192.168.1.2" = [ "backend" "dummy-oidc" ]; + }; + interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [ + { address = myIP; prefixLength = 24; } + ]; + }; + }; in { + pomerium = { pkgs, lib, ... }: { + imports = [ (base "192.168.1.1") ]; + services.pomerium = { + enable = true; + settings = { + address = ":80"; + insecure_server = true; + authenticate_service_url = "http://pom-auth"; + + idp_provider = "oidc"; + idp_scopes = [ "oidc" ]; + idp_client_id = "dummy"; + idp_provider_url = "http://dummy-oidc"; + + policy = [{ + from = "https://my.website"; + to = "http://192.168.1.2"; + allow_public_unauthenticated_access = true; + preserve_host_header = true; + } { + from = "https://login.required"; + to = "http://192.168.1.2"; + allowed_domains = [ "my.domain" ]; + preserve_host_header = true; + }]; + }; + secretsFile = pkgs.writeText "pomerium-secrets" '' + # 12345678901234567890123456789012 in base64 + COOKIE_SECRET=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI= + IDP_CLIENT_SECRET=dummy + ''; + }; + }; + backend = { pkgs, lib, ... }: { + imports = [ (base "192.168.1.2") ]; + services.nginx.enable = true; + services.nginx.virtualHosts."my.website" = { + root = pkgs.runCommand "testdir" {} '' + mkdir "$out" + echo hello world > "$out/index.html" + ''; + }; + services.nginx.virtualHosts."dummy-oidc" = { + root = pkgs.runCommand "testdir" {} '' + mkdir -p "$out/.well-known" + cat <<EOF >"$out/.well-known/openid-configuration" + { + "issuer": "http://dummy-oidc", + "authorization_endpoint": "http://dummy-oidc/auth.txt", + "token_endpoint": "http://dummy-oidc/token", + "jwks_uri": "http://dummy-oidc/jwks.json", + "userinfo_endpoint": "http://dummy-oidc/userinfo", + "id_token_signing_alg_values_supported": ["RS256"] + } + EOF + echo hello I am login page >"$out/auth.txt" + ''; + }; + }; + }; + + testScript = { ... }: '' + backend.wait_for_unit("nginx") + backend.wait_for_open_port(80) + + pomerium.wait_for_unit("pomerium") + pomerium.wait_for_open_port(80) + + with subtest("no authentication required"): + pomerium.succeed( + "curl --resolve my.website:80:127.0.0.1 http://my.website | grep -q 'hello world'" + ) + + with subtest("login required"): + pomerium.succeed( + "curl -I --resolve login.required:80:127.0.0.1 http://login.required | grep -q pom-auth" + ) + pomerium.succeed( + "curl -L --resolve login.required:80:127.0.0.1 http://login.required | grep -q 'hello I am login page'" + ) + ''; +}) diff --git a/nixos/tests/privacyidea.nix b/nixos/tests/privacyidea.nix index b71ff0a1669f..4a94f0727946 100644 --- a/nixos/tests/privacyidea.nix +++ b/nixos/tests/privacyidea.nix @@ -12,10 +12,16 @@ import ./make-test-python.nix ({ pkgs, ...} : rec { services.privacyidea = { enable = true; - secretKey = "testing"; - pepper = "testing"; + secretKey = "$SECRET_KEY"; + pepper = "$PEPPER"; adminPasswordFile = pkgs.writeText "admin-password" "testing"; adminEmail = "root@localhost"; + + # Don't try this at home! + environmentFile = pkgs.writeText "pi-secrets.env" '' + SECRET_KEY=testing + PEPPER=testing + ''; }; services.nginx = { enable = true; @@ -29,6 +35,8 @@ import ./make-test-python.nix ({ pkgs, ...} : rec { machine.start() machine.wait_for_unit("multi-user.target") machine.succeed("curl --fail http://localhost | grep privacyIDEA") + machine.succeed("grep \"SECRET_KEY = 'testing'\" /var/lib/privacyidea/privacyidea.cfg") + machine.succeed("grep \"PI_PEPPER = 'testing'\" /var/lib/privacyidea/privacyidea.cfg") machine.succeed( "curl --fail http://localhost/auth -F username=admin -F password=testing | grep token" ) diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 290cb87abbe1..62c0080dd516 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -136,6 +136,24 @@ let ''; }; + bitcoin = { + exporterConfig = { + enable = true; + rpcUser = "bitcoinrpc"; + rpcPasswordFile = pkgs.writeText "password" "hunter2"; + }; + metricProvider = { + services.bitcoind.default.enable = true; + services.bitcoind.default.rpc.users.bitcoinrpc.passwordHMAC = "e8fe33f797e698ac258c16c8d7aadfbe$872bdb8f4d787367c26bcfd75e6c23c4f19d44a69f5d1ad329e5adf3f82710f7"; + }; + exporterTest = '' + wait_for_unit("prometheus-bitcoin-exporter.service") + wait_for_unit("bitcoind-default.service") + wait_for_open_port(9332) + succeed("curl -sSf http://localhost:9332/metrics | grep -q '^bitcoin_blocks '") + ''; + }; + blackbox = { exporterConfig = { enable = true; @@ -201,6 +219,22 @@ let ''; }; + # Access to WHOIS server is required to properly test this exporter, so + # just perform basic sanity check that the exporter is running and returns + # a failure. + domain = { + exporterConfig = { + enable = true; + }; + exporterTest = '' + wait_for_unit("prometheus-domain-exporter.service") + wait_for_open_port(9222) + succeed( + "curl -sSf 'http://localhost:9222/probe?target=nixos.org' | grep -q 'domain_probe_success 0'" + ) + ''; + }; + dovecot = { exporterConfig = { enable = true; @@ -603,6 +637,66 @@ let ''; }; + openldap = { + exporterConfig = { + enable = true; + ldapCredentialFile = "${pkgs.writeText "exporter.yml" '' + ldapUser: "cn=root,dc=example" + ldapPass: "notapassword" + ''}"; + }; + metricProvider = { + services.openldap = { + enable = true; + settings.children = { + "cn=schema".includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ]; + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/openldap"; + olcSuffix = "dc=example"; + olcRootDN = { + # cn=root,dc=example + base64 = "Y249cm9vdCxkYz1leGFtcGxl"; + }; + olcRootPW = { + path = "${pkgs.writeText "rootpw" "notapassword"}"; + }; + }; + }; + "olcDatabase={2}monitor".attrs = { + objectClass = [ "olcDatabaseConfig" ]; + olcDatabase = "{2}monitor"; + olcAccess = [ "to dn.subtree=cn=monitor by users read" ]; + }; + }; + declarativeContents."dc=example" = '' + dn: dc=example + objectClass: domain + dc: example + + dn: ou=users,dc=example + objectClass: organizationalUnit + ou: users + ''; + }; + }; + exporterTest = '' + wait_for_unit("prometheus-openldap-exporter.service") + wait_for_open_port(389) + wait_for_open_port(9330) + wait_until_succeeds( + "curl -sSf http://localhost:9330/metrics | grep -q 'openldap_scrape{result=\"ok\"} 1'" + ) + ''; + }; + openvpn = { exporterConfig = { enable = true; diff --git a/nixos/tests/restic.nix b/nixos/tests/restic.nix index 0cc8bd39afbb..16979eab8217 100644 --- a/nixos/tests/restic.nix +++ b/nixos/tests/restic.nix @@ -45,6 +45,10 @@ import ./make-test-python.nix ( ''; inherit passwordFile initialize paths pruneOpts; }; + remoteprune = { + inherit repository passwordFile; + pruneOpts = [ "--keep-last 1" ]; + }; }; environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local"; @@ -84,6 +88,8 @@ import ./make-test-python.nix ( "systemctl start restic-backups-rclonebackup.service", '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', + "systemctl start restic-backups-remoteprune.service", + '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', ) ''; } diff --git a/nixos/tests/snapcast.nix b/nixos/tests/snapcast.nix index 2fef63625140..ef35d586c9c8 100644 --- a/nixos/tests/snapcast.nix +++ b/nixos/tests/snapcast.nix @@ -34,6 +34,10 @@ in { type = "tcp"; location = "127.0.0.1:${toString tcpStreamPort}"; }; + meta = { + type = "meta"; + location = "/mpd/bluetooth/tcp"; + }; }; }; }; diff --git a/nixos/tests/systemd-template-override.nix b/nixos/tests/systemd-template-override.nix deleted file mode 100644 index d8ef4a6c1c9b..000000000000 --- a/nixos/tests/systemd-template-override.nix +++ /dev/null @@ -1,41 +0,0 @@ -import ./make-test-python.nix { - name = "systemd-template-override"; - - machine = { pkgs, lib, ... }: let - touchTmp = pkgs.writeTextFile { - name = "touch-tmp@.service"; - text = '' - [Service] - Type=oneshot - ExecStart=${pkgs.coreutils}/bin/touch /tmp/%I - ''; - destination = "/etc/systemd/system/touch-tmp@.service"; - }; - in { - systemd.packages = [ touchTmp ]; - - systemd.services."touch-tmp@forbidden" = { - serviceConfig.ExecStart = [ "" '' - ${pkgs.coreutils}/bin/true - '']; - }; - - systemd.services."touch-tmp@intercept" = { - serviceConfig.ExecStart = [ "" '' - ${pkgs.coreutils}/bin/touch /tmp/renamed - '']; - }; - }; - - testScript = '' - machine.wait_for_unit("default.target") - - machine.succeed("systemctl start touch-tmp@normal") - machine.succeed("systemctl start touch-tmp@forbbidden") - machine.succeed("systemctl start touch-tmp@intercept") - - machine.succeed("[ -e /tmp/normal ]") - machine.succeed("[ ! -e /tmp/forbidden ]") - machine.succeed("[ -e /tmp/renamed ]") - ''; -} diff --git a/nixos/tests/systemd-unit-path.nix b/nixos/tests/systemd-unit-path.nix new file mode 100644 index 000000000000..5998a187188a --- /dev/null +++ b/nixos/tests/systemd-unit-path.nix @@ -0,0 +1,47 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +let + exampleScript = pkgs.writeTextFile { + name = "example.sh"; + text = '' + #! ${pkgs.runtimeShell} -e + + while true; do + echo "Example script running" >&2 + ${pkgs.coreutils}/bin/sleep 1 + done + ''; + executable = true; + }; + + unitFile = pkgs.writeTextFile { + name = "example.service"; + text = '' + [Unit] + Description=Example systemd service unit file + + [Service] + ExecStart=${exampleScript} + + [Install] + WantedBy=multi-user.target + ''; + }; +in +{ + name = "systemd-unit-path"; + + machine = { pkgs, lib, ... }: { + boot.extraSystemdUnitPaths = [ "/etc/systemd-rw/system" ]; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.succeed("mkdir -p /etc/systemd-rw/system") + machine.succeed( + "cp ${unitFile} /etc/systemd-rw/system/example.service" + ) + machine.succeed("systemctl start example.service") + machine.succeed("systemctl status example.service | grep 'Active: active'") + ''; +}) diff --git a/nixos/tests/wiki-js.nix b/nixos/tests/wiki-js.nix new file mode 100644 index 000000000000..9aa87d15366b --- /dev/null +++ b/nixos/tests/wiki-js.nix @@ -0,0 +1,152 @@ +import ./make-test-python.nix ({ pkgs, lib, ...} : { + name = "wiki-js"; + meta = with pkgs.lib.maintainers; { + maintainers = [ ma27 ]; + }; + + machine = { pkgs, ... }: { + virtualisation.memorySize = 2048; + services.wiki-js = { + enable = true; + settings.db.host = "/run/postgresql"; + settings.db.user = "wiki-js"; + settings.logLevel = "debug"; + }; + services.postgresql = { + enable = true; + ensureDatabases = [ "wiki" ]; + ensureUsers = [ + { name = "wiki-js"; + ensurePermissions."DATABASE wiki" = "ALL PRIVILEGES"; + } + ]; + }; + systemd.services.wiki-js = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + }; + environment.systemPackages = with pkgs; [ jq ]; + }; + + testScript = let + payloads.finalize = pkgs.writeText "finalize.json" (builtins.toJSON { + adminEmail = "webmaster@example.com"; + adminPassword = "notapassword"; + adminPasswordConfirm = "notapassword"; + siteUrl = "http://localhost:3000"; + telemetry = false; + }); + payloads.login = pkgs.writeText "login.json" (builtins.toJSON [{ + operationName = null; + extensions = {}; + query = '' + mutation ($username: String!, $password: String!, $strategy: String!) { + authentication { + login(username: $username, password: $password, strategy: $strategy) { + responseResult { + succeeded + errorCode + slug + message + __typename + } + jwt + mustChangePwd + mustProvideTFA + mustSetupTFA + continuationToken + redirect + tfaQRImage + __typename + } + __typename + } + } + ''; + variables = { + password = "notapassword"; + strategy = "local"; + username = "webmaster@example.com"; + }; + }]); + payloads.content = pkgs.writeText "content.json" (builtins.toJSON [{ + extensions = {}; + operationName = null; + query = '' + mutation ($content: String!, $description: String!, $editor: String!, $isPrivate: Boolean!, $isPublished: Boolean!, $locale: String!, $path: String!, $publishEndDate: Date, $publishStartDate: Date, $scriptCss: String, $scriptJs: String, $tags: [String]!, $title: String!) { + pages { + create(content: $content, description: $description, editor: $editor, isPrivate: $isPrivate, isPublished: $isPublished, locale: $locale, path: $path, publishEndDate: $publishEndDate, publishStartDate: $publishStartDate, scriptCss: $scriptCss, scriptJs: $scriptJs, tags: $tags, title: $title) { + responseResult { + succeeded + errorCode + slug + message + __typename + } + page { + id + updatedAt + __typename + } + __typename + } + __typename + } + } + ''; + variables = { + content = "# Header\n\nHello world!"; + description = ""; + editor = "markdown"; + isPrivate = false; + isPublished = true; + locale = "en"; + path = "home"; + publishEndDate = ""; + publishStartDate = ""; + scriptCss = ""; + scriptJs = ""; + tags = []; + title = "Hello world"; + }; + }]); + in '' + machine.start() + machine.wait_for_unit("multi-user.target") + machine.wait_for_open_port(3000) + + machine.succeed("curl -sSf localhost:3000") + + with subtest("Setup"): + result = machine.succeed( + "set -o pipefail; curl -sSf localhost:3000/finalize -X POST -d " + + "@${payloads.finalize} -H 'Content-Type: application/json' " + + "| jq .ok | xargs echo" + ) + assert result.strip() == "true", f"Expected true, got {result}" + + # During the setup the service gets restarted, so we use this + # to check if the setup is done. + machine.wait_until_fails("curl -sSf localhost:3000") + machine.wait_until_succeeds("curl -sSf localhost:3000") + + with subtest("Base functionality"): + auth = machine.succeed( + "set -o pipefail; curl -sSf localhost:3000/graphql -X POST " + + "-d @${payloads.login} -H 'Content-Type: application/json' " + + "| jq '.[0].data.authentication.login.jwt' | xargs echo" + ).strip() + + assert auth + + create = machine.succeed( + "set -o pipefail; curl -sSf localhost:3000/graphql -X POST " + + "-d @${payloads.content} -H 'Content-Type: application/json' " + + f"-H 'Authorization: Bearer {auth}' " + + "| jq '.[0].data.pages.create.responseResult.succeeded'|xargs echo" + ) + assert create.strip() == "true", f"Expected true, got {create}" + + machine.shutdown() + ''; +}) diff --git a/nixos/tests/wireguard/basic.nix b/nixos/tests/wireguard/basic.nix index a31e92e8649d..36ab226cde0e 100644 --- a/nixos/tests/wireguard/basic.nix +++ b/nixos/tests/wireguard/basic.nix @@ -52,9 +52,9 @@ import ../make-test-python.nix ({ pkgs, lib, ...} : inherit (wg-snakeoil-keys.peer0) publicKey; }; - postSetup = let inherit (pkgs) iproute; in '' - ${iproute}/bin/ip route replace 10.23.42.1/32 dev wg0 - ${iproute}/bin/ip route replace fc00::1/128 dev wg0 + postSetup = let inherit (pkgs) iproute2; in '' + ${iproute2}/bin/ip route replace 10.23.42.1/32 dev wg0 + ${iproute2}/bin/ip route replace fc00::1/128 dev wg0 ''; }; }; |