Files
rtomik-helm-charts/charts/tandoor/templates/deployment.yaml
2025-12-08 17:02:52 +01:00

403 lines
18 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "tandoor.fullname" . }}
labels:
{{- include "tandoor.labels" . | nindent 4 }}
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "tandoor.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
{{- include "tandoor.selectorLabels" . | nindent 8 }}
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.containerSecurityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.config.tandoorPort }}
protocol: TCP
{{- if .Values.probes.liveness.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.probes.liveness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
successThreshold: {{ .Values.probes.liveness.successThreshold }}
{{- end }}
{{- if .Values.probes.readiness.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.probes.readiness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
successThreshold: {{ .Values.probes.readiness.successThreshold }}
{{- end }}
env:
# Database configuration
- name: DB_ENGINE
value: "django.db.backends.postgresql"
- name: POSTGRES_HOST
value: {{ include "tandoor.postgresql.host" . | quote }}
- name: POSTGRES_PORT
value: {{ include "tandoor.postgresql.port" . | quote }}
- name: POSTGRES_DB
value: {{ .Values.postgresql.database | quote }}
- name: POSTGRES_USER
value: {{ .Values.postgresql.username | quote }}
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.postgresql.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.postgresql.passwordKey | default "postgresql-password" }}
# Security
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.config.secretKey.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.secretKey.secretKey | default "secret-key" }}
- name: ALLOWED_HOSTS
value: {{ .Values.config.allowedHosts | quote }}
{{- if .Values.config.csrfTrustedOrigins }}
- name: CSRF_TRUSTED_ORIGINS
value: {{ .Values.config.csrfTrustedOrigins | quote }}
{{- end }}
- name: CORS_ALLOW_ALL_ORIGINS
value: {{ ternary "1" "0" .Values.config.corsAllowOrigins | quote }}
# Server configuration
- name: TANDOOR_PORT
value: {{ .Values.config.tandoorPort | quote }}
- name: GUNICORN_WORKERS
value: {{ .Values.config.gunicornWorkers | quote }}
- name: GUNICORN_THREADS
value: {{ .Values.config.gunicornThreads | quote }}
- name: GUNICORN_TIMEOUT
value: {{ .Values.config.gunicornTimeout | quote }}
- name: GUNICORN_MEDIA
value: {{ .Values.config.gunicornMedia | quote }}
# URL configuration
{{- if .Values.config.scriptName }}
- name: SCRIPT_NAME
value: {{ .Values.config.scriptName | quote }}
{{- end }}
# Session cookie configuration
{{- if .Values.config.sessionCookieDomain }}
- name: SESSION_COOKIE_DOMAIN
value: {{ .Values.config.sessionCookieDomain | quote }}
{{- end }}
- name: SESSION_COOKIE_NAME
value: {{ .Values.config.sessionCookieName | quote }}
# Time and locale
- name: TZ
value: {{ .Values.config.timezone | quote }}
# Feature toggles
- name: ENABLE_SIGNUP
value: {{ ternary "1" "0" .Values.config.enableSignup | quote }}
- name: ENABLE_METRICS
value: {{ ternary "1" "0" .Values.config.enableMetrics | quote }}
- name: ENABLE_PDF_EXPORT
value: {{ ternary "1" "0" .Values.config.enablePdfExport | quote }}
- name: SORT_TREE_BY_NAME
value: {{ ternary "1" "0" .Values.config.sortTreeByName | quote }}
# Social authentication
- name: SOCIAL_DEFAULT_ACCESS
value: {{ .Values.config.socialDefaultAccess | quote }}
- name: SOCIAL_DEFAULT_GROUP
value: {{ .Values.config.socialDefaultGroup | quote }}
{{- if or .Values.config.socialProviders .Values.config.oidc.enabled }}
- name: SOCIAL_PROVIDERS
value: {{ .Values.config.socialProviders | default "allauth.socialaccount.providers.openid_connect" | quote }}
{{- end }}
{{- if .Values.config.socialAccountProviders }}
- name: SOCIALACCOUNT_PROVIDERS
value: {{ .Values.config.socialAccountProviders | quote }}
{{- end }}
# OpenID Connect / OAuth configuration (e.g., Authentik, Keycloak)
# Note: For production, consider using extraEnvFrom with a secret containing SOCIALACCOUNT_PROVIDERS
{{- if .Values.config.oidc.enabled }}
{{- $clientId := .Values.config.oidc.clientId }}
{{- $clientSecret := .Values.config.oidc.clientSecret }}
- name: SOCIALACCOUNT_PROVIDERS
value: '{"openid_connect":{"APPS":[{"provider_id":"{{ .Values.config.oidc.providerId }}","name":"{{ .Values.config.oidc.providerName }}","client_id":"{{ $clientId }}","secret":"{{ $clientSecret }}","settings":{"server_url":"{{ .Values.config.oidc.serverUrl }}"}}]}}'
{{- end }}
# Remote user authentication
- name: REMOTE_USER_AUTH
value: {{ ternary "1" "0" .Values.config.remoteUserAuth | quote }}
# LDAP configuration
{{- if .Values.config.ldap.enabled }}
- name: LDAP_AUTH
value: "1"
- name: AUTH_LDAP_SERVER_URI
value: {{ .Values.config.ldap.serverUri | quote }}
{{- if .Values.config.ldap.bindDn }}
- name: AUTH_LDAP_BIND_DN
value: {{ .Values.config.ldap.bindDn | quote }}
{{- end }}
{{- if or .Values.config.ldap.bindPassword .Values.config.ldap.existingSecret }}
- name: AUTH_LDAP_BIND_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.config.ldap.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.ldap.bindPasswordKey | default "ldap-bind-password" }}
{{- end }}
{{- if .Values.config.ldap.userSearchBaseDn }}
- name: AUTH_LDAP_USER_SEARCH_BASE_DN
value: {{ .Values.config.ldap.userSearchBaseDn | quote }}
{{- end }}
{{- if .Values.config.ldap.tlsCacertFile }}
- name: AUTH_LDAP_TLS_CACERTFILE
value: {{ .Values.config.ldap.tlsCacertFile | quote }}
{{- end }}
{{- if .Values.config.ldap.startTls }}
- name: AUTH_LDAP_START_TLS
value: "True"
{{- end }}
{{- end }}
# Email configuration
{{- if .Values.config.email.host }}
- name: EMAIL_HOST
value: {{ .Values.config.email.host | quote }}
- name: EMAIL_PORT
value: {{ .Values.config.email.port | quote }}
{{- if .Values.config.email.user }}
- name: EMAIL_HOST_USER
value: {{ .Values.config.email.user | quote }}
- name: EMAIL_HOST_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.config.email.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.email.passwordKey | default "email-password" }}
{{- end }}
- name: EMAIL_USE_TLS
value: {{ ternary "1" "0" .Values.config.email.useTls | quote }}
- name: EMAIL_USE_SSL
value: {{ ternary "1" "0" .Values.config.email.useSsl | quote }}
- name: DEFAULT_FROM_EMAIL
value: {{ .Values.config.email.defaultFrom | quote }}
- name: ACCOUNT_EMAIL_SUBJECT_PREFIX
value: {{ .Values.config.email.accountEmailSubjectPrefix | quote }}
{{- end }}
# S3/Object storage configuration
{{- if .Values.config.s3.enabled }}
- name: S3_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.config.s3.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.s3.accessKeyKey | default "s3-access-key" }}
- name: S3_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.config.s3.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.s3.secretAccessKeyKey | default "s3-secret-access-key" }}
- name: S3_BUCKET_NAME
value: {{ .Values.config.s3.bucketName | quote }}
{{- if .Values.config.s3.regionName }}
- name: S3_REGION_NAME
value: {{ .Values.config.s3.regionName | quote }}
{{- end }}
{{- if .Values.config.s3.endpointUrl }}
- name: S3_ENDPOINT_URL
value: {{ .Values.config.s3.endpointUrl | quote }}
{{- end }}
{{- if .Values.config.s3.customDomain }}
- name: S3_CUSTOM_DOMAIN
value: {{ .Values.config.s3.customDomain | quote }}
{{- end }}
- name: S3_QUERYSTRING_AUTH
value: {{ ternary "1" "0" .Values.config.s3.querystringAuth | quote }}
- name: S3_QUERYSTRING_EXPIRE
value: {{ .Values.config.s3.querystringExpire | quote }}
{{- end }}
# AI features
{{- if .Values.config.ai.enabled }}
- name: SPACE_AI_ENABLED
value: "1"
- name: SPACE_AI_CREDITS_MONTHLY
value: {{ .Values.config.ai.creditsMonthly | quote }}
- name: AI_RATELIMIT
value: {{ .Values.config.ai.rateLimit | quote }}
{{- end }}
# Food Data Central API
- name: FDC_API_KEY
value: {{ .Values.config.fdcApiKey | quote }}
# External connectors
- name: DISABLE_EXTERNAL_CONNECTORS
value: {{ ternary "1" "0" .Values.config.disableExternalConnectors | quote }}
- name: EXTERNAL_CONNECTORS_QUEUE_SIZE
value: {{ .Values.config.externalConnectorsQueueSize | quote }}
# Rate limiting
{{- if .Values.config.ratelimitUrlImportRequests }}
- name: RATELIMIT_URL_IMPORT_REQUESTS
value: {{ .Values.config.ratelimitUrlImportRequests | quote }}
{{- end }}
- name: DRF_THROTTLE_RECIPE_URL_IMPORT
value: {{ .Values.config.drfThrottleRecipeUrlImport | quote }}
# Space defaults
- name: SPACE_DEFAULT_MAX_RECIPES
value: {{ .Values.config.spaceDefaultMaxRecipes | quote }}
- name: SPACE_DEFAULT_MAX_USERS
value: {{ .Values.config.spaceDefaultMaxUsers | quote }}
- name: SPACE_DEFAULT_MAX_FILES
value: {{ .Values.config.spaceDefaultMaxFiles | quote }}
- name: SPACE_DEFAULT_ALLOW_SHARING
value: {{ ternary "1" "0" .Values.config.spaceDefaultAllowSharing | quote }}
# User preference defaults
- name: FRACTION_PREF_DEFAULT
value: {{ ternary "1" "0" .Values.config.fractionPrefDefault | quote }}
- name: COMMENT_PREF_DEFAULT
value: {{ ternary "1" "0" .Values.config.commentPrefDefault | quote }}
- name: STICKY_NAV_PREF_DEFAULT
value: {{ ternary "1" "0" .Values.config.stickyNavPrefDefault | quote }}
- name: MAX_OWNED_SPACES_PREF_DEFAULT
value: {{ .Values.config.maxOwnedSpacesPrefDefault | quote }}
# Cosmetic
- name: UNAUTHENTICATED_THEME_FROM_SPACE
value: {{ .Values.config.unauthenticatedThemeFromSpace | quote }}
- name: FORCE_THEME_FROM_SPACE
value: {{ .Values.config.forceThemeFromSpace | quote }}
# Performance
- name: SHOPPING_MIN_AUTOSYNC_INTERVAL
value: {{ .Values.config.shoppingMinAutosyncInterval | quote }}
- name: EXPORT_FILE_CACHE_DURATION
value: {{ .Values.config.exportFileCacheDuration | quote }}
# Legal URLs
{{- if .Values.config.termsUrl }}
- name: TERMS_URL
value: {{ .Values.config.termsUrl | quote }}
{{- end }}
{{- if .Values.config.privacyUrl }}
- name: PRIVACY_URL
value: {{ .Values.config.privacyUrl | quote }}
{{- end }}
{{- if .Values.config.imprintUrl }}
- name: IMPRINT_URL
value: {{ .Values.config.imprintUrl | quote }}
{{- end }}
# hCaptcha
{{- if .Values.config.hcaptcha.siteKey }}
- name: HCAPTCHA_SITEKEY
value: {{ .Values.config.hcaptcha.siteKey | quote }}
- name: HCAPTCHA_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.config.hcaptcha.existingSecret | default (printf "%s-secrets" (include "tandoor.fullname" .)) }}
key: {{ .Values.config.hcaptcha.secretKeyKey | default "hcaptcha-secret" }}
{{- end }}
# Debugging
- name: DEBUG
value: {{ ternary "1" "0" .Values.config.debug | quote }}
- name: DEBUG_TOOLBAR
value: {{ ternary "1" "0" .Values.config.debugToolbar | quote }}
- name: SQL_DEBUG
value: {{ ternary "1" "0" .Values.config.sqlDebug | quote }}
- name: LOG_LEVEL
value: {{ .Values.config.logLevel | quote }}
- name: GUNICORN_LOG_LEVEL
value: {{ .Values.config.gunicornLogLevel | quote }}
# Custom environment variables
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- with .Values.extraEnvFrom }}
envFrom:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: staticfiles
mountPath: /opt/recipes/staticfiles
- name: mediafiles
mountPath: /opt/recipes/mediafiles
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
{{- if .Values.persistence.staticfiles.enabled }}
- name: staticfiles
persistentVolumeClaim:
claimName: {{ .Values.persistence.staticfiles.existingClaim | default (printf "%s-staticfiles" (include "tandoor.fullname" .)) }}
{{- else }}
- name: staticfiles
emptyDir: {}
{{- end }}
{{- if .Values.persistence.mediafiles.enabled }}
- name: mediafiles
persistentVolumeClaim:
claimName: {{ .Values.persistence.mediafiles.existingClaim | default (printf "%s-mediafiles" (include "tandoor.fullname" .)) }}
{{- else }}
- name: mediafiles
emptyDir: {}
{{- end }}
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}