Skip to content

Commit eb6bd08

Browse files
author
Matt Pryor
authored
Document applying integration tests to deployments (azimuth-cloud#129)
* Initial commit of testing docs * First pass at testing docs * Add run-tests script * Add test jobs to the sample GitLab config + document * Add testing to best practice doc * Add documentation about generating an unrestricted appcred * Add small clarification * Remove test generation from run-tests script * Rework CI jobs to better support multiple appcreds for testing * Incorporate review suggestions
1 parent b090a56 commit eb6bd08

File tree

14 files changed

+587
-49
lines changed

14 files changed

+587
-49
lines changed

.github/environments/arcus-ha/ansible.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[defaults]
2-
inventory = ../../../environments/base/inventory,../../../environments/ha/inventory,../../../environments/demo/inventory,../arcus/inventory,./inventory
2+
inventory = ../../../environments/base/inventory,../../../environments/ha/inventory,../../../environments/demo/inventory,../common/inventory,../arcus/inventory,./inventory
33
roles_path = ../../../.ansible/roles
44
collections_path = ../../../.ansible/collections
55

.github/environments/arcus/ansible.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[defaults]
2-
inventory = ../../../environments/base/inventory,../../../environments/singlenode/inventory,../../../environments/demo/inventory,./inventory
2+
inventory = ../../../environments/base/inventory,../../../environments/singlenode/inventory,../../../environments/demo/inventory,../common/inventory,./inventory
33
roles_path = ../../../.ansible/roles
44
collections_path = ../../../.ansible/collections
55

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
3+
#####
4+
# This file defines the test cases used in CI
5+
#####
6+
7+
#-----
8+
# Settings for the CaaS test suite
9+
#-----
10+
# Only generate tests for specifically enabled cluster types
11+
generate_tests_caas_default_test_case_enabled: false
12+
13+
# Enable the workstation, slurm, repo2docker and rstudio test cases
14+
generate_tests_caas_test_case_workstation_enabled: true
15+
generate_tests_caas_test_case_slurm_enabled: true
16+
generate_tests_caas_test_case_repo2docker_enabled: true
17+
generate_tests_caas_test_case_rstudio_enabled: true
18+
19+
#-----
20+
# Settings for the Kubernetes test suite
21+
#-----
22+
# Generate test cases for the most recent Kubernetes versions only
23+
generate_tests_kubernetes_test_cases_latest_only: true
24+
25+
#-----
26+
# Settings for the Kubernetes apps test suite
27+
#-----
28+
# Only generate tests for specifically enabled app templates
29+
generate_tests_kubernetes_apps_default_test_case_enabled: false
30+
31+
# Enable the jupyterhub and daskhub apps
32+
generate_tests_kubernetes_apps_test_case_jupyterhub_enabled: true
33+
generate_tests_kubernetes_apps_test_case_daskhub_enabled: true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# This file exists so that Ansible treats the directory as an inventory
2+
3+
[terraform_provision]
4+
# This group should contain the hosts that are used to provision the infrastructure
5+
# onto which Azimuth will be deployed
6+
# E.g.:
7+
# localhost ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"

.github/environments/leafcloud-ha/ansible.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[defaults]
2-
inventory = ../../../environments/base/inventory,../../../environments/ha/inventory,../../../environments/demo/inventory,../leafcloud/inventory,./inventory
2+
inventory = ../../../environments/base/inventory,../../../environments/ha/inventory,../../../environments/demo/inventory,../common/inventory,../leafcloud/inventory,./inventory
33
roles_path = ../../../.ansible/roles
44
collections_path = ../../../.ansible/collections
55

.github/environments/leafcloud/ansible.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[defaults]
2-
inventory = ../../../environments/base/inventory,../../../environments/singlenode/inventory,../../../environments/demo/inventory,./inventory
2+
inventory = ../../../environments/base/inventory,../../../environments/singlenode/inventory,../../../environments/demo/inventory,../common/inventory,./inventory
33
roles_path = ../../../.ansible/roles
44
collections_path = ../../../.ansible/collections
55

.gitlab-ci.yml.sample

Lines changed: 127 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ variables:
77
# Because we are installing git-crypt as part of the job, we cannot reuse old
88
# checkouts where git-crypt is already initialised as this results in an error
99
GIT_STRATEGY: clone
10-
# Write the Azimuth URL to an envfile in the local directory
11-
AZIMUTH_URL_ENVFILE: ${CI_PROJECT_DIR}/azimuth.env
1210
# Use the pipeline credentials for Terraform
1311
# This assumes that we are using GitLab-managed Terraform state (recommended when available)
1412
TF_HTTP_USERNAME: gitlab-ci-token
@@ -19,10 +17,16 @@ stages:
1917
- scheduled
2018
# This stage owns the deploy and teardown jobs for dynamic environments
2119
- aio
22-
# This stage owns the deploy job for our staging environment
20+
# This stage runs tests for dynamic environments
21+
- aio_test
22+
# This stage owns the deploy job for the staging environment
2323
- staging
24-
# This stage owns the deploy job for our production environment
24+
# This stage owns the test job for the staging environment
25+
- staging_test
26+
# This stage owns the deploy job for the production environment
2527
- production
28+
# This stage owns the test job for the production environment
29+
- production_test
2630

2731
#####
2832
# This job checks to see if there is a new release that needs to be merged
@@ -76,9 +80,7 @@ check_for_release:
7680
fi
7781

7882
#####
79-
# This job deploys a dynamic review environment for the current branch
80-
#
81-
# Runs for every commit to every branch except main
83+
# This job deploys a dynamic review environment for a merge request
8284
#
8385
# Each environment is a single node deployment that is isolated from the other
8486
# branches with it's own GitLab environment, Terraform state and OpenStack resources
@@ -98,8 +100,8 @@ deploy_aio:
98100
when: never
99101
# Allow deployments to be manually triggered even when there are no changed files
100102
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "web"
101-
# Run when there is a push to a branch that is not main changes one of the relevant files
102-
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "push"
103+
# Run when there is a push to a branch with a merge request that changes one of the relevant files
104+
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "merge_request_event"
103105
changes:
104106
# Files that affect the aio environment
105107
- env
@@ -109,19 +111,52 @@ deploy_aio:
109111
- environments/singlenode/**/*
110112
- environments/site/**/*
111113
- environments/aio/**/*
112-
artifacts:
113-
reports:
114-
dotenv: azimuth.env
115114
environment:
116115
name: aio/$CI_COMMIT_REF_SLUG
117-
url: $AZIMUTH_URL
118116
on_stop: stop_aio
119117
variables:
120118
# This is normally taken from the GitLab environment name, but in this case that
121119
# depends on the branch name so we need to be explicit about the config to use
122120
AZIMUTH_CONFIG_ENVIRONMENT: aio
121+
ANSIBLE_FORCE_COLOR: true
122+
before_script:
123+
- source ./bin/ci-setup
123124
script:
124-
- ./bin/ci-exec provision
125+
- ansible-playbook stackhpc.azimuth_ops.provision
126+
127+
#####
128+
# This job executes tests against dynamic review environments each time they are deployed
129+
#####
130+
test_aio:
131+
stage: aio_test
132+
rules:
133+
# Do not run for commits to main
134+
- if: $CI_COMMIT_BRANCH == "main"
135+
when: never
136+
# Allow deployments to be manually triggered even when there are no changed files
137+
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "web"
138+
# Run when there is a push to a branch with a merge request that changes one of the relevant files
139+
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "merge_request_event"
140+
changes:
141+
# Files that affect the aio environment
142+
- env
143+
- env.secret
144+
- requirements.yml
145+
- environments/base/**/*
146+
- environments/singlenode/**/*
147+
- environments/site/**/*
148+
- environments/aio/**/*
149+
environment:
150+
name: aio/$CI_COMMIT_REF_SLUG
151+
variables:
152+
AZIMUTH_CONFIG_ENVIRONMENT: aio
153+
ANSIBLE_FORCE_COLOR: true
154+
before_script:
155+
- source ./bin/ci-setup
156+
script:
157+
- ansible-playbook stackhpc.azimuth_ops.generate_tests
158+
# Use the unrestricted application credential to execute the tests, as per the docs
159+
- OS_CLOUD=unrestricted ./bin/run-tests
125160

126161
#####
127162
# This job tears down dynamic review environments
@@ -139,7 +174,7 @@ stop_aio:
139174
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "web"
140175
when: manual
141176
allow_failure: true
142-
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "push"
177+
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "merge_request_event"
143178
changes:
144179
# Files that affect the aio environment
145180
- env
@@ -157,14 +192,16 @@ stop_aio:
157192
variables:
158193
AZIMUTH_CONFIG_ENVIRONMENT: aio
159194
GIT_STRATEGY: none
195+
ANSIBLE_FORCE_COLOR: true
160196
before_script:
161197
- git clone ${CI_REPOSITORY_URL} ${CI_PROJECT_NAME}
162198
- cd ${CI_PROJECT_NAME}
163199
# Use the commit SHA if it still exists because git garbage collection hasn't run yet
164200
# If not, assume the branch has been merged and run the destroy from main instead
165201
- git checkout ${CI_COMMIT_SHA} || git checkout main
202+
- source ./bin/ci-setup
166203
script:
167-
- ./bin/ci-exec destroy
204+
- ansible-playbook stackhpc.azimuth_ops.destroy
168205

169206
#####
170207
# This job deploys Azimuth to the staging environment
@@ -192,14 +229,48 @@ deploy_staging:
192229
- environments/site/**/*
193230
- environments/site-ha/**/*
194231
- environments/staging/**/*
195-
artifacts:
196-
reports:
197-
dotenv: azimuth.env
198232
environment:
199233
name: staging
200-
url: $AZIMUTH_URL
234+
variables:
235+
ANSIBLE_FORCE_COLOR: true
236+
before_script:
237+
- source ./bin/ci-setup
238+
script:
239+
- ansible-playbook stackhpc.azimuth_ops.provision
240+
241+
#####
242+
# This job executes tests against the staging environment each time it is deployed
243+
#####
244+
test_staging:
245+
stage: staging_test
246+
rules:
247+
# Prevent the job from running on any branch that is not main
248+
- if: $CI_COMMIT_BRANCH != "main"
249+
when: never
250+
# Allow deployments to be manually triggered on main even when there are no changed files
251+
- if: $CI_PIPELINE_SOURCE == "web"
252+
# Run for commits to main that change particular files
253+
- if: $CI_PIPELINE_SOURCE == "push"
254+
changes:
255+
# Files that affect the staging environment
256+
- env
257+
- env.secret
258+
- requirements.yml
259+
- environments/base/**/*
260+
- environments/ha/**/*
261+
- environments/site/**/*
262+
- environments/site-ha/**/*
263+
- environments/staging/**/*
264+
environment:
265+
name: staging
266+
variables:
267+
ANSIBLE_FORCE_COLOR: true
268+
before_script:
269+
- source ./bin/ci-setup
201270
script:
202-
- ./bin/ci-exec provision
271+
- ansible-playbook stackhpc.azimuth_ops.generate_tests
272+
# Use the unrestricted application credential to execute the tests, as per the docs
273+
- OS_CLOUD=unrestricted ./bin/run-tests
203274

204275
#####
205276
# This job deploys Azimuth to the production environment
@@ -231,11 +302,41 @@ deploy_production:
231302
- environments/site-ha/**/*
232303
- environments/production/**/*
233304
when: manual
234-
artifacts:
235-
reports:
236-
dotenv: azimuth.env
237305
environment:
238306
name: production
239-
url: $AZIMUTH_URL
307+
variables:
308+
ANSIBLE_FORCE_COLOR: true
309+
before_script:
310+
- source ./bin/ci-setup
311+
script:
312+
- ansible-playbook stackhpc.azimuth_ops.provision
313+
314+
#####
315+
# This job executes tests against the production environment each time it is deployed
316+
#####
317+
test_production:
318+
stage: production_test
319+
rules:
320+
- if: $CI_COMMIT_BRANCH != "main"
321+
when: never
322+
- if: $CI_PIPELINE_SOURCE == "web"
323+
- if: $CI_PIPELINE_SOURCE == "push"
324+
changes:
325+
- env
326+
- env.secret
327+
- requirements.yml
328+
- environments/base/**/*
329+
- environments/ha/**/*
330+
- environments/site/**/*
331+
- environments/site-ha/**/*
332+
- environments/production/**/*
333+
environment:
334+
name: production
335+
variables:
336+
ANSIBLE_FORCE_COLOR: true
337+
before_script:
338+
- source ./bin/ci-setup
240339
script:
241-
- ./bin/ci-exec provision
340+
- ansible-playbook stackhpc.azimuth_ops.generate_tests
341+
# Use the unrestricted application credential to execute the tests, as per the docs
342+
- OS_CLOUD=unrestricted ./bin/run-tests

bin/ci-exec renamed to bin/ci-setup

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
11
#!/usr/bin/env bash
22

33
#####
4-
# This script is designed to be run in a CI pipeline in an isolated Ubuntu Jammy environment
4+
# This script performs setup for a CI job in a clean Ubuntu Jammy environment
55
#####
66

77
set -eo pipefail
88

9-
case "$1" in
10-
provision | destroy)
11-
echo "Executing operation '$1'..."
12-
AZIMUTH_OPERATION="$1"
13-
;;
14-
*)
15-
echo "No operation given - please specify either 'provision' or 'destroy'"
16-
exit 1
17-
;;
18-
esac
19-
20-
# Now we have processed the operation, drop the argument
21-
shift
22-
239
# Runs apt with sudo only if required
2410
# Required for environments where sudo is not present
2511
function run_apt {
@@ -55,11 +41,9 @@ fi
5541

5642
run_apt update
5743
run_apt install -y git python3 python3-pip qemu-utils
44+
5845
pip install -U pip
5946
pip install -r requirements.txt
6047

6148
source ./bin/activate "$AZIMUTH_CONFIG_ENVIRONMENT" "$AZIMUTH_ENVIRONMENT"
6249
ansible-galaxy install -f -r requirements.yml
63-
# Force Ansible to print colours for nicer logs
64-
export ANSIBLE_FORCE_COLOR=true
65-
exec ansible-playbook "stackhpc.azimuth_ops.${AZIMUTH_OPERATION}" "$@"

bin/run-tests

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
3+
#####
4+
## This script generates and then runs tests for the active environment
5+
#####
6+
7+
set -exo pipefail
8+
9+
10+
if [ -z "$AZIMUTH_CONFIG_ROOT" ] || [ -z "$AZIMUTH_CONFIG_ENVIRONMENT_ROOT" ]; then
11+
echo "Please activate an environment" >&2
12+
exit 1
13+
fi
14+
15+
16+
ansible_variable() {
17+
ANSIBLE_LOAD_CALLBACK_PLUGINS=true \
18+
ANSIBLE_STDOUT_CALLBACK=json \
19+
ansible -m debug -a "var=$1" all | \
20+
jq -r ".plays[0].tasks[0].hosts.localhost.$1"
21+
}
22+
23+
24+
# Get the test directory
25+
test_directory="$(ansible_variable generate_tests_suite_directory)"
26+
# Use a headless browser by default
27+
export MOZ_HEADLESS="${MOZ_HEADLESS:-"1"}"
28+
# Execute the test suite, including any args we were given
29+
exec robot --loglevel debug --consolecolors on "$@" "$test_directory"

docs/best-practice.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ Merging to `main` will also create a job to deploy to `production`, but that job
110110
manual trigger. Once the change has been validated in `staging`, the job to deploy to `production`
111111
can be actioned.
112112

113+
It is also possible to run [integration tests](./deployment/testing.md) against a
114+
deployment. It is recommended that this is configured to run automatically for at least
115+
`aio` and `staging` environments. It should also be safe to run against `production` as
116+
long as the tests are configured to target an isolated project.
117+
113118
A
114119
[sample GitLab CI/CD configuration](https://github.com/stackhpc/azimuth-config/tree/stable/.gitlab-ci.yml.sample)
115120
is provided that implements this workflow for GitLab-hosted repositories.

0 commit comments

Comments
 (0)