From 1aac0ee2870b85e14526ca6e27914289b7fe9d6a Mon Sep 17 00:00:00 2001 From: Gabriele Fedi Date: Tue, 16 Dec 2025 10:51:33 +0100 Subject: [PATCH 1/5] feat: automate e2e env setup Add tasks to bootstrap a kind environment with ImageVolume feature gate enabled and install CNPG operator. Everything runs through dagger so no additional runtime dependencies are needed. Signed-off-by: Gabriele Fedi --- Taskfile.yml | 141 +++++++++++++++++++++++++++++++++++++++++++++++ kind-config.yaml | 4 ++ 2 files changed, 145 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index c82155f..6e2c8ad 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -8,6 +8,16 @@ vars: RED: \033[0;31m NC: \033[0m + E2E_NETWORK: pg-extensions-e2e + DAGGER_ENGINE_NAME: dagger-engine-pg-extensions + REGISTRY_NAME: registry.pg-extensions + REGISTRY_HOST_PORT: 5000 + # TODO: renovate + K8S_VERSION: 1.34.2 + # TODO: renovate ? + CNPG_RELEASE: 1.28 + KIND_CLUSTER_NAME: pg-extensions-{{ .K8S_VERSION }} + tasks: default: desc: Build all targets (default) @@ -116,3 +126,134 @@ tasks: vars: TARGET: "{{.ITEM}}" task: update-os-libs + + e2e:create-docker-network: + description: Create Docker network to connect all the services, such as the Registry, Kind nodes, Chainsaw, etc. + run: once + cmds: + - docker network create {{ .E2E_NETWORK }} + status: + - docker network inspect {{ .E2E_NETWORK }} + + e2e:start-container-registry: + description: Start a local Docker registry to push the built images for E2E tests + deps: + - e2e:create-docker-network + run: once + vars: + REGISTRY_VERSION: 2 + cmds: + - > + docker run -d --name {{ .REGISTRY_NAME }} --rm -p {{ .REGISTRY_HOST_PORT }}:5000 + --network {{ .E2E_NETWORK }} registry:{{ .REGISTRY_VERSION }} + status: + - test "$(docker inspect -f {{`'{{json .State.Running}}'`}} {{ .REGISTRY_NAME }})" == "true" + + e2e:start-dagger-engine: + description: Start a custom Dagger engine so we can connect it to the E2E Docker network + deps: + - e2e:create-docker-network + run: once + vars: + # TODO: renovate + DAGGER_ENGINE_VERSION: v0.19.8 + cmds: + - > + docker run -d -v /var/lib/dagger --name {{ .DAGGER_ENGINE_NAME }} --rm --network {{ .E2E_NETWORK }} + --privileged registry.dagger.io/engine:{{ .DAGGER_ENGINE_VERSION }} + status: + - test "$(docker inspect -f {{`'{{json .State.Running}}'`}} {{ .DAGGER_ENGINE_NAME }})" == "true" + + e2e:kind-setup: + description: Setup Kind cluster for E2E tests + deps: + - e2e:start-container-registry + - e2e:start-dagger-engine + run: once + vars: + #TODO: renovate + DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 + REGISTRY_DIR: /etc/containerd/certs.d/localhost:{{ .REGISTRY_HOST_PORT }} + DOCKER_SOCKET: + sh: docker context inspect -f {{`'{{json .Endpoints.docker.Host}}'`}} $(docker context show) + env: + _EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }} + cmds: + - > + dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} --socket {{ .DOCKER_SOCKET }} + container with-env-variable --name=KIND_EXPERIMENTAL_DOCKER_NETWORK --value={{ .E2E_NETWORK }} with-env-variable --name=CACHE_BUSTER --value="$(date)" + with-file --source=kind-config.yaml --path=/root/kind-config.yaml + with-exec --args="kind","create","cluster","--name","{{ .KIND_CLUSTER_NAME }}","--image","kindest/node:v{{ .K8S_VERSION }}","--config","/root/kind-config.yaml" sync + - docker exec "{{ .KIND_CLUSTER_NAME }}-control-plane" mkdir -p "{{ .REGISTRY_DIR }}" + - | + cat < + test "$(dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} + --socket {{ .DOCKER_SOCKET }} cluster --name {{ .KIND_CLUSTER_NAME }} exist)" == "true" + + e2e:cnpg-install: + description: Install CloudNativePG operator in the Kind cluster + deps: + - e2e:start-dagger-engine + - e2e:kind-setup + vars: + # TODO: renovate + DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 + DOCKER_SOCKET: + sh: docker context inspect -f {{`'{{json .Endpoints.docker.Host}}'`}} $(docker context show) + CNPG_MANIFEST: + sh: | + if [ "{{ .CNPG_RELEASE }}" = "main" ]; then + echo "https://raw.githubusercontent.com/cloudnative-pg/artifacts/main/manifests/operator-manifest.yaml" + else + echo "https://raw.githubusercontent.com/cloudnative-pg/artifacts/release-{{ .CNPG_RELEASE }}/manifests/operator-manifest.yaml" + fi + env: + _EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }} + cmds: + - | + kubeconfig=$(dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} \ + --socket {{ .DOCKER_SOCKET }} container \ + with-exec --args "kind","get","kubeconfig","--internal","--name","{{ .KIND_CLUSTER_NAME }}" stdout) + + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ + with-env-variable --name=CACHEBUSTER --value="$(date)" \ + with-exec --args="apply","--server-side","-f","{{ .CNPG_MANIFEST }}" --use-entrypoint sync + + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ + with-env-variable --name=CACHEBUSTER --value="$(date)" \ + with-exec --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" --use-entrypoint sync + + e2e:env-setup: + description: Setup E2E environment + silent: true + deps: + - e2e:create-docker-network + - e2e:start-container-registry + - e2e:start-dagger-engine + - e2e:kind-setup + - e2e:cnpg-install + cmds: + - echo -e "{{.GREEN}}--- E2E environment setup complete ---{{.NC}}" + + e2e:cleanup: + description: Cleanup E2E resources + deps: + - e2e:start-dagger-engine + vars: + # TODO: renovate + DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 + DOCKER_SOCKET: + sh: docker context inspect -f {{`'{{json .Endpoints.docker.Host}}'`}} $(docker context show) + env: + _EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }} + cmds: + - > + dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} + --socket {{ .DOCKER_SOCKET }} cluster --name {{ .KIND_CLUSTER_NAME }} delete || true + - docker rm -fv {{ .DAGGER_ENGINE_NAME }} || true + - docker rm -fv {{ .REGISTRY_NAME }} || true + - docker network rm {{ .E2E_NETWORK }} || true diff --git a/kind-config.yaml b/kind-config.yaml index 8b16432..04e6447 100644 --- a/kind-config.yaml +++ b/kind-config.yaml @@ -2,3 +2,7 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 featureGates: ImageVolume: true +containerdConfigPatches: + - |- + [plugins."io.containerd.grpc.v1.cri".registry] + config_path = "/etc/containerd/certs.d" From c8d1c13411c6b28310deb18f578a366db5fbdf5e Mon Sep 17 00:00:00 2001 From: Gabriele Fedi Date: Thu, 18 Dec 2025 17:47:34 +0100 Subject: [PATCH 2/5] ci: setup env via task Signed-off-by: Gabriele Fedi --- .github/workflows/bake_targets.yml | 26 +++++++++++--------------- Taskfile.yml | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/.github/workflows/bake_targets.yml b/.github/workflows/bake_targets.yml index bf0c7a0..a6f7c7d 100644 --- a/.github/workflows/bake_targets.yml +++ b/.github/workflows/bake_targets.yml @@ -130,24 +130,20 @@ jobs: with: persist-credentials: false - - name: Create kind cluster - uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 - with: - version: ${{ env.KIND_VERSION }} - kubectl_version: ${{ env.KIND_NODE_VERSION }} - node_image: kindest/node:${{ env.KIND_NODE_VERSION }} - config: kind-config.yaml + - name: Install Task + uses: go-task/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1.0.0 - - name: Install CNPG (${{ matrix.cnpg }}) + - name: Install Dagger env: - CNPG_RELEASE: ${{ matrix.cnpg }} + # renovate: datasource=github-tags depName=dagger/dagger versioning=semver + DAGGER_VERSION: 0.19.8 run: | - operator_manifest="https://raw.githubusercontent.com/cloudnative-pg/artifacts/release-$CNPG_RELEASE/manifests/operator-manifest.yaml" - if [[ "$CNPG_RELEASE" == "main" ]]; then - operator_manifest="https://raw.githubusercontent.com/cloudnative-pg/artifacts/main/manifests/operator-manifest.yaml" - fi - curl -sSfL "$operator_manifest" | kubectl apply --server-side -f - - kubectl wait --for=condition=Available --timeout=2m -n cnpg-system deployments cnpg-controller-manager + curl -L https://dl.dagger.io/dagger/install.sh | BIN_DIR=$HOME/.local/bin sh + + - name: Set up environment + run: | + task e2e:env-setup + task e2e:export-kubeconfig - name: Generate Chainsaw testing values uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 # v8.2.0 diff --git a/Taskfile.yml b/Taskfile.yml index 6e2c8ad..539fb73 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -227,6 +227,26 @@ tasks: with-env-variable --name=CACHEBUSTER --value="$(date)" \ with-exec --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" --use-entrypoint sync + e2e:export-kubeconfig: + description: Export Kind cluster kubeconfig + deps: + - e2e:start-dagger-engine + - e2e:kind-setup + vars: + DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 + KUBECONFIG_PATH: '{{.KUBECONFIG_PATH| default "~/.kube/config"}}' + DOCKER_SOCKET: + sh: docker context inspect -f {{`'{{json .Endpoints.docker.Host}}'`}} $(docker context show) + env: + _EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }} + cmds: + - | + CONFIG=$(dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} \ + --socket {{ .DOCKER_SOCKET }} container \ + with-exec --args "kind","get","kubeconfig","--name","{{ .KIND_CLUSTER_NAME }}" stdout) + mkdir -p $(dirname {{ .KUBECONFIG_PATH }}) + echo "${CONFIG}" > {{ .KUBECONFIG_PATH }} + e2e:env-setup: description: Setup E2E environment silent: true From c7aab820c73a0466c55a30bdd2c6368b0297f21b Mon Sep 17 00:00:00 2001 From: Gabriele Fedi Date: Mon, 22 Dec 2025 09:16:24 +0100 Subject: [PATCH 3/5] fix: tasks description Signed-off-by: Gabriele Fedi --- Taskfile.yml | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 539fb73..203c718 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -25,7 +25,7 @@ tasks: - task: bake:all prereqs: - description: Ensure prerequisites are met + desc: Ensure prerequisites are met run: once silent: true cmds: @@ -38,7 +38,7 @@ tasks: - echo -e "{{.GREEN}}All prerequisites satisfied!{{.NC}}" checks: - description: Run checks for the specified target + desc: Run checks for the specified target deps: - prereqs prefix: 'checks-{{.TARGET}}' @@ -54,7 +54,7 @@ tasks: - name: TARGET checks:all: - description: Run checks for all the available targets + desc: Run checks for all the available targets vars: TARGETS: sh: dagger call -sm ./dagger/maintenance/ get-targets | tr -d '[]"' | tr ',' '\n' @@ -66,7 +66,7 @@ tasks: task: checks bake: - description: Bake the specified target + desc: Bake the specified target deps: - prereqs prefix: 'bake-{{.TARGET}}' @@ -91,7 +91,7 @@ tasks: - name: TARGET bake:all: - description: Bake all the available targets + desc: Bake all the available targets vars: TARGETS: sh: dagger call -sm ./dagger/maintenance/ get-targets | tr -d '[]"' | tr ',' '\n' @@ -103,7 +103,7 @@ tasks: task: bake update-os-libs: - description: Update OS libs on the specified target + desc: Update OS libs on the specified target deps: - prereqs prefix: 'update-os-libs-{{.TARGET}}' @@ -116,7 +116,7 @@ tasks: - name: TARGET update-os-libs:all: - description: Update OS libs for all the available targets + desc: Update OS libs for all the available targets vars: TARGETS: sh: dagger call -sm ./dagger/maintenance/ get-oslibs-targets | tr -d '[]"' | tr ',' '\n' @@ -128,17 +128,19 @@ tasks: task: update-os-libs e2e:create-docker-network: - description: Create Docker network to connect all the services, such as the Registry, Kind nodes, Chainsaw, etc. + desc: Create Docker network to connect all the services, such as the Registry, Kind nodes, Chainsaw, etc. run: once + internal: true cmds: - docker network create {{ .E2E_NETWORK }} status: - docker network inspect {{ .E2E_NETWORK }} e2e:start-container-registry: - description: Start a local Docker registry to push the built images for E2E tests + desc: Start a local Docker registry to push the built images for E2E tests deps: - e2e:create-docker-network + internal: true run: once vars: REGISTRY_VERSION: 2 @@ -150,9 +152,10 @@ tasks: - test "$(docker inspect -f {{`'{{json .State.Running}}'`}} {{ .REGISTRY_NAME }})" == "true" e2e:start-dagger-engine: - description: Start a custom Dagger engine so we can connect it to the E2E Docker network + desc: Start a custom Dagger engine so we can connect it to the E2E Docker network deps: - e2e:create-docker-network + internal: true run: once vars: # TODO: renovate @@ -165,10 +168,11 @@ tasks: - test "$(docker inspect -f {{`'{{json .State.Running}}'`}} {{ .DAGGER_ENGINE_NAME }})" == "true" e2e:kind-setup: - description: Setup Kind cluster for E2E tests + desc: Setup Kind cluster for E2E tests deps: - e2e:start-container-registry - e2e:start-dagger-engine + internal: true run: once vars: #TODO: renovate @@ -195,10 +199,11 @@ tasks: --socket {{ .DOCKER_SOCKET }} cluster --name {{ .KIND_CLUSTER_NAME }} exist)" == "true" e2e:cnpg-install: - description: Install CloudNativePG operator in the Kind cluster + desc: Install CloudNativePG operator in the Kind cluster deps: - e2e:start-dagger-engine - e2e:kind-setup + internal: true vars: # TODO: renovate DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 @@ -219,20 +224,25 @@ tasks: --socket {{ .DOCKER_SOCKET }} container \ with-exec --args "kind","get","kubeconfig","--internal","--name","{{ .KIND_CLUSTER_NAME }}" stdout) - dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} + with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ with-env-variable --name=CACHEBUSTER --value="$(date)" \ with-exec --args="apply","--server-side","-f","{{ .CNPG_MANIFEST }}" --use-entrypoint sync - dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} + with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ with-env-variable --name=CACHEBUSTER --value="$(date)" \ - with-exec --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" --use-entrypoint sync + with-exec + --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" + --use-entrypoint sync e2e:export-kubeconfig: - description: Export Kind cluster kubeconfig + desc: Export Kind cluster kubeconfig at path defined by KUBECONFIG_PATH var (default ~/.kube/config) deps: - e2e:start-dagger-engine - e2e:kind-setup vars: + # TODO: renovate DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 KUBECONFIG_PATH: '{{.KUBECONFIG_PATH| default "~/.kube/config"}}' DOCKER_SOCKET: @@ -248,7 +258,7 @@ tasks: echo "${CONFIG}" > {{ .KUBECONFIG_PATH }} e2e:env-setup: - description: Setup E2E environment + desc: Setup E2E environment silent: true deps: - e2e:create-docker-network @@ -260,7 +270,7 @@ tasks: - echo -e "{{.GREEN}}--- E2E environment setup complete ---{{.NC}}" e2e:cleanup: - description: Cleanup E2E resources + desc: Cleanup E2E resources deps: - e2e:start-dagger-engine vars: From 9e03909c099f83e5e0b4fe520015a959fdffaecf Mon Sep 17 00:00:00 2001 From: Gabriele Fedi Date: Mon, 22 Dec 2025 09:21:59 +0100 Subject: [PATCH 4/5] style: tasks name Signed-off-by: Gabriele Fedi --- .github/workflows/bake_targets.yml | 2 +- Taskfile.yml | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/bake_targets.yml b/.github/workflows/bake_targets.yml index a6f7c7d..9bba905 100644 --- a/.github/workflows/bake_targets.yml +++ b/.github/workflows/bake_targets.yml @@ -142,7 +142,7 @@ jobs: - name: Set up environment run: | - task e2e:env-setup + task e2e:setup-env task e2e:export-kubeconfig - name: Generate Chainsaw testing values diff --git a/Taskfile.yml b/Taskfile.yml index 203c718..9ca8247 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -167,7 +167,7 @@ tasks: status: - test "$(docker inspect -f {{`'{{json .State.Running}}'`}} {{ .DAGGER_ENGINE_NAME }})" == "true" - e2e:kind-setup: + e2e:setup-kind: desc: Setup Kind cluster for E2E tests deps: - e2e:start-container-registry @@ -198,11 +198,11 @@ tasks: test "$(dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }} --socket {{ .DOCKER_SOCKET }} cluster --name {{ .KIND_CLUSTER_NAME }} exist)" == "true" - e2e:cnpg-install: + e2e:install-cnpg: desc: Install CloudNativePG operator in the Kind cluster deps: - e2e:start-dagger-engine - - e2e:kind-setup + - e2e:setup-kind internal: true vars: # TODO: renovate @@ -224,23 +224,23 @@ tasks: --socket {{ .DOCKER_SOCKET }} container \ with-exec --args "kind","get","kubeconfig","--internal","--name","{{ .KIND_CLUSTER_NAME }}" stdout) - dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} \ with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ with-env-variable --name=CACHEBUSTER --value="$(date)" \ with-exec --args="apply","--server-side","-f","{{ .CNPG_MANIFEST }}" --use-entrypoint sync - dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} + dagger core container from --address=alpine/kubectl:{{ .K8S_VERSION }} \ with-new-file --contents "${kubeconfig}" --path /root/.kube/config --expand \ with-env-variable --name=CACHEBUSTER --value="$(date)" \ - with-exec - --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" + with-exec \ + --args="wait","--for=condition=Available","--timeout=2m","-n","cnpg-system","deployments","cnpg-controller-manager" \ --use-entrypoint sync e2e:export-kubeconfig: desc: Export Kind cluster kubeconfig at path defined by KUBECONFIG_PATH var (default ~/.kube/config) deps: - e2e:start-dagger-engine - - e2e:kind-setup + - e2e:setup-kind vars: # TODO: renovate DAGGER_KIND_SHA: dadbc09a1e0790ccbf1d88f796308b26a12f0488 @@ -257,15 +257,15 @@ tasks: mkdir -p $(dirname {{ .KUBECONFIG_PATH }}) echo "${CONFIG}" > {{ .KUBECONFIG_PATH }} - e2e:env-setup: + e2e:setup-env: desc: Setup E2E environment silent: true deps: - e2e:create-docker-network - e2e:start-container-registry - e2e:start-dagger-engine - - e2e:kind-setup - - e2e:cnpg-install + - e2e:setup-kind + - e2e:install-cnpg cmds: - echo -e "{{.GREEN}}--- E2E environment setup complete ---{{.NC}}" From 198551cd3b7d4610c66fda062b46b20a682c4420 Mon Sep 17 00:00:00 2001 From: Gabriele Fedi Date: Mon, 22 Dec 2025 10:18:54 +0100 Subject: [PATCH 5/5] docs: updated documentation Signed-off-by: Gabriele Fedi --- BUILD.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/BUILD.md b/BUILD.md index 0a1ae67..7301b62 100644 --- a/BUILD.md +++ b/BUILD.md @@ -83,3 +83,33 @@ task DRY_RUN=true # or task bake TARGET=pgvector DRY_RUN=true ``` + +## Testing locally + +Local testing can be performed by using a local Docker container registry and a Kind cluster with CNPG installed. +The Taskfile includes utilities to set up and tear down such an environment. + +### Create a local test environment + +The `e2e:setup-env` task takes care of setting up a Kind cluster with a local Docker container registry connected to the same +Docker network and installs CloudNativePG by default. + +```bash +task e2e:setup-env +``` + +The container registry will be exposed locally at `localhost:5000`. + +The Kubeconfig to connect to the Kind cluster can be retrieved with: + +```bash +task e2e:export-kubeconfig KUBECONFIG_PATH= +``` + +### Tear down the local test environment + +To clean up all the resources created by the `e2e:setup-env` task, run: + +```bash +task e2e:cleanup +```