From e6f48a0ee28f705d9109553eff498bb420a67afd Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sun, 14 Mar 2021 20:29:58 +0000
Subject: [PATCH] Add a test driver to run CI tests

---
 .gitlab-ci.yml |  69 ++++++++++++++------------
 float          |  12 ++++-
 test-driver    | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+), 33 deletions(-)
 create mode 100755 test-driver

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 71f8da78..98957c51 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,3 @@
-image: registry.git.autistici.org/ai3/docker/float-runner:master
 
 stages:
   - docker_build
@@ -6,44 +5,34 @@ stages:
 
 variables:
   IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+  BUILD_DIR: build-$CI_JOB_ID
 
-base_test:
+.base_test_template: &base_test
   stage: test
-  script:
-    - mkdir -p .vagrant.d && ln -s $PWD/.vagrant.d $HOME/.vagrant.d
-    - "cd test && timeout 1h with-ssh-key ./run-test.sh --docker ${APT_PROXY_ADDR:+--apt-proxy $APT_PROXY_ADDR} base"
-  tags: [ai3]
-  except:
-    - schedules
-  cache:
-    key: buster
-    paths:
-      - .vagrant.d
-
-base_bullseye_test:
   image: registry.git.autistici.org/ai3/docker/float-runner:bullseye
-  stage: test
-  script:
+  before_script:
     - mkdir -p .vagrant.d && ln -s $PWD/.vagrant.d $HOME/.vagrant.d
-    - "cd test && timeout 1h with-ssh-key env ANSIBLE_PYTHON_INTERPRETER=/usr/bin/python3 ./run-test.sh --docker ${APT_PROXY_ADDR:+--apt-proxy $APT_PROXY_ADDR} base-bullseye"
-  tags: [ai3]
-  except:
-    - schedules
-  cache:
-    key: buster
-    paths:
-      - .vagrant.d
-
-full_test:
-  stage: test
   script:
-    - mkdir -p .vagrant.d && ln -s $PWD/.vagrant.d $HOME/.vagrant.d
-    - "cd test && timeout 1h with-ssh-key ./run-test.sh --save-logs ${CI_PROJECT_DIR}/test-logs --docker --wait-time 300 ${APT_PROXY_ADDR:+--apt-proxy $APT_PROXY_ADDR} full"
+    - mkdir -p $BUILD_DIR
+    - ./float create-env \
+          --domain=example.com \
+          --services=${TEST_DIR}/services.yml \
+          --passwords=${TEST_DIR}/passwords.yml \
+          --num-hosts=1 \
+          ${LIBVIRT:+-e libvirt.remote_host=${LIBVIRT#*@} -e libvirt.remote_user=${LIBVIRT%@*}} \
+          ${MITOGEN:+-e ansible_cfg.defaults.strategy=mitogen_linear} \
+          $CREATE_ENV_VARS $BUILD_DIR
+    - ./test-driver init $BUILD_DIR
+    - with-ssh-key ./test-driver run $BUILD_DIR
+  after_script:
+    - ./test-driver cleanup $BUILD_DIR
+  variables:
+    CREATE_ENV_VARS: ""
+    TEST_DIR: ""
   tags: [ai3]
-  only:
+  except:
     - schedules
   cache:
-    key: buster
     paths:
       - .vagrant.d
   artifacts:
@@ -51,7 +40,23 @@ full_test:
     expire_in: 1 week
     name: "${CI_JOB_NAME}_${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHORT_SHA}"
     paths:
-      - test-logs
+      - "${BUILD_DIR}/logs"
+
+base_test:
+  <<: *base_test
+  variables:
+    TEST_DIR: "test/base.ref"
+
+base_bullseye_test:
+  <<: *base_test
+  variables:
+    CREATE_ENV_VARS: "-e config.float_debian_dist=bullseye"
+    TEST_DIR: "test/base.ref"
+
+full_test:
+  <<: *base_test
+  variables:
+    TEST_DIR: "test/full.ref"
 
 docker_build_and_release_tests:
   stage: docker_build
diff --git a/float b/float
index 0e0995a7..acd6d29c 100755
--- a/float
+++ b/float
@@ -78,6 +78,7 @@ ANSIBLE_CFG_TEMPLATE = '''
 # Skeleton directories that should be created.
 SKEL_DIRS = [
     'credentials',
+    'credentials/x509',
     'group_vars/all',
     'playbooks',
 ]
@@ -94,6 +95,15 @@ services_file: services.yml
 hosts_file: hosts.yml
 passwords_file: passwords.yml
 credentials_dir: credentials
+''',
+    'credentials/x509/dhparam': '''-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEAnFKabVK0PhdBAr3X+8QZp2pkD8DWsrBBnPMSF3SySVy+rW5xlfsx
+Y1KiP+pEbTA4OLhdKPI4hncFv7/RamhfVq0tcNmf2kKUDxcW4dBg+C+obAc76AYn
+4DyZnodSNvPab8rgNjK2O3zX5q72L5p3SRMfE5X5t3au7d7zyg9wXN2BTqxIMQUh
+PuHYpiji6G3rrGMItnTuHOBr0FB+HW/J2UsB5md/rxL/HzqOQhRlFjc1+sH8VcoR
+FqRAHyKEu6BNYVdfA1eWn++V2lO8BavLRCmdGGpTARoGJWaB+ckQZknM4KarmAR2
+VVSaq+sWqN+ugjpj9sJ++/O1uSiUPNZdIwIBAg==
+-----END DH PARAMETERS-----
 ''',
 
     # If you do not specify custom paths, services.yml / passwords.yml
@@ -122,7 +132,7 @@ include:
 ''',
 }
 
-
+# Internal configuration, used in the above templates.
 DEFAULT_VARS = {
     # Paths, some set by command-line options.
     'srcdir': SRCDIR,
diff --git a/test-driver b/test-driver
new file mode 100755
index 00000000..c3789eb0
--- /dev/null
+++ b/test-driver
@@ -0,0 +1,130 @@
+#!/bin/sh
+
+# Find the absolute path to this script's directory
+# (so that we can find the 'float' root dir).
+bin_dir=$(dirname "$0")
+bin_dir=${bin_dir:-.}
+bin_dir=$(cd "${bin_dir}" && pwd)
+float_dir="${bin_dir}"
+
+log() {
+    echo >&2
+    echo " [*] $*" >&2
+    echo >&2
+}
+
+die() {
+    echo "ERROR: $*" >&2
+    exit 1
+}
+
+start_vagrant() {
+    log Starting VMs
+    vagrant box update
+    vagrant up ${VAGRANT_PROVIDER:+--provider ${VAGRANT_PROVIDER}}
+    return $?
+}
+
+stop_vagrant() {
+    log Stopping VMs
+    vagrant destroy --force --parallel
+}
+
+wait_for_vms() {
+    log Waiting for VMs to become available
+
+    # Wait at most 30 seconds for the vms to become reachable.
+    local i=0
+    local ok=1
+    while [ $i -lt 10 ]; do
+        sleep 3
+        if ansible -v -i config.yml all -m ping; then
+            ok=0
+            break
+        fi
+        i=$(($i + 1))
+    done
+    return $ok
+}
+
+save_logs() {
+    local out_dir="$1"
+
+    ANSIBLE_STDOUT_CALLBACK=unixy \
+    ${float_dir}/float run --extra-vars "out_dir=$out_dir" \
+        ${float_dir}/test/save-logs.yml
+}
+
+run_init() {
+    start_vagrant \
+        || die "could not start VMs"
+
+    log Running init-credentials playbook
+    ${float_dir}/float run init-credentials.yml \
+        || die "failed to run the init-credentials playbook"
+
+    log Running main playbook
+    ${float_dir}/float run site.yml \
+        || die "failed to run the main playbook"
+
+    wait_for_vms \
+        || die "could not reach the VMs with Ansible"
+}
+
+run_cleanup() {
+    stop_vagrant
+}
+
+usage() {
+    cat <<EOF
+Usage: test-driver [COMMAND] [DIR]
+Commands:
+
+  init       Initialize the test environment (turn up VMs, set up
+             credentials, run the main float playbook)
+
+  cleanup    Cleanup the test environment (turn down VMs, etc)
+
+  run        Run the test suite, using the playbook specified by
+             an additional command-line argument
+
+If DIR is specified, chdir there before running anything.
+
+EOF
+    exit 2
+}
+
+cmd="$1"
+shift
+
+if [ $# -gt 0 ]; then
+    cd "$1"
+    shift
+fi
+
+case "$cmd" in
+    init)
+        run_init
+        ;;
+
+    cleanup)
+        save_logs logs
+        run_cleanup
+        ;;
+
+    run)
+        what="${float_dir}/test/integration-test-docker.yml"
+        if [ $# -gt 0]; then
+            what="$1"
+        fi
+        log Running test playbook ${what}
+        ${float_dir}/float run ${what} \
+            || die "test playbook failed"
+        ;;
+
+    *)
+        usage
+        ;;
+esac
+
+exit 0
-- 
GitLab