diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 4bdee73b6f27..53e78330d67c 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -474,7 +474,7 @@ in activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix; activation-perlless = runTest ./activation/perlless.nix; etcd = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./etcd/etcd.nix; - etcd-cluster = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./etcd/etcd-cluster.nix { }; + etcd-cluster = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./etcd/etcd-cluster.nix; etebase-server = runTest ./etebase-server.nix; etesync-dav = runTest ./etesync-dav.nix; evcc = runTest ./evcc.nix; diff --git a/nixos/tests/etcd/etcd-cluster.nix b/nixos/tests/etcd/etcd-cluster.nix index 7ab3e4342593..aa66c8498356 100644 --- a/nixos/tests/etcd/etcd-cluster.nix +++ b/nixos/tests/etcd/etcd-cluster.nix @@ -1,178 +1,173 @@ # This test runs simple etcd cluster -import ../make-test-python.nix ( - { pkgs, ... }: - let +{ lib, pkgs, ... }: +let + runWithOpenSSL = + file: cmd: + pkgs.runCommand file { + buildInputs = [ pkgs.openssl ]; + } cmd; - runWithOpenSSL = - file: cmd: - pkgs.runCommand file { - buildInputs = [ pkgs.openssl ]; - } cmd; + ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048"; + ca_pem = runWithOpenSSL "ca.pem" '' + openssl req \ + -x509 -new -nodes -key ${ca_key} \ + -days 10000 -out $out -subj "/CN=etcd-ca" + ''; + etcd_key = runWithOpenSSL "etcd-key.pem" "openssl genrsa -out $out 2048"; + etcd_csr = runWithOpenSSL "etcd.csr" '' + openssl req \ + -new -key ${etcd_key} \ + -out $out -subj "/CN=etcd" \ + -config ${openssl_cnf} + ''; + etcd_cert = runWithOpenSSL "etcd.pem" '' + openssl x509 \ + -req -in ${etcd_csr} \ + -CA ${ca_pem} -CAkey ${ca_key} \ + -CAcreateserial -out $out \ + -days 365 -extensions v3_req \ + -extfile ${openssl_cnf} + ''; - ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048"; - ca_pem = runWithOpenSSL "ca.pem" '' - openssl req \ - -x509 -new -nodes -key ${ca_key} \ - -days 10000 -out $out -subj "/CN=etcd-ca" - ''; - etcd_key = runWithOpenSSL "etcd-key.pem" "openssl genrsa -out $out 2048"; - etcd_csr = runWithOpenSSL "etcd.csr" '' - openssl req \ - -new -key ${etcd_key} \ - -out $out -subj "/CN=etcd" \ - -config ${openssl_cnf} - ''; - etcd_cert = runWithOpenSSL "etcd.pem" '' - openssl x509 \ - -req -in ${etcd_csr} \ - -CA ${ca_pem} -CAkey ${ca_key} \ - -CAcreateserial -out $out \ - -days 365 -extensions v3_req \ - -extfile ${openssl_cnf} - ''; + etcd_client_key = runWithOpenSSL "etcd-client-key.pem" "openssl genrsa -out $out 2048"; - etcd_client_key = runWithOpenSSL "etcd-client-key.pem" "openssl genrsa -out $out 2048"; + etcd_client_csr = runWithOpenSSL "etcd-client-key.pem" '' + openssl req \ + -new -key ${etcd_client_key} \ + -out $out -subj "/CN=etcd-client" \ + -config ${client_openssl_cnf} + ''; - etcd_client_csr = runWithOpenSSL "etcd-client-key.pem" '' - openssl req \ - -new -key ${etcd_client_key} \ - -out $out -subj "/CN=etcd-client" \ - -config ${client_openssl_cnf} - ''; + etcd_client_cert = runWithOpenSSL "etcd-client.crt" '' + openssl x509 \ + -req -in ${etcd_client_csr} \ + -CA ${ca_pem} -CAkey ${ca_key} -CAcreateserial \ + -out $out -days 365 -extensions v3_req \ + -extfile ${client_openssl_cnf} + ''; - etcd_client_cert = runWithOpenSSL "etcd-client.crt" '' - openssl x509 \ - -req -in ${etcd_client_csr} \ - -CA ${ca_pem} -CAkey ${ca_key} -CAcreateserial \ - -out $out -days 365 -extensions v3_req \ - -extfile ${client_openssl_cnf} - ''; + openssl_cnf = pkgs.writeText "openssl.cnf" '' + ions = v3_req + distinguished_name = req_distinguished_name + [req_distinguished_name] + [ v3_req ] + basicConstraints = CA:FALSE + keyUsage = digitalSignature, keyEncipherment + extendedKeyUsage = serverAuth, clientAuth + subjectAltName = @alt_names + [alt_names] + DNS.1 = node1 + DNS.2 = node2 + DNS.3 = node3 + IP.1 = 127.0.0.1 + ''; - openssl_cnf = pkgs.writeText "openssl.cnf" '' - ions = v3_req - distinguished_name = req_distinguished_name - [req_distinguished_name] - [ v3_req ] - basicConstraints = CA:FALSE - keyUsage = digitalSignature, keyEncipherment - extendedKeyUsage = serverAuth, clientAuth - subjectAltName = @alt_names - [alt_names] - DNS.1 = node1 - DNS.2 = node2 - DNS.3 = node3 - IP.1 = 127.0.0.1 - ''; + client_openssl_cnf = pkgs.writeText "client-openssl.cnf" '' + ions = v3_req + distinguished_name = req_distinguished_name + [req_distinguished_name] + [ v3_req ] + basicConstraints = CA:FALSE + keyUsage = digitalSignature, keyEncipherment + extendedKeyUsage = clientAuth + ''; - client_openssl_cnf = pkgs.writeText "client-openssl.cnf" '' - ions = v3_req - distinguished_name = req_distinguished_name - [req_distinguished_name] - [ v3_req ] - basicConstraints = CA:FALSE - keyUsage = digitalSignature, keyEncipherment - extendedKeyUsage = clientAuth - ''; + nodeConfig = { + services = { + etcd = { + enable = true; + keyFile = etcd_key; + certFile = etcd_cert; + trustedCaFile = ca_pem; + clientCertAuth = true; + listenClientUrls = [ "https://127.0.0.1:2379" ]; + listenPeerUrls = [ "https://0.0.0.0:2380" ]; + }; + }; - nodeConfig = { - services = { - etcd = { - enable = true; - keyFile = etcd_key; - certFile = etcd_cert; - trustedCaFile = ca_pem; - clientCertAuth = true; - listenClientUrls = [ "https://127.0.0.1:2379" ]; - listenPeerUrls = [ "https://0.0.0.0:2380" ]; + environment.variables = { + ETCD_CERT_FILE = "${etcd_client_cert}"; + ETCD_KEY_FILE = "${etcd_client_key}"; + ETCD_CA_FILE = "${ca_pem}"; + ETCDCTL_ENDPOINTS = "https://127.0.0.1:2379"; + ETCDCTL_CACERT = "${ca_pem}"; + ETCDCTL_CERT = "${etcd_cert}"; + ETCDCTL_KEY = "${etcd_key}"; + }; + + networking.firewall.allowedTCPPorts = [ 2380 ]; + }; +in +{ + name = "etcd-cluster"; + + meta.maintainers = with lib.maintainers; [ offline ]; + + nodes = { + node1 = + { ... }: + { + require = [ nodeConfig ]; + services.etcd = { + initialCluster = [ + "node1=https://node1:2380" + "node2=https://node2:2380" + ]; + initialAdvertisePeerUrls = [ "https://node1:2380" ]; }; }; - environment.variables = { - ETCD_CERT_FILE = "${etcd_client_cert}"; - ETCD_KEY_FILE = "${etcd_client_key}"; - ETCD_CA_FILE = "${ca_pem}"; - ETCDCTL_ENDPOINTS = "https://127.0.0.1:2379"; - ETCDCTL_CACERT = "${ca_pem}"; - ETCDCTL_CERT = "${etcd_cert}"; - ETCDCTL_KEY = "${etcd_key}"; + node2 = + { ... }: + { + require = [ nodeConfig ]; + services.etcd = { + initialCluster = [ + "node1=https://node1:2380" + "node2=https://node2:2380" + ]; + initialAdvertisePeerUrls = [ "https://node2:2380" ]; + }; }; - networking.firewall.allowedTCPPorts = [ 2380 ]; - }; - in - { - name = "etcd-cluster"; - - meta = with pkgs.lib.maintainers; { - maintainers = [ offline ]; - }; - - nodes = { - node1 = - { ... }: - { - require = [ nodeConfig ]; - services.etcd = { - initialCluster = [ - "node1=https://node1:2380" - "node2=https://node2:2380" - ]; - initialAdvertisePeerUrls = [ "https://node1:2380" ]; - }; + node3 = + { ... }: + { + require = [ nodeConfig ]; + services.etcd = { + initialCluster = [ + "node1=https://node1:2380" + "node2=https://node2:2380" + "node3=https://node3:2380" + ]; + initialAdvertisePeerUrls = [ "https://node3:2380" ]; + initialClusterState = "existing"; }; + }; + }; - node2 = - { ... }: - { - require = [ nodeConfig ]; - services.etcd = { - initialCluster = [ - "node1=https://node1:2380" - "node2=https://node2:2380" - ]; - initialAdvertisePeerUrls = [ "https://node2:2380" ]; - }; - }; + testScript = '' + with subtest("should start etcd cluster"): + node1.start() + node2.start() + node1.wait_for_unit("etcd.service") + node2.wait_for_unit("etcd.service") + node2.wait_until_succeeds("etcdctl endpoint status") + node1.succeed("etcdctl put /foo/bar 'Hello world'") + node2.succeed("etcdctl get /foo/bar | grep 'Hello world'") - node3 = - { ... }: - { - require = [ nodeConfig ]; - services.etcd = { - initialCluster = [ - "node1=https://node1:2380" - "node2=https://node2:2380" - "node3=https://node3:2380" - ]; - initialAdvertisePeerUrls = [ "https://node3:2380" ]; - initialClusterState = "existing"; - }; - }; - }; + with subtest("should add another member"): + node1.wait_until_succeeds("etcdctl member add node3 --peer-urls=https://node3:2380") + node3.start() + node3.wait_for_unit("etcd.service") + node3.wait_until_succeeds("etcdctl member list | grep 'node3'") + node3.succeed("etcdctl endpoint status") - testScript = '' - with subtest("should start etcd cluster"): - node1.start() - node2.start() - node1.wait_for_unit("etcd.service") - node2.wait_for_unit("etcd.service") - node2.wait_until_succeeds("etcdctl endpoint status") - node1.succeed("etcdctl put /foo/bar 'Hello world'") - node2.succeed("etcdctl get /foo/bar | grep 'Hello world'") - - with subtest("should add another member"): - node1.wait_until_succeeds("etcdctl member add node3 --peer-urls=https://node3:2380") - node3.start() - node3.wait_for_unit("etcd.service") - node3.wait_until_succeeds("etcdctl member list | grep 'node3'") - node3.succeed("etcdctl endpoint status") - - with subtest("should survive member crash"): - node3.crash() - node1.succeed("etcdctl endpoint status") - node1.succeed("etcdctl put /foo/bar 'Hello degraded world'") - node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'") - ''; - } -) + with subtest("should survive member crash"): + node3.crash() + node1.succeed("etcdctl endpoint status") + node1.succeed("etcdctl put /foo/bar 'Hello degraded world'") + node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'") + ''; +}