Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: v1
name: pgdog
version: v0.95
version: v0.96
appVersion: "v0.1.63"
18 changes: 18 additions & 0 deletions templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ spec:
{{- end }}
spec:
serviceAccountName: {{ include "pgdog.serviceAccountName" . }}
{{- if hasKey .Values "automountServiceAccountToken" }}
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}
{{- end }}
{{- if .Values.shareProcessNamespace }}
shareProcessNamespace: true
{{- end }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- end }}
Expand Down Expand Up @@ -149,7 +155,16 @@ spec:
containerPort: {{ .Values.port }}
- name: metrics
containerPort: {{ .Values.openMetricsPort }}
{{- if .Values.lifecycle }}
{{- if .Values.preStopSleepSeconds }}
{{- fail "lifecycle replaces the preStop that preStopSleepSeconds renders; set one of them" }}
{{- end }}
{{- if and .Values.lifecycle.preStop (not .Values.terminationGracePeriodSeconds) }}
{{- fail "lifecycle.preStop needs an explicit terminationGracePeriodSeconds that covers the preStop plus shutdownTimeout" }}
{{- end }}
lifecycle:
{{- toYaml .Values.lifecycle | nindent 12 }}
{{- else if .Values.preStopSleepSeconds }}
lifecycle:
preStop:
sleep:
Expand Down Expand Up @@ -233,6 +248,9 @@ spec:
- name: prom
mountPath: /etc/prom
{{- end }}
{{- with .Values.extraContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: config
{{- if .Values.configSecret.name }}
Expand Down
2 changes: 2 additions & 0 deletions templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ spec:
protocol: TCP
port: {{ .Values.port }}
targetPort: {{ .Values.port }}
{{- if or (not (hasKey .Values.service "exposeMetrics")) .Values.service.exposeMetrics }}
- name: openmetrics
protocol: TCP
port: {{ .Values.openMetricsPort }}
targetPort: {{ .Values.openMetricsPort }}
{{- end }}
{{- if .Values.healthcheckPort }}
- name: healthcheck
protocol: TCP
Expand Down
3 changes: 3 additions & 0 deletions templates/servicemonitor.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{{- if .Values.serviceMonitor.enabled }}
{{- if and (hasKey .Values.service "exposeMetrics") (not .Values.service.exposeMetrics) (not .Values.statefulSet.enabled) }}
{{- fail "serviceMonitor scrapes the Service's openmetrics port; it needs service.exposeMetrics: true" }}
{{- end }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
Expand Down
48 changes: 48 additions & 0 deletions test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,53 @@ else
exit 1
fi

echo ""
echo "==> Validating pod extension points..."
pod_spec() {
helm template test-release "$CHART_DIR" -f "$@" \
| yq -o=json -I=0 'select(.kind == "Deployment") | .spec.template.spec | {"automount": .automountServiceAccountToken, "shareProcessNamespace": .shareProcessNamespace, "containers": (.containers | map(.name)), "lifecycle": .containers[0].lifecycle}'
}
service_ports() {
helm template test-release "$CHART_DIR" -f "$@" \
| yq -o=json -I=0 'select(.kind == "Service" and .metadata.name == "test-release-pgdog") | .spec.ports | map(.name)'
}
expect() {
if [ "$2" != "$3" ]; then
echo " FAIL: $1"
echo " Expected: $3"
echo " Got: $2"
exit 1
fi
}
expect_fail() {
if helm template test-release "$CHART_DIR" "${@:2}" >/dev/null 2>&1; then
echo " FAIL: rendered although $1"
exit 1
fi
}

expect "extension points render as set" "$(pod_spec "$TEST_DIR/values-pod-extensions.yaml")" \
'{"automount":false,"shareProcessNamespace":true,"containers":["pgdog","reloader"],"lifecycle":{"preStop":{"exec":{"command":["/bin/sh","-c","sleep 30"]}}}}'
expect "defaults render none of them" "$(pod_spec "$TEST_DIR/values-default.yaml")" \
'{"automount":null,"shareProcessNamespace":null,"containers":["pgdog"],"lifecycle":null}'
expect "preStopSleepSeconds still renders its preStop" "$(pod_spec "$TEST_DIR/values-default.yaml" --set preStopSleepSeconds=25 | yq -o=json -I=0 .lifecycle)" \
'{"preStop":{"sleep":{"seconds":25}}}'
expect "automountServiceAccountToken true renders" "$(pod_spec "$TEST_DIR/values-default.yaml" --set automountServiceAccountToken=true | yq .automount)" 'true'
expect "extraContainers follow the prometheus sidecar" "$(pod_spec "$TEST_DIR/values-pod-extensions.yaml" --set prometheusPort=9091 | yq -o=json -I=0 .containers)" \
'["pgdog","prom","reloader"]'

expect "exposeMetrics false drops the metrics port" "$(service_ports "$TEST_DIR/values-pod-extensions.yaml")" '["pgdog"]'
expect "metrics port is on the Service by default" "$(service_ports "$TEST_DIR/values-default.yaml")" '["pgdog","openmetrics"]'
# helm upgrade --reuse-values keeps the old release's values, which lack the key.
expect "missing exposeMetrics keeps the metrics port" "$(service_ports "$TEST_DIR/values-default.yaml" --set service.exposeMetrics=null)" '["pgdog","openmetrics"]'
helm template test-release "$CHART_DIR" -f "$TEST_DIR/values-monitoring.yaml" --set service.exposeMetrics=null >/dev/null
helm template test-release "$CHART_DIR" -f "$TEST_DIR/values-monitoring.yaml" -f "$TEST_DIR/values-statefulset.yaml" --set service.exposeMetrics=false >/dev/null

expect_fail "serviceMonitor has no Service metrics port" -f "$TEST_DIR/values-monitoring.yaml" --set service.exposeMetrics=false
expect_fail "lifecycle and preStopSleepSeconds are both set" -f "$TEST_DIR/values-pod-extensions.yaml" --set preStopSleepSeconds=25
helm template test-release "$CHART_DIR" --set-json 'lifecycle={"postStart":{"exec":{"command":["true"]}}}' >/dev/null
expect_fail "lifecycle.preStop has no explicit terminationGracePeriodSeconds" -f "$TEST_DIR/values-pod-extensions.yaml" --set terminationGracePeriodSeconds=null
echo " lifecycle, extraContainers, shareProcessNamespace, automountServiceAccountToken and service.exposeMetrics render as set, and only when set"

echo ""
echo "==> All tests passed!"
15 changes: 15 additions & 0 deletions test/values-pod-extensions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Custom preStop, a sidecar sharing the process namespace, no API token, and
# metrics kept off the Service.
terminationGracePeriodSeconds: 120
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30"]
extraContainers:
- name: reloader
image: busybox
command: ["sh", "-c", "sleep infinity"]
shareProcessNamespace: true
automountServiceAccountToken: false
service:
exposeMetrics: false
47 changes: 47 additions & 0 deletions values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,21 @@ replicas: 2
# This is useful in combination with short client connection lifetimes to avoid errors during pod shutdown.
# preStopSleepSeconds: 25

# Optional: lifecycle hooks for the pgdog container, instead of preStopSleepSeconds
# (set one, not both). A preStop requires terminationGracePeriodSeconds covering
# it plus shutdownTimeout. The image's stop signal is SIGINT, PgDog's graceful
# shutdown, so a preStop only needs to wait, e.g. until clients have left:
# lifecycle:
# preStop:
# exec:
# command:
# - /bin/sh
# - -c
# - |
# sleep 30
# until curl -fsS localhost:9090 | awk '$1 == "pgdog_clients" && $2 == 0 {f = 1} END {exit !f}'; do sleep 5; done
# terminationGracePeriodSeconds: 3600

# Optional: Deployment rollout strategy (Deployment only)
# strategy: {}

Expand Down Expand Up @@ -140,6 +155,34 @@ env: []
# mountPath: /pki
extraInitContainers: []

# extraContainers adds sidecar containers next to pgdog (and the prometheus
# sidecar, if enabled), e.g. one that sends SIGHUP to reload a renewed TLS
# certificate. Combine with shareProcessNamespace to signal the pgdog process.
# Sidecars get the pod's service account token unless automountServiceAccountToken
# is false, and inherit nothing from securityContext: set their own. Run only
# trusted images pinned by digest.
# Example:
# extraContainers:
# - name: sidecar
# image: busybox:1.37@sha256:<digest>
# command: ['sh', '-c', 'sleep infinity']
# securityContext:
# allowPrivilegeEscalation: false
# capabilities:
# drop: [ALL]
extraContainers: []

# shareProcessNamespace lets containers in the pod see and signal each other's
# processes. PID 1 is then the pause container, not pgdog: signal pgdog by name
# (pidof -s pgdog). A container running as pgdog's user can read its environment
# and files through /proc, users.toml passwords included.
# shareProcessNamespace: false

# automountServiceAccountToken controls whether the pod gets a Kubernetes API
# token. PgDog does not call the Kubernetes API; set to false when nothing else
# in the pod does. Omitted from the pod spec unless set.
# automountServiceAccountToken: false

# extraVolumes allows adding custom volumes to the pod
# These volumes can be referenced by extraVolumeMounts or extraInitContainers
# Example:
Expand Down Expand Up @@ -387,6 +430,10 @@ service:
# Leave empty to use cluster defaults.
# Note: Order matters - first family is primary.
ipFamilies: []
# exposeMetrics adds the openMetricsPort to the Service. Set to false for any
# internet-facing LoadBalancer and scrape the pods directly (e.g. a PodMonitor);
# serviceMonitor needs it true, except with statefulSet (headless Service).
exposeMetrics: true
# aws configures AWS Load Balancer Controller annotations
# When enabled, service type is automatically set to LoadBalancer
aws:
Expand Down