test: add container support

This commit is contained in:
Erik Arvstedt 2020-09-27 12:43:28 +02:00
parent e99b7edb8e
commit fcc67da9f4
No known key found for this signature in database
GPG Key ID: 33312B944DD97846
5 changed files with 129 additions and 1 deletions

89
test/lib/make-container.sh Executable file
View File

@ -0,0 +1,89 @@
#!/usr/bin/env bash
# Usage:
#
# run-tests.sh [--scenario|-s <scenario>] container
#
# Start container and start a shell session with helper commands
# for accessing the container.
# A short command documentation is printed at the start of the session.
# The container is destroyed after exiting the shell.
# An existing container is destroyed before starting.
#
# Supported arguments:
#
# --destroy|-d to destroy
#
# When `run-tests.sh container` from inside an existing shell session,
# the current container is updated without restarting by switching
# its NixOS configuration.
# Use this arg to destroy and restart the container instead.
#
# --no-destroy|-n
#
# By default, all commands destroy an existing container before starting and,
# when appropriate, before exiting.
# This ensures that containers start with no leftover filesystem state from
# previous runs and that containers don't consume system resources after use.
# This args disables auto-destructing containers.
#
#
# run-tests.sh container --run|-r c systemctl status bitcoind
#
# Run a command in the shell session environmentand exit.
# Destroy the container afterwards.
# All arguments following `--run` are used as a command.
# Supports argument '--no-destroy|-n' (see above for an explanation).
#
# Example: Start shell inside container
# run-tests.sh container --run c
#
#
# run-tests.sh [--scenario|-s <scenario>] container --command|--c
#
# Provide a custom extra-container command.
#
# Example:
# run-tests.sh container --command create -s
# Create and start a container without a shell.
#
#
# All extra args are passed to extra-container (unless --command is used):
# run-tests.sh container --build-args --builders 'ssh://worker - - 8'
set -euo pipefail
if [[ $EUID != 0 ]]; then
# NixOS containers require root permissions.
# By using sudo here and not at the user's call-site extra-container can detect if it is running
# inside an existing shell session (by checking an internal environment variable).
exec sudo scenario="$scenario" testDir="$testDir" NIX_PATH="$NIX_PATH" PATH="$PATH" \
scenarioOverridesFile="${scenarioOverridesFile:-}" "$testDir/lib/make-container.sh" "$@"
fi
export containerName=nb-test
containerCommand=shell
while [[ $# > 0 ]]; do
case $1 in
--command|-c)
shift
containerCommand=$1
shift
;;
*)
break
esac
done
containerBin=$(type -P extra-container) || true
if [[ ! ($containerBin && $(realpath $containerBin) == *extra-container-0.5*) ]]; then
echo "Building extra-container. Skip this step by adding extra-container 0.5 to PATH."
nix-build --out-link /tmp/extra-container "$testDir"/../pkgs -A extra-container >/dev/null
export PATH="/tmp/extra-container/bin${PATH:+:}$PATH"
fi
read -d '' src <<EOF || true
(import "$testDir/tests.nix" { scenario = "$scenario"; }).container
EOF
exec extra-container $containerCommand -E "$src" "$@"

View File

@ -38,4 +38,14 @@ scenario: testConfig:
'' ''
]; ];
}; };
container = {
# The container name has a 11 char length limit
containers.nb-test = { config, ...}: {
config = {
extra = config.config.test.container;
config = testConfig;
};
};
};
} }

View File

@ -5,7 +5,7 @@ with lib;
test = { test = {
noConnections = mkOption { noConnections = mkOption {
type = types.bool; type = types.bool;
default = true; default = !config.test.container.enableWAN;
description = '' description = ''
Whether services should be configured to not connect to external hosts. Whether services should be configured to not connect to external hosts.
This can silence some warnings while running the test in an offline environment. This can silence some warnings while running the test in an offline environment.
@ -19,6 +19,15 @@ with lib;
dictionary variable 'test_data'. The data is exported via JSON. dictionary variable 'test_data'. The data is exported via JSON.
''; '';
}; };
container = {
# Forwarded to extra-container. For descriptions, see
# https://github.com/erikarvstedt/extra-container/blob/master/eval-config.nix
addressPrefix = mkOption { default = "10.225.255"; };
enableWAN = mkOption { default = false; };
firewallAllowHost = mkOption { default = true; };
exposeLocalhost = mkOption { default = false; };
};
}; };
tests = mkOption { tests = mkOption {

View File

@ -25,6 +25,14 @@
# This starts the testing VM and drops you into a Python REPL where you can # This starts the testing VM and drops you into a Python REPL where you can
# manually execute the tests from ./tests.py # manually execute the tests from ./tests.py
# #
# Run a test scenario in a container
# sudo ./run-tests.sh [--scenario <scenario>] container
#
# This is useful for quick experiments; containers start much faster than VMs.
# Running the Python test suite in containers is not yet supported.
# For now, creating NixOS containers requires root permissions.
# See ./lib/make-container.sh for a complete documentation.
#
# To add custom scenarios, set the environment variable `scenarioOverridesFile`. # To add custom scenarios, set the environment variable `scenarioOverridesFile`.
set -eo pipefail set -eo pipefail
@ -108,6 +116,10 @@ debug() {
run --interactive run --interactive
} }
container() {
. "$testDir/lib/make-container.sh" "$@"
}
# Run the test by building the test derivation # Run the test by building the test derivation
buildTest() { buildTest() {
if [[ $outLinkPrefix ]]; then if [[ $outLinkPrefix ]]; then

View File

@ -115,6 +115,14 @@ let testEnv = rec {
}; };
}; };
# Container-specific features
containerFeatures = {
# Container has WAN access and bitcoind connects to external nodes
test.container.enableWAN = true;
# See ./lib/test-lib.nix for a description
test.container.exposeLocalhost = true;
};
adhoc = { adhoc = {
# <Add your config here> # <Add your config here>
# You can also set the env var `scenarioOverridesFile` (used below) to define custom scenarios. # You can also set the env var `scenarioOverridesFile` (used below) to define custom scenarios.