···
# This test runs simple etcd cluster
-
import ../make-test-python.nix (
-
buildInputs = [ pkgs.openssl ];
-
ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
-
ca_pem = runWithOpenSSL "ca.pem" ''
-
-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" ''
-
-new -key ${etcd_key} \
-
-out $out -subj "/CN=etcd" \
-
etcd_cert = runWithOpenSSL "etcd.pem" ''
-
-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_csr = runWithOpenSSL "etcd-client-key.pem" ''
-
-new -key ${etcd_client_key} \
-
-out $out -subj "/CN=etcd-client" \
-
-config ${client_openssl_cnf}
-
etcd_client_cert = runWithOpenSSL "etcd-client.crt" ''
-
-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" ''
-
distinguished_name = req_distinguished_name
-
[req_distinguished_name]
-
basicConstraints = CA:FALSE
-
keyUsage = digitalSignature, keyEncipherment
-
extendedKeyUsage = serverAuth, clientAuth
-
subjectAltName = @alt_names
-
client_openssl_cnf = pkgs.writeText "client-openssl.cnf" ''
-
distinguished_name = req_distinguished_name
-
[req_distinguished_name]
-
basicConstraints = CA:FALSE
-
keyUsage = digitalSignature, keyEncipherment
-
extendedKeyUsage = clientAuth
-
trustedCaFile = ca_pem;
-
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 ];
-
meta = with pkgs.lib.maintainers; {
-
maintainers = [ offline ];
-
require = [ nodeConfig ];
-
"node1=https://node1:2380"
-
"node2=https://node2:2380"
-
initialAdvertisePeerUrls = [ "https://node1:2380" ];
-
require = [ nodeConfig ];
-
"node1=https://node1:2380"
-
"node2=https://node2:2380"
-
initialAdvertisePeerUrls = [ "https://node2:2380" ];
-
require = [ nodeConfig ];
-
"node1=https://node1:2380"
-
"node2=https://node2:2380"
-
"node3=https://node3:2380"
-
initialAdvertisePeerUrls = [ "https://node3:2380" ];
-
initialClusterState = "existing";
-
with subtest("should start etcd cluster"):
-
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.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"):
-
node1.succeed("etcdctl endpoint status")
-
node1.succeed("etcdctl put /foo/bar 'Hello degraded world'")
-
node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")