# services/health/wger-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wger
  namespace: health
spec:
  replicas: 1
  revisionHistoryLimit: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      app: wger
  template:
    metadata:
      labels:
        app: wger
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "health"
        vault.hashicorp.com/agent-inject-secret-wger-env: "kv/data/atlas/health/wger-db"
        vault.hashicorp.com/agent-inject-template-wger-env: |
          {{ with secret "kv/data/atlas/health/wger-db" }}
          export DJANGO_DB_HOST="{{ .Data.data.DJANGO_DB_HOST }}"
          export DJANGO_DB_PORT="{{ .Data.data.DJANGO_DB_PORT }}"
          export DJANGO_DB_DATABASE="{{ .Data.data.DJANGO_DB_DATABASE }}"
          export DJANGO_DB_USER="{{ .Data.data.DJANGO_DB_USER }}"
          export DJANGO_DB_PASSWORD="$(cat /vault/secrets/wger-db-password)"
          {{ end }}
          {{ with secret "kv/data/atlas/health/wger-secrets" }}
          export SECRET_KEY="$(cat /vault/secrets/wger-secret-key)"
          export SIGNING_KEY="$(cat /vault/secrets/wger-signing-key)"
          {{ end }}
        vault.hashicorp.com/agent-inject-secret-wger-db-password: "kv/data/atlas/health/wger-db"
        vault.hashicorp.com/agent-inject-template-wger-db-password: |
          {{- with secret "kv/data/atlas/health/wger-db" -}}
          {{ .Data.data.DJANGO_DB_PASSWORD }}
          {{- end -}}
        vault.hashicorp.com/agent-inject-secret-wger-secret-key: "kv/data/atlas/health/wger-secrets"
        vault.hashicorp.com/agent-inject-template-wger-secret-key: |
          {{- with secret "kv/data/atlas/health/wger-secrets" -}}
          {{ .Data.data.SECRET_KEY }}
          {{- end -}}
        vault.hashicorp.com/agent-inject-secret-wger-signing-key: "kv/data/atlas/health/wger-secrets"
        vault.hashicorp.com/agent-inject-template-wger-signing-key: |
          {{- with secret "kv/data/atlas/health/wger-secrets" -}}
          {{ .Data.data.SIGNING_KEY }}
          {{- end -}}
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: NotIn
                    values: ["titan-13", "titan-15", "titan-17", "titan-19"]
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              preference:
                matchExpressions:
                  - key: hardware
                    operator: In
                    values: ["rpi5"]
            - weight: 70
              preference:
                matchExpressions:
                  - key: hardware
                    operator: In
                    values: ["rpi4"]
      securityContext:
        fsGroup: 1000
        fsGroupChangePolicy: OnRootMismatch
      nodeSelector:
        kubernetes.io/arch: arm64
        node-role.kubernetes.io/worker: "true"
      serviceAccountName: health-vault-sync
      initContainers:
        - name: init-storage
          image: alpine:3.20
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -e
              mkdir -p /wger/static /wger/media
              chown -R 1000:1000 /wger
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          volumeMounts:
            - name: wger-static
              mountPath: /wger/static
            - name: wger-media
              mountPath: /wger/media
      containers:
        - name: wger
          image: wger/server@sha256:710588b78af4e0aa0b4d8a8061e4563e16eae80eeaccfe7f9e0d9cbdd7f0cbc5
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -eu
              . /vault/secrets/wger-env
              exec /home/wger/entrypoint.sh
          ports:
            - name: app
              containerPort: 8000
          env:
            - name: SITE_URL
              value: https://health.bstein.dev
            - name: CSRF_TRUSTED_ORIGINS
              value: https://health.bstein.dev
            - name: X_FORWARDED_PROTO_HEADER_SET
              value: "true"
            - name: NUMBER_OF_PROXIES
              value: "1"
            - name: TIME_ZONE
              value: Etc/UTC
            - name: TZ
              value: Etc/UTC
            - name: DJANGO_DEBUG
              value: "False"
            - name: DJANGO_PERFORM_MIGRATIONS
              value: "True"
            - name: DJANGO_DB_ENGINE
              value: django.db.backends.postgresql
            - name: DJANGO_CACHE_BACKEND
              value: django.core.cache.backends.locmem.LocMemCache
            - name: DJANGO_CACHE_LOCATION
              value: wger-cache
            - name: DJANGO_CACHE_TIMEOUT
              value: "3600"
            - name: ALLOW_REGISTRATION
              value: "False"
            - name: ALLOW_GUEST_USERS
              value: "False"
            - name: ALLOW_UPLOAD_VIDEOS
              value: "False"
            - name: USE_CELERY
              value: "False"
            - name: SYNC_EXERCISES_CELERY
              value: "False"
            - name: SYNC_INGREDIENTS_CELERY
              value: "False"
            - name: SYNC_EXERCISE_IMAGES_CELERY
              value: "False"
            - name: SYNC_EXERCISE_VIDEOS_CELERY
              value: "False"
            - name: CACHE_API_EXERCISES_CELERY
              value: "False"
            - name: DOWNLOAD_INGREDIENTS_FROM
              value: "None"
            - name: ENABLE_EMAIL
              value: "False"
          volumeMounts:
            - name: wger-static
              mountPath: /home/wger/static
            - name: wger-media
              mountPath: /home/wger/media
          startupProbe:
            httpGet:
              path: /api/v2/version/
              port: app
            failureThreshold: 60
            periodSeconds: 10
            timeoutSeconds: 3
          readinessProbe:
            httpGet:
              path: /api/v2/version/
              port: app
            initialDelaySeconds: 20
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 6
          livenessProbe:
            httpGet:
              path: /api/v2/version/
              port: app
            initialDelaySeconds: 45
            periodSeconds: 20
            timeoutSeconds: 3
            failureThreshold: 6
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 2Gi
        - name: nginx
          image: nginx:1.27.5-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10
          imagePullPolicy: IfNotPresent
          command:
            - nginx
          args:
            - -g
            - daemon off;
          ports:
            - name: http
              containerPort: 8080
          securityContext:
            runAsUser: 101
            runAsGroup: 101
            allowPrivilegeEscalation: false
          volumeMounts:
            - name: wger-nginx-config
              mountPath: /etc/nginx/conf.d/default.conf
              subPath: default.conf
            - name: wger-nginx-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
            - name: wger-static
              mountPath: /wger/static
            - name: wger-media
              mountPath: /wger/media
          startupProbe:
            httpGet:
              path: /api/v2/version/
              port: http
            failureThreshold: 60
            periodSeconds: 10
            timeoutSeconds: 3
          readinessProbe:
            httpGet:
              path: /api/v2/version/
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 6
          livenessProbe:
            httpGet:
              path: /api/v2/version/
              port: http
            initialDelaySeconds: 30
            periodSeconds: 20
            timeoutSeconds: 3
            failureThreshold: 6
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 200m
              memory: 256Mi
      volumes:
        - name: wger-static
          persistentVolumeClaim:
            claimName: wger-static
        - name: wger-media
          persistentVolumeClaim:
            claimName: wger-media
        - name: wger-nginx-config
          configMap:
            name: wger-nginx-config
            defaultMode: 0444
