From 4d7604ab63b9fe90cbe22a5b5ab2f2daf432126c Mon Sep 17 00:00:00 2001 From: Matheus Pimenta Date: Tue, 3 Feb 2026 14:19:29 +0000 Subject: [PATCH] chart: introduce configurable Job hook Signed-off-by: Matheus Pimenta --- .github/workflows/e2e.yml | 2 +- charts/podinfo/README.md | 151 ++++++++++++------------ charts/podinfo/templates/hooks/job.yaml | 37 ++++++ charts/podinfo/values.yaml | 59 +++++++++ test/deploy.sh | 1 + 5 files changed, 176 insertions(+), 74 deletions(-) create mode 100644 charts/podinfo/templates/hooks/job.yaml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index fb89b1f..aeda64d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Helm uses: azure/setup-helm@v4 with: - version: v3.17.3 + version: v4.1.0 - name: Deploy run: ./test/deploy.sh - name: Run integration tests diff --git a/charts/podinfo/README.md b/charts/podinfo/README.md index 5594cee..875daf3 100644 --- a/charts/podinfo/README.md +++ b/charts/podinfo/README.md @@ -52,79 +52,84 @@ The command removes all the Kubernetes components associated with the chart and The following tables lists the configurable parameters of the podinfo chart and their default values. -| Parameter | Default | Description | -|-----------------------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------| -| `replicaCount` | `1` | Desired number of pods | -| `logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error` | -| `backend` | `None` | Echo backend URL | -| `backends` | `[]` | Array of echo backend URLs | -| `cache` | `None` | Redis address in the format `tcp://:` | -| `redis.enabled` | `false` | Create Redis deployment for caching purposes | -| `redis.repository` | `docker.io/redis` | Redis image repository | -| `redis.tag` | `` | Redis image tag | -| `redis.imagePullSecrets` | `[]` | Redis image pull secrets | -| `ui.color` | `#34577c` | UI color | -| `ui.message` | `None` | UI greetings message | -| `ui.logo` | `None` | UI logo | -| `faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds | -| `faults.error` | `false` | 1/3 chances of a random HTTP response error | -| `faults.unhealthy` | `false` | When set, the healthy state is never reached | -| `faults.unready` | `false` | When set, the ready state is never reached | -| `faults.testFail` | `false` | When set, a helm test is included which always fails | -| `faults.testTimeout` | `false` | When set, a helm test is included which always times out | -| `image.repository` | `ghcr.io/stefanprodan/podinfo` | Image repository | -| `image.tag` | `` | Image tag | -| `image.pullPolicy` | `IfNotPresent` | Image pull policy | -| `image.pullSecrets` | `[]` | Image pull secrets | -| `service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app) | -| `service.type` | `ClusterIP` | Type of the Kubernetes Service | -| `service.metricsPort` | `9797` | Prometheus metrics endpoint port | -| `service.httpPort` | `9898` | Container HTTP port | -| `service.externalPort` | `9898` | ClusterIP HTTP port | -| `service.grpcPort` | `9999` | ClusterIP gPRC port | -| `service.grpcService` | `podinfo` | gPRC service name | -| `service.nodePort` | `31198` | NodePort for the HTTP endpoint | -| `service.trafficDistribution` | `""` | Traffic distribution strategy | -| `service.additionalLabels` | `{}` | Additional labels to add to the service | -| `service.externalTrafficPolicy` | `None` | External traffic policy for LoadBalance service | -| `h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2) | -| `extraArgs` | `[]` | Additional command line arguments to pass to podinfo container | -| `extraEnvs` | `[]` | Extra environment variables for the podinfo container | -| `config.path` | `""` | config file path | -| `config.name` | `""` | config file name | -| `hpa.enabled` | `false` | Enables the Kubernetes HPA | -| `hpa.maxReplicas` | `10` | Maximum amount of pods | -| `hpa.cpu` | `None` | Target CPU usage per pod | -| `hpa.memory` | `None` | Target memory usage per pod | -| `hpa.requests` | `None` | Target HTTP requests per second per pod | -| `serviceAccount.enabled` | `false` | Whether a service account should be created | -| `serviceAccount.name` | `None` | The name of the service account to use, if not set and create is true, a name is generated using the fullname template | -| `serviceAccount.imagePullSecrets` | `[]` | List of image pull secrets if pulling from private registries. | -| `securityContext` | `{}` | The security context to be set on the podinfo container | -| `podSecurityContext` | `{}` | The security context to be set on the pod | -| `podAnnotations` | `{}` | Pod annotations | -| `serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created | -| `serviceMonitor.interval` | `15s` | Prometheus scraping interval | -| `serviceMonitor.additionalLabels` | `{}` | Add additional labels to the service monitor | -| `ingress.enabled` | `false` | Enables Ingress | -| `ingress.className` | `""` | Use ingressClassName | -| `ingress.additionalLabels` | `{}` | Add additional labels to the ingress | -| `ingress.annotations` | `{}` | Ingress annotations | -| `ingress.hosts` | `[]` | Ingress accepted hosts | -| `ingress.tls` | `[]` | Ingress TLS configuration | -| `httpRoute.enabled` | `false` | Enables Gateway API HTTPRoute | -| `httpRoute.additionalLabels` | `{}` | Add additional labels to the HTTPRoute | -| `httpRoute.annotations` | `{}` | HTTPRoute annotations | -| `httpRoute.parentRefs` | `[]` | Gateways that this route is attached to | -| `httpRoute.hostnames` | `["podinfo.local"]` | Hostnames matching HTTP header | -| `httpRoute.rules` | `[]` | List of rules and filters applied | -| `resources.requests.cpu` | `1m` | Pod CPU request | -| `resources.requests.memory` | `16Mi` | Pod memory request | -| `resources.limits.cpu` | `None` | Pod CPU limit | -| `resources.limits.memory` | `None` | Pod memory limit | -| `nodeSelector` | `{}` | Node labels for pod assignment | -| `tolerations` | `[]` | List of node taints to tolerate | -| `affinity` | `None` | Node/pod affinities | +| Parameter | Default | Description | +|--------------------------------------------------|--------------------------------|---------------------------------------------------------------------------------------------------| +| `replicaCount` | `1` | Desired number of pods | +| `logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error` | +| `backend` | `None` | Echo backend URL | +| `backends` | `[]` | Array of echo backend URLs | +| `cache` | `None` | Redis address in the format `tcp://:` | +| `redis.enabled` | `false` | Create Redis deployment for caching purposes | +| `redis.repository` | `docker.io/redis` | Redis image repository | +| `redis.tag` | `` | Redis image tag | +| `redis.imagePullSecrets` | `[]` | Redis image pull secrets | +| `ui.color` | `#34577c` | UI color | +| `ui.message` | `None` | UI greetings message | +| `ui.logo` | `None` | UI logo | +| `faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds | +| `faults.error` | `false` | 1/3 chances of a random HTTP response error | +| `faults.unhealthy` | `false` | When set, the healthy state is never reached | +| `faults.unready` | `false` | When set, the ready state is never reached | +| `faults.testFail` | `false` | When set, a helm test is included which always fails | +| `faults.testTimeout` | `false` | When set, a helm test is included which always times out | +| `image.repository` | `ghcr.io/stefanprodan/podinfo` | Image repository | +| `image.tag` | `` | Image tag | +| `image.pullPolicy` | `IfNotPresent` | Image pull policy | +| `image.pullSecrets` | `[]` | Image pull secrets | +| `service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app) | +| `service.type` | `ClusterIP` | Type of the Kubernetes Service | +| `service.metricsPort` | `9797` | Prometheus metrics endpoint port | +| `service.httpPort` | `9898` | Container HTTP port | +| `service.externalPort` | `9898` | ClusterIP HTTP port | +| `service.grpcPort` | `9999` | ClusterIP gPRC port | +| `service.grpcService` | `podinfo` | gPRC service name | +| `service.nodePort` | `31198` | NodePort for the HTTP endpoint | +| `service.trafficDistribution` | `""` | Traffic distribution strategy | +| `service.additionalLabels` | `{}` | Additional labels to add to the service | +| `service.externalTrafficPolicy` | `None` | External traffic policy for LoadBalance service | +| `h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2) | +| `extraArgs` | `[]` | Additional command line arguments to pass to podinfo container | +| `extraEnvs` | `[]` | Extra environment variables for the podinfo container | +| `config.path` | `""` | config file path | +| `config.name` | `""` | config file name | +| `hpa.enabled` | `false` | Enables the Kubernetes HPA | +| `hpa.maxReplicas` | `10` | Maximum amount of pods | +| `hpa.cpu` | `None` | Target CPU usage per pod | +| `hpa.memory` | `None` | Target memory usage per pod | +| `hpa.requests` | `None` | Target HTTP requests per second per pod | +| `serviceAccount.enabled` | `false` | Whether a service account should be created | +| `serviceAccount.name` | `None` | The name of the service account to use, if not set a name is generated using the fullname template| +| `serviceAccount.imagePullSecrets` | `[]` | List of image pull secrets if pulling from private registries | +| `securityContext` | `{}` | The security context to be set on the podinfo container | +| `podSecurityContext` | `{}` | The security context to be set on the pod | +| `podAnnotations` | `{}` | Pod annotations | +| `serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created | +| `serviceMonitor.interval` | `15s` | Prometheus scraping interval | +| `serviceMonitor.additionalLabels` | `{}` | Add additional labels to the service monitor | +| `ingress.enabled` | `false` | Enables Ingress | +| `ingress.className` | `""` | Use ingressClassName | +| `ingress.additionalLabels` | `{}` | Add additional labels to the ingress | +| `ingress.annotations` | `{}` | Ingress annotations | +| `ingress.hosts` | `[]` | Ingress accepted hosts | +| `ingress.tls` | `[]` | Ingress TLS configuration | +| `httpRoute.enabled` | `false` | Enables Gateway API HTTPRoute | +| `httpRoute.additionalLabels` | `{}` | Add additional labels to the HTTPRoute | +| `httpRoute.annotations` | `{}` | HTTPRoute annotations | +| `httpRoute.parentRefs` | `[]` | Gateways that this route is attached to | +| `httpRoute.hostnames` | `["podinfo.local"]` | Hostnames matching HTTP header | +| `httpRoute.rules` | `[]` | List of rules and filters applied | +| `hooks..job.enabled` | `false` | Create a Helm hook job for testing (hookType: see values.yaml for available hooks) | +| `hooks..job.hookDeletePolicy` | `hook-succeeded,hook-failed` | Helm hook delete policy | +| `hooks..job.ttlSecondsAfterFinished` | `None` | Job TTL after finished | +| `hooks..job.sleepSeconds` | `None` | Sleep duration before job exits | +| `hooks..job.exitCode` | `0` | Job exit code | +| `resources.requests.cpu` | `1m` | Pod CPU request | +| `resources.requests.memory` | `16Mi` | Pod memory request | +| `resources.limits.cpu` | `None` | Pod CPU limit | +| `resources.limits.memory` | `None` | Pod memory limit | +| `nodeSelector` | `{}` | Node labels for pod assignment | +| `tolerations` | `[]` | List of node taints to tolerate | +| `affinity` | `None` | Node/pod affinities | Specify each parameter using the `--set key=value[,key=value]` argument: diff --git a/charts/podinfo/templates/hooks/job.yaml b/charts/podinfo/templates/hooks/job.yaml new file mode 100644 index 0000000..7dc975b --- /dev/null +++ b/charts/podinfo/templates/hooks/job.yaml @@ -0,0 +1,37 @@ +{{- $hooks := dict "preInstall" "pre-install" "postInstall" "post-install" "preDelete" "pre-delete" "postDelete" "post-delete" "preUpgrade" "pre-upgrade" "postUpgrade" "post-upgrade" "preRollback" "pre-rollback" "postRollback" "post-rollback" }} +{{- range $hookName, $hookType := $hooks }} +{{- $hookConfig := index $.Values.hooks $hookName }} +{{- if and $hookConfig $hookConfig.job $hookConfig.job.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "podinfo.fullname" $ }}-{{ $hookType }} + namespace: {{ include "podinfo.namespace" $ }} + labels: + {{- include "podinfo.labels" $ | nindent 4 }} + annotations: + "helm.sh/hook": {{ $hookType }} + "helm.sh/hook-delete-policy": {{ $hookConfig.job.hookDeletePolicy }} +spec: + {{- if kindIs "float64" $hookConfig.job.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ $hookConfig.job.ttlSecondsAfterFinished | int }} + {{- end }} + template: + spec: + containers: + - name: job + image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + command: + - sh + - -c + - | + {{- if kindIs "float64" $hookConfig.job.sleepSeconds }} + sleep {{ $hookConfig.job.sleepSeconds | int }} + {{- end }} + exit {{ $hookConfig.job.exitCode | default 0 }} + restartPolicy: Never + backoffLimit: 1 +{{- end }} +{{- end }} diff --git a/charts/podinfo/values.yaml b/charts/podinfo/values.yaml index 91a1ea4..4f68824 100644 --- a/charts/podinfo/values.yaml +++ b/charts/podinfo/values.yaml @@ -93,6 +93,65 @@ certificate: dnsNames: - podinfo +# Helm hooks (for testing purposes) +hooks: + preInstall: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + postInstall: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + preDelete: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + postDelete: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + preUpgrade: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + postUpgrade: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + preRollback: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + postRollback: + job: + enabled: false + hookDeletePolicy: hook-succeeded,hook-failed + ttlSecondsAfterFinished: + sleepSeconds: + exitCode: 0 + # metrics-server add-on required hpa: enabled: false diff --git a/test/deploy.sh b/test/deploy.sh index 75356a4..fe33cfc 100755 --- a/test/deploy.sh +++ b/test/deploy.sh @@ -26,4 +26,5 @@ helm upgrade --install podinfo ./charts/podinfo \ --set certificate.create=true \ --set hpa.enabled=true \ --set hpa.cpu=95 \ + --set hooks.postInstall.job.enabled=true \ --namespace=default