at 18.03-beta 4.7 kB view raw
1# This test runs simple etcd cluster 2 3import ./make-test.nix ({ pkgs, ... } : let 4 5 runWithOpenSSL = file: cmd: pkgs.runCommand file { 6 buildInputs = [ pkgs.openssl ]; 7 } cmd; 8 9 ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048"; 10 ca_pem = runWithOpenSSL "ca.pem" '' 11 openssl req \ 12 -x509 -new -nodes -key ${ca_key} \ 13 -days 10000 -out $out -subj "/CN=etcd-ca" 14 ''; 15 etcd_key = runWithOpenSSL "etcd-key.pem" "openssl genrsa -out $out 2048"; 16 etcd_csr = runWithOpenSSL "etcd.csr" '' 17 openssl req \ 18 -new -key ${etcd_key} \ 19 -out $out -subj "/CN=etcd" \ 20 -config ${openssl_cnf} 21 ''; 22 etcd_cert = runWithOpenSSL "etcd.pem" '' 23 openssl x509 \ 24 -req -in ${etcd_csr} \ 25 -CA ${ca_pem} -CAkey ${ca_key} \ 26 -CAcreateserial -out $out \ 27 -days 365 -extensions v3_req \ 28 -extfile ${openssl_cnf} 29 ''; 30 31 etcd_client_key = runWithOpenSSL "etcd-client-key.pem" 32 "openssl genrsa -out $out 2048"; 33 34 etcd_client_csr = runWithOpenSSL "etcd-client-key.pem" '' 35 openssl req \ 36 -new -key ${etcd_client_key} \ 37 -out $out -subj "/CN=etcd-client" \ 38 -config ${client_openssl_cnf} 39 ''; 40 41 etcd_client_cert = runWithOpenSSL "etcd-client.crt" '' 42 openssl x509 \ 43 -req -in ${etcd_client_csr} \ 44 -CA ${ca_pem} -CAkey ${ca_key} -CAcreateserial \ 45 -out $out -days 365 -extensions v3_req \ 46 -extfile ${client_openssl_cnf} 47 ''; 48 49 openssl_cnf = pkgs.writeText "openssl.cnf" '' 50 ions = v3_req 51 distinguished_name = req_distinguished_name 52 [req_distinguished_name] 53 [ v3_req ] 54 basicConstraints = CA:FALSE 55 keyUsage = digitalSignature, keyEncipherment 56 extendedKeyUsage = serverAuth 57 subjectAltName = @alt_names 58 [alt_names] 59 DNS.1 = node1 60 DNS.2 = node2 61 DNS.3 = node3 62 IP.1 = 127.0.0.1 63 ''; 64 65 client_openssl_cnf = pkgs.writeText "client-openssl.cnf" '' 66 ions = v3_req 67 distinguished_name = req_distinguished_name 68 [req_distinguished_name] 69 [ v3_req ] 70 basicConstraints = CA:FALSE 71 keyUsage = digitalSignature, keyEncipherment 72 extendedKeyUsage = clientAuth 73 ''; 74 75 nodeConfig = { 76 services = { 77 etcd = { 78 enable = true; 79 keyFile = etcd_key; 80 certFile = etcd_cert; 81 trustedCaFile = ca_pem; 82 peerClientCertAuth = true; 83 listenClientUrls = ["https://127.0.0.1:2379"]; 84 listenPeerUrls = ["https://0.0.0.0:2380"]; 85 }; 86 }; 87 88 environment.variables = { 89 ETCDCTL_CERT_FILE = "${etcd_client_cert}"; 90 ETCDCTL_KEY_FILE = "${etcd_client_key}"; 91 ETCDCTL_CA_FILE = "${ca_pem}"; 92 ETCDCTL_PEERS = "https://127.0.0.1:2379"; 93 }; 94 95 networking.firewall.allowedTCPPorts = [ 2380 ]; 96 }; 97in { 98 name = "etcd"; 99 100 meta = with pkgs.stdenv.lib.maintainers; { 101 maintainers = [ offline ]; 102 }; 103 104 nodes = { 105 node1 = { config, pkgs, nodes, ... }: { 106 require = [nodeConfig]; 107 services.etcd = { 108 initialCluster = ["node1=https://node1:2380" "node2=https://node2:2380"]; 109 initialAdvertisePeerUrls = ["https://node1:2380"]; 110 }; 111 }; 112 113 node2 = { config, pkgs, ... }: { 114 require = [nodeConfig]; 115 services.etcd = { 116 initialCluster = ["node1=https://node1:2380" "node2=https://node2:2380"]; 117 initialAdvertisePeerUrls = ["https://node2:2380"]; 118 }; 119 }; 120 121 node3 = { config, pkgs, ... }: { 122 require = [nodeConfig]; 123 services.etcd = { 124 initialCluster = ["node1=https://node1:2380" "node2=https://node2:2380" "node3=https://node3:2380"]; 125 initialAdvertisePeerUrls = ["https://node3:2380"]; 126 initialClusterState = "existing"; 127 }; 128 }; 129 }; 130 131 testScript = '' 132 subtest "should start etcd cluster", sub { 133 $node1->start(); 134 $node2->start(); 135 $node1->waitForUnit("etcd.service"); 136 $node2->waitForUnit("etcd.service"); 137 $node2->waitUntilSucceeds("etcdctl cluster-health"); 138 $node1->succeed("etcdctl set /foo/bar 'Hello world'"); 139 $node2->succeed("etcdctl get /foo/bar | grep 'Hello world'"); 140 }; 141 142 subtest "should add another member", sub { 143 $node1->succeed("etcdctl member add node3 https://node3:2380"); 144 $node3->start(); 145 $node3->waitForUnit("etcd.service"); 146 $node3->waitUntilSucceeds("etcdctl member list | grep 'node3'"); 147 $node3->succeed("etcdctl cluster-health"); 148 }; 149 150 subtest "should survive member crash", sub { 151 $node3->crash; 152 $node1->succeed("etcdctl cluster-health"); 153 $node1->succeed("etcdctl set /foo/bar 'Hello degraded world'"); 154 $node1->succeed("etcdctl get /foo/bar | grep 'Hello degraded world'"); 155 }; 156 ''; 157})