From 03807c5330feb955db66d3161fe66d6395b853a1 Mon Sep 17 00:00:00 2001 From: Michael Scrivo Date: Wed, 12 Aug 2026 15:13:08 -0400 Subject: [PATCH 1/2] feat: support pgdog.toml from an existing Secret (configSecret) Add a configSecret value mirroring usersSecret: when configSecret.name is set, the config volume is sourced from that existing Secret (with the key remapped to pgdog.toml) instead of the chart-rendered ConfigMap, which is then skipped entirely. This makes it possible to run pgdog when pgdog.toml contains values that must not live in a ConfigMap, e.g. database hosts and the admin password rendered from a secrets manager (External Secrets, sealed-secrets, SOPS). Overlaying such a file on top of the chart's ConfigMap with a subPath volume mount is not an option: the mount target is a symlink inside the ConfigMap volume and container runtimes reject the mount at pod start (kubernetes/kubernetes#61545), so swapping the volume source is the only way to provide the whole file. All parameters optional; default rendering is unchanged. Co-Authored-By: Claude Fable 5 --- README.md | 37 +++++++++++++++++++++++++ templates/config.yaml | 2 ++ templates/deployment.yaml | 8 ++++++ test/test.sh | 37 +++++++++++++++++++++++++ test/values-existing-config-secret.yaml | 12 ++++++++ values.yaml | 21 ++++++++++++++ 6 files changed, 117 insertions(+) create mode 100644 test/values-existing-config-secret.yaml diff --git a/README.md b/README.md index 5f0beee..2a58355 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,43 @@ kubectl create secret generic my-pgdog-users \ The value is mounted at `/etc/secrets/pgdog/users.toml` regardless of the key name. A custom `key` is remapped automatically. +#### pgdog.toml from an existing Secret + +Set `configSecret.name` to reference a Secret you created that holds the +`pgdog.toml` file. The chart then skips rendering its own pgdog.toml +ConfigMap and mounts your Secret as the config volume instead. Use this when +your pgdog.toml contains values that must not live in a ConfigMap, such as +database hosts or the admin password sourced from a secrets manager: + +```yaml +configSecret: + name: my-pgdog-config # existing Secret in the same namespace + key: pgdog.toml # key holding the pgdog.toml content (default: pgdog.toml) +``` + +Create the Secret, for example: + +```bash +kubectl create secret generic my-pgdog-config \ + --from-file=pgdog.toml=./pgdog.toml +``` + +The value is mounted at `/etc/pgdog/pgdog.toml` regardless of the key name. +A custom `key` is remapped automatically. All pgdog.toml-related chart values +(`databases`, `defaultPoolSize`, sharding settings, etc.) are ignored, since +your Secret provides the whole file. + +Note: swapping the volume source is required — overlaying a Secret-provided +`pgdog.toml` on top of the chart's ConfigMap with a `subPath` volume mount +fails at container start (the mount target is a symlink inside the ConfigMap +volume; see +[kubernetes/kubernetes#61545](https://github.com/kubernetes/kubernetes/issues/61545)). + +Note: `plugins[].config` entries render into the chart's ConfigMap and are +not mounted when `configSecret.name` is set. A Secret-provided pgdog.toml +controls its own plugin config paths, so mount plugin files elsewhere via +`extraVolumes`/`extraVolumeMounts`. + #### Datadog API key from an existing Secret PgDog reads the Datadog API key from the `DD_API_KEY` environment variable. diff --git a/templates/config.yaml b/templates/config.yaml index e7c51eb..cb1c86a 100644 --- a/templates/config.yaml +++ b/templates/config.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.configSecret.name }} apiVersion: v1 kind: ConfigMap metadata: @@ -618,3 +619,4 @@ data: {{ .config | indent 8 }} {{- end }} {{- end }} +{{- end }} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 332448b..5bb7089 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -209,8 +209,16 @@ spec: {{- end }} volumes: - name: config + {{- if .Values.configSecret.name }} + secret: + secretName: {{ .Values.configSecret.name }} + items: + - key: {{ .Values.configSecret.key | default "pgdog.toml" }} + path: pgdog.toml + {{- else }} configMap: name: {{ include "pgdog.fullname" . }} + {{- end }} - name: users secret: {{- if .Values.usersSecret.name }} diff --git a/test/test.sh b/test/test.sh index 5b7b938..ce6ce4a 100755 --- a/test/test.sh +++ b/test/test.sh @@ -37,5 +37,42 @@ else exit 1 fi +# Validate configSecret swaps the config volume source and skips the ConfigMap +echo "" +echo "==> Validating configSecret volume and ConfigMap suppression..." +rendered=$(helm template test-release "$CHART_DIR" -f "$TEST_DIR/values-existing-config-secret.yaml") + +config_volume=$(echo "$rendered" \ + | yq -r 'select(.kind == "Deployment") | .spec.template.spec.volumes[] | select(.name == "config") | .secret.secretName') + +if [ "$config_volume" = "my-pgdog-config" ]; then + echo " config volume sourced from the existing Secret" +else + echo " FAIL: config volume not sourced from the existing Secret" + echo " Got: $config_volume" + exit 1 +fi + +config_key=$(echo "$rendered" \ + | yq -r 'select(.kind == "Deployment") | .spec.template.spec.volumes[] | select(.name == "config") | .secret.items[0] | .key + ":" + .path') + +if [ "$config_key" = "my-config-key.toml:pgdog.toml" ]; then + echo " custom key remapped to pgdog.toml" +else + echo " FAIL: custom key not remapped to pgdog.toml" + echo " Got: $config_key" + exit 1 +fi + +config_map=$(echo "$rendered" \ + | yq -r 'select(.kind == "ConfigMap" and .metadata.name == "test-release-pgdog") | .metadata.name') + +if [ -z "$config_map" ]; then + echo " chart pgdog.toml ConfigMap not rendered" +else + echo " FAIL: chart pgdog.toml ConfigMap still rendered" + exit 1 +fi + echo "" echo "==> All tests passed!" diff --git a/test/values-existing-config-secret.yaml b/test/values-existing-config-secret.yaml new file mode 100644 index 0000000..e04f025 --- /dev/null +++ b/test/values-existing-config-secret.yaml @@ -0,0 +1,12 @@ +# Test referencing an existing, user-created Secret for pgdog.toml instead of +# the chart-rendered ConfigMap. Covers: +# - configSecret: mount pgdog.toml from an existing Secret, with a custom key +# remapped to pgdog.toml; the chart's pgdog.toml ConfigMap is not rendered + +configSecret: + name: my-pgdog-config + key: my-config-key.toml + +usersSecret: + name: my-pgdog-users + key: users.toml diff --git a/values.yaml b/values.yaml index c79f598..4437501 100644 --- a/values.yaml +++ b/values.yaml @@ -474,6 +474,27 @@ usersSecret: # it is mounted at /etc/secrets/pgdog/users.toml regardless of the key name key: users.toml +# configSecret references an existing Secret (that you created yourself in +# this namespace) holding the pgdog.toml file. When name is set, the chart +# does not render its own pgdog.toml ConfigMap and mounts this Secret as the +# /etc/pgdog directory instead. Use this when your pgdog.toml contains values +# that must not live in a ConfigMap (e.g. database hosts or the admin +# password sourced from a secrets manager). +# Note: overlaying a Secret-provided pgdog.toml on top of the chart's +# ConfigMap with a subPath volume mount does not work — the mount target is +# a symlink inside the ConfigMap volume and the container runtime rejects it +# (kubernetes/kubernetes#61545) — which is why this swaps the volume source. +# Note: plugins[].config entries render into the chart's ConfigMap and are +# not mounted when configSecret.name is set; a Secret-provided pgdog.toml +# controls its own plugin config paths, so mount plugin files elsewhere via +# extraVolumes/extraVolumeMounts. +configSecret: + # name of the existing Secret containing pgdog.toml + name: "" + # key within that Secret whose value is the pgdog.toml content; + # it is mounted at /etc/pgdog/pgdog.toml regardless of the key name + key: pgdog.toml + # otel configures OpenTelemetry metrics export. Left unset by default so the # [otel] section is omitted from pgdog.toml. Uncomment and fill in to enable. # otel: From 77b1b3bbebf42e43c1d15f90009bfcec50bd9e56 Mon Sep 17 00:00:00 2001 From: Michael Scrivo Date: Wed, 12 Aug 2026 15:19:35 -0400 Subject: [PATCH 2/2] review: drop bespoke test.sh assertions, test values are auto-validated Co-Authored-By: Claude Fable 5 --- test/test.sh | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/test/test.sh b/test/test.sh index ce6ce4a..5b7b938 100755 --- a/test/test.sh +++ b/test/test.sh @@ -37,42 +37,5 @@ else exit 1 fi -# Validate configSecret swaps the config volume source and skips the ConfigMap -echo "" -echo "==> Validating configSecret volume and ConfigMap suppression..." -rendered=$(helm template test-release "$CHART_DIR" -f "$TEST_DIR/values-existing-config-secret.yaml") - -config_volume=$(echo "$rendered" \ - | yq -r 'select(.kind == "Deployment") | .spec.template.spec.volumes[] | select(.name == "config") | .secret.secretName') - -if [ "$config_volume" = "my-pgdog-config" ]; then - echo " config volume sourced from the existing Secret" -else - echo " FAIL: config volume not sourced from the existing Secret" - echo " Got: $config_volume" - exit 1 -fi - -config_key=$(echo "$rendered" \ - | yq -r 'select(.kind == "Deployment") | .spec.template.spec.volumes[] | select(.name == "config") | .secret.items[0] | .key + ":" + .path') - -if [ "$config_key" = "my-config-key.toml:pgdog.toml" ]; then - echo " custom key remapped to pgdog.toml" -else - echo " FAIL: custom key not remapped to pgdog.toml" - echo " Got: $config_key" - exit 1 -fi - -config_map=$(echo "$rendered" \ - | yq -r 'select(.kind == "ConfigMap" and .metadata.name == "test-release-pgdog") | .metadata.name') - -if [ -z "$config_map" ]; then - echo " chart pgdog.toml ConfigMap not rendered" -else - echo " FAIL: chart pgdog.toml ConfigMap still rendered" - exit 1 -fi - echo "" echo "==> All tests passed!"