From a43a93a8757b6eed3340659f4278c217e2da32ea Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 30 Jan 2025 16:54:08 +0100
Subject: [PATCH] fix browser setup & merging in defaults

---
 src/main/cljc/dda/c4k_forgejo/core.cljc      | 61 ++++++-------
 src/main/cljc/dda/c4k_forgejo/forgejo.cljc   | 24 ++---
 src/main/cljs/dda/c4k_forgejo/browser.cljs   | 92 ++++++--------------
 src/test/cljc/dda/c4k_forgejo/core_test.cljc | 13 ++-
 4 files changed, 82 insertions(+), 108 deletions(-)

diff --git a/src/main/cljc/dda/c4k_forgejo/core.cljc b/src/main/cljc/dda/c4k_forgejo/core.cljc
index 2a1d136..b753784 100644
--- a/src/main/cljc/dda/c4k_forgejo/core.cljc
+++ b/src/main/cljc/dda/c4k_forgejo/core.cljc
@@ -20,10 +20,9 @@
                       :pv-storage-size-gb 5
                       :pvc-storage-class-name ""
                       :postgres-image "postgres:14"
-                      :postgres-size :2gb})
-
-(def rate-limit-defaults {:max-rate 10, :max-concurrent-requests 5})
-
+                      :postgres-size :2gb
+                      :max-rate 10, 
+                      :max-concurrent-requests 5})
 
 (def config? (s/keys :req-un [::forgejo/fqdn
                               ::forgejo/mailer-from
@@ -48,40 +47,42 @@
 
 (defn-spec config-objects p/map-or-seq?
   [config config?]
-  (let [storage-class (if (contains? config :postgres-data-volume-path) :manual :local-path)]
+  (let [resolved-config (merge config-defaults config)
+        storage-class (if (contains? resolved-config :postgres-data-volume-path) :manual :local-path)]
     (map yaml/to-string
          (filter #(not (nil? %))
                  (cm/concat-vec
-                  (ns/generate config)
-                  [(postgres/generate-configmap config)
-                   (when (contains? config :postgres-data-volume-path)
-                     (postgres/generate-persistent-volume (select-keys config [:postgres-data-volume-path :pv-storage-size-gb])))
-                   (postgres/generate-pvc (merge config {:pvc-storage-class-name storage-class}))
-                   (postgres/generate-deployment config)
-                   (postgres/generate-service config)
-                   (forgejo/generate-deployment config)
+                  (ns/generate resolved-config)
+                  [(postgres/generate-configmap resolved-config)
+                   (when (contains? resolved-config :postgres-data-volume-path)
+                     (postgres/generate-persistent-volume (select-keys resolved-config [:postgres-data-volume-path :pv-storage-size-gb])))
+                   (postgres/generate-pvc (merge resolved-config {:pvc-storage-class-name storage-class}))
+                   (postgres/generate-deployment resolved-config)
+                   (postgres/generate-service resolved-config)
+                   (forgejo/generate-deployment resolved-config)
                    (forgejo/generate-service)
                    (forgejo/generate-service-ssh)
-                   (forgejo/generate-data-volume config)
-                   (forgejo/generate-appini-env config)]
-                  (forgejo/generate-ratelimit-ingress-and-cert config) ; this function has a vector as output
-                  (when (contains? config :restic-repository)
-                    [(backup/generate-config config)
+                   (forgejo/generate-data-volume resolved-config)
+                   (forgejo/generate-appini-env resolved-config)]
+                  (forgejo/generate-ratelimit-ingress-and-cert resolved-config) ; this function has a vector as output
+                  (when (contains? resolved-config :restic-repository)
+                    [(backup/generate-config resolved-config)
                      (backup/generate-cron)
-                     (backup/generate-backup-restore-deployment config)])
-                  (when (contains? config :mon-cfg)
+                     (backup/generate-backup-restore-deployment resolved-config)])
+                  (when (contains? resolved-config :mon-cfg)
                     (mon/generate-config)))))))
 
 (defn-spec auth-objects p/map-or-seq?
   [config config?
    auth auth?]
-  (map yaml/to-string
-       (filter #(not (nil? %))
-               (cm/concat-vec
-                (ns/generate config)
-                [(postgres/generate-secret config auth)
-                 (forgejo/generate-secrets auth)]
-                (when (contains? config :restic-repository)
-                  [(backup/generate-secret auth)])
-                (when (contains? config :mon-cfg)
-                  (mon/generate-auth (:mon-cfg config) (:mon-auth auth)))))))
+  (let [resolved-config (merge config-defaults config)]
+    (map yaml/to-string
+         (filter #(not (nil? %))
+                 (cm/concat-vec
+                  (ns/generate resolved-config)
+                  [(postgres/generate-secret resolved-config auth)
+                   (forgejo/generate-secrets auth)]
+                  (when (contains? resolved-config :restic-repository)
+                    [(backup/generate-secret auth)])
+                  (when (contains? resolved-config :mon-cfg)
+                    (mon/generate-auth (:mon-cfg resolved-config) (:mon-auth auth))))))))
diff --git a/src/main/cljc/dda/c4k_forgejo/forgejo.cljc b/src/main/cljc/dda/c4k_forgejo/forgejo.cljc
index 357f3cb..971ae9e 100644
--- a/src/main/cljc/dda/c4k_forgejo/forgejo.cljc
+++ b/src/main/cljc/dda/c4k_forgejo/forgejo.cljc
@@ -100,18 +100,18 @@
         federation-enabled-bool (boolean-from-string federation-enabled)]
     (->
      (yaml/load-as-edn "forgejo/appini-env-configmap.yaml")
-     (cm/replace-all-matching-values-by-new-value "APPNAME" default-app-name)
-     (cm/replace-all-matching-values-by-new-value "FQDN" fqdn)
-     (cm/replace-all-matching-values-by-new-value "URL" (str "https://" fqdn))
-     (cm/replace-all-matching-values-by-new-value "FROM" mailer-from)
-     (cm/replace-all-matching-values-by-new-value "MAILERHOST" mailer-host)
-     (cm/replace-all-matching-values-by-new-value "MAILERPORT" mailer-port)
-     (cm/replace-all-matching-values-by-new-value "WHITELISTDOMAINS" service-domain-whitelist)
-     (cm/replace-all-matching-values-by-new-value "NOREPLY" service-noreply-address)
-     (cm/replace-all-matching-values-by-new-value "IS_FEDERATED"
-                                                  (if federation-enabled-bool
-                                                    "true"
-                                                    "false")))))
+     (cm/replace-all-matching "APPNAME" default-app-name)
+     (cm/replace-all-matching "FQDN" fqdn)
+     (cm/replace-all-matching "URL" (str "https://" fqdn))
+     (cm/replace-all-matching "FROM" mailer-from)
+     (cm/replace-all-matching "MAILERHOST" mailer-host)
+     (cm/replace-all-matching "MAILERPORT" mailer-port)
+     (cm/replace-all-matching "WHITELISTDOMAINS" service-domain-whitelist)
+     (cm/replace-all-matching "NOREPLY" service-noreply-address)
+     (cm/replace-all-matching "IS_FEDERATED"
+                              (if federation-enabled-bool
+                                "true"
+                                "false")))))
 
 (defn-spec generate-secrets pred/map-or-seq?
   [auth ::auth]
diff --git a/src/main/cljs/dda/c4k_forgejo/browser.cljs b/src/main/cljs/dda/c4k_forgejo/browser.cljs
index ba59420..59d1f3c 100644
--- a/src/main/cljs/dda/c4k_forgejo/browser.cljs
+++ b/src/main/cljs/dda/c4k_forgejo/browser.cljs
@@ -1,9 +1,7 @@
 (ns dda.c4k-forgejo.browser
   (:require
-   [clojure.string :as st]
    [clojure.tools.reader.edn :as edn]
    [dda.c4k-forgejo.core :as core]
-   [dda.c4k-forgejo.forgejo :as forgejo]
    [dda.c4k-common.browser :as br]
    [dda.c4k-common.common :as cm]))
 
@@ -26,31 +24,33 @@
    [(assoc
      (br/generate-needs-validation) :content
      (cm/concat-vec
+      (br/generate-group
+       "config"
+       (br/generate-text-area
+        "config" "Your config.edn:"
+        "{:fqdn \"forgejo.your.domain\"
+ :mailer-from \"test@test.de\"
+ :mailer-host \"test.de\"
+ :mailer-port \"25\"                                                                                  
+ :deploy-federated \"false\"                                                          
+ :service-noreply-address \"no-reply@test.de\"
+ :volume-total-storage-size \"20\"
+ :restic-repository \"s3://yourbucket/your-repo\"
+       :mon-cfg {:cluster-name \"forgejo\"
+                       :cluster-stage \"test\"
+                       :grafana-cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
+        "11"))
       (generate-group
-       "domain"
-       (cm/concat-vec
-        (br/generate-input-field "fqdn" "Your fqdn:" "repo.test.de")
-        (br/generate-input-field "mailer-from" "Your mailer email address:" "test@test.de")
-        (br/generate-input-field "mailer-host" "Your mailer host:" "test.de")
-        (br/generate-input-field "mailer-port" "Your mailer port:" "123")
-        (br/generate-input-field "service-noreply-address" "Your noreply domain:" "test.de")
-        (br/generate-input-field "deploy-federated" "(Optional) Deploy a federated version of forgejo:" "")
-        (br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "")
-        (br/generate-input-field "app-name" "(Optional) Your app name:" "")
-        (br/generate-input-field "domain-whitelist" "(Optional) Domain whitelist for registration email-addresses:" "")))
-      (generate-group
-       "provider"
-       (cm/concat-vec
-        (br/generate-input-field "volume-total-storage-size" "Your forgejo volume-total-storage-size:" "20")))
-      (generate-group
-       "credentials"
+       "auth"
        (br/generate-text-area
         "auth" "Your auth.edn:"
         "{:postgres-db-user \"forgejo\"
-         :postgres-db-password \"forgejo-db-password\"
-         :mailer-user \"test@test.de\"
-         :mailer-pw \"mail-test-password\"}"
-        "5"))
+:postgres-db-password \"forgejo-db-password\"
+:mailer-user \"test@test.de\"
+:mailer-pw \"mail-test-password\"
+:mon-auth {:grafana-cloud-user \"your-user-id\"
+           :grafana-cloud-password \"your-cloud-password\"}}"
+        "6"))
       [(br/generate-br)]
       (br/generate-button "generate-button" "Generate c4k yaml")))]
    (br/generate-output "c4k-forgejo-output" "Your c4k deployment.yaml:" "25")))
@@ -62,44 +62,15 @@
    :content
    (generate-content)})
 
-(defn config-from-document []
-  (let [issuer (br/get-content-from-element "issuer" :optional true)
-        app-name (br/get-content-from-element "app-name" :optional true)
-        domain-whitelist (br/get-content-from-element "domain-whitelist" :optional true)]
-    (merge
-     {:fqdn (br/get-content-from-element "fqdn")
-      :deploy-federated (br/get-content-from-element "deploy-federated")
-      :mailer-from (br/get-content-from-element "mailer-from")
-      :mailer-host (br/get-content-from-element "mailer-host")
-      :mailer-port (br/get-content-from-element "mailer-port")
-      :service-noreply-address (br/get-content-from-element "service-noreply-address")
-      :volume-total-storage-size (br/get-content-from-element "volume-total-storage-size" :deserializer js/parseInt)}
-     (when (not (st/blank? issuer))
-       {:issuer issuer})
-     (when (not (st/blank? app-name))
-       {:default-app-name app-name})
-     (when (not (st/blank? domain-whitelist))
-       {:service-domain-whitelist domain-whitelist}))))
-
 (defn validate-all! []
-  (br/validate! "fqdn" ::forgejo/fqdn)
-  (br/validate! "mailer-from" ::forgejo/mailer-from)
-  (br/validate! "mailer-host" ::forgejo/mailer-host)
-  (br/validate! "mailer-port" ::forgejo/mailer-port)
-  (br/validate! "service-noreply-address" ::forgejo/service-noreply-address)
-  (br/validate! "deploy-federated" ::forgejo/deploy-federated :optional true)
-  (br/validate! "issuer" ::forgejo/issuer :optional true)
-  (br/validate! "app-name" ::forgejo/default-app-name :optional true)
-  (br/validate! "domain-whitelist" ::forgejo/service-domain-whitelist :optional true)
-  (br/validate! "volume-total-storage-size" ::forgejo/volume-total-storage-size :deserializer js/parseInt)
-  (br/validate! "auth" forgejo/auth? :deserializer edn/read-string)
+  (br/validate! "config" core/config? :deserializer edn/read-string)
+  (br/validate! "auth" core/auth? :deserializer edn/read-string)
   (br/set-form-validated!))
 
 (defn add-validate-listener [name]
   (-> (br/get-element-by-id name)
       (.addEventListener "blur" #(do (validate-all!)))))
 
-
 (defn init []
   (br/append-hickory (generate-content-div))
   (let [config-only false
@@ -109,7 +80,7 @@
         (.addEventListener "click"
                            #(do (validate-all!)
                                 (-> (cm/generate-cm
-                                     (config-from-document)
+                                     (br/get-content-from-element "config" :deserializer edn/read-string)
                                      (br/get-content-from-element "auth" :deserializer edn/read-string)
                                      core/config-defaults
                                      core/config-objects
@@ -117,14 +88,5 @@
                                      config-only
                                      auth-only)
                                     (br/set-output!))))))
-  (add-validate-listener "fqdn")
-  (add-validate-listener "deploy-federated")
-  (add-validate-listener "mailer-from")
-  (add-validate-listener "mailer-host")
-  (add-validate-listener "mailer-port")
-  (add-validate-listener "service-noreply-address")
-  (add-validate-listener "app-name")
-  (add-validate-listener "domain-whitelist")
-  (add-validate-listener "volume-total-storage-size")
-  (add-validate-listener "issuer")
+  (add-validate-listener "config")
   (add-validate-listener "auth"))
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_forgejo/core_test.cljc b/src/test/cljc/dda/c4k_forgejo/core_test.cljc
index 5386019..936e6e0 100644
--- a/src/test/cljc/dda/c4k_forgejo/core_test.cljc
+++ b/src/test/cljc/dda/c4k_forgejo/core_test.cljc
@@ -16,4 +16,15 @@
 
 (deftest validate-valid-resources
   (is (s/valid? cut/config? (yaml/load-as-edn "forgejo-test/valid-config.yaml")))
-  (is (s/valid? cut/auth? (yaml/load-as-edn "forgejo-test/valid-auth.yaml"))))
\ No newline at end of file
+  (is (s/valid? cut/auth? (yaml/load-as-edn "forgejo-test/valid-auth.yaml"))))
+
+(deftest test-whole-generation
+  (is (= 32
+         (count
+          (cut/config-objects
+           (yaml/load-as-edn "forgejo-test/valid-config.yaml")))))
+  (is (= 5
+         (count
+          (cut/auth-objects
+           (yaml/load-as-edn "forgejo-test/valid-config.yaml")
+           (yaml/load-as-edn "forgejo-test/valid-auth.yaml"))))))