158 lines
4.5 KiB
Nix
158 lines
4.5 KiB
Nix
# This test runs simple etcd cluster
|
|
|
|
import ./make-test.nix ({ pkgs, ... } : let
|
|
|
|
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}
|
|
'';
|
|
|
|
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_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
|
|
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
|
|
'';
|
|
|
|
nodeConfig = {
|
|
services = {
|
|
etcd = {
|
|
enable = true;
|
|
keyFile = etcd_key;
|
|
certFile = etcd_cert;
|
|
trustedCaFile = ca_pem;
|
|
peerClientCertAuth = true;
|
|
listenClientUrls = ["https://127.0.0.1:2379"];
|
|
listenPeerUrls = ["https://0.0.0.0:2380"];
|
|
};
|
|
};
|
|
|
|
environment.variables = {
|
|
ETCDCTL_CERT_FILE = "${etcd_client_cert}";
|
|
ETCDCTL_KEY_FILE = "${etcd_client_key}";
|
|
ETCDCTL_CA_FILE = "${ca_pem}";
|
|
ETCDCTL_PEERS = "https://127.0.0.1:2379";
|
|
};
|
|
|
|
networking.firewall.allowedTCPPorts = [ 2380 ];
|
|
};
|
|
in {
|
|
name = "etcd";
|
|
|
|
meta = with pkgs.stdenv.lib.maintainers; {
|
|
maintainers = [ offline ];
|
|
};
|
|
|
|
nodes = {
|
|
node1 = { ... }: {
|
|
require = [nodeConfig];
|
|
services.etcd = {
|
|
initialCluster = ["node1=https://node1:2380" "node2=https://node2:2380"];
|
|
initialAdvertisePeerUrls = ["https://node1:2380"];
|
|
};
|
|
};
|
|
|
|
node2 = { ... }: {
|
|
require = [nodeConfig];
|
|
services.etcd = {
|
|
initialCluster = ["node1=https://node1:2380" "node2=https://node2:2380"];
|
|
initialAdvertisePeerUrls = ["https://node2: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";
|
|
};
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
subtest "should start etcd cluster", sub {
|
|
$node1->start();
|
|
$node2->start();
|
|
$node1->waitForUnit("etcd.service");
|
|
$node2->waitForUnit("etcd.service");
|
|
$node2->waitUntilSucceeds("etcdctl cluster-health");
|
|
$node1->succeed("etcdctl set /foo/bar 'Hello world'");
|
|
$node2->succeed("etcdctl get /foo/bar | grep 'Hello world'");
|
|
};
|
|
|
|
subtest "should add another member", sub {
|
|
$node1->succeed("etcdctl member add node3 https://node3:2380");
|
|
$node3->start();
|
|
$node3->waitForUnit("etcd.service");
|
|
$node3->waitUntilSucceeds("etcdctl member list | grep 'node3'");
|
|
$node3->succeed("etcdctl cluster-health");
|
|
};
|
|
|
|
subtest "should survive member crash", sub {
|
|
$node3->crash;
|
|
$node1->succeed("etcdctl cluster-health");
|
|
$node1->succeed("etcdctl set /foo/bar 'Hello degraded world'");
|
|
$node1->succeed("etcdctl get /foo/bar | grep 'Hello degraded world'");
|
|
};
|
|
'';
|
|
})
|