mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-01-11 05:13:10 +01:00
test(e2e): environment setup (#43)
Create the CI and testing infrastructure for e2e testing. Running the ci task now will push the plugin and sidecar images to a local registry, start kind, install the CloudNativePG and cert-manager operators, and then install the plugin-barman-cloud one. No actual test is implemented. Signed-off-by: Francesco Canovai <francesco.canovai@enterprisedb.com>
This commit is contained in:
parent
b7c4a4bb10
commit
74bc9e221e
23
.github/workflows/ci.yml
vendored
23
.github/workflows/ci.yml
vendored
@ -8,12 +8,35 @@ jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup Disk
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
tool-cache: true
|
||||
large-packages: false
|
||||
swap-storage: false
|
||||
- name: Cleanup docker cache
|
||||
run: |
|
||||
echo "-------------Disk info before cleanup----------------"
|
||||
df -h
|
||||
echo "-----------------------------------------------------"
|
||||
docker system prune -a -f
|
||||
echo "-------------Disk info after cleanup----------------"
|
||||
df -h
|
||||
echo "-----------------------------------------------------"
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
# We need the full history for the commitlint task
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# TODO: remove this when we daggerize the e2e
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23.x'
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
- name: Install Dagger
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -34,3 +34,8 @@ go.work
|
||||
|
||||
# Taskfile cache
|
||||
.task
|
||||
|
||||
# E2e test artifacts
|
||||
test/e2e/bin
|
||||
# Test registry certificates
|
||||
certs/
|
||||
|
||||
122
Taskfile.yml
122
Taskfile.yml
@ -1,5 +1,12 @@
|
||||
version: 3
|
||||
|
||||
# Environment variables that are shared across tasks.
|
||||
env:
|
||||
REGISTRY_NETWORK: barman-cloud-plugin
|
||||
REGISTRY_NAME: registry.barman-cloud-plugin
|
||||
REGISTRY_PORT: 5000
|
||||
DAGGER_ENGINE_CONTAINER_NAME: e2e-dagger-engine
|
||||
|
||||
tasks:
|
||||
lint:
|
||||
desc: Run golangci-lint
|
||||
@ -66,25 +73,111 @@ tasks:
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
generate-certs:
|
||||
desc: Generate certificates for the local registry
|
||||
run: once
|
||||
cmds:
|
||||
- >
|
||||
mkdir -p certs &&
|
||||
pushd certs &&
|
||||
openssl genrsa -out ca-key.pem 4096 &&
|
||||
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem \
|
||||
-subj "/O=CloudNativePG/OU=Barman Cloud Plugin Testing" &&
|
||||
openssl genrsa -out server-key.pem 4096 &&
|
||||
openssl req -subj "/CN=${REGISTRY_NAME}" -sha256 -new -key server-key.pem -out server.csr &&
|
||||
echo subjectAltName = DNS:${REGISTRY_NAME},IP:127.0.0.1 >> extfile.cnf &&
|
||||
echo extendedKeyUsage = serverAuth >> extfile.cnf &&
|
||||
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
|
||||
-CAcreateserial -out server-cert.pem -extfile extfile.cnf &&
|
||||
popd
|
||||
status:
|
||||
- test -f certs/ca-key.pem
|
||||
- test -f certs/ca.pem
|
||||
- test -f certs/server-key.pem
|
||||
- test -f certs/server.csr
|
||||
- test -f certs/server-cert.pem
|
||||
|
||||
start-build-network:
|
||||
desc: Create a docker network for image building used by the dagger engine and the registry
|
||||
run: once
|
||||
cmds:
|
||||
- docker network create ${REGISTRY_NETWORK}
|
||||
status:
|
||||
- docker network inspect ${REGISTRY_NETWORK}
|
||||
|
||||
start-registry:
|
||||
desc: Start a container registry
|
||||
run: once
|
||||
deps:
|
||||
- generate-certs
|
||||
- start-build-network
|
||||
env:
|
||||
# TODO: renovate
|
||||
REGISTRY_VERSION: 2
|
||||
cmds:
|
||||
- >
|
||||
docker run -d --name ${REGISTRY_NAME}
|
||||
-p ${REGISTRY_PORT}:5000
|
||||
--network ${REGISTRY_NETWORK}
|
||||
-v $(pwd)/certs:/certs
|
||||
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server-cert.pem -e REGISTRY_HTTP_TLS_KEY=/certs/server-key.pem
|
||||
registry:${REGISTRY_VERSION}
|
||||
status:
|
||||
- \[ "$(docker inspect -f {{`'{{.State.Running}}'`}} "${REGISTRY_NAME}" 2> /dev/null )" == 'true' \]
|
||||
|
||||
|
||||
# Start a dagger engine that mounts the CA certificate for the local registry.
|
||||
start-dagger-engine-for-local-builds:
|
||||
desc: Start a dagger engine mounting the CA
|
||||
run: once
|
||||
deps:
|
||||
- generate-certs
|
||||
- start-build-network
|
||||
env:
|
||||
# TODO: renovate
|
||||
DAGGER_ENGINE_IMAGE: registry.dagger.io/engine:v0.13.6
|
||||
cmds:
|
||||
- >
|
||||
docker run -d -v /var/lib/dagger --name "${DAGGER_ENGINE_CONTAINER_NAME}"
|
||||
--network=${REGISTRY_NETWORK}
|
||||
-v $(pwd)/certs/ca.pem:/usr/local/share/ca-certificates/ca.crt
|
||||
--privileged ${DAGGER_ENGINE_IMAGE}
|
||||
status:
|
||||
- \[ "$(docker inspect -f {{`'{{.State.Running}}'`}} "${DAGGER_ENGINE_CONTAINER_NAME}" 2> /dev/null )" == 'true' \]
|
||||
|
||||
# We build an image and push it to a local registry.
|
||||
# The name is always `plugin-barman-cloud:testing`.
|
||||
build-plugin-image:
|
||||
desc: Build the operator container image for the plugin
|
||||
deps:
|
||||
- start-registry
|
||||
- start-dagger-engine-for-local-builds
|
||||
env:
|
||||
# renovate: datasource=git-refs depName=docker lookupName=https://github.com/purpleclay/daggerverse currentValue=main
|
||||
DAGGER_DOCKER_SHA: 4778f39b9cf56e0242c124000a563f9486dafa4b
|
||||
_EXPERIMENTAL_DAGGER_RUNNER_HOST: docker-container://{{.DAGGER_ENGINE_CONTAINER_NAME}}
|
||||
cmds:
|
||||
- >
|
||||
GITHUB_REF= dagger -s call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
build --dir . --file containers/Dockerfile.plugin --platform linux/amd64 image > /dev/null
|
||||
GITHUB_REF= dagger call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
build --dir . --file containers/Dockerfile.plugin --platform linux/amd64
|
||||
publish --ref ${REGISTRY_NAME}:${REGISTRY_PORT}/plugin-barman-cloud --tags testing
|
||||
|
||||
# We build an image and push it to a local registry.
|
||||
# The name is always `sidecar-barman-cloud:testing`.
|
||||
build-sidecar-image:
|
||||
desc: Build the sidecar container image for the plugin
|
||||
deps:
|
||||
- start-registry
|
||||
- start-dagger-engine-for-local-builds
|
||||
env:
|
||||
# renovate: datasource=git-refs depName=docker lookupName=https://github.com/purpleclay/daggerverse currentValue=main
|
||||
DAGGER_DOCKER_SHA: 4778f39b9cf56e0242c124000a563f9486dafa4b
|
||||
_EXPERIMENTAL_DAGGER_RUNNER_HOST: docker-container://{{.DAGGER_ENGINE_CONTAINER_NAME}}
|
||||
cmds:
|
||||
- >
|
||||
GITHUB_REF= dagger -s call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
build --dir . --file containers/Dockerfile.sidecar --platform linux/amd64 image > /dev/null
|
||||
GITHUB_REF= dagger call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
build --dir . --file containers/Dockerfile.sidecar --platform linux/amd64
|
||||
publish --ref ${REGISTRY_NAME}:${REGISTRY_PORT}/sidecar-barman-cloud --tags testing
|
||||
|
||||
build-images:
|
||||
desc: Build the container images for the plugin
|
||||
@ -92,6 +185,21 @@ tasks:
|
||||
- build-plugin-image
|
||||
- build-sidecar-image
|
||||
|
||||
# TODO: see if it is possible to daggerize this. It will have to manage docker to make kind work.
|
||||
# TODO: add a task to clean up the kind cluster for new test runs.
|
||||
# Run the e2e tests. This task will start a kind cluster, deploy the plugin, and run the tests.
|
||||
# Running the e2e tests requires:
|
||||
# * The registry to have a valid TLS certificate.
|
||||
# * The registry to be in the same network of the dagger-engine.
|
||||
# * The dagger-engine to mount the CA.
|
||||
# * The kind cluster to mount the CA.
|
||||
e2e:
|
||||
desc: Run e2e tests
|
||||
deps:
|
||||
- build-images
|
||||
cmds:
|
||||
- go test -v ./test/e2e
|
||||
|
||||
ci:
|
||||
desc: Run the CI pipeline
|
||||
deps:
|
||||
@ -100,7 +208,7 @@ tasks:
|
||||
- uncommitted
|
||||
- lint
|
||||
- go-test
|
||||
- build-images
|
||||
- e2e
|
||||
|
||||
publish:
|
||||
desc: Build and publish a container image for the plugin
|
||||
@ -125,12 +233,12 @@ tasks:
|
||||
DAGGER_DOCKER_SHA: 4778f39b9cf56e0242c124000a563f9486dafa4b
|
||||
cmds:
|
||||
- >
|
||||
dagger -s call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
dagger call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
--registry ghcr.io --username $REGISTRY_USER --password env:REGISTRY_PASSWORD
|
||||
build --dir . --file containers/Dockerfile.plugin --platform linux/amd64 --platform linux/arm64
|
||||
publish --ref {{.PLUGIN_IMAGE_NAME}} --tags {{.IMAGE_VERSION}}
|
||||
- >
|
||||
dagger -s call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
dagger call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
||||
--registry ghcr.io --username $REGISTRY_USER --password env:REGISTRY_PASSWORD
|
||||
build --dir . --file containers/Dockerfile.sidecar --platform linux/amd64 --platform linux/arm64
|
||||
publish --ref {{.SIDECAR_IMAGE_NAME}} --tags {{.IMAGE_VERSION}}
|
||||
|
||||
54
go.mod
54
go.mod
@ -5,26 +5,31 @@ go 1.23
|
||||
toolchain go1.23.1
|
||||
|
||||
require (
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1
|
||||
github.com/cert-manager/cert-manager v1.16.1
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241113134512-8608232c2813
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241109002750-8abd359df734
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b
|
||||
github.com/onsi/ginkgo/v2 v2.20.2
|
||||
github.com/onsi/gomega v1.34.2
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241030141148-670a0f16f836
|
||||
github.com/onsi/ginkgo/v2 v2.21.0
|
||||
github.com/onsi/gomega v1.35.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
google.golang.org/grpc v1.67.1
|
||||
google.golang.org/grpc v1.68.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.31.2
|
||||
k8s.io/apiextensions-apiserver v0.31.2
|
||||
k8s.io/apimachinery v0.31.2
|
||||
k8s.io/client-go v0.31.2
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078
|
||||
sigs.k8s.io/controller-runtime v0.19.1
|
||||
sigs.k8s.io/kustomize/api v0.17.3
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
@ -37,6 +42,7 @@ require (
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-logr/zapr v1.3.0 // indirect
|
||||
@ -51,12 +57,13 @@ require (
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@ -70,11 +77,12 @@ require (
|
||||
github.com/moby/spdystream v0.4.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2 // indirect
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.78.1 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.59.1 // indirect
|
||||
@ -91,14 +99,16 @@ require (
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/thoas/go-funk v0.9.3 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
|
||||
go.opentelemetry.io/otel v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.29.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.starlark.net v0.0.0-20240925182052-1207426daebd // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
@ -109,21 +119,21 @@ require (
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.25.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.31.2 // indirect
|
||||
k8s.io/apiserver v0.31.2 // indirect
|
||||
k8s.io/component-base v0.31.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
|
||||
sigs.k8s.io/gateway-api v1.1.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
|
||||
106
go.sum
106
go.sum
@ -2,8 +2,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
@ -12,20 +12,22 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cert-manager/cert-manager v1.16.1 h1:1ceFMqTtwiqY2vyfaRT85CNiVmK7pJjt3GebYCx9awY=
|
||||
github.com/cert-manager/cert-manager v1.16.1/go.mod h1:MfLVTL45hFZsqmaT1O0+b2ugaNNQQZttSFV9hASHUb0=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b h1:LZ9tIgKmWb8ZvyLg/J8ExXtmBtEWP2dr3Y4TU4nCq/w=
|
||||
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b/go.mod h1:mzd1EvoLYy16jJdne6/4nwhoj7t4IZ0MqJMEH4mla8Q=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a h1:0v1ML9Eibfq3helbT9GtU0EstqFtG91k/MPO9azY5ME=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a/go.mod h1:Jm0tOp5oB7utpt8wz6RfSv31h1mThOtffjfyxVupriE=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230 h1:zRqm1WUMOqkPWGyvtvCAdWlQ+WTtb0iQA/rvCar27/E=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230/go.mod h1:La89zdElTqqZ5LXHFm/UjOwvS9iHSE8GuOW4fYUgHw8=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1 h1:v3Vr+FH5BXmS7Eqx17u51oijZ4T7y62vUMCUAr7CffE=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1/go.mod h1:fAU7ySVzjpt/RZntxWZiWJCjaBJayzIxEnd0NuO7oQc=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14 h1:HX5pXyzVAqfjcDgCa1l8b4sumf7XYnGqiP+6XMgbB2E=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14/go.mod h1:HPGwXHlatQEnb2HdsbGTZLEo8qlxKLdxTHiTeF9TTqw=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241113134512-8608232c2813 h1:XWpr5y28JRwcA4BzxBkHFx7C8JDqOSdDIN7RbRdI6Dg=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241113134512-8608232c2813/go.mod h1:f4hObdRVoQtMmVtWqZ6VDZBrI6ok9Td/UMhojQ+EPmk=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241109002750-8abd359df734 h1:4jq/FUrlAKxu0Kw9PL5lj5Njq8pAnmUpP/kXKOrJAaE=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20241109002750-8abd359df734/go.mod h1:3U7miYasKr2rYCQzrn/IvbSQc0OpYF8ieZt2FKG4nv0=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19 h1:qy+LrScvQpIwt4qeg9FfCJuoC9CbX/kpFGLF8vSobXg=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19/go.mod h1:X6r1fRuUEIAv4+5SSBY2RmQ201K6GcptOXgnmaX/8tY=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b h1:4Q2VQsPlLHliJdi87zodQ0FHLd1cJINMm4N70eu8rRg=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b/go.mod h1:+mUFdys1IX+qwQUrV+/i56Tey/mYh8ZzWZYttwivRns=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241030141148-670a0f16f836 h1:Hhg+I2QcaPNN5XaSsYb7Xw3PbQlvCA9eDY+SvVf902Q=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241030141148-670a0f16f836/go.mod h1:+mUFdys1IX+qwQUrV+/i56Tey/mYh8ZzWZYttwivRns=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -33,8 +35,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
|
||||
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
|
||||
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
@ -45,6 +47,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-faker/faker/v4 v4.4.1 h1:LY1jDgjVkBZWIhATCt+gkl0x9i/7wC61gZx73GTFb+Q=
|
||||
github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@ -78,18 +82,20 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 h1:c5FlPPgxOn7kJz3VoPLkQYQXGBS3EklQ4Zfi57uOuqQ=
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@ -125,14 +131,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -140,8 +148,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2 h1:F/MALZ518KfI1zEg+Kg8/uTzoXKDyqw+LNC/5irJlJE=
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2/go.mod h1:D0KY8md81DQKdaR/cXwnhoWB3MYYyc/UjvqE8GFkIvA=
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.78.1 h1:Fm9Z+FabnB+6EoGq15j+pyLmaK6hYrYOpBlTzOLTQ+E=
|
||||
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.78.1/go.mod h1:SvsRXw4m1F2vk7HquU5h475bFpke27mIUswfyw9u3ug=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
@ -159,6 +167,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/snorwin/jsonpatch v1.5.0 h1:0m56YSt9cHiJOn8U+OcqdPGcDQZmhPM/zsG7Dv5QQP0=
|
||||
github.com/snorwin/jsonpatch v1.5.0/go.mod h1:e0IDKlyFBLTFPqM0wa79dnMwjMs3XFvmKcrgCRpDqok=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
@ -178,9 +188,11 @@ github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8w
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
@ -193,24 +205,28 @@ github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
|
||||
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.starlark.net v0.0.0-20240925182052-1207426daebd h1:S+EMisJOHklQxnS3kqsY8jl2y5aF0FDEdcLnOw3q22E=
|
||||
go.starlark.net v0.0.0-20240925182052-1207426daebd/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@ -254,20 +270,20 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
||||
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -302,14 +318,20 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 h1:1dWzkmJrrprYvjGwh9kEUxmcUV/CtNU8QM7h1FLWQOo=
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38/go.mod h1:coRQXBK9NxO98XUv3ZD6AK3xzHCxV6+b7lrquKwaKzA=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk=
|
||||
sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
|
||||
sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM=
|
||||
sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.17.3 h1:6GCuHSsxq7fN5yhF2XrC+AAr8gxQwhexgHflOAD/JJU=
|
||||
sigs.k8s.io/kustomize/api v0.17.3/go.mod h1:TuDH4mdx7jTfK61SQ/j1QZM/QWR+5rmEiNjvYlhzFhc=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.2 h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
|
||||
0
scripts/setup-kind.sh
Normal file
0
scripts/setup-kind.sh
Normal file
11
test/e2e/config/kind-config.yaml
Normal file
11
test/e2e/config/kind-config.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
# Kind configuration file for running e2e tests
|
||||
# Certificates must be mounted on each node because the registry is using TLS
|
||||
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
extraMounts:
|
||||
- hostPath: ../../certs/ca.pem
|
||||
containerPath: /usr/local/share/ca-certificates/ca.crt
|
||||
readOnly: true
|
||||
@ -17,13 +17,113 @@ limitations under the License.
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
apimachineryTypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
kustomizeTypes "sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/deployment"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/e2etestenv"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
// We don't want multiple ginkgo nodes to run the setup concurrently, we use a single cluster for all tests.
|
||||
var _ = SynchronizedBeforeSuite(func(ctx SpecContext) []byte {
|
||||
var cl client.Client
|
||||
var err error
|
||||
if cl, err = e2etestenv.Setup(ctx,
|
||||
e2etestenv.WithKindAdditionalNetworks([]string{"barman-cloud-plugin"})); err != nil {
|
||||
Fail(fmt.Sprintf("failed to setup environment: %v", err))
|
||||
}
|
||||
|
||||
const barmanCloudKustomizationPath = "./kustomize/kubernetes/"
|
||||
barmanCloudKustomization := &kustomizeTypes.Kustomization{
|
||||
Resources: []string{barmanCloudKustomizationPath},
|
||||
Images: []kustomizeTypes.Image{
|
||||
{
|
||||
Name: "docker.io/library/plugin-barman-cloud",
|
||||
NewName: "registry.barman-cloud-plugin:5000/plugin-barman-cloud",
|
||||
NewTag: "testing",
|
||||
},
|
||||
},
|
||||
SecretGenerator: []kustomizeTypes.SecretArgs{
|
||||
{
|
||||
GeneratorArgs: kustomizeTypes.GeneratorArgs{
|
||||
Name: "plugin-barman-cloud",
|
||||
Behavior: "replace",
|
||||
KvPairSources: kustomizeTypes.KvPairSources{
|
||||
LiteralSources: []string{"SIDECAR_IMAGE=registry.barman-cloud-plugin:5000/sidecar-barman-cloud:testing"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
if err := corev1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add core/v1 to scheme: %v", err))
|
||||
}
|
||||
if err := apiextensionsv1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add apiextensions/v1 to scheme: %v", err))
|
||||
}
|
||||
if err := admissionregistrationv1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add admissionregistration/v1 to scheme: %v", err))
|
||||
}
|
||||
if err := rbacv1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add rbac/v1 to scheme: %v", err))
|
||||
}
|
||||
if err := appsv1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add apps/v1 to scheme: %v", err))
|
||||
}
|
||||
if err := certmanagerv1.AddToScheme(scheme); err != nil {
|
||||
Fail(fmt.Sprintf("failed to add cert-manager.io/v1 to scheme: %v", err))
|
||||
}
|
||||
|
||||
if err := kustomize.ApplyKustomization(ctx, cl, barmanCloudKustomization); err != nil {
|
||||
Fail(fmt.Sprintf("failed to apply kustomization: %v", err))
|
||||
}
|
||||
const defaultTimeout = 1 * time.Minute
|
||||
ctxDeploy, cancel := context.WithTimeout(ctx, defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
deploy := apimachineryTypes.NamespacedName{
|
||||
Namespace: "cnpg-system",
|
||||
Name: "barman-cloud",
|
||||
}
|
||||
err = wait.PollUntilContextCancel(ctxDeploy, 5*time.Second, false,
|
||||
func(ctx context.Context) (bool, error) {
|
||||
ready, err := deployment.IsReady(ctx, cl, deploy)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to check if %s is ready: %w", deploy, err)
|
||||
}
|
||||
if ready {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
Fail(fmt.Sprintf("failed to wait for deployment to be ready: %v", err))
|
||||
}
|
||||
|
||||
return []byte{}
|
||||
}, func(_ []byte) {})
|
||||
|
||||
// Run e2e tests using the Ginkgo runner.
|
||||
func TestE2E(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
|
||||
@ -17,108 +17,14 @@ limitations under the License.
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/utils"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const namespace = "plugin-barman-cloud-system"
|
||||
// const namespace = "plugin-barman-cloud-system"
|
||||
|
||||
var _ = Describe("controller", Ordered, func() {
|
||||
BeforeAll(func() {
|
||||
By("installing prometheus operator")
|
||||
Expect(utils.InstallPrometheusOperator()).To(Succeed())
|
||||
|
||||
By("installing the cert-manager")
|
||||
Expect(utils.InstallCertManager()).To(Succeed())
|
||||
|
||||
By("creating manager namespace")
|
||||
cmd := exec.Command("kubectl", "create", "ns", namespace)
|
||||
_, _ = utils.Run(cmd)
|
||||
})
|
||||
|
||||
AfterAll(func() {
|
||||
By("uninstalling the Prometheus manager bundle")
|
||||
utils.UninstallPrometheusOperator()
|
||||
|
||||
By("uninstalling the cert-manager bundle")
|
||||
utils.UninstallCertManager()
|
||||
|
||||
By("removing manager namespace")
|
||||
cmd := exec.Command("kubectl", "delete", "ns", namespace)
|
||||
_, _ = utils.Run(cmd)
|
||||
})
|
||||
|
||||
Context("Operator", func() {
|
||||
It("should run successfully", func() {
|
||||
var controllerPodName string
|
||||
var err error
|
||||
|
||||
// projectimage stores the name of the image used in the example
|
||||
projectimage := "example.com/plugin-barman-cloud:v0.0.1"
|
||||
|
||||
By("building the manager(Operator) image")
|
||||
//nolint:gosec,perfsprint
|
||||
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectimage))
|
||||
_, err = utils.Run(cmd)
|
||||
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||
|
||||
By("loading the manager(Operator) image on Kind")
|
||||
err = utils.LoadImageToKindClusterWithName(projectimage)
|
||||
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||
|
||||
By("installing CRDs")
|
||||
cmd = exec.Command("make", "install")
|
||||
_, err = utils.Run(cmd)
|
||||
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||
|
||||
By("deploying the controller-manager")
|
||||
//nolint:gosec,perfsprint
|
||||
cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectimage))
|
||||
_, err = utils.Run(cmd)
|
||||
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||
|
||||
By("validating that the controller-manager pod is running as expected")
|
||||
verifyControllerUp := func() error {
|
||||
// Get pod name
|
||||
|
||||
cmd = exec.Command("kubectl", "get",
|
||||
"pods", "-l", "control-plane=controller-manager",
|
||||
"-o", "go-template={{ range .items }}"+
|
||||
"{{ if not .metadata.deletionTimestamp }}"+
|
||||
"{{ .metadata.name }}"+
|
||||
"{{ \"\\n\" }}{{ end }}{{ end }}",
|
||||
"-n", namespace,
|
||||
)
|
||||
|
||||
podOutput, err := utils.Run(cmd)
|
||||
ExpectWithOffset(2, err).NotTo(HaveOccurred())
|
||||
podNames := utils.GetNonEmptyLines(string(podOutput))
|
||||
if len(podNames) != 1 {
|
||||
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
|
||||
}
|
||||
controllerPodName = podNames[0]
|
||||
ExpectWithOffset(2, controllerPodName).Should(ContainSubstring("controller-manager"))
|
||||
|
||||
// Validate pod status
|
||||
cmd = exec.Command("kubectl", "get",
|
||||
"pods", controllerPodName, "-o", "jsonpath={.status.phase}",
|
||||
"-n", namespace,
|
||||
)
|
||||
status, err := utils.Run(cmd)
|
||||
ExpectWithOffset(2, err).NotTo(HaveOccurred())
|
||||
if string(status) != "Running" {
|
||||
return fmt.Errorf("controller pod in %s status", status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
EventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())
|
||||
})
|
||||
It("passes", func() {
|
||||
Expect(true).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
106
test/e2e/internal/certmanager/certmanager.go
Normal file
106
test/e2e/internal/certmanager/certmanager.go
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package certmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
types2 "k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/deployment"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
|
||||
)
|
||||
|
||||
// InstallOptions contains the options for installing cert-manager
|
||||
type InstallOptions struct {
|
||||
Version string
|
||||
IgnoreExistResources bool
|
||||
}
|
||||
|
||||
// InstallOption is a function that sets up an option for installing cert-manager
|
||||
type InstallOption func(*InstallOptions)
|
||||
|
||||
// WithVersion sets the version of cert-manager to install
|
||||
func WithVersion(version string) InstallOption {
|
||||
return func(opts *InstallOptions) {
|
||||
opts.Version = version
|
||||
}
|
||||
}
|
||||
|
||||
// WithIgnoreExistingResources sets whether to ignore existing resources
|
||||
func WithIgnoreExistingResources(ignore bool) InstallOption {
|
||||
return func(opts *InstallOptions) {
|
||||
opts.IgnoreExistResources = ignore
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: renovate
|
||||
|
||||
// DefaultVersion is the default version of cert-manager to install
|
||||
const DefaultVersion = "v1.15.1"
|
||||
|
||||
// Install installs cert-manager using kubectl
|
||||
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
|
||||
options := &InstallOptions{
|
||||
Version: DefaultVersion,
|
||||
IgnoreExistResources: true,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
// Define the KustomizationResourceURL for the cert-manager manifests
|
||||
url := fmt.Sprintf("https://github.com/cert-manager/cert-manager/releases/download/%s/cert-manager.yaml",
|
||||
options.Version)
|
||||
|
||||
// Generate the Kustomization
|
||||
kustomization := &types.Kustomization{
|
||||
Resources: []string{url},
|
||||
}
|
||||
|
||||
// Add all the resources defined in the cert-manager manifests
|
||||
if err := kustomize.ApplyKustomization(ctx, cl, kustomization); err != nil {
|
||||
return fmt.Errorf("failed to apply kustomization: %w", err)
|
||||
}
|
||||
|
||||
// Set default timeout if none is provided
|
||||
const defaultTimeout = 5 * time.Minute
|
||||
|
||||
if _, ok := ctx.Deadline(); !ok {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
deployments := []string{"cert-manager", "cert-manager-cainjector", "cert-manager-webhook"}
|
||||
interval := 5 * time.Second
|
||||
for _, deploymentName := range deployments {
|
||||
if err := deployment.WaitForDeploymentReady(ctx, cl, types2.NamespacedName{
|
||||
Namespace: "cert-manager",
|
||||
Name: deploymentName,
|
||||
}, interval); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
19
test/e2e/internal/certmanager/doc.go
Normal file
19
test/e2e/internal/certmanager/doc.go
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package certmanager provides utilities for setting up and managing
|
||||
// cert-manager for end-to-end testing.
|
||||
package certmanager
|
||||
153
test/e2e/internal/cloudnativepg/cloudnativepg.go
Normal file
153
test/e2e/internal/cloudnativepg/cloudnativepg.go
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudnativepg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
types2 "k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/deployment"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
|
||||
)
|
||||
|
||||
// InstallCloudNativePGOptions contains the options for installing CloudNativePG
|
||||
type InstallCloudNativePGOptions struct {
|
||||
ImageName string
|
||||
ImageTag string
|
||||
KustomizationResourceURL string
|
||||
KustomizationRef string
|
||||
KustomizationTimeout string
|
||||
IgnoreExistResources bool
|
||||
}
|
||||
|
||||
// InstallOption is a function that sets up an option for installing CloudNativePG
|
||||
type InstallOption func(*InstallCloudNativePGOptions)
|
||||
|
||||
// WithImageName sets the name for the CloudNativePG image
|
||||
func WithImageName(ref string) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.ImageName = ref
|
||||
}
|
||||
}
|
||||
|
||||
// WithImageTag sets the tag for the CloudNativePG image
|
||||
func WithImageTag(tag string) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.ImageTag = tag
|
||||
}
|
||||
}
|
||||
|
||||
// WithKustomizationResourceURL sets the URL for the CloudNativePG kustomization
|
||||
func WithKustomizationResourceURL(url string) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.KustomizationResourceURL = url
|
||||
}
|
||||
}
|
||||
|
||||
// WithKustomizationRef sets the ref for the CloudNativePG kustomization
|
||||
func WithKustomizationRef(ref string) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.KustomizationRef = ref
|
||||
}
|
||||
}
|
||||
|
||||
// WithKustomizationTimeout sets the timeout for the kustomization resources
|
||||
func WithKustomizationTimeout(timeout string) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.KustomizationTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// WithIgnoreExistingResources sets whether to ignore existing resources
|
||||
func WithIgnoreExistingResources(ignore bool) InstallOption {
|
||||
return func(opts *InstallCloudNativePGOptions) {
|
||||
opts.IgnoreExistResources = ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Install installs CloudNativePG using kubectl
|
||||
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
|
||||
// Defining the default options
|
||||
options := &InstallCloudNativePGOptions{
|
||||
ImageName: "ghcr.io/cloudnative-pg/cloudnative-pg-testing",
|
||||
ImageTag: "main",
|
||||
KustomizationResourceURL: "https://github.com/cloudnative-pg/cloudnative-pg.git/config/default",
|
||||
KustomizationRef: "main",
|
||||
KustomizationTimeout: "120",
|
||||
IgnoreExistResources: true,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
kustomizationFullURL := fmt.Sprintf("%s/?ref=%s&timeout=%s", options.KustomizationResourceURL,
|
||||
options.KustomizationRef, options.KustomizationTimeout)
|
||||
|
||||
// Generate the Kustomization
|
||||
kustomization := &types.Kustomization{
|
||||
Resources: []string{kustomizationFullURL},
|
||||
Images: []types.Image{
|
||||
{
|
||||
Name: "controller",
|
||||
NewName: options.ImageName,
|
||||
NewTag: options.ImageTag,
|
||||
},
|
||||
},
|
||||
Patches: []types.Patch{
|
||||
{
|
||||
Patch: fmt.Sprintf(`[{"op": "replace", "path": "/spec/template/spec/containers/0/env/0/value", "value": "%v:%v"}]`,
|
||||
options.ImageName, options.ImageTag),
|
||||
Target: &types.Selector{
|
||||
ResId: resid.ResId{
|
||||
Gvk: resid.Gvk{Kind: "Deployment", Version: "v1", Group: "apps"},
|
||||
Name: "cnpg-controller-manager",
|
||||
Namespace: "cnpg-system",
|
||||
},
|
||||
},
|
||||
Options: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := kustomize.ApplyKustomization(ctx, cl, kustomization); err != nil {
|
||||
return fmt.Errorf("failed to apply kustomization: %w", err)
|
||||
}
|
||||
|
||||
// Set default timeout if none is provided
|
||||
const defaultTimeout = 5 * time.Minute
|
||||
|
||||
if _, ok := ctx.Deadline(); !ok {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if err := deployment.WaitForDeploymentReady(ctx, cl, types2.NamespacedName{
|
||||
Namespace: "cnpg-system",
|
||||
Name: "cnpg-controller-manager",
|
||||
}, 5*time.Second); err != nil {
|
||||
return fmt.Errorf("failed to wait for deployment to be ready: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
19
test/e2e/internal/cloudnativepg/doc.go
Normal file
19
test/e2e/internal/cloudnativepg/doc.go
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package cloudnativepg provides utilities for setting up and managing
|
||||
// CloudNativePG environments for end-to-end testing.
|
||||
package cloudnativepg
|
||||
69
test/e2e/internal/deployment/deployment.go
Normal file
69
test/e2e/internal/deployment/deployment.go
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package deployment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// IsReady checks if the deployment is ready.
|
||||
func IsReady(ctx context.Context, cl client.Client, name types.NamespacedName) (bool, error) {
|
||||
deployment := &appsv1.Deployment{}
|
||||
err := cl.Get(ctx, name, deployment)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get %s deployment: %w", name, err)
|
||||
}
|
||||
|
||||
// Check if the deployment is ready
|
||||
ready := false
|
||||
for _, condition := range deployment.Status.Conditions {
|
||||
if condition.Type == appsv1.DeploymentAvailable && condition.Status == "True" {
|
||||
ready = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ready {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// WaitForDeploymentReady waits for the deployment to be ready. ctx should have a timeout set.
|
||||
func WaitForDeploymentReady(
|
||||
ctx context.Context, cl client.Client, namespacedName types.NamespacedName, interval time.Duration,
|
||||
) error {
|
||||
return wait.PollUntilContextCancel(ctx, interval, false,
|
||||
func(ctx context.Context) (bool, error) {
|
||||
ready, err := IsReady(ctx, cl, namespacedName)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to check if %s is ready: %w", namespacedName, err)
|
||||
}
|
||||
if ready {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
18
test/e2e/internal/deployment/doc.go
Normal file
18
test/e2e/internal/deployment/doc.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package deployment provides utilities for managing Kubernetes deployments
|
||||
package deployment
|
||||
18
test/e2e/internal/e2etestenv/doc.go
Normal file
18
test/e2e/internal/e2etestenv/doc.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package e2etestenv provides a test environment for end-to-end tests.
|
||||
package e2etestenv
|
||||
272
test/e2e/internal/e2etestenv/main.go
Normal file
272
test/e2e/internal/e2etestenv/main.go
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2etestenv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/certmanager"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/cloudnativepg"
|
||||
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kind"
|
||||
)
|
||||
|
||||
// SetupOptions contains the options for setting up the test environment.
|
||||
type SetupOptions struct {
|
||||
K8sVersion string
|
||||
|
||||
KindVersion string
|
||||
KindClusterNamePrefix string
|
||||
KindAdditionalNetworks []string
|
||||
|
||||
CNPGKustomizationURL string
|
||||
CNPGKustomizationRef string
|
||||
CNPGKustomizationTimeout string
|
||||
CNPGImageName string
|
||||
CNPGImageTag string
|
||||
|
||||
CertManagerVersion string
|
||||
|
||||
IgnoreExistingResources bool
|
||||
}
|
||||
|
||||
// SetupOption is a function that sets up an option for the test environment setup.
|
||||
type SetupOption func(*SetupOptions)
|
||||
|
||||
// WithK8sVersion sets the Kubernetes version for the test environment.
|
||||
func WithK8sVersion(version string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.K8sVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
// WithKindVersion sets the Kind version for the test environment.
|
||||
func WithKindVersion(version string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.KindVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
// WithKindAdditionalNetworks sets the additional networks for the Kind cluster for the test environment.
|
||||
func WithKindAdditionalNetworks(networks []string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.KindAdditionalNetworks = networks
|
||||
}
|
||||
}
|
||||
|
||||
// WithCNPGKustomizationURL sets the CloudNativePG kustomization URL for the test environment.
|
||||
func WithCNPGKustomizationURL(url string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CNPGKustomizationURL = url
|
||||
}
|
||||
}
|
||||
|
||||
// WithCNPGKustomizationRef sets the CloudNativePG kustomization ref for the test environment.
|
||||
func WithCNPGKustomizationRef(ref string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CNPGKustomizationRef = ref
|
||||
}
|
||||
}
|
||||
|
||||
// WithCNPGKustomizationTimeout sets the CloudNativePG kustomization timeout for the test environment.
|
||||
func WithCNPGKustomizationTimeout(timeout string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CNPGKustomizationTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// WithCNPGImageName sets the CloudNativePG image name for the test environment.
|
||||
func WithCNPGImageName(name string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CNPGImageName = name
|
||||
}
|
||||
}
|
||||
|
||||
// WithCNPGImageTag sets the CloudNativePG image tag for the test environment.
|
||||
func WithCNPGImageTag(tag string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CNPGImageTag = tag
|
||||
}
|
||||
}
|
||||
|
||||
// WithCertManagerVersion sets the cert-manager version for the test environment.
|
||||
func WithCertManagerVersion(version string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.CertManagerVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
// WithIgnoreExistingResources sets the option to ignore existing resources when creating the test environment,
|
||||
// instead of returning an error.
|
||||
func WithIgnoreExistingResources(ignore bool) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.IgnoreExistingResources = ignore
|
||||
}
|
||||
}
|
||||
|
||||
// WithKindClusterNamePrefix sets the prefix for the Kind cluster name for the test environment.
|
||||
func withKindClusterNamePrefix(name string) SetupOption {
|
||||
return func(opts *SetupOptions) {
|
||||
opts.KindClusterNamePrefix = name
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
kindConfigFile = "config/kind-config.yaml"
|
||||
)
|
||||
|
||||
func defaultSetupOptions() SetupOptions {
|
||||
// TODO: renovate
|
||||
return SetupOptions{
|
||||
K8sVersion: "v1.31.1",
|
||||
KindVersion: "v0.24.0",
|
||||
CertManagerVersion: "v1.15.1",
|
||||
KindClusterNamePrefix: "e2e",
|
||||
KindAdditionalNetworks: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// Setup sets up the test environment for the e2e tests, starting kind and installing the necessary components.
|
||||
func Setup(ctx context.Context, opts ...SetupOption) (client.Client, error) {
|
||||
options := defaultSetupOptions()
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
if err := setupKind(options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cl, err := getClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := installCertManager(ctx, cl, options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := installCNPG(ctx, cl, options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return the Kubernetes client used for the tests
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
func installCNPG(ctx context.Context, cl client.Client, options SetupOptions) error {
|
||||
// Install CloudNativePG
|
||||
var cnpgIstallOptions []cloudnativepg.InstallOption
|
||||
if options.CNPGKustomizationURL != "" {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions,
|
||||
cloudnativepg.WithKustomizationResourceURL(options.CNPGKustomizationURL))
|
||||
}
|
||||
if options.CNPGKustomizationRef != "" {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions, cloudnativepg.WithKustomizationRef(options.CNPGKustomizationRef))
|
||||
}
|
||||
if options.CNPGKustomizationTimeout != "" {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions,
|
||||
cloudnativepg.WithKustomizationTimeout(options.CNPGKustomizationTimeout))
|
||||
}
|
||||
if options.CNPGImageName != "" {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions, cloudnativepg.WithImageName(options.CNPGImageName))
|
||||
}
|
||||
if options.CNPGImageTag != "" {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions, cloudnativepg.WithImageTag(options.CNPGImageTag))
|
||||
}
|
||||
if options.IgnoreExistingResources {
|
||||
cnpgIstallOptions = append(cnpgIstallOptions,
|
||||
cloudnativepg.WithIgnoreExistingResources(options.IgnoreExistingResources))
|
||||
}
|
||||
if err := cloudnativepg.Install(ctx, cl, cnpgIstallOptions...); err != nil {
|
||||
return fmt.Errorf("failed to install cloudnative-pg: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func installCertManager(ctx context.Context, cl client.Client, options SetupOptions) error {
|
||||
// Install cert-manager
|
||||
var certManagerInstallOptions []certmanager.InstallOption
|
||||
if options.CertManagerVersion != "" {
|
||||
certManagerInstallOptions = append(certManagerInstallOptions,
|
||||
certmanager.WithVersion(options.CertManagerVersion))
|
||||
}
|
||||
if options.IgnoreExistingResources {
|
||||
certManagerInstallOptions = append(certManagerInstallOptions,
|
||||
certmanager.WithIgnoreExistingResources(options.IgnoreExistingResources))
|
||||
}
|
||||
cmCtx, cmCtxCancel := context.WithTimeout(ctx, 2*time.Minute)
|
||||
defer cmCtxCancel()
|
||||
if err := certmanager.Install(cmCtx, cl,
|
||||
certManagerInstallOptions...); err != nil {
|
||||
return fmt.Errorf("failed to install cert-manager: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getClient() (client.Client, error) {
|
||||
// Use the current kubernetes client configuration
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Kubernetes config: %w", err)
|
||||
}
|
||||
cl, err := client.New(cfg, client.Options{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create Kubernetes client: %w", err)
|
||||
}
|
||||
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
func setupKind(options SetupOptions) error {
|
||||
// This function sets up the environment for the e2e tests
|
||||
// by creating the cluster and installing the necessary
|
||||
// components.
|
||||
if err := kind.EnsureVersion(options.KindVersion); err != nil {
|
||||
return fmt.Errorf("failed to ensure Kind kindVersion: %w", err)
|
||||
}
|
||||
|
||||
expectedClusterName := kindClusterName(options.KindClusterNamePrefix, options.K8sVersion)
|
||||
clusterIsRunning, err := kind.IsClusterRunning(expectedClusterName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if Kind cluster is running: %w", err)
|
||||
}
|
||||
if !clusterIsRunning {
|
||||
kindOpts := []kind.CreateClusterOption{
|
||||
kind.WithK8sVersion(options.K8sVersion),
|
||||
kind.WithConfigFile(kindConfigFile),
|
||||
kind.WithNetworks(options.KindAdditionalNetworks),
|
||||
}
|
||||
if err := kind.CreateCluster(expectedClusterName, kindOpts...); err != nil {
|
||||
return fmt.Errorf("failed to create Kind cluster: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func kindClusterName(prefix, k8sVersion string) string {
|
||||
k8sVersion = strings.ReplaceAll(k8sVersion, ".", "-")
|
||||
return fmt.Sprintf("%s-%s", prefix, k8sVersion)
|
||||
}
|
||||
133
test/e2e/internal/kind/cluster.go
Normal file
133
test/e2e/internal/kind/cluster.go
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kind
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsClusterRunning checks if a Kind cluster with the given name is running
|
||||
func IsClusterRunning(clusterName string) (bool, error) {
|
||||
cmd := exec.Command(Kind, "get", "clusters")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get Kind clusters: %w, output: %s", err, string(output))
|
||||
}
|
||||
|
||||
clusters := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
for _, cluster := range clusters {
|
||||
if cluster == clusterName {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// CreateClusterOptions are the options for creating a Kind cluster
|
||||
type CreateClusterOptions struct {
|
||||
ConfigFile string
|
||||
K8sVersion string
|
||||
Networks []string
|
||||
}
|
||||
|
||||
// CreateClusterOption is the option for creating a Kind cluster
|
||||
type CreateClusterOption func(*CreateClusterOptions)
|
||||
|
||||
// WithConfigFile sets the config file for creating a Kind cluster
|
||||
func WithConfigFile(configFile string) CreateClusterOption {
|
||||
return func(opts *CreateClusterOptions) {
|
||||
opts.ConfigFile = configFile
|
||||
}
|
||||
}
|
||||
|
||||
// WithK8sVersion sets the Kubernetes version for creating a Kind cluster
|
||||
func WithK8sVersion(k8sVersion string) CreateClusterOption {
|
||||
return func(opts *CreateClusterOptions) {
|
||||
opts.K8sVersion = k8sVersion
|
||||
}
|
||||
}
|
||||
|
||||
// WithNetwork sets the network for creating a Kind cluster
|
||||
func WithNetworks(networks []string) CreateClusterOption {
|
||||
return func(opts *CreateClusterOptions) {
|
||||
opts.Networks = networks
|
||||
}
|
||||
}
|
||||
|
||||
// CreateCluster creates a Kind cluster with the given name
|
||||
func CreateCluster(name string, opts ...CreateClusterOption) error {
|
||||
options := &CreateClusterOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
args := []string{"create", "cluster", "--name", name}
|
||||
if options.ConfigFile != "" {
|
||||
args = append(args, "--config", options.ConfigFile)
|
||||
}
|
||||
if options.K8sVersion != "" {
|
||||
args = append(args, "--image", fmt.Sprintf("kindest/node:%s", options.K8sVersion))
|
||||
}
|
||||
|
||||
cmd := exec.Command(Kind, args...) // #nosec
|
||||
cmd.Dir, _ = os.Getwd()
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("'kind create cluster' failed: %w, output: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Since a cluster can mount additional certificates, we need to make sure they are
|
||||
// usable by the nodes in the cluster.
|
||||
nodes, err := getNodes(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, node := range nodes {
|
||||
cmd = exec.Command("docker", "exec", node, "update-ca-certificates") // #nosec
|
||||
output, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update CA certificates in node %s: %w, output: %s", node, err, string(output))
|
||||
}
|
||||
}
|
||||
|
||||
for _, network := range options.Networks {
|
||||
for _, node := range nodes {
|
||||
cmd = exec.Command("docker", "network", "connect", network, node) // #nosec
|
||||
output, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect node %s to network %s: %w, output: %s", node, network, err,
|
||||
string(output))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getNodes(clusterName string) ([]string, error) {
|
||||
cmd := exec.Command(Kind, "get", "nodes", "--name", clusterName)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Kind nodes: %w, output: %s", err, string(output))
|
||||
}
|
||||
|
||||
return strings.Split(strings.TrimSpace(string(output)), "\n"), nil
|
||||
}
|
||||
19
test/e2e/internal/kind/doc.go
Normal file
19
test/e2e/internal/kind/doc.go
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package kind provides utilities for ensuring the presence and correct version of the Kind binary,
|
||||
// as well as functions for installing and managing the Kind binary in a local project.
|
||||
package kind
|
||||
116
test/e2e/internal/kind/kind.go
Normal file
116
test/e2e/internal/kind/kind.go
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kind
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Kind is the name of the Kind binary
|
||||
const Kind = "kind"
|
||||
|
||||
// EnsureVersion ensures that there is a Kind binary, is at the correct version, and is in the PATH
|
||||
func EnsureVersion(requiredVersion string) error {
|
||||
if _, err := exec.LookPath(Kind); err == nil {
|
||||
version, err := Version()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.Contains(version, requiredVersion) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return Install(requiredVersion)
|
||||
}
|
||||
|
||||
// InstallOptions are the options for installing the Kind binary
|
||||
type InstallOptions struct {
|
||||
BinDir string
|
||||
}
|
||||
|
||||
// InstallOption is the option for installing the Kind binary
|
||||
type InstallOption func(*InstallOptions)
|
||||
|
||||
// WithBinDir sets the directory to install the Kind binary
|
||||
func WithBinDir(binDir string) InstallOption {
|
||||
return func(opts *InstallOptions) {
|
||||
opts.BinDir = binDir
|
||||
}
|
||||
}
|
||||
|
||||
// Install installs the Kind binary in the local project's /bin directory
|
||||
func Install(version string, opts ...InstallOption) error {
|
||||
options := &InstallOptions{
|
||||
BinDir: filepath.Join(".", "bin"), // default bin directory
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
// Get BinDir absolute path
|
||||
absBinDir, err := filepath.Abs(options.BinDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get absolute path for bin directory: %w", err)
|
||||
}
|
||||
options.BinDir = absBinDir
|
||||
|
||||
// Ensure the /bin directory exists
|
||||
if err := os.MkdirAll(options.BinDir, os.ModeDir); err != nil {
|
||||
return fmt.Errorf("failed to create bin directory: %w", err)
|
||||
}
|
||||
|
||||
// Determine the OS and architecture
|
||||
osName := runtime.GOOS
|
||||
arch := runtime.GOARCH
|
||||
|
||||
// Download the Kind binary
|
||||
url := fmt.Sprintf("https://github.com/kubernetes-sigs/kind/releases/download/%s/kind-%s-%s", version, osName, arch)
|
||||
binaryPath := filepath.Join(options.BinDir, Kind)
|
||||
cmd := exec.Command("curl", "-Lo", binaryPath, url) // #nosec
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to download Kind binary: %w, output: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Make the Kind binary executable
|
||||
cmd = exec.Command("chmod", "+x", binaryPath) // #nosec
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to make Kind binary executable: %w, output: %s", err, string(output))
|
||||
}
|
||||
|
||||
if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", options.BinDir, os.Getenv("PATH"))); err != nil {
|
||||
return fmt.Errorf("failed to set PATH: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Version returns the current version of the Kind binary
|
||||
func Version() (string, error) {
|
||||
cmd := exec.Command(Kind, "version")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get Kind version: %w, output: %s", err, string(output))
|
||||
}
|
||||
version := strings.TrimSpace(string(output))
|
||||
return version, nil
|
||||
}
|
||||
19
test/e2e/internal/kustomize/doc.go
Normal file
19
test/e2e/internal/kustomize/doc.go
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package kustomize provides utilities for applying and managing Kubernetes
|
||||
// customizations using Kustomize.
|
||||
package kustomize
|
||||
139
test/e2e/internal/kustomize/kustomize.go
Normal file
139
test/e2e/internal/kustomize/kustomize.go
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kustomize
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
apimachineryerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
// ApplyKustomizationOptions holds options for applying kustomizations
|
||||
type ApplyKustomizationOptions struct {
|
||||
IgnoreExistingResources bool
|
||||
}
|
||||
|
||||
// ApplyKustomizationOption is a functional option for ApplyKustomization
|
||||
type ApplyKustomizationOption func(*ApplyKustomizationOptions)
|
||||
|
||||
// ApplyKustomization builds the kustomization and creates the resources
|
||||
func ApplyKustomization(
|
||||
ctx context.Context,
|
||||
cl client.Client,
|
||||
kustomization *types.Kustomization,
|
||||
options ...ApplyKustomizationOption,
|
||||
) error {
|
||||
opts := &ApplyKustomizationOptions{
|
||||
IgnoreExistingResources: true,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(opts)
|
||||
}
|
||||
|
||||
// We'd rather use an in-memory filesystem, but krusty doesn't support it yet for git URLs
|
||||
// See https://github.com/kubernetes-sigs/kustomize/issues/4390
|
||||
// Create an in-memory filesystem
|
||||
fSys := filesys.MakeFsOnDisk()
|
||||
|
||||
// Write the Kustomization to the filesystem
|
||||
kustomizationYAML, err := yaml.Marshal(kustomization)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal kustomization: %w", err)
|
||||
}
|
||||
|
||||
err = fSys.WriteFile("kustomization.yaml", kustomizationYAML)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write kustomization.yaml: %w", err)
|
||||
}
|
||||
defer fSys.RemoveAll("kustomization.yaml") //nolint:errcheck
|
||||
|
||||
// Build the Kustomization
|
||||
k := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
|
||||
resourceMap, err := k.Run(fSys, ".")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run kustomize: %w", err)
|
||||
}
|
||||
|
||||
return applyResourceMap(ctx, cl, resourceMap)
|
||||
}
|
||||
|
||||
func applyResourceMap(ctx context.Context, cl client.Client, resourceMap resmap.ResMap) error {
|
||||
yamlBytes, err := resourceMap.AsYaml()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert resources to YAML: %w", err)
|
||||
}
|
||||
r := bytes.NewReader(yamlBytes)
|
||||
dec := yaml.NewDecoder(r)
|
||||
for {
|
||||
// parse the YAML doc
|
||||
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
|
||||
err := dec.Decode(obj.Object)
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not decode object: %w", err)
|
||||
}
|
||||
if obj.Object == nil {
|
||||
continue
|
||||
}
|
||||
if err := applyResource(ctx, cl, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyResource(ctx context.Context, cl client.Client, obj *unstructured.Unstructured) error {
|
||||
if err := cl.Create(ctx, obj); err != nil {
|
||||
if apimachineryerrors.IsAlreadyExists(err) {
|
||||
// If the resource already exists, retrieve the existing resource
|
||||
existing := &unstructured.Unstructured{}
|
||||
existing.SetGroupVersionKind(obj.GroupVersionKind())
|
||||
key := client.ObjectKey{
|
||||
Namespace: obj.GetNamespace(),
|
||||
Name: obj.GetName(),
|
||||
}
|
||||
if err := cl.Get(ctx, key, existing); err != nil {
|
||||
log.Fatalf("Error getting existing resource: %v", err)
|
||||
}
|
||||
|
||||
// Update the existing resource with the new data
|
||||
obj.SetResourceVersion(existing.GetResourceVersion())
|
||||
err = cl.Update(ctx, obj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error updating resource: %v", err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("error creating resource: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
test/e2e/kustomize/config
Symbolic link
1
test/e2e/kustomize/config
Symbolic link
@ -0,0 +1 @@
|
||||
../../../config/
|
||||
1
test/e2e/kustomize/kubernetes
Symbolic link
1
test/e2e/kustomize/kubernetes
Symbolic link
@ -0,0 +1 @@
|
||||
../../../kubernetes/
|
||||
@ -1,144 +0,0 @@
|
||||
/*
|
||||
Copyright 2024.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
prometheusOperatorVersion = "v0.72.0"
|
||||
prometheusOperatorURL = "https://github.com/prometheus-operator/prometheus-operator/" +
|
||||
"releases/download/%s/bundle.yaml"
|
||||
|
||||
certmanagerVersion = "v1.14.4"
|
||||
certmanagerURLTmpl = "https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml"
|
||||
)
|
||||
|
||||
func warnError(err error) {
|
||||
_, _ = fmt.Fprintf(GinkgoWriter, "warning: %v\n", err)
|
||||
}
|
||||
|
||||
// InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics.
|
||||
func InstallPrometheusOperator() error {
|
||||
url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)
|
||||
cmd := exec.Command("kubectl", "create", "-f", url)
|
||||
_, err := Run(cmd)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Run executes the provided command within this context.
|
||||
func Run(cmd *exec.Cmd) ([]byte, error) {
|
||||
dir, _ := GetProjectDir()
|
||||
cmd.Dir = dir
|
||||
|
||||
if err := os.Chdir(cmd.Dir); err != nil {
|
||||
_, _ = fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err)
|
||||
}
|
||||
|
||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||
command := strings.Join(cmd.Args, " ")
|
||||
_, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return output, fmt.Errorf("%s failed with error: (%w) %s", command, err, string(output))
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// UninstallPrometheusOperator uninstalls the prometheus.
|
||||
func UninstallPrometheusOperator() {
|
||||
url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)
|
||||
cmd := exec.Command("kubectl", "delete", "-f", url)
|
||||
if _, err := Run(cmd); err != nil {
|
||||
warnError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// UninstallCertManager uninstalls the cert manager.
|
||||
func UninstallCertManager() {
|
||||
url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)
|
||||
cmd := exec.Command("kubectl", "delete", "-f", url)
|
||||
if _, err := Run(cmd); err != nil {
|
||||
warnError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// InstallCertManager installs the cert manager bundle.
|
||||
func InstallCertManager() error {
|
||||
url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)
|
||||
cmd := exec.Command("kubectl", "apply", "-f", url)
|
||||
if _, err := Run(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
// Wait for cert-manager-webhook to be ready, which can take time if cert-manager
|
||||
// was re-installed after uninstalling on a cluster.
|
||||
cmd = exec.Command("kubectl", "wait", "deployment.apps/cert-manager-webhook",
|
||||
"--for", "condition=Available",
|
||||
"--namespace", "cert-manager",
|
||||
"--timeout", "5m",
|
||||
)
|
||||
|
||||
_, err := Run(cmd)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadImageToKindClusterWithName loads a local docker image to the kind cluster.
|
||||
func LoadImageToKindClusterWithName(name string) error {
|
||||
cluster := "kind"
|
||||
if v, ok := os.LookupEnv("KIND_CLUSTER"); ok {
|
||||
cluster = v
|
||||
}
|
||||
kindOptions := []string{"load", "docker-image", name, "--name", cluster}
|
||||
cmd := exec.Command("kind", kindOptions...)
|
||||
_, err := Run(cmd)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetNonEmptyLines converts given command output string into individual objects
|
||||
// according to line breakers, and ignores the empty elements in it.
|
||||
func GetNonEmptyLines(output string) []string {
|
||||
var res []string
|
||||
elements := strings.Split(output, "\n")
|
||||
for _, element := range elements {
|
||||
if element != "" {
|
||||
res = append(res, element)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetProjectDir will return the directory where the project is.
|
||||
func GetProjectDir() (string, error) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return wd, fmt.Errorf("failed to get the current working directory: %w", err)
|
||||
}
|
||||
wd = strings.ReplaceAll(wd, "/test/e2e", "")
|
||||
|
||||
return wd, nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user