diff --git a/src/main/clj/dda/c4k_forgejo/uberjar.clj b/src/main/clj/dda/c4k_forgejo/uberjar.clj new file mode 100644 index 0000000..98fe8bd --- /dev/null +++ b/src/main/clj/dda/c4k_forgejo/uberjar.clj @@ -0,0 +1,9 @@ +(ns dda.c4k-forgejo.uberjar + (:gen-class) + (:require + [dda.c4k-forgejo.core :as core] + [dda.c4k-forgejo.forgejo :as forgejo] + [dda.c4k-common.uberjar :as uberjar])) + +(defn -main [& cmd-args] + (uberjar/main-common "c4k-forgejo" core/config? core/auth? core/config-defaults core/k8s-objects cmd-args)) diff --git a/src/main/cljc/dda/c4k_forgejo/backup.cljc b/src/main/cljc/dda/c4k_forgejo/backup.cljc new file mode 100644 index 0000000..eb55172 --- /dev/null +++ b/src/main/cljc/dda/c4k_forgejo/backup.cljc @@ -0,0 +1,44 @@ +(ns dda.c4k-forgejo.backup + (:require + [clojure.spec.alpha :as s] + #?(:cljs [shadow.resource :as rc]) + [dda.c4k-common.yaml :as yaml] + [dda.c4k-common.base64 :as b64] + [dda.c4k-common.common :as cm])) + +(s/def ::aws-access-key-id cm/bash-env-string?) +(s/def ::aws-secret-access-key cm/bash-env-string?) +(s/def ::restic-password cm/bash-env-string?) +(s/def ::restic-repository cm/bash-env-string?) + +#?(:cljs + (defmethod yaml/load-resource :backup [resource-name] + (case resource-name + "backup/config.yaml" (rc/inline "backup/config.yaml") + "backup/cron.yaml" (rc/inline "backup/cron.yaml") + "backup/secret.yaml" (rc/inline "backup/secret.yaml") + "backup/backup-restore-deployment.yaml" (rc/inline "backup/backup-restore-deployment.yaml") + (throw (js/Error. "Undefined Resource!"))))) + +(defn generate-config [my-conf] + (let [{:keys [restic-repository]} my-conf] + (-> + (yaml/from-string (yaml/load-resource "backup/config.yaml")) + (cm/replace-key-value :restic-repository restic-repository)))) + +(defn generate-cron [] + (yaml/from-string (yaml/load-resource "backup/cron.yaml"))) + +(defn generate-backup-restore-deployment [my-conf] + (let [backup-restore-yaml (yaml/from-string (yaml/load-resource "backup/backup-restore-deployment.yaml"))] + (if (and (contains? my-conf :local-integration-test) (= true (:local-integration-test my-conf))) + (cm/replace-named-value backup-restore-yaml "CERTIFICATE_FILE" "/var/run/secrets/localstack-secrets/ca.crt") + backup-restore-yaml))) + +(defn generate-secret [my-auth] + (let [{:keys [aws-access-key-id aws-secret-access-key restic-password]} my-auth] + (-> + (yaml/from-string (yaml/load-resource "backup/secret.yaml")) + (cm/replace-key-value :aws-access-key-id (b64/encode aws-access-key-id)) + (cm/replace-key-value :aws-secret-access-key (b64/encode aws-secret-access-key)) + (cm/replace-key-value :restic-password (b64/encode restic-password))))) diff --git a/src/main/cljc/dda/c4k_forgejo/core.cljc b/src/main/cljc/dda/c4k_forgejo/core.cljc new file mode 100644 index 0000000..7d243a9 --- /dev/null +++ b/src/main/cljc/dda/c4k_forgejo/core.cljc @@ -0,0 +1,54 @@ +(ns dda.c4k-forgejo.core + (:require + [clojure.spec.alpha :as s] + [dda.c4k-common.yaml :as yaml] + [dda.c4k-common.common :as cm] + [dda.c4k-forgejo.forgejo :as forgejo] + [dda.c4k-forgejo.backup :as backup] + [dda.c4k-common.postgres :as postgres])) + +(def config-defaults {:issuer "staging"}) + +(def config? (s/keys :req-un [::forgejo/fqdn + ::forgejo/mailer-from + ::forgejo/mailer-host-port + ::forgejo/service-noreply-address] + :opt-un [::forgejo/issuer + ::forgejo/default-app-name + ::forgejo/service-domain-whitelist + ::backup/restic-repository])) + +(def auth? (s/keys :req-un [::postgres/postgres-db-user ::postgres/postgres-db-password + ::forgejo/mailer-user ::forgejo/mailer-pw + ::backup/aws-access-key-id ::backup/aws-secret-access-key] + :opt-un [::backup/restic-password])) ; TODO gec: Is restic password opt or req? + +(def vol? (s/keys :req-un [::forgejo/volume-total-storage-size])) + +(defn k8s-objects [config] + (let [storage-class (if (contains? config :postgres-data-volume-path) :manual :local-path)] + (map yaml/to-string + (filter #(not (nil? %)) + (cm/concat-vec + [(postgres/generate-config {:postgres-size :2gb :db-name "forgejo"}) + (postgres/generate-secret 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 {:pv-storage-size-gb 5 + :pvc-storage-class-name storage-class}) + (postgres/generate-deployment {:postgres-image "postgres:14" + :postgres-size :2gb}) + (postgres/generate-service) + (forgejo/generate-deployment) + (forgejo/generate-service) + (forgejo/generate-service-ssh) + (forgejo/generate-data-volume config) + (forgejo/generate-appini-env config) + (forgejo/generate-secrets config) + (forgejo/generate-ingress config) + (forgejo/generate-certificate config)] + (when (contains? config :restic-repository) + [(backup/generate-config config) + (backup/generate-secret config) + (backup/generate-cron) + (backup/generate-backup-restore-deployment config)])))))) diff --git a/src/main/cljc/dda/c4k_forgejo/forgejo.cljc b/src/main/cljc/dda/c4k_forgejo/forgejo.cljc new file mode 100644 index 0000000..c58b48a --- /dev/null +++ b/src/main/cljc/dda/c4k_forgejo/forgejo.cljc @@ -0,0 +1,138 @@ +(ns dda.c4k-forgejo.forgejo + (:require + [clojure.spec.alpha :as s] + [clojure.string :as st] + #?(:cljs [shadow.resource :as rc]) + #?(:clj [orchestra.core :refer [defn-spec]] + :cljs [orchestra.core :refer-macros [defn-spec]]) + #?(:clj [clojure.edn :as edn] + :cljs [cljs.reader :as edn]) + [dda.c4k-common.yaml :as yaml] + [dda.c4k-common.common :as cm] + [dda.c4k-common.base64 :as b64] + [dda.c4k-common.predicate :as pred] + [dda.c4k-common.postgres :as postgres])) + +(defn domain-list? + [input] + (or + (st/blank? input) + (pred/string-of-separated-by? pred/fqdn-string? #"," input))) + +(s/def ::default-app-name string?) +(s/def ::fqdn pred/fqdn-string?) +(s/def ::mailer-from pred/bash-env-string?) +(s/def ::mailer-host-port pred/host-and-port-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)) + +(def config-defaults {:issuer "staging"}) + +(def config? (s/keys :req-un [::fqdn + ::mailer-from + ::mailer-host-port + ::service-noreply-address] + :opt-un [::issuer + ::default-app-name + ::service-domain-whitelist])) + +(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) + + +#?(:cljs + (defmethod yaml/load-resource :forgejo [resource-name] + (case resource-name + "forgejo/appini-env-configmap.yaml" (rc/inline "forgejo/appini-env-configmap.yaml") + "forgejo/deployment.yaml" (rc/inline "forgejo/deployment.yaml") + "forgejo/certificate.yaml" (rc/inline "forgejo/certificate.yaml") + "forgejo/ingress.yaml" (rc/inline "forgejo/ingress.yaml") + "forgejo/secrets.yaml" (rc/inline "forgejo/secrets.yaml") + "forgejo/service.yaml" (rc/inline "forgejo/service.yaml") + "forgejo/service-ssh.yaml" (rc/inline "forgejo/service-ssh.yaml") + "forgejo/datavolume.yaml" (rc/inline "forgejo/datavolume.yaml") + (throw (js/Error. "Undefined Resource!"))))) + +#?(:cljs + (defmethod yaml/load-as-edn :forgejo [resource-name] + (yaml/from-string (yaml/load-resource resource-name)))) + +(defn generate-appini-env + [config] + (let [{:keys [default-app-name + fqdn + mailer-from + mailer-host-port + service-domain-whitelist + service-noreply-address] + :or {default-app-name "forgejo instance" + service-domain-whitelist fqdn}} + config] + (-> + (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 "HOSTANDPORT" mailer-host-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)))) + +(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 + [config] + (let [{:keys [fqdn]} config] + (-> + (yaml/load-as-edn "forgejo/ingress.yaml") + (cm/replace-all-matching-values-by-new-value "FQDN" fqdn)))) + +(defn generate-certificate + [config] + (let [{:keys [fqdn issuer] + :or {issuer "staging"}} config + letsencrypt-issuer (name issuer)] + (-> + (yaml/load-as-edn "forgejo/certificate.yaml") + (assoc-in [:spec :issuerRef :name] letsencrypt-issuer) + (cm/replace-all-matching-values-by-new-value "FQDN" fqdn)))) + +(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 generate-deployment + [] + (yaml/load-as-edn "forgejo/deployment.yaml")) + +(defn generate-service + [] + (yaml/load-as-edn "forgejo/service.yaml")) + +(defn generate-service-ssh + [] + (yaml/load-as-edn "forgejo/service-ssh.yaml")) diff --git a/src/main/cljs/dda/c4k_forgejo/browser.cljs b/src/main/cljs/dda/c4k_forgejo/browser.cljs new file mode 100644 index 0000000..910e99c --- /dev/null +++ b/src/main/cljs/dda/c4k_forgejo/browser.cljs @@ -0,0 +1,118 @@ +(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])) + +(defn generate-group + [name + content] + [{:type :element + :tag :div + :attrs {:class "rounded border border-3 m-3 p-2"} + :content [{:type :element + :tag :b + :attrs {:style "z-index: 1; position: relative; top: -1.3rem;"} + :content name} + {:type :element + :tag :fieldset + :content content}]}]) + +(defn generate-content [] + (cm/concat-vec + [(assoc + (br/generate-needs-validation) :content + (cm/concat-vec + (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-port" "Your mailer host with port:" "test.de:123") + (br/generate-input-field "service-noreply-address" "Your noreply domain:" "test.de") + (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" + (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")) + [(br/generate-br)] + (br/generate-button "generate-button" "Generate c4k yaml")))] + (br/generate-output "c4k-forgejo-output" "Your c4k deployment.yaml:" "25"))) + +(defn generate-content-div + [] + {:type :element + :tag :div + :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") + :mailer-from (br/get-content-from-element "mailer-from") + :mailer-host-port (br/get-content-from-element "mailer-host-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-port" ::forgejo/mailer-host-port) + (br/validate! "service-noreply-address" ::forgejo/service-noreply-address) + (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/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)) + (-> js/document + (.getElementById "generate-button") + (.addEventListener "click" + #(do (validate-all!) + (-> (cm/generate-common + (config-from-document) + (br/get-content-from-element "auth" :deserializer edn/read-string) + forgejo/config-defaults + core/k8s-objects) + (br/set-output!))))) + (add-validate-listener "fqdn") + (add-validate-listener "mailer-from") + (add-validate-listener "mailer-host-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 "auth")) \ No newline at end of file diff --git a/src/main/resources/forgejo/appini-env-configmap.yaml b/src/main/resources/forgejo/appini-env-configmap.yaml new file mode 100644 index 0000000..c2e1090 --- /dev/null +++ b/src/main/resources/forgejo/appini-env-configmap.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: forgejo-env + namespace: default +data: + #[admin] + FORGEJO__admin__DEFAULT_EMAIL_NOTIFICATIONS: "enabled" # Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled + + #[attachments] + FORGEJO__attachments__PATH: /data/gitea/attachments + + #[database] + FORGEJO__database__DB_TYPE: "postgres" + FORGEJO__database__HOST: "postgresql-service:5432" + FORGEJO__database__NAME: forgejo + FORGEJO__database__LOG_SQL: "false" + FORGEJO__database__SSL_MODE: disable + FORGEJO__database__CHARSET: utf8 + + #[DEFAULT] + APP_NAME: APPNAME + RUN_MODE: prod + RUN_USER: git + + #[federation] + FORGEJO__federation__ENABLED: "true" + + #[indexer] + FORGEJO__indexer__ISSUE_INDEXER_PATH: /data/gitea/indexers/issues.bleve + + #[log] + FORGEJO__log__MODE: "console, file" + FORGEJO__log__LEVEL: Info + FORGEJO__log__ROOT_PATH: /data/gitea/log + + #[mailer] + FORGEJO__mailer__ENABLED: "true" + FORGEJO__mailer__FROM: FROM + FORGEJO__mailer__MAILER_TYPE: smtp+startls + # TODO: jem 2022-08-02: outdated with v1.18, use SMTP_ADDR & SMTP_PORT instead + FORGEJO__mailer__HOST: HOSTANDPORT + + #[oauth2] + FORGEJO__oauth2__ENABLE: "true" + + #[openid] + FORGEJO__openid__ENABLE_OPENID: "true" + FORGEJO__openid__ENABLE_OPENID_SIGNIN: "true" + FORGEJO__openid__ENABLE_OPENID_SIGNUP: "true" + + #[picture] + FORGEJO__picture__AVATAR_UPLOAD_PATH: /data/gitea/avatars + FORGEJO__picture__REPOSITORY_AVATAR_UPLOAD_PATH: /data/gitea/repo-avatars + FORGEJO__picture__DISABLE_GRAVATAR: "false" + FORGEJO__picture__ENABLE_FEDERATED_AVATAR: "true" # Enable support for federated avatars (see http://www.libravatar.org). + + #[repository] + FORGEJO__repository__ROOT: /data/git/repositories + FORGEJO__repository__DEFAULT_PRIVATE: last + FORGEJO__repository__LOCAL_COPY_PATH: /data/gitea/tmp/local-repo + FORGEJO__repository__TEMP_PATH: /data/gitea/uploads + + #[security] + FORGEJO__security__INSTALL_LOCK: "true" + + #[server] + FORGEJO__server__DOMAIN: FQDN + FORGEJO__server__SSH_DOMAIN: FQDN + FORGEJO__server__ROOT_URL: URL + FORGEJO__server__HTTP_PORT: "3000" # HTTP listen port of the server (in the pod) + FORGEJO__server__SSH_PORT: "2222" # SSH port displayed in clone URL + + #[service] + FORGEJO__service__DISABLE_REGISTRATION: "false" + FORGEJO__service__REQUIRE_SIGNIN_VIEW: "false" + FORGEJO__service__REGISTER_EMAIL_CONFIRM: "true" + FORGEJO__service__ENABLE_NOTIFY_MAIL: "true" + FORGEJO__service__EMAIL_DOMAIN_WHITELIST: WHITELISTDOMAINS + FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION: "false" + FORGEJO__service__ENABLE_BASIC_AUTHENTICATION: "true" + FORGEJO__service__ENABLE_CAPTCHA: "false" + FORGEJO__service__DEFAULT_KEEP_EMAIL_PRIVATE: "true" + FORGEJO__service__DEFAULT_ALLOW_CREATE_ORGANIZATION: "true" + FORGEJO__service__DEFAULT_ENABLE_TIMETRACKING: "true" + FORGEJO__service__NO_REPLY_ADDRESS: NOREPLY + + #[session] + FORGEJO__session__PROVIDER_CONFIG: /data/gitea/sessions + FORGEJO__session__PROVIDER: file diff --git a/src/main/resources/forgejo/certificate.yaml b/src/main/resources/forgejo/certificate.yaml new file mode 100644 index 0000000..e99bb95 --- /dev/null +++ b/src/main/resources/forgejo/certificate.yaml @@ -0,0 +1,15 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: forgejo-cert + namespace: default +spec: + secretName: forgejo-cert + commonName: FQDN + duration: 2160h # 90d + renewBefore: 360h # 15d + dnsNames: + - FQDN + issuerRef: + name: staging + kind: ClusterIssuer \ No newline at end of file diff --git a/src/main/resources/forgejo/datavolume.yaml b/src/main/resources/forgejo/datavolume.yaml new file mode 100644 index 0000000..44c8fd0 --- /dev/null +++ b/src/main/resources/forgejo/datavolume.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: forgejo-data-pvc + namespace: default + labels: + app: forgejo +spec: + storageClassName: local-path + accessModes: + - ReadWriteOnce + resources: + requests: + storage: DATASTORAGESIZE + \ No newline at end of file diff --git a/src/main/resources/forgejo/deployment.yaml b/src/main/resources/forgejo/deployment.yaml new file mode 100644 index 0000000..7efc943 --- /dev/null +++ b/src/main/resources/forgejo/deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: forgejo + namespace: default + labels: + app: forgejo +spec: + replicas: 1 + selector: + matchLabels: + app: forgejo + template: + metadata: + name: forgejo + labels: + app: forgejo + spec: + containers: + - name: forgejo + image: codeberg.org/forgejo/forgejo:1.18 + imagePullPolicy: IfNotPresent + # config settings + envFrom: + - configMapRef: + name: forgejo-env + - secretRef: + name: forgejo-secrets + volumeMounts: + - name: forgejo-data-volume + mountPath: "/data" + ports: + - containerPort: 22 + name: git-ssh + - containerPort: 3000 + name: forgejo + volumes: + - name: forgejo-data-volume + persistentVolumeClaim: + claimName: forgejo-data-pvc + diff --git a/src/main/resources/forgejo/ingress.yaml b/src/main/resources/forgejo/ingress.yaml new file mode 100644 index 0000000..751c45b --- /dev/null +++ b/src/main/resources/forgejo/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-forgejo + namespace: default + annotations: + ingress.kubernetes.io/ssl-redirect: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd +spec: + tls: + - hosts: + - FQDN + secretName: forgejo-cert + rules: + - host: FQDN + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: forgejo-service + port: + number: 3000 diff --git a/src/main/resources/forgejo/secrets.yaml b/src/main/resources/forgejo/secrets.yaml new file mode 100644 index 0000000..0c2a224 --- /dev/null +++ b/src/main/resources/forgejo/secrets.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: forgejo-secrets +data: + FORGEJO__database__USER: DBUSER + FORGEJO__database__PASSWD: DBPW + + FORGEJO__mailer__USER: MAILERUSER + FORGEJO__mailer__PASSWD: MAILERPW + \ No newline at end of file diff --git a/src/main/resources/forgejo/service-ssh.yaml b/src/main/resources/forgejo/service-ssh.yaml new file mode 100644 index 0000000..1694958 --- /dev/null +++ b/src/main/resources/forgejo/service-ssh.yaml @@ -0,0 +1,17 @@ +kind: Service +apiVersion: v1 +metadata: + name: forgejo-ssh-service + namespace: default + annotations: + metallb.universe.tf/allow-shared-ip: "shared-ip-service-group" + metallb.universe.tf/address-pool: public +spec: + type: LoadBalancer + selector: + app: forgejo + ports: + - port: 2222 + targetPort: 22 + protocol: TCP + diff --git a/src/main/resources/forgejo/service.yaml b/src/main/resources/forgejo/service.yaml new file mode 100644 index 0000000..e8fed3f --- /dev/null +++ b/src/main/resources/forgejo/service.yaml @@ -0,0 +1,12 @@ +kind: Service +apiVersion: v1 +metadata: + name: forgejo-service + namespace: default +spec: + selector: + app: forgejo + ports: + - name: forgejo-http + port: 3000 + diff --git a/src/test/cljc/dda/c4k_forgejo/forgejo_test.cljc b/src/test/cljc/dda/c4k_forgejo/forgejo_test.cljc new file mode 100644 index 0000000..c1b7075 --- /dev/null +++ b/src/test/cljc/dda/c4k_forgejo/forgejo_test.cljc @@ -0,0 +1,73 @@ +(ns dda.c4k-forgejo.forgejo-test + (:require + #?(:clj [clojure.test :refer [deftest is are testing run-tests]] + :cljs [cljs.test :refer-macros [deftest is are testing run-tests]]) + [clojure.spec.test.alpha :as st] + [dda.c4k-common.test-helper :as th] + [dda.c4k-common.base64 :as b64] + [dda.c4k-forgejo.forgejo :as cut])) + +(st/instrument `cut/generate-appini-env) +(st/instrument `cut/generate-ingress) +(st/instrument `cut/generate-secrets) + +(deftest should-generate-appini-env + (is (= {:APP_NAME-c1 "", + :APP_NAME-c2 "test forgejo", + :FORGEJO__mailer__FROM-c1 "", + :FORGEJO__mailer__FROM-c2 "test@test.com", + :FORGEJO__mailer__HOST-c1 "m.t.de:123", + :FORGEJO__mailer__HOST-c2 "mail.test.com:123", + :FORGEJO__server__DOMAIN-c1 "test.de", + :FORGEJO__server__DOMAIN-c2 "test.com", + :FORGEJO__server__ROOT_URL-c1 "https://test.de", + :FORGEJO__server__ROOT_URL-c2 "https://test.com", + :FORGEJO__server__SSH_DOMAIN-c1 "test.de", + :FORGEJO__server__SSH_DOMAIN-c2 "test.com", + :FORGEJO__service__EMAIL_DOMAIN_WHITELIST-c1 "adb.de", + :FORGEJO__service__EMAIL_DOMAIN_WHITELIST-c2 "test.com,test.net", + :FORGEJO__service__NO_REPLY_ADDRESS-c1 "", + :FORGEJO__service__NO_REPLY_ADDRESS-c2 "noreply@test.com"} + (th/map-diff (cut/generate-appini-env {:default-app-name "" + :fqdn "test.de" + :mailer-from "" + :mailer-host-port "m.t.de:123" + :service-domain-whitelist "adb.de" + :service-noreply-address "" + }) + (cut/generate-appini-env {:default-app-name "test forgejo" + :fqdn "test.com" + :mailer-from "test@test.com" + :mailer-host-port "mail.test.com:123" + :service-domain-whitelist "test.com,test.net" + :service-noreply-address "noreply@test.com" + }))))) + +(deftest should-generate-certificate + (is (= {:name-c2 "prod", :name-c1 "staging"} + (th/map-diff (cut/generate-certificate {}) + (cut/generate-certificate {:issuer "prod"}))))) + +(deftest should-generate-secret + (is (= {:FORGEJO__database__USER-c1 "", + :FORGEJO__database__USER-c2 (b64/encode "pg-user"), + :FORGEJO__database__PASSWD-c1 "", + :FORGEJO__database__PASSWD-c2 (b64/encode "pg-pw"), + :FORGEJO__mailer__USER-c1 "", + :FORGEJO__mailer__USER-c2 (b64/encode "maileruser"), + :FORGEJO__mailer__PASSWD-c1 "", + :FORGEJO__mailer__PASSWD-c2 (b64/encode "mailerpw")} + (th/map-diff (cut/generate-secrets {:postgres-db-user "" + :postgres-db-password "" + :mailer-user "" + :mailer-pw ""}) + (cut/generate-secrets {:postgres-db-user "pg-user" + :postgres-db-password "pg-pw" + :mailer-user "maileruser" + :mailer-pw "mailerpw"}))))) + +(deftest should-generate-data-volume + (is (= {:storage-c1 "1Gi", + :storage-c2 "15Gi"} + (th/map-diff (cut/generate-data-volume {:volume-total-storage-size 1}) + (cut/generate-data-volume {:volume-total-storage-size 15}))))) \ No newline at end of file