You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.5 KiB
Clojure
173 lines
6.5 KiB
Clojure
(ns dda.c4k-forgejo.forgejo
|
|
(:require
|
|
[clojure.spec.alpha :as s]
|
|
[clojure.string :as st]
|
|
#?(:clj [orchestra.core :refer [defn-spec]]
|
|
:cljs [orchestra.core :refer-macros [defn-spec]])
|
|
[dda.c4k-common.yaml :as yaml]
|
|
[dda.c4k-common.common :as cm]
|
|
[dda.c4k-common.ingress :as ing]
|
|
[dda.c4k-common.base64 :as b64]
|
|
[dda.c4k-common.predicate :as pred]
|
|
[dda.c4k-common.postgres :as postgres]
|
|
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
|
|
|
|
(defn domain-list?
|
|
[input]
|
|
(or
|
|
(st/blank? input)
|
|
(pred/string-of-separated-by? pred/fqdn-string? #"," input)))
|
|
|
|
(defn boolean-from-string [input]
|
|
(cond
|
|
(= input "true") true
|
|
(= input "false") false
|
|
:else nil))
|
|
|
|
(defn boolean-string?
|
|
[input]
|
|
(and
|
|
(string? input)
|
|
(boolean? (boolean-from-string input))))
|
|
|
|
(s/def ::default-app-name string?)
|
|
(s/def ::fqdn pred/fqdn-string?)
|
|
(s/def ::deploy-federated boolean-string?)
|
|
(s/def ::mailer-from pred/bash-env-string?)
|
|
(s/def ::mailer-host pred/bash-env-string?)
|
|
(s/def ::mailer-port pred/bash-env-string?)
|
|
(s/def ::service-domain-whitelist domain-list?)
|
|
(s/def ::service-noreply-address string?)
|
|
(s/def ::mailer-user pred/bash-env-string?)
|
|
(s/def ::mailer-pw pred/bash-env-string?)
|
|
(s/def ::issuer pred/letsencrypt-issuer?)
|
|
(s/def ::volume-total-storage-size (partial pred/int-gt-n? 5))
|
|
(s/def ::max-rate int?)
|
|
(s/def ::max-concurrent-requests int?)
|
|
|
|
(def config? (s/keys :req-un [::fqdn
|
|
::mailer-from
|
|
::mailer-host
|
|
::mailer-port
|
|
::service-noreply-address]
|
|
:opt-un [::issuer
|
|
::deploy-federated
|
|
::default-app-name
|
|
::service-domain-whitelist]))
|
|
|
|
(def rate-limit-config? (s/keys :req-un [::max-rate
|
|
::max-concurrent-requests]))
|
|
|
|
(def auth? (s/keys :req-un [::postgres/postgres-db-user ::postgres/postgres-db-password ::mailer-user ::mailer-pw]))
|
|
|
|
(def vol? (s/keys :req-un [::volume-total-storage-size]))
|
|
|
|
(defn data-storage-by-volume-size
|
|
[total]
|
|
total)
|
|
|
|
(def federated-image-name "domaindrivenarchitecture/c4k-forgejo-federated:latest")
|
|
(def non-federated-image-name "codeberg.org/forgejo/forgejo:1.19")
|
|
|
|
#?(:cljs
|
|
(defmethod yaml/load-resource :forgejo [resource-name]
|
|
(get (inline-resources "forgejo") resource-name)))
|
|
|
|
(defn generate-appini-env
|
|
[config]
|
|
(let [{:keys [default-app-name
|
|
deploy-federated
|
|
fqdn
|
|
mailer-from
|
|
mailer-host
|
|
mailer-port
|
|
service-domain-whitelist
|
|
service-noreply-address]
|
|
:or {default-app-name "forgejo instance"
|
|
service-domain-whitelist fqdn}} config
|
|
deploy-federated-bool (boolean-from-string deploy-federated)]
|
|
(->
|
|
(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 deploy-federated-bool
|
|
"true"
|
|
"false")))))
|
|
|
|
(defn generate-secrets
|
|
[auth]
|
|
(let [{:keys [postgres-db-user
|
|
postgres-db-password
|
|
mailer-user
|
|
mailer-pw]} auth]
|
|
(->
|
|
(yaml/load-as-edn "forgejo/secrets.yaml")
|
|
(cm/replace-all-matching-values-by-new-value "DBUSER" (b64/encode postgres-db-user))
|
|
(cm/replace-all-matching-values-by-new-value "DBPW" (b64/encode postgres-db-password))
|
|
(cm/replace-all-matching-values-by-new-value "MAILERUSER" (b64/encode mailer-user))
|
|
(cm/replace-all-matching-values-by-new-value "MAILERPW" (b64/encode mailer-pw)))))
|
|
|
|
(defn generate-ingress-and-cert
|
|
[config]
|
|
(let [{:keys [fqdn]} config]
|
|
(ing/generate-ingress-and-cert
|
|
(merge
|
|
{:service-name "forgejo-service"
|
|
:service-port 3000
|
|
:fqdns [fqdn]}
|
|
config))))
|
|
|
|
(defn-spec generate-rate-limit-ingress-and-cert pred/map-or-seq?
|
|
[config config?]
|
|
(->
|
|
(generate-ingress-and-cert config) ; returns a vector
|
|
(#(assoc-in % ; Attention: heavily relying on the output order of ing/generate-ingress-and-cert
|
|
[1 :metadata :annotations :traefik.ingress.kubernetes.io/router.middlewares]
|
|
(str
|
|
(-> (second %) :metadata :annotations :traefik.ingress.kubernetes.io/router.middlewares)
|
|
", default-ratelimit@kubernetescrd")))))
|
|
|
|
|
|
; using :average and :burst seems sensible, :period may be interesting for fine tuning later on
|
|
(defn-spec generate-rate-limit-middleware pred/map-or-seq?
|
|
[config rate-limit-config?]
|
|
(let [{:keys [max-rate max-concurrent-requests]} config]
|
|
(->
|
|
(yaml/load-as-edn "forgejo/middleware-ratelimit.yaml")
|
|
(cm/replace-key-value :average max-rate)
|
|
(cm/replace-key-value :burst max-concurrent-requests))))
|
|
|
|
(defn-spec generate-data-volume pred/map-or-seq?
|
|
[config vol?]
|
|
(let [{:keys [volume-total-storage-size]} config
|
|
data-storage-size (data-storage-by-volume-size volume-total-storage-size)]
|
|
(->
|
|
(yaml/load-as-edn "forgejo/datavolume.yaml")
|
|
(cm/replace-all-matching-values-by-new-value "DATASTORAGESIZE" (str (str data-storage-size) "Gi")))))
|
|
|
|
(defn-spec generate-deployment pred/map-or-seq?
|
|
[config config?]
|
|
(let [{:keys [deploy-federated]} config
|
|
deploy-federated-bool (boolean-from-string deploy-federated)]
|
|
(->
|
|
(yaml/load-as-edn "forgejo/deployment.yaml")
|
|
(cm/replace-all-matching-values-by-new-value "IMAGE_NAME"
|
|
(if deploy-federated-bool
|
|
federated-image-name
|
|
non-federated-image-name)))))
|
|
|
|
(defn generate-service
|
|
[]
|
|
(yaml/load-as-edn "forgejo/service.yaml"))
|
|
|
|
(defn generate-service-ssh
|
|
[]
|
|
(yaml/load-as-edn "forgejo/service-ssh.yaml"))
|