diff --git a/chart/files/pod-template-file.kubernetes-helm-yaml b/chart/files/pod-template-file.kubernetes-helm-yaml index 70ac65c8e7380..d0d004c90277c 100644 --- a/chart/files/pod-template-file.kubernetes-helm-yaml +++ b/chart/files/pod-template-file.kubernetes-helm-yaml @@ -23,6 +23,7 @@ {{- $topologySpreadConstraints := or .Values.workers.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.workers) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.workers) }} +{{- $containerLifecycleHooks := or .Values.workers.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: v1 kind: Pod metadata: @@ -64,6 +65,9 @@ spec: image: {{ template "pod_template_image" . }} imagePullPolicy: {{ .Values.images.pod_template.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 8 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 8 }} + {{- end }} name: base resources: {{- toYaml .Values.workers.resources | nindent 8 }} volumeMounts: diff --git a/chart/templates/dag-processor/dag-processor-deployment.yaml b/chart/templates/dag-processor/dag-processor-deployment.yaml index e748e9dff401d..e3dbd34ff3c52 100644 --- a/chart/templates/dag-processor/dag-processor-deployment.yaml +++ b/chart/templates/dag-processor/dag-processor-deployment.yaml @@ -29,6 +29,7 @@ {{- $revisionHistoryLimit := or .Values.dagProcessor.revisionHistoryLimit .Values.revisionHistoryLimit }} {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.dagProcessor) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.dagProcessor) }} +{{- $containerLifecycleHooks := or .Values.dagProcessor.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: Deployment metadata: @@ -144,6 +145,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.dagProcessor.command }} command: {{ tpl (toYaml .Values.dagProcessor.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/flower/flower-deployment.yaml b/chart/templates/flower/flower-deployment.yaml index 199d9010d327a..debc7aacded6c 100644 --- a/chart/templates/flower/flower-deployment.yaml +++ b/chart/templates/flower/flower-deployment.yaml @@ -29,6 +29,7 @@ {{- $revisionHistoryLimit := or .Values.flower.revisionHistoryLimit .Values.revisionHistoryLimit }} {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.flower) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.flower) }} +{{- $containerLifecycleHooks := or .Values.flower.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: Deployment metadata: @@ -90,6 +91,9 @@ spec: image: {{ template "flower_image" . }} imagePullPolicy: {{ .Values.images.flower.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.flower.command }} command: {{ tpl (toYaml .Values.flower.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/jobs/create-user-job.yaml b/chart/templates/jobs/create-user-job.yaml index 94d0970ae4f64..c1c2f25031cc2 100644 --- a/chart/templates/jobs/create-user-job.yaml +++ b/chart/templates/jobs/create-user-job.yaml @@ -27,6 +27,7 @@ {{- $topologySpreadConstraints := or .Values.createUserJob.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.createUserJob) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.createUserJob) }} +{{- $containerLifecycleHooks := or .Values.createUserJob.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: batch/v1 kind: Job metadata: @@ -88,6 +89,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.createUserJob.command }} command: {{ tpl (toYaml .Values.createUserJob.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/jobs/migrate-database-job.yaml b/chart/templates/jobs/migrate-database-job.yaml index 30dda11b5b8d3..8cc3fb321f77b 100644 --- a/chart/templates/jobs/migrate-database-job.yaml +++ b/chart/templates/jobs/migrate-database-job.yaml @@ -27,6 +27,7 @@ {{- $topologySpreadConstraints := or .Values.migrateDatabaseJob.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.migrateDatabaseJob) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.migrateDatabaseJob) }} +{{- $containerLifecycleHooks := or .Values.migrateDatabaseJob.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: batch/v1 kind: Job metadata: @@ -88,6 +89,9 @@ spec: image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.migrateDatabaseJob.command }} command: {{- tpl (toYaml .Values.migrateDatabaseJob.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/pgbouncer/pgbouncer-deployment.yaml b/chart/templates/pgbouncer/pgbouncer-deployment.yaml index 14665692fcf61..c5a882e1d3f59 100644 --- a/chart/templates/pgbouncer/pgbouncer-deployment.yaml +++ b/chart/templates/pgbouncer/pgbouncer-deployment.yaml @@ -29,6 +29,8 @@ {{- $securityContext := include "localPodSecurityContext" .Values.pgbouncer }} {{- $containerSecurityContext := include "externalContainerSecurityContext" .Values.pgbouncer }} {{- $containerSecurityContextMetricsExporter := include "externalContainerSecurityContext" .Values.pgbouncer.metricsExporterSidecar }} +{{- $containerLifecycleHooks := .Values.pgbouncer.containerLifecycleHooks }} +{{- $containerLifecycleHooksMetricsExporter := .Values.pgbouncer.metricsExporterSidecar.containerLifecycleHooks }} apiVersion: apps/v1 kind: Deployment metadata: @@ -143,11 +145,9 @@ spec: {{- if .Values.pgbouncer.extraVolumeMounts }} {{- tpl (toYaml .Values.pgbouncer.extraVolumeMounts) . | nindent 12 }} {{- end }} - lifecycle: - preStop: - exec: - # Allow existing queries clients to complete within 120 seconds - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} - name: metrics-exporter resources: {{- toYaml .Values.pgbouncer.metricsExporterSidecar.resources | nindent 12 }} image: {{ template "pgbouncer_exporter_image" . }} @@ -178,6 +178,9 @@ spec: initialDelaySeconds: {{ .Values.pgbouncer.metricsExporterSidecar.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.pgbouncer.metricsExporterSidecar.readinessProbe.periodSeconds }} timeoutSeconds: {{ .Values.pgbouncer.metricsExporterSidecar.readinessProbe.timeoutSeconds }} + {{- if $containerLifecycleHooksMetricsExporter }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksMetricsExporter) . | nindent 12 }} + {{- end }} volumes: - name: pgbouncer-config secret: diff --git a/chart/templates/redis/redis-statefulset.yaml b/chart/templates/redis/redis-statefulset.yaml index ec544cc6f23c8..d83d63967931c 100644 --- a/chart/templates/redis/redis-statefulset.yaml +++ b/chart/templates/redis/redis-statefulset.yaml @@ -27,6 +27,7 @@ {{- $topologySpreadConstraints := or .Values.redis.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $securityContext := include "localPodSecurityContext" .Values.redis }} {{- $containerSecurityContext := include "externalContainerSecurityContext" .Values.redis }} +{{- $containerLifecycleHooks := .Values.redis.containerLifecycleHooks }} apiVersion: apps/v1 kind: StatefulSet metadata: @@ -81,6 +82,9 @@ spec: image: {{ template "redis_image" . }} imagePullPolicy: {{ .Values.images.redis.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} command: ["/bin/sh"] resources: {{- toYaml .Values.redis.resources | nindent 12 }} args: ["-c", "redis-server --requirepass ${REDIS_PASSWORD}"] diff --git a/chart/templates/scheduler/scheduler-deployment.yaml b/chart/templates/scheduler/scheduler-deployment.yaml index 60e4101618b2a..04be915e8c263 100644 --- a/chart/templates/scheduler/scheduler-deployment.yaml +++ b/chart/templates/scheduler/scheduler-deployment.yaml @@ -41,6 +41,9 @@ {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.scheduler) }} {{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.scheduler.waitForMigrations) }} {{- $containerSecurityContextLogGroomerSidecar := include "containerSecurityContext" (list . .Values.scheduler.logGroomerSidecar) }} +{{- $containerLifecycleHooks := or .Values.scheduler.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksWaitForMigrations := or .Values.scheduler.waitForMigrations.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksLogGroomerSidecar := or .Values.scheduler.logGroomerSidecar.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: {{ if $stateful }}StatefulSet{{ else }}Deployment{{ end }} metadata: @@ -140,6 +143,9 @@ spec: image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} + {{- if $containerLifecycleHooksWaitForMigrations }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksWaitForMigrations) . | nindent 12 }} + {{- end }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -172,6 +178,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.scheduler.command }} command: {{ tpl (toYaml .Values.scheduler.command) . | nindent 12 }} {{- end }} @@ -244,6 +253,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextLogGroomerSidecar | nindent 12 }} + {{- if $containerLifecycleHooksLogGroomerSidecar }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }} + {{- end }} {{- if .Values.scheduler.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.scheduler.logGroomerSidecar.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/statsd/statsd-deployment.yaml b/chart/templates/statsd/statsd-deployment.yaml index 583151331aaf1..b32caa9980472 100644 --- a/chart/templates/statsd/statsd-deployment.yaml +++ b/chart/templates/statsd/statsd-deployment.yaml @@ -28,6 +28,7 @@ {{- $revisionHistoryLimit := or .Values.statsd.revisionHistoryLimit .Values.revisionHistoryLimit }} {{- $securityContext := include "localPodSecurityContext" .Values.statsd }} {{- $containerSecurityContext := include "externalContainerSecurityContext" .Values.statsd }} +{{- $containerLifecycleHooks := .Values.statsd.containerLifecycleHooks }} apiVersion: apps/v1 kind: Deployment metadata: @@ -90,6 +91,9 @@ spec: image: {{ template "statsd_image" . }} imagePullPolicy: {{ .Values.images.statsd.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.statsd.args }} args: {{ tpl (toYaml .Values.statsd.args) . | nindent 12 }} {{- else}} diff --git a/chart/templates/triggerer/triggerer-deployment.yaml b/chart/templates/triggerer/triggerer-deployment.yaml index 3d327e944ac44..c60cec3cd3371 100644 --- a/chart/templates/triggerer/triggerer-deployment.yaml +++ b/chart/templates/triggerer/triggerer-deployment.yaml @@ -33,6 +33,9 @@ {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.triggerer) }} {{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.triggerer.waitForMigrations) }} {{- $containerSecurityContextLogGroomer := include "containerSecurityContext" (list . .Values.triggerer.logGroomerSidecar) }} +{{- $containerLifecycleHooks := or .Values.triggerer.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksWaitForMigrations := or .Values.triggerer.waitForMigrations.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksLogGroomerSidecar := or .Values.triggerer.logGroomerSidecar.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: {{ if $persistence }}StatefulSet{{ else }}Deployment{{ end }} metadata: @@ -128,6 +131,9 @@ spec: image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} + {{- if $containerLifecycleHooksWaitForMigrations }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksWaitForMigrations) . | nindent 12 }} + {{- end }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -159,6 +165,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.triggerer.command }} command: {{ tpl (toYaml .Values.triggerer.command) . | nindent 12 }} {{- end }} @@ -214,6 +223,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextLogGroomer | nindent 12 }} + {{- if $containerLifecycleHooksLogGroomerSidecar }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }} + {{- end }} {{- if .Values.triggerer.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.triggerer.logGroomerSidecar.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/webserver/webserver-deployment.yaml b/chart/templates/webserver/webserver-deployment.yaml index 7f326bab2264d..3b53a064a41ea 100644 --- a/chart/templates/webserver/webserver-deployment.yaml +++ b/chart/templates/webserver/webserver-deployment.yaml @@ -28,6 +28,8 @@ {{- $securityContext := include "airflowPodSecurityContext" (list . .Values.webserver) }} {{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.webserver) }} {{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.webserver.waitForMigrations) }} +{{- $containerLifecycleHooks := or .Values.webserver.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksWaitForMigrations := or .Values.webserver.waitForMigrations.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: Deployment metadata: @@ -134,6 +136,9 @@ spec: image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} + {{- if $containerLifecycleHooksWaitForMigrations }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksWaitForMigrations) . | nindent 12 }} + {{- end }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -165,6 +170,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ or $containerSecurityContext .Values.webserver.securityContexts.container .Values.securityContexts.container | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.webserver.command }} command: {{ tpl (toYaml .Values.webserver.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/workers/worker-deployment.yaml b/chart/templates/workers/worker-deployment.yaml index 235f3f783f6fd..31956363d0630 100644 --- a/chart/templates/workers/worker-deployment.yaml +++ b/chart/templates/workers/worker-deployment.yaml @@ -34,6 +34,11 @@ {{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.workers.waitForMigrations) }} {{- $containerSecurityContextLogGroomerSidecar := include "containerSecurityContext" (list . .Values.workers.logGroomerSidecar) }} {{- $containerSecurityContextKerberosSidecar := include "containerSecurityContext" (list . .Values.workers.kerberosSidecar) }} +{{- $containerLifecycleHooks := or .Values.workers.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksPersistence := or .Values.workers.persistence.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksWaitForMigrations := or .Values.workers.waitForMigrations.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksLogGroomerSidecar := or .Values.workers.logGroomerSidecar.containerLifecycleHooks .Values.containerLifecycleHooks }} +{{- $containerLifecycleHooksKerberosSidecar := or .Values.workers.kerberosSidecar.containerLifecycleHooks .Values.containerLifecycleHooks }} apiVersion: apps/v1 kind: {{ if $persistence }}StatefulSet{{ else }}Deployment{{ end }} metadata: @@ -144,6 +149,9 @@ spec: - "{{ include "airflowPodSecurityContextsIds" (list . .Values.workers) }}" - {{ template "airflow_logs" . }} securityContext: {{ $containerSecurityContextPersistence | nindent 12 }} + {{- if $containerLifecycleHooksPersistence }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksPersistence) . | nindent 12 }} + {{- end }} volumeMounts: - name: logs mountPath: {{ template "airflow_logs" . }} @@ -154,6 +162,9 @@ spec: image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} + {{- if $containerLifecycleHooksWaitForMigrations }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksWaitForMigrations) . | nindent 12 }} + {{- end }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -185,6 +196,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContext | nindent 12 }} + {{- if $containerLifecycleHooks }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12 }} + {{- end }} {{- if .Values.workers.command }} command: {{ tpl (toYaml .Values.workers.command) . | nindent 12 }} {{- end }} @@ -262,6 +276,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextLogGroomerSidecar | nindent 12 }} + {{- if $containerLifecycleHooksLogGroomerSidecar }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }} + {{- end }} {{- if .Values.workers.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.workers.logGroomerSidecar.command) . | nindent 12 }} {{- end }} @@ -292,6 +309,9 @@ spec: image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} securityContext: {{ $containerSecurityContextKerberosSidecar | nindent 12 }} + {{- if $containerLifecycleHooksKerberosSidecar }} + lifecycle: {{- tpl (toYaml $containerLifecycleHooksKerberosSidecar) . | nindent 12 }} + {{- end }} args: ["kerberos"] resources: {{- toYaml .Values.workers.kerberosSidecar.resources | nindent 12 }} volumeMounts: diff --git a/chart/values.schema.json b/chart/values.schema.json index f3e62911ea65f..0333781438ada 100644 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -136,6 +136,35 @@ } } }, + "containerLifecycleHooks": { + "description": "Default Container Lifecycle Hooks definition. The values in this parameter will be used when `containerLifecycleHooks` is not defined for specific containers.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "nodeSelector": { "description": "Select certain nodes for all pods.", "type": "object", @@ -1523,6 +1552,35 @@ "type": "string" } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the persistence. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the persistence. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -1577,6 +1635,35 @@ ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the kerberos sidecar. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the kerberos sidecar. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -1774,6 +1861,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the worker. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the workers. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -1843,6 +1959,35 @@ "additionalProperties": false } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the worker. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -2254,6 +2399,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the scheduler. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the scheduler. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -2323,6 +2497,35 @@ "additionalProperties": false } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the wait for migrations. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -2692,6 +2895,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the triggerer. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the triggerer. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -2765,6 +2997,35 @@ "additionalProperties": false } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the wait for migrations. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -3080,6 +3341,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the dag processor. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the dag processor. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -3153,6 +3443,35 @@ "additionalProperties": false } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the wait for migrations. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -3373,6 +3692,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the create user job. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the create user job. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -3642,6 +3990,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the migrate database job. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the migrate database job. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -4000,6 +4377,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the webserver. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the webserver. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -4342,6 +4748,35 @@ "additionalProperties": false } }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the wait for migrations. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -4740,6 +5175,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the network policy. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the network policy. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -4963,6 +5427,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the statsd. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the statsd.", "type": "object", @@ -5207,6 +5700,45 @@ ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the PgBouncer. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": { + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "killall -INT pgbouncer && sleep 120" + ] + } + } + }, + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the PgBouncer.", "type": "object", @@ -5485,6 +6017,35 @@ ], "default": "disable" }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the metrics exporter sidecar. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the metrics exporter sidecar. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -5722,6 +6283,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the redis. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the redis.", "type": "object", @@ -6129,6 +6719,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the cleanup. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the cleanup. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -6430,6 +7049,35 @@ } ] }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the git sync sidecar. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the git sync sidecar. If not set, the values from global `securityContexts` will be used.", "type": "object", @@ -9377,6 +10025,35 @@ ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" }, + "containerLifecycleHooks": { + "description": "Container Lifecycle Hooks definition for the log groomer sidecar. If not set, the values from global `containerLifecycleHooks` will be used.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle", + "default": "{}", + "x-docsSection": "Kubernetes", + "examples": [ + { + "postStart": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo postStart handler > /usr/share/message" + ] + } + }, + "preStop": { + "exec": { + "command": [ + "/bin/sh", + "-c", + "echo preStop handler > /usr/share/message" + ] + } + } + } + ] + }, "securityContexts": { "description": "Security context definition for the log groomer sidecar. If not set, the values from global `securityContexts` will be used.", "type": "object", diff --git a/chart/values.yaml b/chart/values.yaml index de17c8d104fff..fda63d6ff7bdd 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -43,6 +43,9 @@ securityContexts: pod: {} containers: {} +# Default container lifecycle hooks for every service except for redis, statsd and pgbouncer. +containerLifecycleHooks: {} + # Airflow home directory # Used for mount paths airflowHome: /opt/airflow @@ -513,6 +516,9 @@ workers: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Create ServiceAccount serviceAccount: # default value is true @@ -585,6 +591,8 @@ workers: # Detailed default security context for persistence for container level securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} kerberosSidecar: # Enable kerberos sidecar @@ -599,6 +607,8 @@ workers: # Detailed default security context for kerberosSidecar for container level securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} resources: {} # limits: @@ -699,6 +709,8 @@ workers: # Detailed default security context for waitForMigrations for container level securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} env: [] @@ -759,6 +771,9 @@ scheduler: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Create ServiceAccount serviceAccount: # default value is true @@ -859,6 +874,8 @@ scheduler: # Detailed default security context for logGroomerSidecar for container level securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} waitForMigrations: # Whether to create init container to wait for db migrations @@ -867,6 +884,8 @@ scheduler: # Detailed default security context for waitForMigrations for container level securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} env: [] @@ -917,6 +936,9 @@ createUserJob: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Create ServiceAccount serviceAccount: # default value is true @@ -1000,6 +1022,9 @@ migrateDatabaseJob: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Create ServiceAccount serviceAccount: # default value is true @@ -1129,6 +1154,9 @@ webserver: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Additional network policies as needed (Deprecated - renamed to `webserver.networkPolicy.ingress.from`) extraNetworkPolicies: [] networkPolicy: @@ -1254,6 +1282,9 @@ webserver: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + env: [] # Airflow Triggerer Config @@ -1310,6 +1341,10 @@ triggerer: securityContexts: pod: {} container: {} + + # container level lifecycle hooks + containerLifecycleHooks: {} + persistence: # Enable persistent volumes enabled: true @@ -1404,6 +1439,9 @@ triggerer: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + waitForMigrations: # Whether to create init container to wait for db migrations enabled: true @@ -1412,6 +1450,9 @@ triggerer: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + env: [] # Airflow Dag Processor Config @@ -1467,6 +1508,9 @@ dagProcessor: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + resources: {} # limits: # cpu: 100m @@ -1596,6 +1640,9 @@ flower: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Create ServiceAccount serviceAccount: # default value is true @@ -1709,6 +1756,9 @@ statsd: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Additional network policies as needed extraNetworkPolicies: [] resources: {} @@ -1881,6 +1931,13 @@ pgbouncer: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: + preStop: + exec: + # Allow existing queries clients to complete within 120 seconds + command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] + metricsExporterSidecar: resources: {} # limits: @@ -1895,6 +1952,9 @@ pgbouncer: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + livenessProbe: initialDelaySeconds: 10 periodSeconds: 10 @@ -1972,6 +2032,9 @@ redis: pod: {} container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + podAnnotations: {} # Auth secret for a private registry # This is used if pulling airflow images from a private registry @@ -2080,6 +2143,9 @@ cleanup: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Specify history limit # When set, overwrite the default k8s number of successful and failed CronJob executions that are saved. failedJobsHistoryLimit: ~ @@ -2285,6 +2351,9 @@ dags: securityContexts: container: {} + # container level lifecycle hooks + containerLifecycleHooks: {} + # Mount additional volumes into git-sync. It can be templated like in the following example: # extraVolumeMounts: # - name: my-templated-extra-volume diff --git a/helm_tests/airflow_aux/test_container_lifecycle.py b/helm_tests/airflow_aux/test_container_lifecycle.py new file mode 100644 index 0000000000000..dd2f5bb0c6fc8 --- /dev/null +++ b/helm_tests/airflow_aux/test_container_lifecycle.py @@ -0,0 +1,226 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +from __future__ import annotations + +import jmespath + +from tests.charts.helm_template_generator import render_chart + +CONTAINER_LIFECYCLE_PARAMETERS = { + "preStop": { + "release_name": "test-release", + "lifecycle_templated": {"exec": {"command": ["echo", "preStop", "{{ .Release.Name }}"]}}, + "lifecycle_parsed": {"exec": {"command": ["echo", "preStop", "test-release"]}}, + }, + "postStart": { + "release_name": "test-release", + "lifecycle_templated": {"exec": {"command": ["echo", "preStop", "{{ .Release.Name }}"]}}, + "lifecycle_parsed": {"exec": {"command": ["echo", "preStop", "test-release"]}}, + }, +} + + +class TestContainerLifecycleHooks: + """Tests container lifecycle hooks.""" + + # Test container lifecycle hooks default setting + def test_check_default_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "webserver": {"defaultUser": {"enabled": True}}, + "flower": {"enabled": True}, + "statsd": {"enabled": True}, + "pgbouncer": {"enabled": True}, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/statsd/statsd-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + "templates/pgbouncer/pgbouncer-deployment.yaml", + ], + ) + + # Default for every service is None except for pgbouncer + for doc in docs[:-1]: + assert jmespath.search("spec.template.spec.containers[0].lifecycle", doc) is None + + pgbouncer_default_value = { + "exec": {"command": ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"]} + } + assert pgbouncer_default_value == jmespath.search( + "spec.template.spec.containers[0].lifecycle.preStop", docs[-1] + ) + assert jmespath.search("spec.template.spec.containers[0].lifecycle.postStart", docs[-1]) is None + + # Test Global container lifecycle hooks for the main services + def test_global_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "containerLifecycleHooks": {hook_type: lifecycle_hook_params["lifecycle_templated"]}, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + ], + ) + + for doc in docs: + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.template.spec.containers[0].lifecycle.{hook_type}", doc + ) + + # Test Global container lifecycle hooks for the main services + def test_global_setting_external(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "containerLifecycleHooks": lifecycle_hooks_config, + }, + show_only=[ + "templates/statsd/statsd-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + "templates/pgbouncer/pgbouncer-deployment.yaml", + ], + ) + + for doc in docs: + assert lifecycle_hook_params["lifecycle_parsed"] != jmespath.search( + "spec.template.spec.containers[0].lifecycle", doc + ) + + # .containerLifecycleWebhooks > containerLifecycleWebhooks + def test_check_main_container_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "containerLifecycleHooks": lifecycle_hooks_config, + "flower": {"containerLifecycleHooks": lifecycle_hooks_config}, + "scheduler": {"containerLifecycleHooks": lifecycle_hooks_config}, + "webserver": {"containerLifecycleHooks": lifecycle_hooks_config}, + "workers": {"containerLifecycleHooks": lifecycle_hooks_config}, + "migrateDatabaseJob": {"containerLifecycleHooks": lifecycle_hooks_config}, + "triggerer": {"containerLifecycleHooks": lifecycle_hooks_config}, + "redis": {"containerLifecycleHooks": lifecycle_hooks_config}, + "statsd": {"containerLifecycleHooks": lifecycle_hooks_config}, + "pgbouncer": { + "enabled": True, + "containerLifecycleHooks": lifecycle_hooks_config, + }, + "dagProcessor": { + "enabled": True, + "containerLifecycleHooks": lifecycle_hooks_config, + }, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/statsd/statsd-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + "templates/pgbouncer/pgbouncer-deployment.yaml", + "templates/dag-processor/dag-processor-deployment.yaml", + ], + ) + + for doc in docs: + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.template.spec.containers[0].lifecycle.{hook_type}", doc + ) + + # Test container lifecycle hooks for metrics-explorer main container + def test_metrics_explorer_container_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "pgbouncer": { + "enabled": True, + "metricsExporterSidecar": {"containerLifecycleHooks": lifecycle_hooks_config}, + }, + }, + show_only=["templates/pgbouncer/pgbouncer-deployment.yaml"], + ) + + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.template.spec.containers[1].lifecycle.{hook_type}", docs[0] + ) + + # Test container lifecycle hooks for worker-kerberos main container + def test_worker_kerberos_container_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "workers": { + "kerberosSidecar": { + "enabled": True, + "containerLifecycleHooks": lifecycle_hooks_config, + } + }, + }, + show_only=["templates/workers/worker-deployment.yaml"], + ) + + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.template.spec.containers[2].lifecycle.{hook_type}", docs[0] + ) + + # Test container lifecycle hooks for log-groomer-sidecar main container + def test_log_groomer_sidecar_container_setting(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "scheduler": {"logGroomerSidecar": {"containerLifecycleHooks": lifecycle_hooks_config}}, + "workers": {"logGroomerSidecar": {"containerLifecycleHooks": lifecycle_hooks_config}}, + }, + show_only=[ + "templates/scheduler/scheduler-deployment.yaml", + "templates/workers/worker-deployment.yaml", + ], + ) + + for doc in docs: + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.template.spec.containers[1].lifecycle.{hook_type}", doc + ) diff --git a/helm_tests/airflow_aux/test_pod_template_file.py b/helm_tests/airflow_aux/test_pod_template_file.py index 4d67b91b19656..3e795d7113fe7 100644 --- a/helm_tests/airflow_aux/test_pod_template_file.py +++ b/helm_tests/airflow_aux/test_pod_template_file.py @@ -24,6 +24,7 @@ import jmespath import pytest +from helm_tests.airflow_aux.test_container_lifecycle import CONTAINER_LIFECYCLE_PARAMETERS from tests.charts.helm_template_generator import render_chart @@ -750,3 +751,19 @@ def test_workers_priority_class_name(self): ) assert "test-priority" == jmespath.search("spec.priorityClassName", docs[0]) + + def test_workers_container_lifecycle_webhooks_are_configurable(self, hook_type="preStop"): + lifecycle_hook_params = CONTAINER_LIFECYCLE_PARAMETERS[hook_type] + lifecycle_hooks_config = {hook_type: lifecycle_hook_params["lifecycle_templated"]} + docs = render_chart( + name=lifecycle_hook_params["release_name"], + values={ + "workers": {"containerLifecycleHooks": lifecycle_hooks_config}, + }, + show_only=["templates/pod-template-file.yaml"], + chart_dir=self.temp_chart_dir, + ) + + assert lifecycle_hook_params["lifecycle_parsed"] == jmespath.search( + f"spec.containers[0].lifecycle.{hook_type}", docs[0] + )