From fcda69e8b616728cb74fd47ec1672c1b27eb6605 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Sep 2020 12:43:17 +0200 Subject: [PATCH] netns test: connect from main netns All services are reachable from the main netns, no need to enter service network namespaces. This allows us to remove extra_tests. --- test/scenarios/default.py | 53 +------------- test/scenarios/withnetns.py | 138 +++++++++++------------------------- test/tests.py | 55 +++++++++----- 3 files changed, 82 insertions(+), 164 deletions(-) diff --git a/test/scenarios/default.py b/test/scenarios/default.py index e5c1eb0..d9ad19e 100644 --- a/test/scenarios/default.py +++ b/test/scenarios/default.py @@ -1,56 +1,5 @@ -def electrs(): - machine.wait_for_open_port(4224) # prometeus metrics provider - - -def nbxplorer(): - machine.wait_for_open_port(24444) - - -def btcpayserver(): - machine.wait_for_open_port(23000) - # test lnd custom macaroon - assert_matches( - 'sudo -u btcpayserver curl -s --cacert /secrets/lnd-cert --header "Grpc-Metadata-macaroon: $(xxd -ps -u -c 1000 /run/lnd/btcpayserver.macaroon)" -X GET https://127.0.0.1:8080/v1/getinfo | jq', - '"version"', - ) - - -def spark_wallet(): - machine.wait_for_open_port(9737) - spark_auth = re.search("login=(.*)", succeed("cat /secrets/spark-wallet-login"))[1] - assert_matches(f"curl -s {spark_auth}@localhost:9737", "Spark") - - -def lightning_charge(): - machine.wait_for_open_port(9112) - charge_auth = re.search("API_TOKEN=(.*)", succeed("cat /secrets/lightning-charge-env"))[1] - assert_matches(f"curl -s api-token:{charge_auth}@localhost:9112/info | jq", '"id"') - - -def nanopos(): - machine.wait_for_open_port(9116) - assert_matches("curl localhost:9116", "tshirt") - - -def web_index(): - machine.wait_for_open_port(80) - assert_matches("curl localhost", "nix-bitcoin") - assert_matches("curl -L localhost/store", "tshirt") - - def prestop(): pass -extra_tests = { - "electrs": electrs, - "nbxplorer": nbxplorer, - "btcpayserver": btcpayserver, - "spark-wallet": spark_wallet, - "lightning-charge": lightning_charge, - "nanopos": nanopos, - "web-index": web_index, - "prestop": prestop, -} - -run_tests(extra_tests) +run_tests() diff --git a/test/scenarios/withnetns.py b/test/scenarios/withnetns.py index 8aec4f5..5c84fbd 100644 --- a/test/scenarios/withnetns.py +++ b/test/scenarios/withnetns.py @@ -1,65 +1,22 @@ -# netns IP addresses -bitcoind_ip = "169.254.1.12" -clightning_ip = "169.254.1.13" -lnd_ip = "169.254.1.14" -liquidd_ip = "169.254.1.15" -electrs_ip = "169.254.1.16" -sparkwallet_ip = "169.254.1.17" -lightningcharge_ip = "169.254.1.18" -nanopos_ip = "169.254.1.19" -recurringdonations_ip = "169.254.1.20" -nginx_ip = "169.254.1.21" -lightningloop_ip = "169.254.1.22" -nbxplorer_ip = "169.254.1.23" -btcpayserver_ip = "169.254.1.24" +netns_ips = { + "bitcoind": "169.254.1.12", + "clightning": "169.254.1.13", + "lnd": "169.254.1.14", + "liquidd": "169.254.1.15", + "electrs": "169.254.1.16", + "spark-wallet": "169.254.1.17", + "lightning-charge": "169.254.1.18", + "nanopos": "169.254.1.19", + "recurring-donations": "169.254.1.20", + "nginx": "169.254.1.21", + "lightning-loop": "169.254.1.22", + "nbxplorer": "169.254.1.23", + "btcpayserver": "169.254.1.24", +} -def electrs(): - # prometeus metrics provider - machine.wait_until_succeeds(f"nc -z {electrs_ip} 4224") - - -def nbxplorer(): - machine.wait_until_succeeds("ip netns exec nb-nbxplorer nc -z %s 24444" % nbxplorer_ip) - - -def btcpayserver(): - machine.wait_until_succeeds("ip netns exec nb-btcpayserver nc -z %s 23000" % btcpayserver_ip) - # test lnd custom macaroon - assert_matches( - 'ip netns exec nb-btcpayserver sudo -u btcpayserver curl -s --cacert /secrets/lnd-cert --header "Grpc-Metadata-macaroon: $(xxd -ps -u -c 1000 /run/lnd/btcpayserver.macaroon)" -X GET https://%s:8080/v1/getinfo | jq' - % lnd_ip, - '"version"', - ) - - -def spark_wallet(): - machine.wait_until_succeeds("ip netns exec nb-spark-wallet nc -z %s 9737" % sparkwallet_ip) - spark_auth = re.search("login=(.*)", succeed("cat /secrets/spark-wallet-login"))[1] - assert_matches( - f"ip netns exec nb-spark-wallet curl -s {spark_auth}@%s:9737" % sparkwallet_ip, "Spark" - ) - - -def lightning_charge(): - machine.wait_until_succeeds("ip netns exec nb-nanopos nc -z %s 9112" % lightningcharge_ip) - charge_auth = re.search("API_TOKEN=(.*)", succeed("cat /secrets/lightning-charge-env"))[1] - assert_matches( - f"ip netns exec nb-nanopos curl -s api-token:{charge_auth}@%s:9112/info | jq" - % lightningcharge_ip, - '"id"', - ) - - -def nanopos(): - machine.wait_until_succeeds("ip netns exec nb-lightning-charge nc -z %s 9116" % nanopos_ip) - assert_matches("ip netns exec nb-lightning-charge curl %s:9116" % nanopos_ip, "tshirt") - - -def web_index(): - machine.wait_until_succeeds("ip netns exec nb-nginx nc -z localhost 80") - assert_matches("ip netns exec nb-nginx curl localhost", "nix-bitcoin") - assert_matches("ip netns exec nb-nginx curl -L localhost/store", "tshirt") +def ip(netns): + return netns_ips[netns] def prestop(): @@ -69,34 +26,34 @@ def prestop(): # Positive ping tests (non-exhaustive) machine.succeed( - "%s %s &&" % (ping_bitcoind, bitcoind_ip) - + "%s %s &&" % (ping_bitcoind, clightning_ip) - + "%s %s &&" % (ping_bitcoind, lnd_ip) - + "%s %s &&" % (ping_bitcoind, liquidd_ip) - + "%s %s &&" % (ping_bitcoind, nbxplorer_ip) - + "%s %s &&" % (ping_nbxplorer, btcpayserver_ip) - + "%s %s &&" % (ping_nanopos, lightningcharge_ip) - + "%s %s &&" % (ping_nanopos, nanopos_ip) - + "%s %s" % (ping_nanopos, nginx_ip) + "%s %s &&" % (ping_bitcoind, ip("bitcoind")) + + "%s %s &&" % (ping_bitcoind, ip("clightning")) + + "%s %s &&" % (ping_bitcoind, ip("lnd")) + + "%s %s &&" % (ping_bitcoind, ip("liquidd")) + + "%s %s &&" % (ping_bitcoind, ip("nbxplorer")) + + "%s %s &&" % (ping_nbxplorer, ip("btcpayserver")) + + "%s %s &&" % (ping_nanopos, ip("lightning-charge")) + + "%s %s &&" % (ping_nanopos, ip("nanopos")) + + "%s %s" % (ping_nanopos, ip("nginx")) ) # Negative ping tests (non-exhaustive) machine.fail( - "%s %s ||" % (ping_bitcoind, sparkwallet_ip) - + "%s %s ||" % (ping_bitcoind, lightningloop_ip) - + "%s %s ||" % (ping_bitcoind, lightningcharge_ip) - + "%s %s ||" % (ping_bitcoind, nanopos_ip) - + "%s %s ||" % (ping_bitcoind, recurringdonations_ip) - + "%s %s ||" % (ping_bitcoind, nginx_ip) - + "%s %s ||" % (ping_nanopos, bitcoind_ip) - + "%s %s ||" % (ping_nanopos, clightning_ip) - + "%s %s ||" % (ping_nanopos, lnd_ip) - + "%s %s ||" % (ping_nanopos, lightningloop_ip) - + "%s %s ||" % (ping_nanopos, liquidd_ip) - + "%s %s ||" % (ping_nanopos, electrs_ip) - + "%s %s ||" % (ping_nanopos, sparkwallet_ip) - + "%s %s ||" % (ping_nanopos, recurringdonations_ip) - + "%s %s" % (ping_nanopos, btcpayserver_ip) + "%s %s ||" % (ping_bitcoind, ip("spark-wallet")) + + "%s %s ||" % (ping_bitcoind, ip("lightning-loop")) + + "%s %s ||" % (ping_bitcoind, ip("lightning-charge")) + + "%s %s ||" % (ping_bitcoind, ip("nanopos")) + + "%s %s ||" % (ping_bitcoind, ip("recurring-donations")) + + "%s %s ||" % (ping_bitcoind, ip("nginx")) + + "%s %s ||" % (ping_nanopos, ip("bitcoind")) + + "%s %s ||" % (ping_nanopos, ip("clightning")) + + "%s %s ||" % (ping_nanopos, ip("lnd")) + + "%s %s ||" % (ping_nanopos, ip("lightning-loop")) + + "%s %s ||" % (ping_nanopos, ip("liquidd")) + + "%s %s ||" % (ping_nanopos, ip("electrs")) + + "%s %s ||" % (ping_nanopos, ip("spark-wallet")) + + "%s %s ||" % (ping_nanopos, ip("recurring-donations")) + + "%s %s" % (ping_nanopos, ip("btcpayserver")) ) # test that netns-exec can't be run for unauthorized namespace @@ -111,15 +68,4 @@ def prestop(): machine.fail("sudo -u clightning netns-exec nb-bitcoind ip a") -extra_tests = { - "electrs": electrs, - "nbxplorer": nbxplorer, - "btcpayserver": btcpayserver, - "spark-wallet": spark_wallet, - "lightning-charge": lightning_charge, - "nanopos": nanopos, - "web-index": web_index, - "prestop": prestop, -} - -run_tests(extra_tests) +run_tests() diff --git a/test/tests.py b/test/tests.py index a2faf79..284dfd8 100644 --- a/test/tests.py +++ b/test/tests.py @@ -32,11 +32,16 @@ def assert_running(unit): assert_no_failure(unit) -def run_tests(extra_tests): - """ - :param extra_tests: Test functions that hook into the testing code below - :type extra_tests: Dict[str, Callable[]] - """ +def wait_for_open_port(address, port): + def is_port_open(_): + status, _ = machine.execute(f"nc -z {address} {port}") + return status == 0 + + with log.nested(f"Waiting for TCP port {address}:{port}"): + retry(is_port_open) + + +def run_tests(): # Don't execute the following test suite when this script is running in interactive mode if is_interactive: raise Exception() @@ -55,7 +60,7 @@ def run_tests(extra_tests): ) assert_running("electrs") - extra_tests.pop("electrs")() + wait_for_open_port(ip("electrs"), 4224) # prometeus metrics provider # Check RPC connection to bitcoind machine.wait_until_succeeds(log_has_string("electrs", "NetworkInfo")) # Stop electrs from spamming the test log with 'wait for bitcoind sync' messages @@ -86,19 +91,34 @@ def run_tests(extra_tests): assert_running("nbxplorer") machine.wait_until_succeeds(log_has_string("nbxplorer", "BTC: RPC connection successful")) - extra_tests.pop("nbxplorer")() + wait_for_open_port(ip("nbxplorer"), 24444) assert_running("btcpayserver") machine.wait_until_succeeds(log_has_string("btcpayserver", "Listening on")) - extra_tests.pop("btcpayserver")() + wait_for_open_port(ip("btcpayserver"), 23000) + # test lnd custom macaroon + assert_matches( + "sudo -u btcpayserver curl -s --cacert /secrets/lnd-cert " + '--header "Grpc-Metadata-macaroon: $(xxd -ps -u -c 1000 /run/lnd/btcpayserver.macaroon)" ' + f"-X GET https://{ip('lnd')}:8080/v1/getinfo | jq", + '"version"', + ) assert_running("spark-wallet") - extra_tests.pop("spark-wallet")() + wait_for_open_port(ip("spark-wallet"), 9737) + spark_auth = re.search("login=(.*)", succeed("cat /secrets/spark-wallet-login"))[1] + assert_matches(f"curl -s {spark_auth}@{ip('spark-wallet')}:9737", "Spark") assert_running("lightning-charge") - extra_tests.pop("lightning-charge")() + wait_for_open_port(ip("lightning-charge"), 9112) + machine.wait_until_succeeds(f"nc -z {ip('lightning-charge')} 9112") + charge_auth = re.search("API_TOKEN=(.*)", succeed("cat /secrets/lightning-charge-env"))[1] + assert_matches( + f"curl -s api-token:{charge_auth}@{ip('lightning-charge')}:9112/info | jq", '"id"' + ) assert_running("nanopos") - extra_tests.pop("nanopos")() + wait_for_open_port(ip("nanopos"), 9116) + assert_matches(f"curl {ip('nanopos')}:9116", "tshirt") assert_running("onion-chef") @@ -115,7 +135,9 @@ def run_tests(extra_tests): # 'create-web-index' implicitly tests 'nodeinfo'. machine.wait_for_unit("create-web-index") assert_running("nginx") - extra_tests.pop("web-index")() + wait_for_open_port(ip("nginx"), 80) + assert_matches(f"curl {ip('nginx')}", "nix-bitcoin") + assert_matches(f"curl -L {ip('nginx')}/store", "tshirt") machine.wait_until_succeeds(log_has_string("bitcoind-import-banlist", "Importing node banlist")) assert_no_failure("bitcoind-import-banlist") @@ -137,7 +159,7 @@ def run_tests(extra_tests): ) assert_no_failure("bitcoind-import-banlist") - extra_tests.pop("prestop")() + prestop() ### Test duplicity @@ -171,9 +193,6 @@ def run_tests(extra_tests): "var/backup/postgresql/btcpaydb.sql.gz", ) - ### Check that all extra_tests have been run - assert len(extra_tests) == 0 - def test_security(): assert_running("setup-secrets") @@ -191,3 +210,7 @@ def test_security(): ) # The 'operator' with group 'proc' has full access assert_full_match("sudo -u operator systemctl status bitcoind 2>&1 >/dev/null", "") + + +def ip(_): + return "127.0.0.1"