Skip to content

Commit 69af2d6

Browse files
authored
Implement runner for e2e tests (zalando#548)
* implement a runner for e2e tests * move e2e tests to a Docker container * integrate e2e tests into build pipelines * add tests for multi-namespace support and logical backup jobs * @FxKu implement the first e2e test for failovers
1 parent ec5b1d4 commit 69af2d6

11 files changed

+507
-4
lines changed

.flake8

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
exclude=.git,__pycache__
3+
max-line-length=120

.gitignore

+56
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,59 @@ scm-source.json
3434
# diagrams
3535
*.aux
3636
*.log
37+
38+
# Python
39+
# Adapted from https://github.com/github/gitignore/blob/master/Python.gitignore
40+
41+
# Byte-compiled / optimized / DLL files
42+
__pycache__/
43+
*.py[cod]
44+
*$py.class
45+
46+
# Distribution / packaging
47+
.Python
48+
build/
49+
develop-eggs/
50+
dist/
51+
downloads/
52+
eggs/
53+
.eggs/
54+
lib/
55+
lib64/
56+
parts/
57+
sdist/
58+
var/
59+
wheels/
60+
pip-wheel-metadata/
61+
share/python-wheels/
62+
*.egg-info/
63+
.installed.cfg
64+
*.egg
65+
MANIFEST
66+
67+
# PyInstaller
68+
# Usually these files are written by a python script from a template
69+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
70+
*.manifest
71+
*.spec
72+
73+
# Installer logs
74+
pip-log.txt
75+
pip-delete-this-directory.txt
76+
77+
# Unit test / coverage reports
78+
htmlcov/
79+
.tox/
80+
.nox/
81+
.coverage
82+
.coverage.*
83+
.cache
84+
nosetests.xml
85+
coverage.xml
86+
*.cover
87+
.hypothesis/
88+
.pytest_cache/
89+
90+
# Translations
91+
*.mo
92+
*.pot

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ before_install:
1515
- go get github.com/mattn/goveralls
1616

1717
install:
18-
- make deps
18+
- make deps e2e-tools e2e-build
1919

2020
script:
2121
- hack/verify-codegen.sh
2222
- travis_wait 20 goveralls -service=travis-ci -package ./pkg/... -v
23+
- make e2e-run

Makefile

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: clean local test linux macos docker push scm-source.json
1+
.PHONY: clean local test linux macos docker push scm-source.json e2e-run e2e-tools e2e-build
22

33
BINARY ?= postgres-operator
44
BUILD_FLAGS ?= -v
@@ -34,7 +34,7 @@ ifdef CDP_PULL_REQUEST_NUMBER
3434
CDP_TAG := -${CDP_BUILD_VERSION}
3535
endif
3636

37-
37+
KIND_PATH := $(GOPATH)/bin
3838
PATH := $(GOPATH)/bin:$(PATH)
3939
SHELL := env PATH=$(PATH) $(SHELL)
4040

@@ -91,3 +91,16 @@ deps:
9191
test:
9292
hack/verify-codegen.sh
9393
@go test ./...
94+
95+
e2e-build:
96+
docker build --tag="postgres-operator-e2e-tests" -f e2e/Dockerfile .
97+
98+
e2e-tools:
99+
# install pinned version of 'kind'
100+
# leave the name as is to avoid overwriting official binary named `kind`
101+
wget https://github.com/kubernetes-sigs/kind/releases/download/v0.3.0/kind-linux-amd64
102+
chmod +x kind-linux-amd64
103+
mv kind-linux-amd64 $(KIND_PATH)
104+
105+
e2e-run: docker
106+
e2e/run.sh

delivery.yaml

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pipeline:
1111
apt-get update
1212
- desc: 'Install required build software'
1313
cmd: |
14-
apt-get install -y make git apt-transport-https ca-certificates curl build-essential
14+
apt-get install -y make git apt-transport-https ca-certificates curl build-essential python3 python3-pip
1515
- desc: 'Install go'
1616
cmd: |
1717
cd /tmp
@@ -41,6 +41,10 @@ pipeline:
4141
export PATH=$PATH:$HOME/go/bin
4242
cd $OPERATOR_TOP_DIR/postgres-operator
4343
go test ./...
44+
- desc: 'Run e2e tests'
45+
cmd: |
46+
cd $OPERATOR_TOP_DIR/postgres-operator
47+
make e2e-tools e2e-build e2e-run
4448
- desc: 'Push docker image'
4549
cmd: |
4650
export PATH=$PATH:$HOME/go/bin

docs/developer.md

+10
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,16 @@ Then you can for example check the Patroni logs:
322322
kubectl logs acid-minimal-cluster-0
323323
```
324324

325+
## End-to-end tests
326+
327+
The operator provides reference e2e (end-to-end) tests to ensure various infra parts work smoothly together.
328+
Each e2e execution tests a Postgres operator image built from the current git branch. The test runner starts a [kind](https://kind.sigs.k8s.io/) (local k8s) cluster and Docker container with tests. The k8s API client from within the container connects to the `kind` cluster using the standard Docker `bridge` network.
329+
The tests utilize examples from `/manifests` (ConfigMap is used for the operator configuration) to avoid maintaining yet another set of configuration files. The kind cluster is deleted if tests complete successfully.
330+
331+
End-to-end tests are executed automatically during builds; to invoke them locally use `make e2e-run` from the project's top directory. Run `make e2e-tools e2e-build` to install `kind` and build the tests' image locally before the first run.
332+
333+
End-to-end tests are written in Python and use `flake8` for code quality. Please run flake8 [before submitting a PR](http://flake8.pycqa.org/en/latest/user/using-hooks.html).
334+
325335
## Introduce additional configuration parameters
326336

327337
In the case you want to add functionality to the operator that shall be

e2e/Dockerfile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM ubuntu:18.04
2+
LABEL maintainer="Team ACID @ Zalando <[email protected]>"
3+
4+
WORKDIR /e2e
5+
6+
COPY manifests ./manifests
7+
COPY e2e/requirements.txt e2e/tests ./
8+
9+
RUN apt-get update \
10+
&& apt-get install --no-install-recommends -y \
11+
python3 \
12+
python3-setuptools \
13+
python3-pip \
14+
curl \
15+
&& pip3 install --no-cache-dir -r requirements.txt \
16+
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/linux/amd64/kubectl \
17+
&& chmod +x ./kubectl \
18+
&& mv ./kubectl /usr/local/bin/kubectl \
19+
&& apt-get clean \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
CMD ["python3", "-m", "unittest", "discover", "--start-directory", ".", "-v"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Cluster
2+
apiVersion: kind.sigs.k8s.io/v1alpha3
3+
nodes:
4+
- role: control-plane
5+
- role: worker
6+
- role: worker

e2e/requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kubernetes==9.0.0
2+
timeout_decorator==0.4.1
3+
pyyaml==5.1

e2e/run.sh

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env bash
2+
3+
# enable unofficial bash strict mode
4+
set -o errexit
5+
set -o nounset
6+
set -o pipefail
7+
IFS=$'\n\t'
8+
9+
readonly cluster_name="postgres-operator-e2e-tests"
10+
readonly operator_image=$(docker images --filter=reference="registry.opensource.zalan.do/acid/postgres-operator" --format "{{.Repository}}:{{.Tag}}" | head -1)
11+
readonly e2e_test_image=${cluster_name}
12+
readonly kubeconfig_path="/tmp/kind-config-${cluster_name}"
13+
14+
15+
function start_kind(){
16+
17+
# avoid interference with previous test runs
18+
if [[ $(kind-linux-amd64 get clusters | grep "^${cluster_name}*") != "" ]]
19+
then
20+
kind-linux-amd64 delete cluster --name ${cluster_name}
21+
fi
22+
23+
kind-linux-amd64 create cluster --name ${cluster_name} --config ./e2e/kind-cluster-postgres-operator-e2e-tests.yaml
24+
kind-linux-amd64 load docker-image "${operator_image}" --name ${cluster_name}
25+
KUBECONFIG="$(kind-linux-amd64 get kubeconfig-path --name=${cluster_name})"
26+
export KUBECONFIG
27+
}
28+
29+
function set_kind_api_server_ip(){
30+
# use the actual kubeconfig to connect to the 'kind' API server
31+
# but update the IP address of the API server to the one from the Docker 'bridge' network
32+
cp "${KUBECONFIG}" /tmp
33+
readonly local kind_api_server_port=6443 # well-known in the 'kind' codebase
34+
readonly local kind_api_server=$(docker inspect --format "{{ .NetworkSettings.IPAddress }}:${kind_api_server_port}" "${cluster_name}"-control-plane)
35+
sed -i "s/server.*$/server: https:\/\/$kind_api_server/g" "${kubeconfig_path}"
36+
}
37+
38+
function run_tests(){
39+
docker run --rm --mount type=bind,source="$(readlink -f ${kubeconfig_path})",target=/root/.kube/config -e OPERATOR_IMAGE="${operator_image}" "${e2e_test_image}"
40+
}
41+
42+
function clean_up(){
43+
unset KUBECONFIG
44+
kind-linux-amd64 delete cluster --name ${cluster_name}
45+
rm -rf ${kubeconfig_path}
46+
}
47+
48+
function main(){
49+
50+
trap "clean_up" QUIT TERM EXIT
51+
52+
start_kind
53+
set_kind_api_server_ip
54+
run_tests
55+
exit 0
56+
}
57+
58+
main "$@"

0 commit comments

Comments
 (0)