Skip to content

swh: Support dynamic webapp configuration

Vincent Sellier requested to merge webapp into production

This inlines the webapp configuration as we do for other templates. So we can reuse most of the existing "configurationRef".

This also adds the cronjob to update the save-code-now statuses (currently implemented as a timer in the static infra).

New secrets have been added in the k8s-private-data for {production,staging}-cassandra.yaml & minikube. So this can be merged. There will be redeployment as the order in the configmap is surely different than what's currently deployed (so hash is different so it will be rolling upgraded). But the resulting deployment will be equivalent nonetheless.

Tests are happy:

  • make minikube
  • make swh-helm-diff [1]
  • make swh-test

[1]

make swh-helm-diff
[swh] Comparing changes between branches production and webapp...
Switched to branch 'production'
Your branch is up to date with 'origin/production'.
[swh] Generate config in production branch for swh/values/default.yaml...
[swh] Generate config in production branch for swh/values/minikube.yaml...
[swh] Generate config in production branch for swh/values/production-cassandra.yaml...
[swh] Generate config in production branch for swh/values/production.yaml...
[swh] Generate config in production branch for swh/values/staging-cassandra.yaml...
[swh] Generate config in production branch for swh/values/staging.yaml...
Switched to branch 'webapp'
Your branch is ahead of 'origin/webapp' by 1 commit.
  (use "git push" to publish your local commits)
[swh] Generate config in webapp branch for swh/values/default.yaml...
[swh] Generate config in webapp branch for swh/values/minikube.yaml...
[swh] Generate config in webapp branch for swh/values/production-cassandra.yaml...
[swh] Generate config in webapp branch for swh/values/production.yaml...
[swh] Generate config in webapp branch for swh/values/staging-cassandra.yaml...
[swh] Generate config in webapp branch for swh/values/staging.yaml...


------------- diff for swh/values/default.yaml -------------

No differences


------------- diff for swh/values/minikube.yaml -------------

No differences


------------- diff for swh/values/production-cassandra.yaml -------------

--- /tmp/swh-chart.swh.G891rP93/production-cassandra.yaml.before        2023-10-05 12:19:21.384028588 +0200
+++ /tmp/swh-chart.swh.G891rP93/production-cassandra.yaml.after 2023-10-05 12:19:22.548029743 +0200
@@ -893,20 +893,138 @@
     if [ -e "${DB_VERSION}" ]; then
       echo "Unable to find the code version"
       exit 1
     fi

     if [ "$DB_VERSION" -ne "$CODE_VERSION" ]; then
       echo "code and DB versions are different. Blocking the deployment"
       exit 1
     fi
 ---
+# Source: swh/templates/web/configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: swh-cassandra
+  name: web-configuration-template
+data:
+  config.yml.template: |
+    storage:
+      cls: remote
+      url: http://storage:5002
+    search:
+      cls: remote
+      url: http://moma.internal.softwareheritage.org:5010
+    scheduler:
+      cls: remote
+      url: http://scheduler.internal.softwareheritage.org:80
+    vault:
+      cls: remote
+      url: http://vangogh.euwest.azure.internal.softwareheritage.org:5005/
+    indexer_storage:
+      cls: remote
+      url: http://saam.internal.softwareheritage.org:5007/
+    counters_backend: swh-counters
+    counters:
+      cls: remote
+      url: http://counters1.internal.softwareheritage.org:5011/
+
+    secret_key: ${DJANGO_SECRET_KEY}
+    client_config:
+      sentry_dsn: ${SWH_SENTRY_DSN}
+    throttling:
+      cache_uri: memcached:11211
+      scopes:
+        swh_api:
+          exempted_networks:
+          - 10.42.0.0/16
+          - 10.43.0.0/16
+          - 127.0.0.0/8
+          - 128.93.166.14
+          - 131.107.174.0/24
+          - 192.168.100.0/24
+          - 192.168.200.0/22
+          - 213.135.60.145
+          - 213.135.60.146
+          - 37.187.137.47
+          - 37.187.96.121
+          limiter_rate:
+            default: 120/h
+        swh_save_origin:
+          exempted_networks:
+          - 10.42.0.0/16
+          - 10.43.0.0/16
+          - 127.0.0.0/8
+          - 128.93.166.14
+          - 131.107.174.0/24
+          - 192.168.100.0/24
+          - 192.168.200.0/22
+          - 213.135.60.145
+          - 213.135.60.146
+          - 37.187.96.121
+          limiter_rate:
+            POST: 10/h
+            default: 120/h
+        swh_vault_cooking:
+          exempted_networks:
+          - 10.42.0.0/16
+          - 10.43.0.0/16
+          - 127.0.0.0/8
+          - 128.93.166.14
+          - 131.107.174.0/24
+          - 192.168.100.0/24
+          - 192.168.200.0/22
+          - 213.135.60.145
+          - 213.135.60.146
+          - 37.187.96.121
+          limiter_rate:
+            GET: 60/m
+            default: 120/h
+        swh_api_origin_search:
+          limiter_rate:
+            default: 10/m
+        swh_api_origin_visit_latest:
+          limiter_rate:
+            default: 700/m
+        swh_raw_object:
+          limiter_rate:
+            default: 120/h
+    add_forge_now:
+      email_address: add-forge-now@archive.softwareheritage.org
+    allowed_hosts:
+    - webapp-cassandra.internal.softwareheritage.org
+    content_display_max_size: 5242880
+    es_workers_index_url: http://esnode1.internal.softwareheritage.org:9200/swh_workers-*
+    give:
+      public_key: ${GIVE_PUBLIC_KEY}
+      token: ${GIVE_PRIVATE_TOKEN}
+    history_counters_url: http://counters1.internal.softwareheritage.org:5011/counters_history/history.json#
+    instance_name: webapp-cassandra.internal.softwareheritage.org
+    keycloak:
+      realm_name: SoftwareHeritage
+      server_url: https://auth.softwareheritage.org/auth/
+    search_config:
+      metadata_backend: swh-search
+    swh_extra_django_apps:
+    - swh.web.add_forge_now
+    - swh.web.archive_coverage
+    - swh.web.badges
+    - swh.web.banners
+    - swh.web.deposit
+    - swh.web.inbound_email
+    - swh.web.jslicenses
+    - swh.web.mailmap
+    - swh.web.metrics
+    - swh.web.save_code_now
+    - swh.web.save_origin_webhooks
+    - swh.web.vault
+---
 # Source: swh/charts/keda/templates/crds/crd-clustertriggerauthentications.yaml
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.12.0
   labels:
     app.kubernetes.io/name: keda-operator
     helm.sh/chart: keda-2.11.0
     app.kubernetes.io/component: operator
@@ -12539,64 +12657,101 @@
     matchLabels:
       app: web
   strategy:
     type: RollingUpdate
     rollingUpdate:
       maxSurge: 1
   template:
     metadata:
       labels:
         app: web
+      annotations:
+        checksum/config: a2002452e950674e079d529d30d26ca9647cecfe1d5407c97dfca676baff6bd9
     spec:
       affinity:
         nodeAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
             nodeSelectorTerms:
             - matchExpressions:
               - key: swh/web
                 operator: In
                 values:
                 - "true"
       priorityClassName: swh-cassandra-frontend-rpc

       initContainers:
-      #  - name: prepare-configuration
-      #    image: debian:bullseye
-      #    imagePullPolicy: IfNotPresent
-      #    command:
-      #    - /bin/bash
-      #    args:
-      #    - -c
-      #    - eval echo "\"$(</etc/softwareheritage/configuration-template/config.yml.template)\"" > /etc/softwareheritage/config.yml
-      #    volumeMounts:
-      #    - name: configuration
-      #      mountPath: /etc/softwareheritage
-      #    - name: configuration-template
-      #      mountPath: /etc/softwareheritage/configuration-template
+        - name: prepare-configuration
+          image: debian:bullseye
+          imagePullPolicy: IfNotPresent
+          command:
+            - /bin/bash
+          args:
+            - -c
+            - eval echo "\"$(</etc/swh/configuration-template/config.yml.template)\"" > /etc/swh/config.yml
+          env:
+
+            - name: DJANGO_SECRET_KEY
+              valueFrom:
+                secretKeyRef:
+                  name:
+                  key: webapp-django-secret-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
+
+            - name: GIVE_PRIVATE_TOKEN
+              valueFrom:
+                secretKeyRef:
+                  name: web-give-secrets
+                  key: private-token
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+            - name: GIVE_PUBLIC_KEY
+              valueFrom:
+                secretKeyRef:
+                  name: web-give-secrets
+                  key: public-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
+            - name: SWH_SENTRY_DSN
+              valueFrom:
+                secretKeyRef:
+                  name: common-secrets
+                  key: web-sentry-dsn
+                  # 'name' secret should exist & include key
+                  # if the setting doesn't exist, sentry pushes will be disabled
+                  optional: false
+
+          volumeMounts:
+            - name: configuration
+              mountPath: /etc/swh
+            - name: configuration-template
+              mountPath: /etc/swh/configuration-template
         - name: prepare-static
-          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231003.1
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
           imagePullPolicy: IfNotPresent
           command:
-          - /bin/bash
+            - /bin/bash
           args:
-          - -c
-          - cp -r $PWD/.local/share/swh/web/static/ /usr/share/swh/web/static/
+            - -c
+            - cp -r $PWD/.local/share/swh/web/static/ /usr/share/swh/web/static/
           volumeMounts:
           - name: static
             mountPath: /usr/share/swh/web/static
       containers:
         - name: web
           resources:
             requests:
               memory: 500Mi
               cpu: 500m
-          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231003.1
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 5004
               name: webapp
           readinessProbe:
             httpGet:
               path: /
               port: webapp
               httpHeaders:
                 - name: Host
@@ -12609,48 +12764,59 @@
             httpGet:
               path: /
               port: webapp
               httpHeaders:
                 - name: Host
                   value: webapp-cassandra.internal.softwareheritage.org
             initialDelaySeconds: 3
             periodSeconds: 10
             timeoutSeconds: 30
           command:
-          - /bin/bash
+            - /bin/bash
           args:
-          - -c
-          - /srv/swh/entrypoint.sh
+            - -c
+            - /opt/swh/entrypoint.sh
           env:
             - name: STATSD_HOST
               value: prometheus-statsd-exporter
             - name: STATSD_PORT
               value: "9125"
             - name: LOG_LEVEL
               value: "INFO"
+            - name: SWH_CONFIG_FILENAME
+              value: /etc/swh/config.yml
             - name: SWH_SENTRY_ENVIRONMENT
               value: production
             - name: SWH_MAIN_PACKAGE
               value: swh.web
             - name: SWH_SENTRY_DSN
               valueFrom:
                 secretKeyRef:
                   name: common-secrets
                   key: web-sentry-dsn
                   # 'name' secret should exist & include key
                   # if the setting doesn't exist, sentry pushes will be disabled
                   optional: true
             - name: SWH_SENTRY_DISABLE_LOGGING_EVENTS
               value: "true"
+
+            - name: DJANGO_SECRET_KEY
+              valueFrom:
+                secretKeyRef:
+                  name:
+                  key: webapp-django-secret-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
           volumeMounts:
           - name: configuration
-            mountPath: /etc/softwareheritage
+            mountPath: /etc/swh
             readOnly: true
         - name: nginx
           resources:
             requests:
               memory: 500Mi
               cpu: 500m
           image: nginx:bullseye
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 80
@@ -12661,40 +12827,32 @@
               port: webstatic
             initialDelaySeconds: 5
             failureThreshold: 30
             periodSeconds: 10
           livenessProbe:
             httpGet:
               path: static/robots.txt
               port: webstatic
             initialDelaySeconds: 3
             periodSeconds: 10
-        #  command:
-        #  - /bin/bash
-        #  args:
-        #  - -c
-        #  - /srv/swh/entrypoint.sh
           volumeMounts:
-          - name: static
-            mountPath: /usr/share/nginx/html
+            - name: static
+              mountPath: /usr/share/nginx/html
       volumes:
       - name: configuration
-        secret:
-          secretName: swh-cassandra-webapp-config
-      #- name: configuration
-      #  emptyDir: {}
-      #- name: configuration-template
-      #  configMap:
-      #    name: web-configuration-template
-      #    items:
-      #    - key: "config.yml.template"
-      #      path: "config.yml.template"
+        emptyDir: {}
+      - name: configuration-template
+        configMap:
+         name: web-configuration-template
+         items:
+         - key: "config.yml.template"
+           path: "config.yml.template"
       - name: static
         emptyDir: {}
 ---
 # Source: swh/templates/graphql/ingress.yaml
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   namespace: swh-cassandra
   name: graphql-ingress
   annotations:


------------- diff for swh/values/production.yaml -------------

No differences


------------- diff for swh/values/staging-cassandra.yaml -------------

--- /tmp/swh-chart.swh.G891rP93/staging-cassandra.yaml.before   2023-10-05 12:19:21.876029077 +0200
+++ /tmp/swh-chart.swh.G891rP93/staging-cassandra.yaml.after    2023-10-05 12:19:23.028030220 +0200
@@ -3425,20 +3425,81 @@
     if [ -e "${DB_VERSION}" ]; then
       echo "Unable to find the code version"
       exit 1
     fi

     if [ "$DB_VERSION" -ne "$CODE_VERSION" ]; then
       echo "code and DB versions are different. Blocking the deployment"
       exit 1
     fi
 ---
+# Source: swh/templates/web/configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: swh-cassandra
+  name: web-configuration-template
+data:
+  config.yml.template: |
+    storage:
+      cls: remote
+      url: http://storage:5002
+    search:
+      cls: remote
+      url: http://search0.internal.staging.swh.network:5010
+    scheduler:
+      cls: remote
+      url: http://scheduler.internal.staging.swh.network:80
+    vault:
+      cls: remote
+      url: http://vault.internal.staging.swh.network:5005/
+    indexer_storage:
+      cls: remote
+      url: http://storage1.internal.staging.swh.network:5007/
+    counters_backend: swh-counters
+    counters:
+      cls: remote
+      url: http://counters0.internal.staging.swh.network:5011/
+
+    secret_key: ${DJANGO_SECRET_KEY}
+    client_config:
+      sentry_dsn: ${SWH_SENTRY_DSN}
+    add_forge_now:
+      email_address: add-forge-now@webapp.staging.swh.network
+    allowed_hosts:
+    - webapp-cassandra.internal.staging.swh.network
+    content_display_max_size: 5242880
+    give:
+      public_key: ${GIVE_PUBLIC_KEY}
+      token: ${GIVE_PRIVATE_TOKEN}
+    history_counters_url: http://counters0.internal.staging.swh.network:5011/counters_history/history.json
+    instance_name: webapp-cassandra.internal.staging.swh.network
+    keycloak:
+      realm_name: SoftwareHeritageStaging
+      server_url: https://auth.softwareheritage.org/auth/
+    matomo: {}
+    search_config:
+      metadata_backend: swh-search
+    swh_extra_django_apps:
+    - swh.web.add_forge_now
+    - swh.web.archive_coverage
+    - swh.web.badges
+    - swh.web.banners
+    - swh.web.deposit
+    - swh.web.inbound_email
+    - swh.web.jslicenses
+    - swh.web.mailmap
+    - swh.web.metrics
+    - swh.web.save_code_now
+    - swh.web.save_origin_webhooks
+    - swh.web.vault
+---
 # Source: swh/charts/keda/templates/crds/crd-clustertriggerauthentications.yaml
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.12.0
   labels:
     app.kubernetes.io/name: keda-operator
     helm.sh/chart: keda-2.11.0
     app.kubernetes.io/component: operator
@@ -19371,64 +19432,101 @@
     matchLabels:
       app: web
   strategy:
     type: RollingUpdate
     rollingUpdate:
       maxSurge: 1
   template:
     metadata:
       labels:
         app: web
+      annotations:
+        checksum/config: 5d5e556085b982849f17c80c17f7e3cb894b17886ce4e33c4d1918bf9a04beac
     spec:
       affinity:
         nodeAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
             nodeSelectorTerms:
             - matchExpressions:
               - key: swh/web
                 operator: In
                 values:
                 - "true"
       priorityClassName: swh-cassandra-frontend-rpc

       initContainers:
-      #  - name: prepare-configuration
-      #    image: debian:bullseye
-      #    imagePullPolicy: IfNotPresent
-      #    command:
-      #    - /bin/bash
-      #    args:
-      #    - -c
-      #    - eval echo "\"$(</etc/softwareheritage/configuration-template/config.yml.template)\"" > /etc/softwareheritage/config.yml
-      #    volumeMounts:
-      #    - name: configuration
-      #      mountPath: /etc/softwareheritage
-      #    - name: configuration-template
-      #      mountPath: /etc/softwareheritage/configuration-template
+        - name: prepare-configuration
+          image: debian:bullseye
+          imagePullPolicy: IfNotPresent
+          command:
+            - /bin/bash
+          args:
+            - -c
+            - eval echo "\"$(</etc/swh/configuration-template/config.yml.template)\"" > /etc/swh/config.yml
+          env:
+
+            - name: DJANGO_SECRET_KEY
+              valueFrom:
+                secretKeyRef:
+                  name:
+                  key: webapp-django-secret-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
+
+            - name: GIVE_PRIVATE_TOKEN
+              valueFrom:
+                secretKeyRef:
+                  name: web-give-secrets
+                  key: private-token
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+            - name: GIVE_PUBLIC_KEY
+              valueFrom:
+                secretKeyRef:
+                  name: web-give-secrets
+                  key: public-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
+            - name: SWH_SENTRY_DSN
+              valueFrom:
+                secretKeyRef:
+                  name: common-secrets
+                  key: web-sentry-dsn
+                  # 'name' secret should exist & include key
+                  # if the setting doesn't exist, sentry pushes will be disabled
+                  optional: false
+
+          volumeMounts:
+            - name: configuration
+              mountPath: /etc/swh
+            - name: configuration-template
+              mountPath: /etc/swh/configuration-template
         - name: prepare-static
-          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231003.1
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
           imagePullPolicy: IfNotPresent
           command:
-          - /bin/bash
+            - /bin/bash
           args:
-          - -c
-          - cp -r $PWD/.local/share/swh/web/static/ /usr/share/swh/web/static/
+            - -c
+            - cp -r $PWD/.local/share/swh/web/static/ /usr/share/swh/web/static/
           volumeMounts:
           - name: static
             mountPath: /usr/share/swh/web/static
       containers:
         - name: web
           resources:
             requests:
               memory: 500Mi
               cpu: 500m
-          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231003.1
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 5004
               name: webapp
           readinessProbe:
             httpGet:
               path: /
               port: webapp
               httpHeaders:
                 - name: Host
@@ -19441,48 +19539,59 @@
             httpGet:
               path: /
               port: webapp
               httpHeaders:
                 - name: Host
                   value: webapp-cassandra.internal.staging.swh.network
             initialDelaySeconds: 3
             periodSeconds: 10
             timeoutSeconds: 30
           command:
-          - /bin/bash
+            - /bin/bash
           args:
-          - -c
-          - /srv/swh/entrypoint.sh
+            - -c
+            - /opt/swh/entrypoint.sh
           env:
             - name: STATSD_HOST
               value: prometheus-statsd-exporter
             - name: STATSD_PORT
               value: "9125"
             - name: LOG_LEVEL
               value: "INFO"
+            - name: SWH_CONFIG_FILENAME
+              value: /etc/swh/config.yml
             - name: SWH_SENTRY_ENVIRONMENT
               value: staging
             - name: SWH_MAIN_PACKAGE
               value: swh.web
             - name: SWH_SENTRY_DSN
               valueFrom:
                 secretKeyRef:
                   name: common-secrets
                   key: web-sentry-dsn
                   # 'name' secret should exist & include key
                   # if the setting doesn't exist, sentry pushes will be disabled
                   optional: true
             - name: SWH_SENTRY_DISABLE_LOGGING_EVENTS
               value: "true"
+
+            - name: DJANGO_SECRET_KEY
+              valueFrom:
+                secretKeyRef:
+                  name:
+                  key: webapp-django-secret-key
+                  # 'name' secret must exist & include that ^ key
+                  optional: false
+
           volumeMounts:
           - name: configuration
-            mountPath: /etc/softwareheritage
+            mountPath: /etc/swh
             readOnly: true
         - name: nginx
           resources:
             requests:
               memory: 500Mi
               cpu: 500m
           image: nginx:bullseye
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 80
@@ -19493,40 +19602,32 @@
               port: webstatic
             initialDelaySeconds: 5
             failureThreshold: 30
             periodSeconds: 10
           livenessProbe:
             httpGet:
               path: static/robots.txt
               port: webstatic
             initialDelaySeconds: 3
             periodSeconds: 10
-        #  command:
-        #  - /bin/bash
-        #  args:
-        #  - -c
-        #  - /srv/swh/entrypoint.sh
           volumeMounts:
-          - name: static
-            mountPath: /usr/share/nginx/html
+            - name: static
+              mountPath: /usr/share/nginx/html
       volumes:
       - name: configuration
-        secret:
-          secretName: swh-cassandra-webapp-config
-      #- name: configuration
-      #  emptyDir: {}
-      #- name: configuration-template
-      #  configMap:
-      #    name: web-configuration-template
-      #    items:
-      #    - key: "config.yml.template"
-      #      path: "config.yml.template"
+        emptyDir: {}
+      - name: configuration-template
+        configMap:
+         name: web-configuration-template
+         items:
+         - key: "config.yml.template"
+           path: "config.yml.template"
       - name: static
         emptyDir: {}
 ---
 # Source: swh/templates/storage/autoscaling.yaml
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   namespace: swh-cassandra
   name: storage
   labels:


------------- diff for swh/values/staging.yaml -------------

No differences

Note: Diff with a cheat (with an local extra commit not present in the MR to keep the old :80 port on the remote scheduler url to reduce the noise)

Refs. swh/infra/sysadm-environment#4812 (closed)

Edited by Antoine R. Dumont

Merge request reports