diff --git a/src/helm/README.md b/src/helm/README.md index 293163ed..e32efecd 100644 --- a/src/helm/README.md +++ b/src/helm/README.md @@ -102,56 +102,24 @@ Our Elasticsearch cluster is all set. In the next section, we will now deploy ### Deploy the LRS: Ralph -Ralph is also distributed as a Helm chart that can be deployed with a single -line of code: +Ralph is also distributed as a Helm chart. Check out the [Ralph Helm chart README](https://github.com/openfun/ralph/blob/main/src/helm/README.md) to deploy it! -```bash -helm install \ - --values charts/ralph/values.yaml \ - --set envSecrets.RALPH_BACKENDS__DATABASE__ES__HOSTS=https://elastic:"${ELASTIC_PASSWORD}"@data-lake-es-http:9200 \ - lrs oci://registry-1.docker.io/openfuncharts/ralph -``` - -One can check if the server is running by opening a network tunnel to the -service using the `port-forward` sub-command: - - -```bash -kubectl port-forward svc/lrs-ralph 8080:8080 -``` - -And then send a request to the server using this tunnel: - -```bash -curl --user admin:password localhost:8080/whoami -``` - -We expect a valid JSON response stating about the user you are using for this -request. - -If everything went well, we can send 22k xAPI statements to the LRS using: +### Deploy the dashboard suite: Warren +Let's create the secrets needed for Warren deployment: ```bash -gunzip -c ../../data/statements.jsonl.gz | \ - sed "s/@timestamp/timestamp/g" | \ - jq -s . | \ - curl -Lk \ - --user admin:password \ - -X POST \ - -H "Content-Type: application/json" \ - http://localhost:8080/xAPI/statements/ -d @- +kubectl apply -f manifests/warren-app-secrets.yaml +kubectl apply -f manifests/warren-api-secrets.yaml ``` -### Deploy the dashboard suite: Warren - -Now that the LRS is running, we can deploy warren along with its dependencies +We can now deploy Warren along with its dependencies using: ```bash # Fetch dependencies -cd warren && helm dependency build +helm dependency build ./warren -# Deploy postgresql for Warren `app` service (Django) +# Install Warren helm install warren ./warren --values development.yaml --debug --atomic ``` @@ -159,6 +127,5 @@ If you want to upgrade your deployment (after a change in a template or a value), you can upgrade deployed version using: ```bash -# Deploy postgresql for Warren `app` service (Django) helm upgrade --install warren ./warren --values development.yaml --debug --atomic ``` diff --git a/src/helm/charts/ralph/values.yaml b/src/helm/charts/ralph/values.yaml index 21d7acc7..a1388247 100644 --- a/src/helm/charts/ralph/values.yaml +++ b/src/helm/charts/ralph/values.yaml @@ -1,15 +1,5 @@ -envSecrets: - RALPH_BACKENDS__DATABASE__ES__INDEX: statements - RALPH_BACKENDS__DATABASE__ES__CLIENT_OPTIONS__ca_certs: "/usr/local/share/ca-certificates/ca.crt" - RALPH_BACKENDS__DATABASE__ES__CLIENT_OPTIONS__verify_certs: "true" - -lrs: - auth: - - username: "admin" - hash: "$2b$12$JFK.YCdbUWD2rS94fT4.m.KC/fIMzUMPMtjaD4t3t1iAfqki3ZPOq" - scopes: ["example_scope"] - -elastic: - enabled: true - mountCACert: true - caSecretName: "data-lake-es-http-certs-public" +database: + tls: + enabled: true + certificatesSecret: "data-lake-es-http-certs-public" + certificatesMountPath: "/usr/local/share/ca-certificates/" diff --git a/src/helm/development.yaml b/src/helm/development.yaml index bb39cdc9..d3b91ed6 100644 --- a/src/helm/development.yaml +++ b/src/helm/development.yaml @@ -3,9 +3,10 @@ # -- Warren - app service -- app: enabled: true - allowedHosts: - - "localhost" - djangoConfiguration: Development + django: + allowedHosts: + - "localhost" + configuration: "Development" image: pullPolicy: Always persistence: @@ -14,7 +15,8 @@ app: # -- Warren - api service -- api: enabled: true - allowedHosts: + fastapi: + allowedHosts: - "http://localhost:8080" image: pullPolicy: Always @@ -24,10 +26,13 @@ postgresql: enabled: true image: tag: 12.17.0-debian-11-r12 - -global: - postgresql: - auth: - username: fun - password: pass - database: warren-api + auth: + username: fun + password: pass + database: warren-api + primary: + initdb: + scripts: + init.sql: | + CREATE DATABASE "warren-app"; + GRANT ALL PRIVILEGES ON DATABASE "warren-app" TO fun; diff --git a/src/helm/manifests/warren-api-secrets.yaml b/src/helm/manifests/warren-api-secrets.yaml new file mode 100644 index 00000000..b75ed3fb --- /dev/null +++ b/src/helm/manifests/warren-api-secrets.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: warren-api-db +type: Opaque +stringData: + WARREN_API_DB_PASSWORD: pass +--- +apiVersion: v1 +kind: Secret +metadata: + name: warren-api-lrs +type: Opaque +stringData: + WARREN_LRS_AUTH_BASIC_PASSWORD: password +--- \ No newline at end of file diff --git a/src/helm/manifests/warren-app-secrets.yaml b/src/helm/manifests/warren-app-secrets.yaml new file mode 100644 index 00000000..2a2bdee6 --- /dev/null +++ b/src/helm/manifests/warren-app-secrets.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: warren-app-db +type: Opaque +stringData: + WARREN_APP_DB_PASSWORD: pass +--- +apiVersion: v1 +kind: Secret +metadata: + name: warren-app-secret-key +type: Opaque +stringData: + WARREN_APP_SECRET_KEY: change_me_please +--- +apiVersion: v1 +kind: Secret +metadata: + name: warren-signing-key +type: Opaque +stringData: + WARREN_APP_SIGNING_KEY: change_me +--- \ No newline at end of file diff --git a/src/helm/manifests/warren-secrets.yaml b/src/helm/manifests/warren-secrets.yaml deleted file mode 100644 index 696255be..00000000 --- a/src/helm/manifests/warren-secrets.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: warren-api-env -type: Opaque -data: - WARREN_LRS_HOSTS: aHR0cDovL2xycy1yYWxwaDo4MDgw - WARREN_LRS_AUTH_BASIC_USERNAME: YWRtaW4= - WARREN_LRS_AUTH_BASIC_PASSWORD: cGFzc3dvcmQ= - WARREN_API_DB_HOST: d2FycmVuLXBvc3RncmVzcWw= - WARREN_API_DB_NAME: d2FycmVuLWFwaQ== - WARREN_API_DB_USER: ZnVu - WARREN_API_DB_PASSWORD: cGFzcw== - WARREN_APP_SIGNING_KEY: TGllMnNoYWE= ---- -apiVersion: v1 -kind: Secret -metadata: - name: warren-app-env -type: Opaque -data: - WARREN_APP_SECRET_KEY: bWVub284Q2hpYmVxdTFTb29oaXVQaDhsCg== - WARREN_APP_DB_HOST: d2FycmVuLXBvc3RncmVzcWw= - # Note that we use the same database for development - WARREN_APP_DB_NAME: d2FycmVuLWFwaQ== - WARREN_APP_DB_USER: ZnVu - WARREN_APP_DB_PASSWORD: cGFzcw== - WARREN_APP_SIGNING_KEY: TGllMnNoYWE= diff --git a/src/helm/warren/Chart.lock b/src/helm/warren/Chart.lock index 39363965..55c465fc 100644 --- a/src/helm/warren/Chart.lock +++ b/src/helm/warren/Chart.lock @@ -7,6 +7,6 @@ dependencies: version: 0.1.0 - name: postgresql repository: oci://registry-1.docker.io/bitnamicharts - version: 13.2.24 -digest: sha256:4b13561dfdca97064192f6861fd5f75f25cdf8b4161a2bb092fbede18f879c61 -generated: "2023-12-07T16:42:14.91623072+01:00" + version: 13.4.6 +digest: sha256:254a201e5c57f8ae32c527f319492b34167626947c642491343413df2bd61874 +generated: "2024-07-03T15:58:33.064365499+02:00" diff --git a/src/helm/warren/charts/api/Chart.yaml b/src/helm/warren/charts/api/Chart.yaml index 8e8b5423..5d7cb249 100644 --- a/src/helm/warren/charts/api/Chart.yaml +++ b/src/helm/warren/charts/api/Chart.yaml @@ -4,4 +4,4 @@ name: api description: Warren HTTP API type: application version: 0.1.0 -appVersion: "0.1.0" +appVersion: "0.3.2" diff --git a/src/helm/warren/charts/api/templates/NOTES.txt b/src/helm/warren/charts/api/templates/NOTES.txt index 1bdec90b..b2fd3835 100644 --- a/src/helm/warren/charts/api/templates/NOTES.txt +++ b/src/helm/warren/charts/api/templates/NOTES.txt @@ -1,21 +1,28 @@ -1. Get the application URL by running these commands: +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +1. Access your Warren api installation: {{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + Connect to one of the following hosts: + {{ if .Values.ingress.tls }} + https://{{ .Values.ingress.host }} + {{- else }} + http://{{ .Values.ingress.host }} {{- end }} -{{- end }} {{- else if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "api.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT + echo "Warren API URL: http://$NODE_IP:$NODE_PORT" {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "api.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "api.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.service.port }} {{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "api.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "api.name" . }},api.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT diff --git a/src/helm/warren/charts/api/templates/_helpers.tpl b/src/helm/warren/charts/api/templates/_helpers.tpl index fe3d9b21..0a51dedc 100644 --- a/src/helm/warren/charts/api/templates/_helpers.tpl +++ b/src/helm/warren/charts/api/templates/_helpers.tpl @@ -48,11 +48,76 @@ Selector labels {{- define "api.selectorLabels" -}} app.kubernetes.io/name: {{ include "api.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: api +app.kubernetes.io/part-of: warren {{- end }} {{/* -Allowed hosts string (environment variable value) +Environment variables */}} -{{- define "api.allowedHosts" -}} -{{- printf "%q" .Values.allowedHosts | replace " " "," | quote -}} +{{- define "api.envs" -}} +- name: "WARREN_API_SERVER_PORT" + value: "{{ .Values.service.port }}" +- name: "WARREN_API_DB_NAME" + value: "{{ .Values.fastapi.db.name }}" +- name: "WARREN_API_DB_USER" + value: "{{ .Values.fastapi.db.user }}" +- name: "WARREN_API_DB_PASSWORD" + valueFrom: + secretKeyRef: + name: warren-api-db + key: WARREN_API_DB_PASSWORD +- name: "WARREN_API_DB_ENGINE" + value: "{{ .Values.fastapi.db.engine }}" +- name: "WARREN_API_DB_HOST" + value: "{{ .Values.fastapi.db.host }}" +- name: "WARREN_API_DB_PORT" + value: "{{ .Values.fastapi.db.port }}" +- name: "WARREN_ALLOWED_HOSTS" + value: {{ printf "%q" .Values.fastapi.allowedHosts | replace " " "," | quote }} +- name: "WARREN_LRS_HOSTS" + value: "{{ .Values.fastapi.lrs.host }}" +- name: "WARREN_LRS_AUTH_BASIC_USERNAME" + value: "{{ .Values.fastapi.lrs.username }}" +- name: "WARREN_LRS_AUTH_BASIC_PASSWORD" + valueFrom: + secretKeyRef: + name: warren-api-lrs + key: WARREN_LRS_AUTH_BASIC_PASSWORD +- name: "WARREN_XI_LMS_BASE_URL" + value: "{{ .Values.fastapi.xi.lmsBaseUrl }}" +- name: "WARREN_XI_LMS_API_TOKEN" + valueFrom: + secretKeyRef: + name: warren-api-lms + key: WARREN_XI_LMS_API_TOKEN +- name: "WARREN_XI_DEFAULT_LANG" + value: "{{ .Values.fastapi.xi.defaultLang }}" +- name: "WARREN_APP_SIGNING_ALGORITHM" + value: "{{ .Values.fastapi.signingAlgorithm }}" +- name: "WARREN_APP_SIGNING_KEY" + valueFrom: + secretKeyRef: + name: warren-signing-key + key: WARREN_APP_SIGNING_KEY +{{- range $key, $val := .Values.env.secret }} +- name: {{ $val.envName }} + valueFrom: + secretKeyRef: + name: {{ $val.secretName }} + key: {{ $val.keyName }} +{{- end }} +{{- end }} + +{{/* +ImagePullSecrets +*/}} +{{- define "fastapi.imagePullSecrets" -}} +{{- $pullSecrets := .Values.imagePullSecrets }} +{{- if (not (empty $pullSecrets)) }} +imagePullSecrets: +{{- range $pullSecrets }} +- name: {{ . }} +{{ end }} +{{- end -}} {{- end }} diff --git a/src/helm/warren/charts/api/templates/cm_logging.yaml b/src/helm/warren/charts/api/templates/configmap.yaml similarity index 78% rename from src/helm/warren/charts/api/templates/cm_logging.yaml rename to src/helm/warren/charts/api/templates/configmap.yaml index 7d96e0f7..f9113cab 100644 --- a/src/helm/warren/charts/api/templates/cm_logging.yaml +++ b/src/helm/warren/charts/api/templates/configmap.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: "{{ .Values.loggingConfigConfigMap }}" + name: "{{ include "api.fullname" . }}-logging-config" labels: {{- include "api.labels" . | nindent 4 }} data: diff --git a/src/helm/warren/charts/api/templates/cronjobs.yaml b/src/helm/warren/charts/api/templates/cronjobs.yaml new file mode 100644 index 00000000..7c384a30 --- /dev/null +++ b/src/helm/warren/charts/api/templates/cronjobs.yaml @@ -0,0 +1,49 @@ +{{- range .Values.fastapi.cronjobs }} +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "api.fullname" $ }}-{{ .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "api.labels" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{ toYaml $.Values.commonLabels | nindent 4 }} + {{- end }} +{{- if $.Values.commonAnnotations }} + annotations: +{{- toYaml $.Values.commonAnnotations | nindent 4 }} +{{- end }} +spec: + schedule: {{ .schedule | quote }} + successfulJobsHistoryLimit: 2 + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 1 + suspend: {{ .suspend }} + jobTemplate: + spec: + template: + metadata: + labels: {{- include "api.selectorLabels" $ | nindent 12 }} + spec: + {{- include "fastapi.imagePullSecrets" $ | nindent 10 }} + containers: + - name: "{{ $.Chart.Name }}-{{ .name }}" + image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + env: + - name: "WARREN_SERVER_HOST" + value: {{ include "api.fullname" $ }} + {{- include "api.envs" $ | nindent 16 }} + command: {{ .command | toJson }} + {{- if $.Values.resources }} + resources: {{ toYaml $.Values.resources | nindent 16 }} + {{- end }} + volumeMounts: + - name: logging-config + mountPath: "/etc/warren/api" + volumes: + - name: logging-config + configMap: + name: {{ include "api.fullname" $ }}-logging-config + restartPolicy: Never +{{- end }} diff --git a/src/helm/warren/charts/api/templates/deployment.yaml b/src/helm/warren/charts/api/templates/deployment.yaml index dea67581..60ed5888 100644 --- a/src/helm/warren/charts/api/templates/deployment.yaml +++ b/src/helm/warren/charts/api/templates/deployment.yaml @@ -2,15 +2,16 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "api.fullname" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "api.labels" . | nindent 4 }} spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} selector: matchLabels: {{- include "api.selectorLabels" . | nindent 6 }} + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} template: metadata: {{- with .Values.podAnnotations }} @@ -19,72 +20,53 @@ spec: {{- end }} labels: {{- include "api.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- include "fastapi.imagePullSecrets" . | nindent 6 }} containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} + - name: "{{ .Chart.Name }}-fastapi" image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.service.port }} - protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} livenessProbe: httpGet: path: /__heartbeat__ - port: http - httpHeaders: - - name: Host - value: '{{ first .Values.allowedHosts | trimPrefix "https://" }}' + port: {{ .Values.fastapi.port }} initialDelaySeconds: 15 periodSeconds: 30 readinessProbe: httpGet: path: /__lbheartbeat__ - port: http - httpHeaders: - - name: Host - value: '{{ first .Values.allowedHosts | trimPrefix "https://" }}' + port: {{ .Values.fastapi.port }} + initialDelaySeconds: 5 + periodSeconds: 5 + startupProbe: + exec: + command: + - "bash" + - "-c" + - "warren migration check" initialDelaySeconds: 5 periodSeconds: 5 + timeoutSeconds: 30 env: - - name: WARREN_API_SERVER_PORT - value: "{{ .Values.service.port }}" - - name: WARREN_API_DB_ENGINE - value: {{ .Values.database.engine }} - - name: WARREN_API_DB_PORT - value: {{ .Values.database.port | quote }} - - name: WARREN_APP_SIGNING_ALGORITHM - value: {{ .Values.signingAlgorithm }} - - name: WARREN_ALLOWED_HOSTS - value: {{ include "api.allowedHosts" . }} + {{- include "api.envs" . | nindent 12 }} + {{- if .Values.fastapi.extraEnvVarsCM }} envFrom: - - secretRef: - name: {{ .Values.envVarsSecret | quote }} - {{ with .Values.podCommand }} + - configMapRef: + name: {{ .Values.fastapi.extraEnvVarsCM }} + {{- end }} + {{ with .Values.fastapi.command }} command: {{- toYaml . | nindent 12 }} {{- end }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.volumeMounts }} volumeMounts: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.volumes }} + - name: logging-config + mountPath: "/etc/warren/api" volumes: - {{- toYaml . | nindent 8 }} - {{- end }} + - name: logging-config + configMap: + name: {{ include "api.fullname" . }}-logging-config {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/src/helm/warren/charts/api/templates/hpa.yaml b/src/helm/warren/charts/api/templates/hpa.yaml deleted file mode 100644 index 4b5caf84..00000000 --- a/src/helm/warren/charts/api/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "api.fullname" . }} - labels: - {{- include "api.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "api.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/src/helm/warren/charts/api/templates/ingress.yaml b/src/helm/warren/charts/api/templates/ingress.yaml index d7a5ccd5..da86640f 100644 --- a/src/helm/warren/charts/api/templates/ingress.yaml +++ b/src/helm/warren/charts/api/templates/ingress.yaml @@ -1,61 +1,36 @@ {{- if .Values.ingress.enabled -}} -{{- $fullName := include "api.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} kind: Ingress metadata: - name: {{ $fullName }} - labels: - {{- include "api.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} + name: {{ template "api.fullname" . }} + labels: {{- include "api.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{ toYaml .Values.commonLabels | nindent 4 }} + {{- end }} annotations: - {{- toYaml . | nindent 4 }} - {{- end }} + {{- if .Values.commonAnnotations }} + {{- toYaml .Values.commonAnnotations | nindent 4 }} + {{- end }} + {{- if .Values.ingress.annotations }} + {{- toYaml .Values.ingress.annotations | nindent 4 }} + {{- end }} spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} + {{- if $.Values.ingress.tls.enabled }} tls: - {{- range .Values.ingress.tls }} - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} + - {{ $.Values.ingress.host }} + secretName: {{ $.Values.ingress.tls.certificateSecretName }} {{- end }} rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} + - host: {{ .Values.ingress.host }} http: paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} + - path: / + pathType: Prefix backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: - name: {{ $fullName }} + name: {{ include "api.fullname" . }} port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} + number: {{ .Values.service.port }} {{- end }} diff --git a/src/helm/warren/charts/api/templates/job_db_migrate.yaml b/src/helm/warren/charts/api/templates/job_db_migrate.yaml deleted file mode 100644 index 97ea3900..00000000 --- a/src/helm/warren/charts/api/templates/job_db_migrate.yaml +++ /dev/null @@ -1,48 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ .Values.jobs.dbMigrate.name }}" - labels: - {{- include "api.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install, pre-upgrade -spec: - template: - metadata: - labels: - {{- include "api.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- 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.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: WARREN_APP_SIGNING_ALGORITHM - value: {{ .Values.signingAlgorithm }} - envFrom: - - secretRef: - name: {{ .Values.envVarsSecret | quote }} - {{ with .Values.jobs.dbMigrate.command }} - command: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.volumeMounts }} - volumeMounts: - {{- toYaml . | nindent 12 }} - {{- end }} - restartPolicy: {{ .Values.jobs.dbMigrate.restartPolicy }} - {{- with .Values.volumes }} - volumes: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/src/helm/warren/charts/api/templates/jobs.yaml b/src/helm/warren/charts/api/templates/jobs.yaml new file mode 100644 index 00000000..ed69372a --- /dev/null +++ b/src/helm/warren/charts/api/templates/jobs.yaml @@ -0,0 +1,42 @@ +{{- range .Values.fastapi.jobs }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "api.fullname" $ }}-{{ .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "api.labels" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{ toYaml $.Values.commonLabels | nindent 4 }} + {{- end }} + annotations: +{{- if $.Values.commonAnnotations }} +{{- toYaml $.Values.commonAnnotations | nindent 4 }} +{{- end }} + "helm.sh/hook": post-upgrade,post-install + "helm.sh/hook-weight": "0" +spec: + template: + metadata: + labels: {{- include "api.selectorLabels" $ | nindent 8 }} + spec: + {{- include "fastapi.imagePullSecrets" $ | nindent 6 }} + containers: + - name: "{{ $.Chart.Name }}-{{ .name }}" + image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + env: + {{- include "api.envs" $ | nindent 12 }} + command: {{ .command | toJson }} + {{- if $.Values.resources }} + resources: {{ toYaml $.Values.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: logging-config + mountPath: "/etc/warren/api" + volumes: + - name: logging-config + configMap: + name: {{ include "api.fullname" $ }}-logging-config + restartPolicy: Never +{{- end }} diff --git a/src/helm/warren/charts/api/templates/service.yaml b/src/helm/warren/charts/api/templates/service.yaml index bc913897..014966d5 100644 --- a/src/helm/warren/charts/api/templates/service.yaml +++ b/src/helm/warren/charts/api/templates/service.yaml @@ -1,15 +1,17 @@ +--- apiVersion: v1 kind: Service metadata: name: {{ include "api.fullname" . }} - labels: - {{- include "api.labels" . | nindent 4 }} + labels: {{- include "api.labels" . | nindent 4 }} spec: - type: {{ .Values.service.type }} ports: - - port: {{ .Values.service.port }} - targetPort: http + - name: "{{ .Values.service.port }}-tcp" + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} protocol: TCP - name: http - selector: - {{- include "api.selectorLabels" . | nindent 4 }} + {{- if (eq .Values.service.type "NodePort") }} + nodePort: {{ .Values.service.nodePort.http }} + {{- end }} + type: {{ .Values.service.type }} + selector: {{- include "api.selectorLabels" . | nindent 4 }} diff --git a/src/helm/warren/charts/api/values.yaml b/src/helm/warren/charts/api/values.yaml index 969523a9..afaa274e 100644 --- a/src/helm/warren/charts/api/values.yaml +++ b/src/helm/warren/charts/api/values.yaml @@ -2,94 +2,64 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 - image: repository: fundocker/warren pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. tag: "api-full-main" +replicaCount: 1 + imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" podAnnotations: {} -podLabels: {} -podCommand: - - "uvicorn" - - "warren.api:app" - - "--proxy-headers" - - "--log-config" - - "/etc/warren/api/logging-config.yaml" - - "--host" - - "0.0.0.0" - - "--port" - - "8000" - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -# Secret name to inject as environment variables -envVarsSecret: "warren-api-env" - -jobs: - dbMigrate: - name: "warren-api-db-migrate" - command: - - "alembic" - - "-c" - - "core/alembic.ini" - - "upgrade" - - "head" - restartPolicy: Never service: type: ClusterIP - port: 8000 + port: 8100 ingress: - enabled: false - className: "" + enabled: true + class_name: "nginx" + host: "" annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi + tls: + enabled: false + certificateSecretName: warren-api-certificate + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: deployment + operator: In + values: + - "warren-app-app" + topologyKey: kubernetes.io/hostname autoscaling: enabled: false minReplicas: 1 - maxReplicas: 100 + maxReplicas: 10 targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +jobs: + dbMigrate: + name: "warren-api-db-migrate" + command: + - "warren" + - "migration" + - "upgrade" + - "head" + + restartPolicy: Never # Additional volumes on the output Deployment definition. volumes: @@ -103,19 +73,52 @@ volumeMounts: mountPath: "/etc/warren/api" readOnly: true -nodeSelector: {} - -tolerations: [] - -affinity: {} - - # API configuration -allowedHosts: [] -database: - engine: postgresql - port: 5432 -loggingConfigConfigMap: api-logging-config +fastapi: + fullname: "api" + port: 8100 + allowedHosts: + - "*" + signingAlgorithm: "HS256" + db: + name: "warren-api" + user: "fun" + engine: "postgresql" + host: "warren-postgresql" + port: 5432 + lrs: + host: "http://lrs-ralph:8080" + username: "admin" + xi: + lmsBaseUrl: "http://my-moodle-instance" + defaultLang: "fr" + command: + - "uvicorn" + - "warren.api:app" + - "--proxy-headers" + - "--log-config" + - "/etc/warren/api/logging-config.yaml" + - "--host" + - "0.0.0.0" + - "--port" + - "8100" + jobs: + - name: dbmigrate + command: ["warren", "migration", "upgrade", "head"] + cronjobs: [] + # Cronjobs should define a name, a schedule, the schedule suspension + # and a command to execute, e.g. + # - name: "index-moodle" + # schedule: "0 1 * * *" + # suspend: false + # command: + # - "warren" + # - "xi" + # - "index" + # - "all" + # - "--ignore-errors" + resources: {} + loggingConfig: version: 1 disable_existing_loggers: false @@ -154,4 +157,6 @@ loggingConfig: - default level: INFO propagate: false -signingAlgorithm: HS256 + +env: + secret: [] \ No newline at end of file diff --git a/src/helm/warren/charts/app/Chart.yaml b/src/helm/warren/charts/app/Chart.yaml index 63ad1fc3..9fa1490c 100644 --- a/src/helm/warren/charts/app/Chart.yaml +++ b/src/helm/warren/charts/app/Chart.yaml @@ -4,4 +4,4 @@ name: app description: Warren integrable and standalone application type: application version: 0.1.0 -appVersion: "0.1.0" +appVersion: "0.3.2" diff --git a/src/helm/warren/charts/app/templates/NOTES.txt b/src/helm/warren/charts/app/templates/NOTES.txt index 01a7d7b1..44c896d4 100644 --- a/src/helm/warren/charts/app/templates/NOTES.txt +++ b/src/helm/warren/charts/app/templates/NOTES.txt @@ -1,14 +1,21 @@ -1. Get the application URL by running these commands: +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +1. Access your Warren app installation: {{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + Connect to one of the following hosts: + {{ if .Values.ingress.tls }} + https://{{ .Values.ingress.host }} + {{- else }} + http://{{ .Values.ingress.host }} {{- end }} -{{- end }} {{- else if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "app.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT + echo "Warren APP URL: http://$NODE_IP:$NODE_PORT" {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "app.fullname" . }}' diff --git a/src/helm/warren/charts/app/templates/_helpers.tpl b/src/helm/warren/charts/app/templates/_helpers.tpl index bd7dc597..e73271df 100644 --- a/src/helm/warren/charts/app/templates/_helpers.tpl +++ b/src/helm/warren/charts/app/templates/_helpers.tpl @@ -48,11 +48,75 @@ Selector labels {{- define "app.selectorLabels" -}} app.kubernetes.io/name: {{ include "app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: app +app.kubernetes.io/part-of: warren {{- end }} {{/* -Allowed hosts string (environment variable value) +Environment variables */}} -{{- define "app.allowedHosts" -}} -{{- .Values.allowedHosts | join "," | quote -}} +{{- define "app.envs" -}} +- name: "DJANGO_SETTINGS_MODULE" + value: "{{ .Values.django.settings }}" +- name: "DJANGO_CONFIGURATION" + value: "{{ .Values.django.configuration }}" +- name: "WARREN_APP_SECRET_KEY" + valueFrom: + secretKeyRef: + name: warren-app-secret-key + key: WARREN_APP_SECRET_KEY +- name: "WARREN_APP_ALLOWED_HOSTS" + value: "{{ .Values.django.allowedHosts | join "," }}" +- name: "WARREN_APP_DB_NAME" + value: "{{ .Values.django.db.name }}" +- name: "WARREN_APP_DB_USER" + value: "{{ .Values.django.db.user }}" +- name: "WARREN_APP_DB_PASSWORD" + valueFrom: + secretKeyRef: + name: warren-app-db + key: WARREN_APP_DB_PASSWORD +- name: "WARREN_APP_DB_HOST" + value: "{{ .Values.django.db.host }}" +- name: "WARREN_APP_DB_PORT" + value: "{{ .Values.django.db.port }}" +- name: "WARREN_APP_SIGNING_ALGORITHM" + value: "{{ .Values.django.signingAlgorithm }}" +- name: "WARREN_APP_SIGNING_KEY" + valueFrom: + secretKeyRef: + name: warren-signing-key + key: WARREN_APP_SIGNING_KEY +- name: "WARREN_APP_ACCESS_TOKEN_LIFETIME" + value: "{{ .Values.django.accessTokenLifetime }}" +- name: "WARREN_APP_REFRESH_TOKEN_LIFETIME" + value: "{{ .Values.django.refreshTokenLifetime }}" +- name: "WARREN_APP_LTI_ACCESS_TOKEN_LIFETIME" + value: "{{ .Values.django.ltiAccessTokenLifetime }}" +- name: "WARREN_API_ROOT_URL" + value: {{ .Values.django.apiRootUrl | quote }} +- name: "WARREN_APP_ROOT_URL" + value: {{ .Values.django.appRootUrl | quote }} +- name: "WARREN_APP_CORS_ALLOWED_ORIGINS" + value: {{ join "," .Values.django.corsAllowedOrigins | quote }} +{{- range $key, $val := .Values.env.secret }} +- name: {{ $val.envName }} + valueFrom: + secretKeyRef: + name: {{ $val.secretName }} + key: {{ $val.keyName }} +{{- end }} +{{- end }} + +{{/* +ImagePullSecrets +*/}} +{{- define "django.imagePullSecrets" -}} +{{- $pullSecrets := .Values.imagePullSecrets }} +{{- if (not (empty $pullSecrets)) }} +imagePullSecrets: +{{- range $pullSecrets }} +- name: {{ . }} +{{ end }} +{{- end -}} {{- end }} diff --git a/src/helm/warren/charts/app/templates/configmap.yaml b/src/helm/warren/charts/app/templates/configmap.yaml new file mode 100644 index 00000000..5b4e08d8 --- /dev/null +++ b/src/helm/warren/charts/app/templates/configmap.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "app.fullname" . }}-nginx" +data: + config: | + events { + worker_connections 1024; # increase if you have lots of clients + accept_mutex off; # set to 'on' if nginx worker_processes > 1 + # 'use epoll;' to enable for Linux 2.6+ + # 'use kqueue;' to enable for FreeBSD, OSX + } + + http { + upstream django_app { + server localhost:{{ .Values.django.port }}; + } + + server { + listen {{ .Values.nginx.port }}; + + root /usr/share/nginx; + location / { + # checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + proxy_pass http://django_app; + } + } + + server { + listen 5000; + server_name localhost; + + location /__status__ { + stub_status; + access_log off; + } + + } + + include /etc/nginx/mime.types; + } diff --git a/src/helm/warren/charts/app/templates/deployment.yaml b/src/helm/warren/charts/app/templates/deployment.yaml index cfa911b6..bd7435ae 100644 --- a/src/helm/warren/charts/app/templates/deployment.yaml +++ b/src/helm/warren/charts/app/templates/deployment.yaml @@ -1,16 +1,17 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "app.fullname" . }} + name: {{ template "app.fullname" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "app.labels" . | nindent 4 }} spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} selector: matchLabels: {{- include "app.selectorLabels" . | nindent 6 }} + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} template: metadata: {{- with .Values.podAnnotations }} @@ -19,107 +20,98 @@ spec: {{- end }} labels: {{- include "app.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- include "django.imagePullSecrets" . | nindent 6 }} + initContainers: + - name: "{{ .Chart.Name }}-collectstatic" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "python" + - "manage.py" + - "collectstatic" + - "--no-input" + env: + {{- include "app.envs" . | nindent 12 }} + volumeMounts: + - name: "static" + mountPath: /app/static containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} + - name: "{{ .Chart.Name }}-django" image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.service.port }} - protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} livenessProbe: httpGet: path: /__heartbeat__ - port: http + port: {{ .Values.django.port }} httpHeaders: - - name: Host - value: "{{ first .Values.allowedHosts }}" + - name: "Host" + value: "{{ .Values.ingress.host }}" + initialDelaySeconds: 15 + periodSeconds: 30 readinessProbe: httpGet: path: /__lbheartbeat__ - port: http + port: {{ .Values.django.port }} httpHeaders: - - name: Host - value: "{{ first .Values.allowedHosts }}" + - name: "Host" + value: "{{ .Values.ingress.host }}" + initialDelaySeconds: 5 + periodSeconds: 5 + startupProbe: + exec: + command: + - python3 + - manage.py + - migrate + - --check + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 30 env: - - name: DJANGO_SETTINGS_MODULE - value: {{ .Values.djangoSettingsModule }} - - name: DJANGO_CONFIGURATION - value: {{ .Values.djangoConfiguration }} - {{- if .Values.persistence.enabled }} - - name: WARREN_APP_MEDIA_ROOT - value: {{ .Values.persistence.volumes.media.mountPath }} - - name: WARREN_APP_STATIC_ROOT - value: {{ .Values.persistence.volumes.static.mountPath }} - {{- end }} - - name: WARREN_APP_DB_PORT - value: {{ .Values.database.port | quote }} - - name: WARREN_APP_SIGNING_ALGORITHM - value: {{ .Values.signingAlgorithm }} - - name: WARREN_APP_ACCESS_TOKEN_LIFETIME - value: {{ .Values.accessTokenLifetime | quote }} - - name: WARREN_APP_REFRESH_TOKEN_LIFETIME - value: {{ .Values.refreshTokenLifetime | quote }} - - name: WARREN_APP_LTI_ACCESS_TOKEN_LIFETIME - value: {{ .Values.ltiAccessTokenLifetime | quote }} - - name: WARREN_API_ROOT_URL - value: {{ .Values.apiRootUrl | quote }} - - name: WARREN_APP_ROOT_URL - value: {{ .Values.appRootUrl | quote }} - - name: WARREN_APP_ALLOWED_HOSTS - value: {{ include "app.allowedHosts" . }} - - name: WARREN_APP_CORS_ALLOWED_ORIGINS - value: {{ join "," .Values.corsAllowedOrigins | quote }} - envFrom: - - secretRef: - name: {{ .Values.envVarsSecret | quote }} - {{ with .Values.podCommand }} + {{- include "app.envs" . | nindent 12 }} + {{ with .Values.django.command }} command: {{- toYaml . | nindent 12 }} {{- end }} - resources: - {{- toYaml .Values.resources | nindent 12 }} + {{- if .Values.persistence.enabled }} volumeMounts: - {{- if .Values.persistence.enabled }} - - name: {{ .Values.persistence.volumes.media.name }} - mountPath: {{ .Values.persistence.volumes.media.mountPath }} - - name: {{ .Values.persistence.volumes.static.name }} - mountPath: {{ .Values.persistence.volumes.static.mountPath }} - {{- end }} - {{- with .Values.volumeMounts }} - {{- toYaml . | nindent 12 }} - {{- end }} + - name: static + mountPath: /app/static + - name: {{ .Values.volumes.media.name }} + mountPath: {{ .Values.volumes.media.mountPath }} + - name: "{{ .Chart.Name }}-nginx" + image: nginx:1.25.4-alpine + volumeMounts: + - name: "static" + mountPath: /usr/share/nginx/static + - name: {{ .Values.volumes.media.name }} + mountPath: /usr/share/nginx/media + - name: nginx + mountPath: /etc/nginx/nginx.conf + subPath: nginx.conf + readOnly: true + livenessProbe: + httpGet: + path: /__status__ + port: 5000 + initialDelaySeconds: 15 + periodSeconds: 30 volumes: - {{- if .Values.persistence.enabled }} - - name: {{ .Values.persistence.volumes.media.name }} + - name: {{ .Values.volumes.media.name }} persistentVolumeClaim: - {{- if .Values.persistence.volumes.media.claimName }} claimName: {{ .Values.volumes.media.claimName }} - {{- else }} - claimName: {{ include "app.fullname" . }}-media - {{- end }} - - name: {{ .Values.persistence.volumes.static.name }} - persistentVolumeClaim: - {{- if .Values.persistence.volumes.static.claimName }} - claimName: {{ .Values.volumes.static.claimName }} - {{- else }} - claimName: {{ include "app.fullname" . }}-static - {{- end }} - {{- end }} - {{- with .Values.volumes }} - {{- toYaml . | nindent 8 }} + - name: nginx + configMap: + items: + - key: config + path: nginx.conf + name: "{{ template "app.fullname" . }}-nginx" + - name: "static" + emptyDir: + sizeLimit: 50Mi {{- end }} {{- with .Values.nodeSelector }} nodeSelector: diff --git a/src/helm/warren/charts/app/templates/hpa.yaml b/src/helm/warren/charts/app/templates/hpa.yaml deleted file mode 100644 index 30fd7564..00000000 --- a/src/helm/warren/charts/app/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "app.fullname" . }} - labels: - {{- include "app.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "app.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/src/helm/warren/charts/app/templates/ingress.yaml b/src/helm/warren/charts/app/templates/ingress.yaml index ced20f9c..e15e46f8 100644 --- a/src/helm/warren/charts/app/templates/ingress.yaml +++ b/src/helm/warren/charts/app/templates/ingress.yaml @@ -1,61 +1,37 @@ {{- if .Values.ingress.enabled -}} -{{- $fullName := include "app.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} kind: Ingress metadata: - name: {{ $fullName }} - labels: - {{- include "app.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} + name: {{ template "app.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "app.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{ toYaml .Values.commonLabels | nindent 4 }} + {{- end }} annotations: - {{- toYaml . | nindent 4 }} - {{- end }} + {{- if .Values.commonAnnotations }} + {{- toYaml .Values.commonAnnotations | nindent 4 }} + {{- end }} + {{- if .Values.ingress.annotations }} + {{- toYaml .Values.ingress.annotations | nindent 4 }} + {{- end }} spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} + ingressClassName: {{ .Values.ingress.class_name }} + {{- if $.Values.ingress.tls.enabled }} tls: - {{- range .Values.ingress.tls }} - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} + - {{ $.Values.ingress.host | quote }} + secretName: {{ $.Values.ingress.tls.certificateSecretName }} {{- end }} rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} + - host: {{ .Values.ingress.host }} http: paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} + - path: / + pathType: Prefix backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: - name: {{ $fullName }} + name: {{ include "app.fullname" . }} port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} + number: {{ .Values.nginx.port }} {{- end }} diff --git a/src/helm/warren/charts/app/templates/job_collect_static.yaml b/src/helm/warren/charts/app/templates/job_collect_static.yaml deleted file mode 100644 index 37276653..00000000 --- a/src/helm/warren/charts/app/templates/job_collect_static.yaml +++ /dev/null @@ -1,77 +0,0 @@ -{{- if .Values.persistence.enabled }} -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ .Values.jobs.collectStatic.name }}" - labels: - {{- include "app.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install, pre-upgrade -spec: - template: - metadata: - labels: - {{- include "app.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- 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.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: DJANGO_SETTINGS_MODULE - value: {{ .Values.djangoSettingsModule }} - - name: DJANGO_CONFIGURATION - value: {{ .Values.djangoConfiguration }} - - name: WARREN_APP_MEDIA_ROOT - value: {{ .Values.persistence.volumes.media.mountPath }} - - name: WARREN_APP_STATIC_ROOT - value: {{ .Values.persistence.volumes.static.mountPath }} - - name: WARREN_APP_DB_PORT - value: {{ .Values.database.port | quote }} - - name: WARREN_APP_SIGNING_ALGORITHM - value: {{ .Values.signingAlgorithm }} - - name: WARREN_APP_ACCESS_TOKEN_LIFETIME - value: {{ .Values.accessTokenLifetime | quote }} - - name: WARREN_APP_REFRESH_TOKEN_LIFETIME - value: {{ .Values.refreshTokenLifetime | quote }} - - name: WARREN_APP_LTI_ACCESS_TOKEN_LIFETIME - value: {{ .Values.ltiAccessTokenLifetime | quote }} - - name: WARREN_APP_ALLOWED_HOSTS - value: {{ include "app.allowedHosts" . }} - envFrom: - - secretRef: - name: {{ .Values.envVarsSecret | quote }} - {{ with .Values.jobs.collectStatic.command }} - command: - {{- toYaml . | nindent 12 }} - {{- end }} - volumeMounts: - - name: {{ .Values.persistence.volumes.static.name }} - mountPath: {{ .Values.persistence.volumes.static.mountPath }} - {{- with .Values.volumeMounts }} - {{- toYaml . | nindent 12 }} - {{- end }} - restartPolicy: {{ .Values.jobs.collectStatic.restartPolicy }} - volumes: - - name: {{ .Values.persistence.volumes.static.name }} - persistentVolumeClaim: - {{- if .Values.persistence.volumes.static.claimName }} - claimName: {{ .Values.volumes.static.claimName }} - {{- else }} - claimName: {{ include "app.fullname" . }}-static - {{- end }} - {{- with .Values.volumes }} - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/src/helm/warren/charts/app/templates/job_db_migrate.yaml b/src/helm/warren/charts/app/templates/job_db_migrate.yaml deleted file mode 100644 index c8f702d2..00000000 --- a/src/helm/warren/charts/app/templates/job_db_migrate.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ .Values.jobs.dbMigrate.name }}" - labels: - {{- include "app.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install, pre-upgrade -spec: - template: - metadata: - labels: - {{- include "app.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- 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.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: DJANGO_SETTINGS_MODULE - value: {{ .Values.djangoSettingsModule }} - - name: DJANGO_CONFIGURATION - value: {{ .Values.djangoConfiguration }} - - name: WARREN_APP_DB_PORT - value: {{ .Values.database.port | quote }} - - name: WARREN_APP_SIGNING_ALGORITHM - value: {{ .Values.signingAlgorithm }} - - name: WARREN_APP_ACCESS_TOKEN_LIFETIME - value: {{ .Values.accessTokenLifetime | quote }} - - name: WARREN_APP_REFRESH_TOKEN_LIFETIME - value: {{ .Values.refreshTokenLifetime | quote }} - - name: WARREN_APP_LTI_ACCESS_TOKEN_LIFETIME - value: {{ .Values.ltiAccessTokenLifetime | quote }} - - name: WARREN_APP_ALLOWED_HOSTS - value: {{ include "app.allowedHosts" . }} - envFrom: - - secretRef: - name: {{ .Values.envVarsSecret | quote }} - {{ with .Values.jobs.dbMigrate.command }} - command: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.volumeMounts }} - volumeMounts: - {{- toYaml . | nindent 12 }} - {{- end }} - restartPolicy: {{ .Values.jobs.dbMigrate.restartPolicy }} - {{- with .Values.volumes }} - volumes: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/src/helm/warren/charts/app/templates/jobs.yaml b/src/helm/warren/charts/app/templates/jobs.yaml new file mode 100644 index 00000000..4475f105 --- /dev/null +++ b/src/helm/warren/charts/app/templates/jobs.yaml @@ -0,0 +1,42 @@ +{{- range .Values.django.jobs }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "app.fullname" $ }}-{{ .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "app.labels" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{ toYaml $.Values.commonLabels | nindent 4 }} + {{- end }} + annotations: +{{- if $.Values.commonAnnotations }} +{{- toYaml $.Values.commonAnnotations | nindent 4 }} +{{- end }} + "helm.sh/hook": post-upgrade,post-install + "helm.sh/hook-weight": "0" +spec: + template: + metadata: + labels: {{- include "app.selectorLabels" $ | nindent 8 }} + spec: + {{- include "django.imagePullSecrets" $ | nindent 6 }} + containers: + - name: "{{ $.Chart.Name }}-{{ .name }}" + image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + env: + {{- include "app.envs" $ | nindent 12 }} + command: {{ .command | toJson }} + {{- if $.Values.resources }} + resources: {{ toYaml $.Values.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: {{ $.Values.volumes.media.name }} + mountPath: {{ $.Values.volumes.media.mountPath }} + volumes: + - name: {{ $.Values.volumes.media.name }} + persistentVolumeClaim: + claimName: {{ $.Values.volumes.media.claimName }} + restartPolicy: Never +{{- end }} diff --git a/src/helm/warren/charts/app/templates/pvc.yaml b/src/helm/warren/charts/app/templates/pvc.yaml index 7add10f5..6844db2c 100644 --- a/src/helm/warren/charts/app/templates/pvc.yaml +++ b/src/helm/warren/charts/app/templates/pvc.yaml @@ -1,11 +1,9 @@ {{- if .Values.persistence.enabled }} -{{- if not .Values.persistence.volumes.media.claimName }} apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ include "app.fullname" . }}-media - labels: - {{- include "app.labels" . | nindent 4 }} + name: {{ .Values.volumes.media.claimName }} + namespace: {{ .Release.Namespace | quote }} spec: accessModes: {{ with .Values.persistence.accessModes }} @@ -14,22 +12,5 @@ spec: storageClassName: {{ .Values.persistence.storageClass }} resources: requests: - storage: {{ .Values.persistence.volumes.media.size }} -{{- end }} -{{- if not .Values.persistence.volumes.static.claimName }} ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "app.fullname" . }}-static -spec: - accessModes: - {{ with .Values.persistence.accessModes }} - {{- toYaml . | indent 4 }} - {{- end }} - storageClassName: {{ .Values.persistence.storageClass }} - resources: - requests: - storage: {{ .Values.persistence.volumes.static.size }} -{{- end }} + storage: {{ .Values.persistence.size }} {{- end }} diff --git a/src/helm/warren/charts/app/templates/service.yaml b/src/helm/warren/charts/app/templates/service.yaml index a3164fc5..10a7393e 100644 --- a/src/helm/warren/charts/app/templates/service.yaml +++ b/src/helm/warren/charts/app/templates/service.yaml @@ -1,15 +1,17 @@ +--- apiVersion: v1 kind: Service metadata: name: {{ include "app.fullname" . }} - labels: - {{- include "app.labels" . | nindent 4 }} + labels: {{- include "app.labels" . | nindent 4 }} spec: - type: {{ .Values.service.type }} ports: - - port: {{ .Values.service.port }} - targetPort: http + - name: "{{ .Values.nginx.port }}-tcp" + port: {{ .Values.nginx.port }} + targetPort: {{ .Values.nginx.port }} protocol: TCP - name: http - selector: - {{- include "app.selectorLabels" . | nindent 4 }} + {{- if (eq .Values.service.type "NodePort") }} + nodePort: {{ .Values.service.nodePort.http }} + {{- end }} + type: {{ .Values.service.type }} + selector: {{- include "app.selectorLabels" . | nindent 4 }} diff --git a/src/helm/warren/charts/app/values.yaml b/src/helm/warren/charts/app/values.yaml index ea99e7b5..b4539764 100644 --- a/src/helm/warren/charts/app/values.yaml +++ b/src/helm/warren/charts/app/values.yaml @@ -2,144 +2,107 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 - image: repository: fundocker/warren pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. tag: "app-main" +replicaCount: 1 + imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" podAnnotations: {} -podLabels: {} -podCommand: - - "gunicorn" - - "-c" - - "/usr/local/etc/gunicorn/warren.py" - - "warren.wsgi:application" - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -# Secret name to inject as environment variables -envVarsSecret: "warren-app-env" - -jobs: - dbMigrate: - name: "warren-app-db-migrate" - command: - - "python" - - "manage.py" - - "migrate" - - "--no-input" - restartPolicy: Never - collectStatic: - name: "warren-app-collect-static" - command: - - "python" - - "manage.py" - - "collectstatic" - - "--no-input" - restartPolicy: Never service: - type: ClusterIP - port: 8000 + type: NodePort + nodePort: + http: 30080 ingress: - enabled: false - className: "" + enabled: true + class_name: "nginx" + host: "" annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local + tls: + enabled: false + certificateSecretName: warren-app-certificate -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi +persistence: + enabled: true + storageClass: "standard" + accessModes: + - ReadWriteMany + size: 2Gi + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: deployment + operator: In + values: + - "warren-app-app" + topologyKey: kubernetes.io/hostname autoscaling: enabled: false minReplicas: 1 - maxReplicas: 100 + maxReplicas: 10 targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -persistence: - enabled: false - storageClass: "standard" - accessModes: - - ReadWriteOnce - volumes: - media: - name: media - claimName: "" - size: 2Gi - mountPath: /srv/media - static: - name: static - claimName: "" - size: 2Gi - mountPath: /srv/static - -# Additional volumes on the output Deployment definition. -volumes: [] -# - name: foo -# secret: -# secretName: mysecret -# optional: false - -# Additional volumeMounts on the output Deployment definition. -volumeMounts: [] -# - name: foo -# mountPath: "/etc/foo" -# readOnly: true + targetMemoryUtilizationPercentage: 80 nodeSelector: {} tolerations: [] -affinity: {} +volumes: + media: + name: "warren-app-media" + claimName: "warren-app-media-pvc" + mountPath: "/app/media" # Django application configuration -accessTokenLifetime: 300 -allowedHosts: [] -database: - port: 5432 -djangoConfiguration: Production -djangoSettingsModule: warren.settings -ltiAccessTokenLifetime: 86400 -refreshTokenLifetime: 86400 -signingAlgorithm: HS256 -apiRootUrl: "http://localhost:8090" -appRootUrl: "http://localhost:8100" -corsAllowedOrigins: - - "http://localhost:8090" +django: + fullname: app + port: 8080 + settings: "warren.settings" + configuration: "Production" + accessTokenLifetime: "300" + ltiAccessTokenLifetime: "86400" + refreshTokenLifetime: "86400" + signingAlgorithm: "HS256" + apiRootUrl: "http://localhost:8100" + appRootUrl: "http://localhost:8090" + corsAllowedOrigins: + - "http://localhost:8090" + allowedHosts: + - "*" + db: + name: "warren-app" + user: "fun" + host: "warren-postgresql" + port: "5432" + command: + - "gunicorn" + - "--config" + - "/usr/local/etc/gunicorn/warren.py" + - "--bind" + - "0.0.0.0:8080" + - "warren.wsgi:application" + jobs: + - name: dbmigrate + command: + - "python" + - "manage.py" + - "migrate" + - "--no-input" + resources: {} + +env: + secret: [] + +nginx: + port: 8000 diff --git a/src/helm/warren/values.yaml b/src/helm/warren/values.yaml index 031ff5ac..92b71e0c 100644 --- a/src/helm/warren/values.yaml +++ b/src/helm/warren/values.yaml @@ -24,7 +24,7 @@ api: postgresql: # If enabled, a postgresql database will be deployed in the k8s cluster, else # a simple gateway can be used (see the postgresql-gw chart) - enabled: true + enabled: false # Global variables are accessible both from charts and subcharts templates using # the "global" prefix path: {{ .Values.global.var_name }}