From 876475904e5f5bd21c23db26cade67e40b459190 Mon Sep 17 00:00:00 2001
From: Leonardo Rossetti <lrossett@redhat.com>
Date: Jan 31 2022 22:49:57 +0000
Subject: messaging support


---

diff --git a/.gitignore b/.gitignore
index 645e6a2..ac83195 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 *.old
+*.pem
diff --git a/operator/config/components/fedora-messaging/kustomization.yaml b/operator/config/components/fedora-messaging/kustomization.yaml
new file mode 100644
index 0000000..c9ecf04
--- /dev/null
+++ b/operator/config/components/fedora-messaging/kustomization.yaml
@@ -0,0 +1,10 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+secretGenerator:
+- name: resultsdb-messaging-certs
+  files:
+    - ca.pem
+    - cert.pem
+    - key.pem
+generatorOptions:
+  disableNameSuffixHash: true
diff --git a/operator/config/samples/gating_v1alpha1_resultsdb.yaml b/operator/config/samples/gating_v1alpha1_resultsdb.yaml
index a83f480..d682571 100644
--- a/operator/config/samples/gating_v1alpha1_resultsdb.yaml
+++ b/operator/config/samples/gating_v1alpha1_resultsdb.yaml
@@ -7,3 +7,6 @@ spec:
   image: quay.io/fedora-kube-sig/resultsdb:latest
   psql_secret_ref: postgres
   htpasswd_secret_ref: resultsdb-htpasswd
+  messaging_secret_ref: resultsdb-messaging-certs
+  messaging_topic_prefix: org.fedoraproject
+  messaging_env: stg
diff --git a/operator/molecule/default/converge.yml b/operator/molecule/default/converge.yml
index 40a9ab1..fe5940b 100644
--- a/operator/molecule/default/converge.yml
+++ b/operator/molecule/default/converge.yml
@@ -31,6 +31,21 @@
         state: present
         wait: true
 
+    - name: Generate fedora-messaging certs secret
+      command: "kustomize build ."
+      args:
+        chdir: "{{ components_dir }}/fedora-messaging"
+      register: out
+      changed_when: false
+
+    - name: Create the generated fedora-message secret
+      k8s:
+        definition: "{{ out.stdout | from_yaml }}"
+        namespace: "{{ namespace }}"
+        state: present
+        wait: true
+
+
     - import_tasks: kustomize.yml
       vars:
         state: present
diff --git a/operator/molecule/default/tasks/resultsdb_test.yml b/operator/molecule/default/tasks/resultsdb_test.yml
index c69280b..a035b0d 100644
--- a/operator/molecule/default/tasks/resultsdb_test.yml
+++ b/operator/molecule/default/tasks/resultsdb_test.yml
@@ -30,6 +30,22 @@
         fail_msg: Failed to retrieve resultsdb settings secret
 
 - block:
+    - name: Test resultsdb messaging configmap
+      community.kubernetes.k8s_info:
+        api_version: v1
+        kind: ConfigMap
+        name: resultsdb-sample-messaging-config
+        namespace: "{{ namespace }}"
+      register: _k8s_info
+
+    - name: Assert resultsdb settings secret
+      assert:
+        that:
+          - _k8s_info.resources | length == 1
+          - "'config.toml' in _k8s_info.resources[0].data"
+        fail_msg: Failed to retrieve resultsdb messaging configmap
+
+- block:
     - name: Test resultsdb deployment
       community.kubernetes.k8s_info:
         api_version: apps/v1
diff --git a/operator/roles/resultsdb/defaults/main.yml b/operator/roles/resultsdb/defaults/main.yml
index 59a8e97..d87ae99 100644
--- a/operator/roles/resultsdb/defaults/main.yml
+++ b/operator/roles/resultsdb/defaults/main.yml
@@ -5,3 +5,6 @@ resultsdb_psql_secret_ref: "{{ psql_secret_ref | default('resultsdb-psql') }}"
 resultsdb_replicas: "{{ replicas | default(1) | int }}"
 resultsdb_secret_key: "{{ secret_key | default('12345') }}"
 resultsdb_htpasswd_secret_ref: "{{  htpasswd_secret_ref | default('resultsdb-htpasswd') }}"
+resultsdb_messaging_secret_ref: "{{  messaging_secret_ref | default('') }}"
+resultsdb_messaging_topic_prefix: "{{ messaging_topic_prefix | default('org.fedoraproject') }}"
+resultsdb_messaging_env: "{{ menssaging_env | default('stg') }}"
diff --git a/operator/roles/resultsdb/tasks/main.yml b/operator/roles/resultsdb/tasks/main.yml
index 9d45350..ea5fd8b 100644
--- a/operator/roles/resultsdb/tasks/main.yml
+++ b/operator/roles/resultsdb/tasks/main.yml
@@ -18,6 +18,17 @@
   register: _k8s_info_htpasswd
   failed_when: "_k8s_info_htpasswd.resources | length == 0"
 
+- name: Check if messaging cert secret exists
+  community.kubernetes.k8s_info:
+    api_version: v1
+    kind: Secret
+    name: "{{ resultsdb_messaging_secret_ref }}"
+    namespace: "{{ ansible_operator_meta.namespace }}"
+  register: _k8s_info_messaging
+  failed_when:
+    - "_k8s_info_messaging.resources | length == 0"
+    - "'ca.pem' not in k8s_info_messaging.resources[0].data"
+  when: "resultsdb_messaging_secret_ref | length > 0"
 
 - name: Set k8s_info secret variables
   set_fact:
@@ -28,7 +39,7 @@
   community.kubernetes.k8s:
     state: present
     wait: true
-    definition: "{{ lookup('template', 'secret-settings.yaml') }}"
+    definition: "{{ lookup('template', 'secret-settings.yaml.j2') }}"
   vars:
     resultsdb_psql_user: "{{ resultsdb_psql_info.data['POSTGRES_USER'] | b64decode }}"
     resultsdb_psql_password: "{{ resultsdb_psql_info.data['POSTGRES_PASSWORD'] | b64decode }}"
@@ -42,11 +53,17 @@
     wait: true
     definition: "{{ lookup('template', 'configmap-httpd.yaml') }}"
 
+- name: Apply resultsdb messaging configmap
+  community.kubernetes.k8s:
+    state: present
+    wait: true
+    definition: "{{ lookup('template', 'configmap-messaging.yaml.j2') }}"
+
 - name: Apply resultsdb deployment
   community.kubernetes.k8s:
     state: present
     wait: true
-    definition: "{{ lookup('template', 'deployment.yaml') }}"
+    definition: "{{ lookup('template', 'deployment.yaml.j2') }}"
 
 - name: Apply resultsdb service
   community.kubernetes.k8s:
diff --git a/operator/roles/resultsdb/templates/configmap-messaging.yaml.j2 b/operator/roles/resultsdb/templates/configmap-messaging.yaml.j2
new file mode 100644
index 0000000..cd3c957
--- /dev/null
+++ b/operator/roles/resultsdb/templates/configmap-messaging.yaml.j2
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: "resultsdb-{{ ansible_operator_meta.name }}-messaging-config"
+  namespace: "{{ ansible_operator_meta.namespace }}"
+  labels:
+    app: "resultsdb-{{ ansible_operator_meta.name }}"
+data:
+  config.toml: |-
+{% if resultsdb_messaging_env == 'stg' %}
+    amqp_url = "amqps://resultsdb:@rabbitmq.stg.fedoraproject.org/%2Fpubsub"
+{% else %}
+    amqp_url = "amqps://resultsdb:@rabbitmq.fedoraproject.org/%2Fpubsub"
+{% endif %}
+    topic_prefix = "{{ resultsdb_messaging_topic_prefix }}.{{ resultsdb_messaging_env }}"
+
+    [tls]
+    ca_cert = "/etc/pki/fedora-messaging/ca.pem"
+    keyfile = "/etc/pki/fedora-messaging/key.pem"
+    certfile = "/etc/pki/fedora-messaging/cert.pem"
diff --git a/operator/roles/resultsdb/templates/deployment.yaml b/operator/roles/resultsdb/templates/deployment.yaml
deleted file mode 100644
index cbbf784..0000000
--- a/operator/roles/resultsdb/templates/deployment.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: "resultsdb-{{ ansible_operator_meta.name }}"
-  namespace: "{{ ansible_operator_meta.namespace }}"
-  labels:
-    app: "resultsdb-{{ ansible_operator_meta.name }}"
-spec:
-  replicas: {{ resultsdb_replicas }}
-  selector:
-    matchLabels:
-      app: "resultsdb-{{ ansible_operator_meta.name }}"
-  template:
-    metadata:
-      labels:
-        app: "resultsdb-{{ ansible_operator_meta.name }}"
-    spec:
-      initContainers:
-        - name: resultsdb-initdb
-          image: "{{ resultsdb_image }}"
-          command:
-            - /bin/sh
-            - -i
-            - -c
-            - |
-              # try for 10 minutes (600 seconds)
-              e=$(( $(date +%s) + 600 ))
-              i=0
-              while [ $(date +%s) -lt $e ]; do
-                echo 'TRY #'$((++i))
-                if resultsdb init_db ; then
-                  exit 0
-                fi
-              done
-              exit 1
-          volumeMounts:
-            - name: config-volume
-              mountPath: /etc/resultsdb
-              readOnly: true
-      containers:
-        - name: resultsdb
-          image: "{{ resultsdb_image }}"
-          ports:
-            - containerPort: 5001
-          readinessProbe:
-            timeoutSeconds: 1
-            initialDelaySeconds: 5
-            httpGet:
-              path: /api/v2.0/
-              port: 5001
-          livenessProbe:
-            timeoutSeconds: 1
-            initialDelaySeconds: 30
-            httpGet:
-              path: /api/v2.0/
-              port: 5001
-          volumeMounts:
-            - name: config-volume
-              mountPath: /etc/resultsdb
-              readOnly: true
-            - name: htpasswd-volume
-              mountPath: /etc/httpd/auth
-              readOnly: true
-            - name: httpd-config
-              mountPath: /etc/httpd/conf.d
-              readOnly: true
-      volumes:
-        - name: config-volume
-          secret:
-            secretName: resultsdb-{{ ansible_operator_meta.name }}-config
-        - name: htpasswd-volume
-          secret:
-            secretName: {{ resultsdb_htpasswd_secret_ref }}
-        - name: httpd-config
-          configMap:
-            name: resultsdb-{{ ansible_operator_meta.name }}-httpd-config
diff --git a/operator/roles/resultsdb/templates/deployment.yaml.j2 b/operator/roles/resultsdb/templates/deployment.yaml.j2
new file mode 100644
index 0000000..b847efb
--- /dev/null
+++ b/operator/roles/resultsdb/templates/deployment.yaml.j2
@@ -0,0 +1,92 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: "resultsdb-{{ ansible_operator_meta.name }}"
+  namespace: "{{ ansible_operator_meta.namespace }}"
+  labels:
+    app: "resultsdb-{{ ansible_operator_meta.name }}"
+spec:
+  replicas: {{ resultsdb_replicas }}
+  selector:
+    matchLabels:
+      app: "resultsdb-{{ ansible_operator_meta.name }}"
+  template:
+    metadata:
+      labels:
+        app: "resultsdb-{{ ansible_operator_meta.name }}"
+    spec:
+      initContainers:
+        - name: resultsdb-initdb
+          image: "{{ resultsdb_image }}"
+          command:
+            - /bin/sh
+            - -i
+            - -c
+            - |
+              # try for 10 minutes (600 seconds)
+              e=$(( $(date +%s) + 600 ))
+              i=0
+              while [ $(date +%s) -lt $e ]; do
+                echo 'TRY #'$((++i))
+                if resultsdb init_db ; then
+                  exit 0
+                fi
+              done
+              exit 1
+          volumeMounts:
+            - name: config-volume
+              mountPath: /etc/resultsdb
+              readOnly: true
+      containers:
+        - name: resultsdb
+          image: "{{ resultsdb_image }}"
+          ports:
+            - containerPort: 5001
+          readinessProbe:
+            timeoutSeconds: 1
+            initialDelaySeconds: 5
+            httpGet:
+              path: /api/v2.0/
+              port: 5001
+          livenessProbe:
+            timeoutSeconds: 1
+            initialDelaySeconds: 30
+            httpGet:
+              path: /api/v2.0/
+              port: 5001
+          volumeMounts:
+            - name: config-volume
+              mountPath: /etc/resultsdb
+              readOnly: true
+            - name: htpasswd-volume
+              mountPath: /etc/httpd/auth
+              readOnly: true 
+            - name: httpd-config
+              mountPath: /etc/httpd/conf.d
+              readOnly: true
+{% if resultsdb_messaging_secret_ref | length > 0 %}
+            - name: messaging-config
+              mountPath: /etc/fedora-messaging
+              readOnly: true
+            - name: messaging-certs-volume
+              mountPath: /etc/pki/fedora-messaging
+              readOnly: true
+{% endif %}
+      volumes:
+        - name: config-volume
+          secret:
+            secretName: resultsdb-{{ ansible_operator_meta.name }}-config
+        - name: htpasswd-volume
+          secret:
+            secretName: {{ resultsdb_htpasswd_secret_ref }} 
+        - name: httpd-config
+          configMap:
+            name: resultsdb-{{ ansible_operator_meta.name }}-httpd-config
+{% if resultsdb_messaging_secret_ref | length > 0 %}
+        - name: messaging-certs-volume
+          secret:
+            secretName: {{ resultsdb_messaging_secret_ref }}
+        - name: messaging-config
+          configMap:
+            name: "resultsdb-{{ ansible_operator_meta.name }}-messaging-config"
+{% endif  %}
diff --git a/operator/roles/resultsdb/templates/secret-settings.yaml b/operator/roles/resultsdb/templates/secret-settings.yaml
deleted file mode 100644
index 37c7360..0000000
--- a/operator/roles/resultsdb/templates/secret-settings.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
-  name: "resultsdb-{{ ansible_operator_meta.name }}-config"
-  namespace: "{{ ansible_operator_meta.namespace }}"
-  labels:
-    app: "resultsdb-{{ ansible_operator_meta.name }}"
-stringData:
-  settings.py: |-
-    SECRET_KEY = '{{ resultsdb_secret_key }}'
-    SQLALCHEMY_DATABASE_URI='postgresql+psycopg2://{{ resultsdb_psql_user }}:{{ resultsdb_psql_password }}@{{ resultsdb_psql_host }}:{{ resultsdb_psql_port }}/{{ resultsdb_psql_db }}'
-
-    FILE_LOGGING = False
-    LOGFILE = '/var/log/resultsdb/resultsdb.log'
-    SYSLOG_LOGGING = False
-    STREAM_LOGGING = True
-    RUN_HOST= '0.0.0.0'
-    RUN_PORT = 5001
-
-    MESSAGE_BUS_PUBLISH = False
-    MESSAGE_BUS_PUBLISH_TASKOTRON = False
-    MESSAGE_BUS_PLUGIN = 'fedmsg'
-
-    MESSAGE_BUS_KWARGS = {'modname': 'resultsdb'}
-    ADDITIONAL_RESULT_OUTCOMES = ['CRASHED', 'QUEUED', 'RUNNING']
diff --git a/operator/roles/resultsdb/templates/secret-settings.yaml.j2 b/operator/roles/resultsdb/templates/secret-settings.yaml.j2
new file mode 100644
index 0000000..255cbaf
--- /dev/null
+++ b/operator/roles/resultsdb/templates/secret-settings.yaml.j2
@@ -0,0 +1,31 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: "resultsdb-{{ ansible_operator_meta.name }}-config"
+  namespace: "{{ ansible_operator_meta.namespace }}"
+  labels:
+    app: "resultsdb-{{ ansible_operator_meta.name }}"
+stringData:
+  settings.py: |-
+    SECRET_KEY = '{{ resultsdb_secret_key }}'
+    SQLALCHEMY_DATABASE_URI='postgresql+psycopg2://{{ resultsdb_psql_user }}:{{ resultsdb_psql_password }}@{{ resultsdb_psql_host }}:{{ resultsdb_psql_port }}/{{ resultsdb_psql_db }}'
+
+    FILE_LOGGING = False
+    LOGFILE = '/var/log/resultsdb/resultsdb.log'
+    SYSLOG_LOGGING = False
+    STREAM_LOGGING = True
+    RUN_HOST= '0.0.0.0'
+    RUN_PORT = 5001
+
+{% if resultsdb_messaging_secret_ref|length > 0 %}
+    MESSAGE_BUS_PUBLISH = True
+    MESSAGE_BUS_PUBLISH_TASKOTRON = True
+    MESSAGE_BUS_PLUGIN = 'fedmsg'
+{% else  %}
+    MESSAGE_BUS_PUBLISH = False
+    MESSAGE_BUS_PUBLISH_TASKOTRON = False
+    MESSAGE_BUS_PLUGIN = 'fedmsg'
+{% endif %}
+
+    MESSAGE_BUS_KWARGS = {'modname': 'resultsdb'}
+    ADDITIONAL_RESULT_OUTCOMES = ['CRASHED', 'QUEUED', 'RUNNING']

