Skip to content

Commit 1078fe6

Browse files
committed
Move pgbackrest-restore test to Kyverno Chainsaw
This test has a number of scripts and jobs that pass and share data. Chainsaw's bindings and templates are a nice way to break this test up, and its "catch" operations provide good context when a step fails. Tested with Kyverno Chainsaw 0.2.12 See: https://kyverno.github.io/chainsaw/main
1 parent c7842e7 commit 1078fe6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1032
-679
lines changed

.github/workflows/test.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,12 @@ jobs:
144144
--env 'RELATED_IMAGE_COLLECTOR=registry.developers.crunchydata.com/crunchydata/postgres-operator:ubi9-5.8.2-0' \
145145
--env 'PGO_FEATURE_GATES=TablespaceVolumes=true,OpenTelemetryLogs=true,OpenTelemetryMetrics=true' \
146146
--name 'postgres-operator' localhost/postgres-operator
147-
- name: Install kuttl
148-
run: |
149-
curl -Lo /usr/local/bin/kubectl-kuttl https://github.com/kudobuilder/kuttl/releases/download/v0.13.0/kubectl-kuttl_0.13.0_linux_x86_64
150-
chmod +x /usr/local/bin/kubectl-kuttl
147+
148+
- run: |
149+
make check-chainsaw && exit
150+
failed=$?
151+
echo '::group::PGO logs'; docker logs 'postgres-operator'; echo '::endgroup::'
152+
exit $failed
151153
152154
- run: make generate-kuttl
153155
env:
@@ -161,8 +163,6 @@ jobs:
161163
failed=$?
162164
echo '::group::PGO logs'; docker logs 'postgres-operator'; echo '::endgroup::'
163165
exit $failed
164-
env:
165-
KUTTL: kubectl-kuttl
166166
167167
- name: Stop PGO
168168
run: docker stop 'postgres-operator' || true

Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ GO_TEST ?= $(GO) test
1212
CONTROLLER ?= $(GO) tool sigs.k8s.io/controller-tools/cmd/controller-gen
1313

1414
# Run tests using the latest tools.
15+
CHAINSAW ?= $(GO) run github.com/kyverno/chainsaw@latest
16+
CHAINSAW_TEST ?= $(CHAINSAW) test
1517
ENVTEST ?= $(GO) run sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
1618
KUTTL ?= $(GO) run github.com/kudobuilder/kuttl/cmd/kubectl-kuttl@latest
1719
KUTTL_TEST ?= $(KUTTL) test
@@ -170,6 +172,17 @@ check-envtest-existing: createnamespaces
170172
$(GO_TEST) -count=1 -cover -p=1 ./...
171173
kubectl delete -k ./config/dev
172174

175+
# Expects operator to be running
176+
#
177+
# Chainsaw runs with a single kubectl context named "chainsaw".
178+
# If you experience `cluster "minikube" does not exist`, try `MINIKUBE_PROFILE=chainsaw`.
179+
#
180+
# https://kyverno.github.io/chainsaw/latest/operations/script#kubeconfig
181+
#
182+
.PHONY: check-chainsaw
183+
check-chainsaw:
184+
$(CHAINSAW_TEST) --config testing/chainsaw/e2e/config.yaml --values testing/chainsaw/e2e/values.yaml testing/chainsaw/e2e
185+
173186
# Expects operator to be running
174187
#
175188
# KUTTL runs with a single kubectl context named "cluster".

testing/chainsaw/e2e/config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha2
2+
kind: Configuration
3+
metadata:
4+
name: end-to-end
5+
spec:
6+
namespace:
7+
template:
8+
metadata:
9+
labels: { postgres-operator-test: chainsaw }
10+
timeouts:
11+
assert: 3m
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: StepTemplate
3+
metadata:
4+
name: 01-create-cluster
5+
spec:
6+
try:
7+
-
8+
description: >
9+
Create a cluster with a single pgBackRest repository
10+
and some parameters that require attention during PostgreSQL recovery
11+
apply:
12+
resource:
13+
apiVersion: postgres-operator.crunchydata.com/v1beta1
14+
kind: PostgresCluster
15+
metadata:
16+
name: original
17+
spec:
18+
postgresVersion: ($postgres.version)
19+
config:
20+
parameters:
21+
archive_timeout: 15
22+
checkpoint_timeout: 30
23+
max_connections: 200
24+
instances:
25+
- dataVolumeClaimSpec: ($volume)
26+
replicas: 2
27+
backups:
28+
pgbackrest:
29+
manual:
30+
repoName: repo1
31+
repos:
32+
- name: repo1
33+
volume:
34+
volumeClaimSpec: ($volume)
35+
36+
-
37+
description: >
38+
Wait for the replica backup to complete
39+
assert:
40+
resource:
41+
apiVersion: postgres-operator.crunchydata.com/v1beta1
42+
kind: PostgresCluster
43+
metadata:
44+
name: original
45+
status:
46+
pgbackrest:
47+
repos:
48+
- name: repo1
49+
replicaCreateBackupComplete: true
50+
stanzaCreated: true
51+
52+
catch:
53+
- podLogs:
54+
selector: postgres-operator.crunchydata.com/cluster in (original)
55+
tail: 50
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: StepTemplate
3+
metadata:
4+
name: 02-create-data
5+
spec:
6+
try:
7+
-
8+
description: >
9+
Create some data that will be restored
10+
apply:
11+
resource:
12+
apiVersion: batch/v1
13+
kind: Job
14+
metadata:
15+
name: original-data
16+
spec:
17+
backoffLimit: 3
18+
template:
19+
spec:
20+
restartPolicy: Never
21+
containers:
22+
- name: psql
23+
image: ($psql.image)
24+
env:
25+
- ($psql.connect)
26+
- name: PGURI
27+
valueFrom: { secretKeyRef: { name: original-pguser-original, key: uri } }
28+
command:
29+
- psql
30+
- $(PGURI)
31+
- --set=ON_ERROR_STOP=1
32+
- --command
33+
- |
34+
CREATE SCHEMA IF NOT EXISTS "original";
35+
CREATE TABLE important (data) AS VALUES ('treasure');
36+
37+
- assert:
38+
resource:
39+
apiVersion: batch/v1
40+
kind: Job
41+
metadata:
42+
name: original-data
43+
status:
44+
succeeded: 1
45+
46+
catch:
47+
-
48+
description: >
49+
Read all log lines from the job pods
50+
podLogs:
51+
selector: batch.kubernetes.io/job-name in (original-data)
52+
tail: -1
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: StepTemplate
3+
metadata:
4+
name: 03-create-backup
5+
spec:
6+
try:
7+
-
8+
description: >
9+
Annotate the cluster to trigger a backup
10+
patch:
11+
resource:
12+
apiVersion: postgres-operator.crunchydata.com/v1beta1
13+
kind: PostgresCluster
14+
metadata:
15+
name: original
16+
annotations:
17+
postgres-operator.crunchydata.com/pgbackrest-backup: one
18+
19+
-
20+
description: >
21+
Wait for it to complete
22+
assert:
23+
resource:
24+
apiVersion: batch/v1
25+
kind: Job
26+
metadata:
27+
annotations:
28+
postgres-operator.crunchydata.com/pgbackrest-backup: one
29+
labels:
30+
postgres-operator.crunchydata.com/cluster: original
31+
postgres-operator.crunchydata.com/pgbackrest-backup: manual
32+
status:
33+
succeeded: 1
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: StepTemplate
3+
metadata:
4+
name: 11-update-cluster
5+
spec:
6+
try:
7+
-
8+
description: >
9+
Find the primary pod
10+
command:
11+
outputs:
12+
- name: primary
13+
value: (trim_space($stdout))
14+
entrypoint: kubectl
15+
args:
16+
- get
17+
- pod
18+
- --namespace=${NAMESPACE}
19+
- --output=name
20+
- --selector
21+
- >-
22+
postgres-operator.crunchydata.com/cluster=original,
23+
postgres-operator.crunchydata.com/role=master
24+
25+
-
26+
description: >
27+
Read the timestamp at which PostgreSQL last started
28+
command:
29+
outputs:
30+
- name: start_before
31+
value: (trim_space($stdout))
32+
env:
33+
- name: PRIMARY
34+
value: ($primary)
35+
entrypoint: kubectl
36+
args:
37+
- exec
38+
- --namespace=${NAMESPACE}
39+
- ${PRIMARY}
40+
- --
41+
- psql
42+
- -qAt
43+
- --command
44+
- SELECT pg_postmaster_start_time()
45+
46+
-
47+
description: >
48+
Update the cluster with parameters that require attention during recovery
49+
patch:
50+
resource:
51+
apiVersion: postgres-operator.crunchydata.com/v1beta1
52+
kind: PostgresCluster
53+
metadata:
54+
name: original
55+
spec:
56+
config:
57+
parameters:
58+
max_connections: 1000
59+
60+
-
61+
description: >
62+
Wait for Postgres to restart
63+
script:
64+
skipCommandOutput: true
65+
timeout: 30s
66+
env:
67+
- name: BEFORE
68+
value: ($start_before)
69+
- name: PRIMARY
70+
value: ($primary)
71+
content: |
72+
while true; do
73+
START=$(
74+
kubectl exec --namespace "${NAMESPACE}" "${PRIMARY}" \
75+
-- psql -qAt --command 'SELECT pg_postmaster_start_time()'
76+
)
77+
if [ "${START}" ] && [ "${START}" != "${BEFORE}" ]; then break; else sleep 1; fi
78+
done
79+
echo "${START} != ${BEFORE}"
80+
81+
# Reset counters in the "pg_stat_archiver" view.
82+
kubectl exec --namespace "${NAMESPACE}" "${PRIMARY}" \
83+
-- psql -qb --command "SELECT pg_stat_reset_shared('archiver')" --output /dev/null
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: StepTemplate
3+
metadata:
4+
name: 12-update-data
5+
spec:
6+
try:
7+
-
8+
description: >
9+
Add more data to the WAL archive
10+
apply:
11+
resource:
12+
apiVersion: batch/v1
13+
kind: Job
14+
metadata:
15+
name: original-more-data
16+
spec:
17+
backoffLimit: 3
18+
template:
19+
spec:
20+
restartPolicy: Never
21+
containers:
22+
- name: psql
23+
image: ($psql.image)
24+
env:
25+
- ($psql.connect)
26+
- name: PGURI
27+
valueFrom: { secretKeyRef: { name: original-pguser-original, key: uri } }
28+
29+
command:
30+
- psql
31+
- $(PGURI)
32+
- --set=ON_ERROR_STOP=1
33+
- --command
34+
- |
35+
INSERT INTO important (data) VALUES ('water'), ('socks');
36+
37+
- assert:
38+
resource:
39+
apiVersion: batch/v1
40+
kind: Job
41+
metadata:
42+
name: original-more-data
43+
status:
44+
succeeded: 1
45+
46+
-
47+
description: >
48+
Wait for the data to be sent to the WAL archive
49+
script:
50+
skipCommandOutput: true
51+
content: |
52+
PRIMARY=$(
53+
kubectl get pod --namespace "${NAMESPACE}" \
54+
--output name --selector '
55+
postgres-operator.crunchydata.com/cluster=original,
56+
postgres-operator.crunchydata.com/role=master'
57+
)
58+
59+
kubectl exec --namespace "${NAMESPACE}" "${PRIMARY}" \
60+
-- psql --command 'SELECT pg_switch_wal()' --pset footer=off
61+
62+
# A prior step reset the "pg_stat_archiver" counters, so anything more than zero should suffice.
63+
while [ 0 = "$(
64+
kubectl exec --namespace "${NAMESPACE}" "${PRIMARY}" \
65+
-- psql -qAt --command 'SELECT archived_count FROM pg_stat_archiver'
66+
)" ]; do sleep 1; done
67+
68+
catch:
69+
-
70+
description: >
71+
Read all log lines from the job pods
72+
podLogs:
73+
selector: batch.kubernetes.io/job-name in (original-more-data)
74+
tail: -1

0 commit comments

Comments
 (0)