···
# This test runs simple etcd cluster
3
-
import ../make-test-python.nix (
7
+
pkgs.runCommand file {
8
+
buildInputs = [ pkgs.openssl ];
9
-
pkgs.runCommand file {
10
-
buildInputs = [ pkgs.openssl ];
11
+
ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
12
+
ca_pem = runWithOpenSSL "ca.pem" ''
14
+
-x509 -new -nodes -key ${ca_key} \
15
+
-days 10000 -out $out -subj "/CN=etcd-ca"
17
+
etcd_key = runWithOpenSSL "etcd-key.pem" "openssl genrsa -out $out 2048";
18
+
etcd_csr = runWithOpenSSL "etcd.csr" ''
20
+
-new -key ${etcd_key} \
21
+
-out $out -subj "/CN=etcd" \
22
+
-config ${openssl_cnf}
24
+
etcd_cert = runWithOpenSSL "etcd.pem" ''
26
+
-req -in ${etcd_csr} \
27
+
-CA ${ca_pem} -CAkey ${ca_key} \
28
+
-CAcreateserial -out $out \
29
+
-days 365 -extensions v3_req \
30
+
-extfile ${openssl_cnf}
13
-
ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
14
-
ca_pem = runWithOpenSSL "ca.pem" ''
16
-
-x509 -new -nodes -key ${ca_key} \
17
-
-days 10000 -out $out -subj "/CN=etcd-ca"
19
-
etcd_key = runWithOpenSSL "etcd-key.pem" "openssl genrsa -out $out 2048";
20
-
etcd_csr = runWithOpenSSL "etcd.csr" ''
22
-
-new -key ${etcd_key} \
23
-
-out $out -subj "/CN=etcd" \
24
-
-config ${openssl_cnf}
26
-
etcd_cert = runWithOpenSSL "etcd.pem" ''
28
-
-req -in ${etcd_csr} \
29
-
-CA ${ca_pem} -CAkey ${ca_key} \
30
-
-CAcreateserial -out $out \
31
-
-days 365 -extensions v3_req \
32
-
-extfile ${openssl_cnf}
33
+
etcd_client_key = runWithOpenSSL "etcd-client-key.pem" "openssl genrsa -out $out 2048";
35
-
etcd_client_key = runWithOpenSSL "etcd-client-key.pem" "openssl genrsa -out $out 2048";
35
+
etcd_client_csr = runWithOpenSSL "etcd-client-key.pem" ''
37
+
-new -key ${etcd_client_key} \
38
+
-out $out -subj "/CN=etcd-client" \
39
+
-config ${client_openssl_cnf}
37
-
etcd_client_csr = runWithOpenSSL "etcd-client-key.pem" ''
39
-
-new -key ${etcd_client_key} \
40
-
-out $out -subj "/CN=etcd-client" \
41
-
-config ${client_openssl_cnf}
44
-
etcd_client_cert = runWithOpenSSL "etcd-client.crt" ''
46
-
-req -in ${etcd_client_csr} \
47
-
-CA ${ca_pem} -CAkey ${ca_key} -CAcreateserial \
48
-
-out $out -days 365 -extensions v3_req \
49
-
-extfile ${client_openssl_cnf}
42
+
etcd_client_cert = runWithOpenSSL "etcd-client.crt" ''
44
+
-req -in ${etcd_client_csr} \
45
+
-CA ${ca_pem} -CAkey ${ca_key} -CAcreateserial \
46
+
-out $out -days 365 -extensions v3_req \
47
+
-extfile ${client_openssl_cnf}
52
-
openssl_cnf = pkgs.writeText "openssl.cnf" ''
54
-
distinguished_name = req_distinguished_name
55
-
[req_distinguished_name]
57
-
basicConstraints = CA:FALSE
58
-
keyUsage = digitalSignature, keyEncipherment
59
-
extendedKeyUsage = serverAuth, clientAuth
60
-
subjectAltName = @alt_names
50
+
openssl_cnf = pkgs.writeText "openssl.cnf" ''
52
+
distinguished_name = req_distinguished_name
53
+
[req_distinguished_name]
55
+
basicConstraints = CA:FALSE
56
+
keyUsage = digitalSignature, keyEncipherment
57
+
extendedKeyUsage = serverAuth, clientAuth
58
+
subjectAltName = @alt_names
68
-
client_openssl_cnf = pkgs.writeText "client-openssl.cnf" ''
70
-
distinguished_name = req_distinguished_name
71
-
[req_distinguished_name]
73
-
basicConstraints = CA:FALSE
74
-
keyUsage = digitalSignature, keyEncipherment
75
-
extendedKeyUsage = clientAuth
66
+
client_openssl_cnf = pkgs.writeText "client-openssl.cnf" ''
68
+
distinguished_name = req_distinguished_name
69
+
[req_distinguished_name]
71
+
basicConstraints = CA:FALSE
72
+
keyUsage = digitalSignature, keyEncipherment
73
+
extendedKeyUsage = clientAuth
83
-
certFile = etcd_cert;
84
-
trustedCaFile = ca_pem;
85
-
clientCertAuth = true;
86
-
listenClientUrls = [ "https://127.0.0.1:2379" ];
87
-
listenPeerUrls = [ "https://0.0.0.0:2380" ];
81
+
certFile = etcd_cert;
82
+
trustedCaFile = ca_pem;
83
+
clientCertAuth = true;
84
+
listenClientUrls = [ "https://127.0.0.1:2379" ];
85
+
listenPeerUrls = [ "https://0.0.0.0:2380" ];
91
-
environment.variables = {
92
-
ETCD_CERT_FILE = "${etcd_client_cert}";
93
-
ETCD_KEY_FILE = "${etcd_client_key}";
94
-
ETCD_CA_FILE = "${ca_pem}";
95
-
ETCDCTL_ENDPOINTS = "https://127.0.0.1:2379";
96
-
ETCDCTL_CACERT = "${ca_pem}";
97
-
ETCDCTL_CERT = "${etcd_cert}";
98
-
ETCDCTL_KEY = "${etcd_key}";
89
+
environment.variables = {
90
+
ETCD_CERT_FILE = "${etcd_client_cert}";
91
+
ETCD_KEY_FILE = "${etcd_client_key}";
92
+
ETCD_CA_FILE = "${ca_pem}";
93
+
ETCDCTL_ENDPOINTS = "https://127.0.0.1:2379";
94
+
ETCDCTL_CACERT = "${ca_pem}";
95
+
ETCDCTL_CERT = "${etcd_cert}";
96
+
ETCDCTL_KEY = "${etcd_key}";
101
-
networking.firewall.allowedTCPPorts = [ 2380 ];
105
-
name = "etcd-cluster";
99
+
networking.firewall.allowedTCPPorts = [ 2380 ];
103
+
name = "etcd-cluster";
107
-
meta = with pkgs.lib.maintainers; {
108
-
maintainers = [ offline ];
105
+
meta.maintainers = with lib.maintainers; [ offline ];
115
-
require = [ nodeConfig ];
118
-
"node1=https://node1:2380"
119
-
"node2=https://node2:2380"
121
-
initialAdvertisePeerUrls = [ "https://node1:2380" ];
111
+
require = [ nodeConfig ];
114
+
"node1=https://node1:2380"
115
+
"node2=https://node2:2380"
117
+
initialAdvertisePeerUrls = [ "https://node1:2380" ];
128
-
require = [ nodeConfig ];
131
-
"node1=https://node1:2380"
132
-
"node2=https://node2:2380"
134
-
initialAdvertisePeerUrls = [ "https://node2:2380" ];
124
+
require = [ nodeConfig ];
127
+
"node1=https://node1:2380"
128
+
"node2=https://node2:2380"
130
+
initialAdvertisePeerUrls = [ "https://node2:2380" ];
141
-
require = [ nodeConfig ];
144
-
"node1=https://node1:2380"
145
-
"node2=https://node2:2380"
146
-
"node3=https://node3:2380"
148
-
initialAdvertisePeerUrls = [ "https://node3:2380" ];
149
-
initialClusterState = "existing";
137
+
require = [ nodeConfig ];
140
+
"node1=https://node1:2380"
141
+
"node2=https://node2:2380"
142
+
"node3=https://node3:2380"
144
+
initialAdvertisePeerUrls = [ "https://node3:2380" ];
145
+
initialClusterState = "existing";
155
-
with subtest("should start etcd cluster"):
158
-
node1.wait_for_unit("etcd.service")
159
-
node2.wait_for_unit("etcd.service")
160
-
node2.wait_until_succeeds("etcdctl endpoint status")
161
-
node1.succeed("etcdctl put /foo/bar 'Hello world'")
162
-
node2.succeed("etcdctl get /foo/bar | grep 'Hello world'")
151
+
with subtest("should start etcd cluster"):
154
+
node1.wait_for_unit("etcd.service")
155
+
node2.wait_for_unit("etcd.service")
156
+
node2.wait_until_succeeds("etcdctl endpoint status")
157
+
node1.succeed("etcdctl put /foo/bar 'Hello world'")
158
+
node2.succeed("etcdctl get /foo/bar | grep 'Hello world'")
164
-
with subtest("should add another member"):
165
-
node1.wait_until_succeeds("etcdctl member add node3 --peer-urls=https://node3:2380")
167
-
node3.wait_for_unit("etcd.service")
168
-
node3.wait_until_succeeds("etcdctl member list | grep 'node3'")
169
-
node3.succeed("etcdctl endpoint status")
160
+
with subtest("should add another member"):
161
+
node1.wait_until_succeeds("etcdctl member add node3 --peer-urls=https://node3:2380")
163
+
node3.wait_for_unit("etcd.service")
164
+
node3.wait_until_succeeds("etcdctl member list | grep 'node3'")
165
+
node3.succeed("etcdctl endpoint status")
171
-
with subtest("should survive member crash"):
173
-
node1.succeed("etcdctl endpoint status")
174
-
node1.succeed("etcdctl put /foo/bar 'Hello degraded world'")
175
-
node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")
167
+
with subtest("should survive member crash"):
169
+
node1.succeed("etcdctl endpoint status")
170
+
node1.succeed("etcdctl put /foo/bar 'Hello degraded world'")
171
+
node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")