Adjusted Tests

Also fixed smaller issues in website.cljc.
Better division of generate-common-*, now these functions
may reside in c4k-common and generate standing ingresses/certs
with only service and fqdn inputs (which need to be set anyways).

Also moved predicates and specs to website.cljc.
This commit is contained in:
erik 2022-10-13 16:39:55 +02:00
parent d9e22a26ed
commit a15b7b0d6f
8 changed files with 268 additions and 278 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -1,45 +1,16 @@
(ns dda.c4k-website.core (ns dda.c4k-website.core
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[dda.c4k-common.yaml :as yaml] [dda.c4k-common.yaml :as yaml]
[dda.c4k-common.common :as cm] [dda.c4k-common.common :as cm]
[dda.c4k-website.website :as website])) [dda.c4k-website.website :as website]))
(def config-defaults {:issuer "staging"}) (def config-defaults {:issuer "staging"})
(s/def ::websites vector?)
(s/def ::auth vector?)
(def config? (s/keys :req-un [::websites]
:opt-un [::website/issuer]))
(def auth? (s/keys :req-un [::auth]))
(defn flatten-and-reduce-config (defn flatten-and-reduce-config
[config] [config]
(merge (-> config :websites first) (-> config :auth first) {:issuer (config :issuer)})) (merge (-> config :websites first) (-> config :auth first) {:issuer (config :issuer)}))
(defn find-needle [needle haystack]
;loop binds initial values once,
;then binds values from each recursion call
(loop [needle needle
maybe-here haystack
not-here '()]
(let [needle? (first maybe-here)]
;test for return or recur
(if (or (= (str needle?) (str needle))
(empty? maybe-here))
;return results
[needle? maybe-here not-here]
;recur calls loop with new values
(recur needle
(rest maybe-here)
(concat not-here (list (first maybe-here))))))))
(defn generate-configs [config] (defn generate-configs [config]
(loop [config config (loop [config config
result []] result []]

View file

@ -12,40 +12,54 @@
[dda.c4k-common.predicate :as pred] [dda.c4k-common.predicate :as pred]
[clojure.string :as str])) [clojure.string :as str]))
(defn keyword-string?
[input]
(str/starts-with? input "fqdn"))
(defn keyword-string-list?
[input]
(every? true? (map keyword-string? input)))
(defn fqdn-list? (defn fqdn-list?
[input] [input]
(every? true? (map pred/fqdn-string? input))) (every? true? (map pred/fqdn-string? input)))
;(s/def ::uname pred/fqdn-string?) (s/def ::uname pred/fqdn-string?)
;(s/def ::issuer pred/letsencrypt-issuer?) (s/def ::issuer pred/letsencrypt-issuer?)
;(s/def ::authtoken pred/bash-env-string?) (s/def ::authtoken pred/bash-env-string?)
;(s/def ::fqdns fqdn-list?) (s/def ::fqdns fqdn-list?)
;(s/def ::gitea-host pred/fqdn-string?) (s/def ::gitea-host pred/fqdn-string?)
;(s/def ::gitea-repo string?) (s/def ::gitea-repo string?)
;(s/def ::branchname string?) (s/def ::branchname string?)
;(s/def ::username string?) (s/def ::username string?)
;(def config? (s/keys :req-un [::uname ::fqdns ::gitea-host ::gitea-repo ::branchname] (def websitedata? (s/keys :req-un [::uname ::fqdns ::gitea-host ::gitea-repo ::branchname]
; :opt-un [::issuer])) :opt-un [::issuer]))
;(def auth? (s/keys :req-un [::authtoken ::username])) (def websiteauth? (s/keys :req-un [::authtoken ::username]))
(s/def ::websites vector?) (defn auth-data-list?
(s/def ::auth vector?) [input]
(every? #(and
(map? %)
(and (s/valid? ::uname (% :uname)) (contains? % :uname))
(and (s/valid? ::username (% :username)) (contains? % :username))
(and (s/valid? ::authtoken (% :authtoken)) (contains? % :authtoken))) input))
(s/def ::auth auth-data-list?)
(def auth? (s/keys :req-un [::auth]))
(defn website-data-list?
[input]
(every? #(and
(map? %)
(and (s/valid? ::uname (% :uname)) (contains? % :uname))
(and (s/valid? ::fqdns (% :fqdns)) (contains? % :fqdns))
(and (s/valid? ::gitea-host (% :gitea-host)) (contains? % :gitea-host))
(and (s/valid? ::gitea-repo (% :gitea-repo)) (contains? % :gitea-repo))
(and (s/valid? ::branchname (% :branchname)) (contains? % :branchname))) input))
(defn websites? [input]
(and (contains? input :websites) (website-data-list? (input :websites))) )
(s/def ::websites website-data-list?)
(def config? (s/keys :req-un [::websites] (def config? (s/keys :req-un [::websites]
:opt-un [::issuer])) :opt-un [::issuer]))
(def auth? (s/keys :req-un [::auth]))
(def volume-size 3) (def volume-size 3)
(defn unique-name-from-fqdn (defn unique-name-from-fqdn
@ -60,6 +74,14 @@
[uname] [uname]
(str (unique-name-from-fqdn uname) "-cert")) (str (unique-name-from-fqdn uname) "-cert"))
(defn generate-http-ingress-name
[uname]
(str (unique-name-from-fqdn uname) "-http-ingress"))
(defn generate-https-ingress-name
[uname]
(str (unique-name-from-fqdn uname) "-https-ingress"))
; https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/main.zip ; https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/main.zip
(defn make-gitrepourl (defn make-gitrepourl
[host repo user branch] [host repo user branch]
@ -101,8 +123,8 @@
(mapv #(assoc-in rule [:host] %) fqdns)) (mapv #(assoc-in rule [:host] %) fqdns))
;create working ingress ;create working ingress
(defn-spec generate-common-http-ingress pred/map-or-seq? (defn generate-common-http-ingress
[config config?] [config]
(let [{:keys [fqdn service-name]} config] (let [{:keys [fqdn service-name]} config]
(-> (->
(yaml/load-as-edn "website/http-ingress.yaml") (yaml/load-as-edn "website/http-ingress.yaml")
@ -110,17 +132,13 @@
(cm/replace-all-matching-values-by-new-value "FQDN" fqdn)))) (cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-website-http-ingress pred/map-or-seq? (defn-spec generate-website-http-ingress pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname fqdns]} config (let [{:keys [uname fqdns]} config
fqdn (first fqdns) spec-rules [:spec :rules]]
spec-rules [:spec :rules]
service-name (generate-service-name uname)]
(-> (->
(generate-common-http-ingress (generate-common-http-ingress
{:fqdn fqdn :service-name service-name}) {:fqdn (first fqdns) :service-name (generate-service-name uname)})
(assoc-in (cm/replace-all-matching-values-by-new-value "c4k-common-http-ingress" (generate-http-ingress-name uname))
[:metadata :name]
(str (unique-name-from-fqdn uname) "-http-ingress"))
(#(assoc-in % (#(assoc-in %
spec-rules spec-rules
(make-host-rules-from-fqdns (make-host-rules-from-fqdns
@ -128,61 +146,49 @@
fqdns)))))) fqdns))))))
;create working ingress ;create working ingress
(defn-spec generate-common-https-ingress pred/map-or-seq? (defn generate-common-https-ingress
[config config?] [config]
(let [{:keys [fqdn service-name cert-name]} config] (let [{:keys [fqdn service-name]} config]
(-> (->
(yaml/load-as-edn "website/https-ingress.yaml") (yaml/load-as-edn "website/https-ingress.yaml")
(cm/replace-all-matching-values-by-new-value "SERVICENAME" service-name) (cm/replace-all-matching-values-by-new-value "SERVICENAME" service-name)
(cm/replace-all-matching-values-by-new-value "CERTNAME" cert-name)
(cm/replace-all-matching-values-by-new-value "FQDN" fqdn)))) (cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-website-https-ingress pred/map-or-seq? (defn-spec generate-website-https-ingress pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname fqdns]} config (let [{:keys [uname fqdns]} config
fqdn (first fqdns)
spec-rules [:spec :rules] spec-rules [:spec :rules]
spec-tls-hosts [:spec :tls 0 :hosts] spec-tls-hosts [:spec :tls 0 :hosts]]
service-name (generate-service-name uname)
cert-name (generate-cert-name uname)]
(-> (->
(generate-common-https-ingress (generate-common-https-ingress
{:fqdn fqdn :service-name service-name :cert-name cert-name}) {:fqdn (first fqdns) :service-name (generate-service-name uname)})
(assoc-in (cm/replace-all-matching-values-by-new-value "c4k-common-https-ingress" (generate-https-ingress-name uname))
[:metadata :name] (cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name uname))
(str (unique-name-from-fqdn uname) "-https-ingress")) (#(assoc-in % spec-tls-hosts fqdns))
(#(assoc-in % (#(assoc-in % spec-rules (make-host-rules-from-fqdns (-> % :spec :rules first) fqdns))))))
spec-tls-hosts
fqdns))
(#(assoc-in %
spec-rules
(make-host-rules-from-fqdns
(-> % :spec :rules first) ;get first ingress rule
fqdns))))))
(defn-spec generate-common-certificate pred/map-or-seq? (defn generate-common-certificate
[config config?] [config]
(let [{:keys [uname fqdns issuer] (let [{:keys [fqdn issuer]
:or {issuer "staging"}} config :or {issuer "staging"}} config
fqdn (first fqdns) letsencrypt-issuer (name issuer)]
letsencrypt-issuer (name issuer)
cert-name (generate-cert-name uname)]
(-> (->
(yaml/load-as-edn "website/certificate.yaml") (yaml/load-as-edn "website/certificate.yaml")
(assoc-in [:spec :issuerRef :name] letsencrypt-issuer) (assoc-in [:spec :issuerRef :name] letsencrypt-issuer)
(cm/replace-all-matching-values-by-new-value "CERTNAME" cert-name)
(cm/replace-all-matching-values-by-new-value "FQDN" fqdn)))) (cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-website-certificate pred/map-or-seq? (defn-spec generate-website-certificate pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [fqdns]} config (let [{:keys [uname issuer fqdns]} config
spec-dnsNames [:spec :dnsNames]] spec-dnsNames [:spec :dnsNames]]
(-> (->
(generate-common-certificate config) (generate-common-certificate
{:issuer issuer, :fqdn (first fqdns)})
(cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name uname))
(assoc-in spec-dnsNames fqdns)))) (assoc-in spec-dnsNames fqdns))))
(defn-spec generate-nginx-configmap pred/map-or-seq? (defn-spec generate-nginx-configmap pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname fqdns]} config] (let [{:keys [uname fqdns]} config]
(-> (->
(yaml/load-as-edn "website/nginx-configmap.yaml") (yaml/load-as-edn "website/nginx-configmap.yaml")
@ -193,21 +199,21 @@
(-> % :data :website.conf) #"FQDN" (str (str/join " " fqdns) ";"))))))) (-> % :data :website.conf) #"FQDN" (str (str/join " " fqdns) ";")))))))
(defn-spec generate-nginx-deployment pred/map-or-seq? (defn-spec generate-nginx-deployment pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname]} config] (let [{:keys [uname]} config]
(-> (->
(yaml/load-as-edn "website/nginx-deployment.yaml") (yaml/load-as-edn "website/nginx-deployment.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)))))
(defn-spec generate-nginx-service pred/map-or-seq? (defn-spec generate-nginx-service pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname]} config] (let [{:keys [uname]} config]
(-> (->
(yaml/load-as-edn "website/nginx-service.yaml") (yaml/load-as-edn "website/nginx-service.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)))))
(defn-spec generate-website-content-volume pred/map-or-seq? (defn-spec generate-website-content-volume pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname]} config] (let [{:keys [uname]} config]
(-> (->
(yaml/load-as-edn "website/website-content-volume.yaml") (yaml/load-as-edn "website/website-content-volume.yaml")
@ -215,21 +221,21 @@
(cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str (str volume-size) "Gi"))))) (cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str (str volume-size) "Gi")))))
(defn-spec generate-website-build-cron pred/map-or-seq? (defn-spec generate-website-build-cron pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname]} config] (let [{:keys [uname]} config]
(-> (->
(yaml/load-as-edn "website/website-build-cron.yaml") (yaml/load-as-edn "website/website-build-cron.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)))))
(defn-spec generate-website-build-deployment pred/map-or-seq? (defn-spec generate-website-build-deployment pred/map-or-seq?
[config config?] [config websitedata?]
(let [{:keys [uname]} config] (let [{:keys [uname]} config]
(-> (->
(yaml/load-as-edn "website/website-build-deployment.yaml") (yaml/load-as-edn "website/website-build-deployment.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)))))
(defn-spec generate-website-build-secret pred/map-or-seq? (defn-spec generate-website-build-secret pred/map-or-seq?
[auth auth?] [auth websiteauth?]
(let [{:keys [uname (let [{:keys [uname
authtoken authtoken
gitea-host gitea-host

View file

@ -29,21 +29,32 @@
(generate-group (generate-group
"domain" "domain"
(cm/concat-vec (cm/concat-vec
(br/generate-input-field "fqdn" "Your first fqdn:" "deineWebsite.de") (br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "")
(br/generate-input-field "fqdn1" "Your second fqdn:" "deineWebsite.com") (br/generate-text-area
(br/generate-input-field "fqdn2" "Your third fqdn:" "meineWebsite.org") "websites" "A map containing fqdns and repo infos for each website:"
(br/generate-input-field "multi" "Holds fqdns pointing to same ingress" "[\"fqdn\", \"fqdn1\"]") "[{:uname \"test.io \",
(br/generate-input-field "single" "Holds fqdn pointing to another ingress" "fqdn") :fqdns [\"test.de \" \"www.test.de \"],
(br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" ""))) :gitea-host \"githost.de \",
:gitea-repo \"repo \",
:branchname \"main \"}
{:uname \"example.io \",
:fqdns [\"example.org \" \"www.example.org \"],
:gitea-host \"githost.org \",
:gitea-repo \"repo \",
:branchname \"main \"}]"
"10")))
(generate-group (generate-group
"credentials" "credentials"
(br/generate-text-area (br/generate-text-area
"auth" "Your auth.edn:" "auth" "Your authentication data for each website/ git repo:"
"{:authtoken \"yourgiteaauthtoken\" "{:auth
:gitrepourl \"https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/<branchname>.zip\" [{:uname \"test.io\",
:singlegitrepourl \"https://your.gitea.host/api/v1/repos/<owner>/<otherRepo>/archive/<branchname>.zip\" :username \"someuser\",
}" :authtoken \"abedjgbasdodj\"}
"3")) {:uname \"example.io\",
:username \"someuser\",
:authtoken \"abedjgbasdodj\"}]}"
"7"))
[(br/generate-br)] [(br/generate-br)]
(br/generate-button "generate-button" "Generate c4k yaml")))] (br/generate-button "generate-button" "Generate c4k yaml")))]
(br/generate-output "c4k-website-output" "Your c4k deployment.yaml:" "15"))) (br/generate-output "c4k-website-output" "Your c4k deployment.yaml:" "15")))
@ -58,25 +69,20 @@
(defn config-from-document [] (defn config-from-document []
(let [issuer (br/get-content-from-element "issuer" :optional true)] (let [issuer (br/get-content-from-element "issuer" :optional true)]
(merge (merge
{:fqdn (br/get-content-from-element "fqdn")} {:websites (br/get-content-from-element "websites" :deserializer edn/read-string)}
(when (not (st/blank? issuer)) (when (not (st/blank? issuer))
{:issuer issuer})))) {:issuer issuer}))))
(defn validate-all! [] (defn validate-all! []
(br/validate! "fqdn" ::website/fqdn) (br/validate! "websites" ::website/websites)
(br/validate! "fqdn1" ::website/fqdn1)
(br/validate! "fqdn2" ::website/fqdn2)
(br/validate! "single" ::website/single)
(br/validate! "multi" ::website/multi)
(br/validate! "issuer" ::website/issuer :optional true) (br/validate! "issuer" ::website/issuer :optional true)
(br/validate! "auth" core/auth? :deserializer edn/read-string) (br/validate! "auth" website/auth? :deserializer edn/read-string)
(br/set-form-validated!)) (br/set-form-validated!))
(defn add-validate-listener [name] (defn add-validate-listener [name]
(-> (br/get-element-by-id name) (-> (br/get-element-by-id name)
(.addEventListener "blur" #(do (validate-all!))))) (.addEventListener "blur" #(do (validate-all!)))))
(defn init [] (defn init []
(br/append-hickory (generate-content-div)) (br/append-hickory (generate-content-div))
(-> js/document (-> js/document
@ -89,10 +95,6 @@
core/config-defaults core/config-defaults
core/k8s-objects) core/k8s-objects)
(br/set-output!))))) (br/set-output!)))))
(add-validate-listener "fqdn") (add-validate-listener "websites")
(add-validate-listener "fqdn1")
(add-validate-listener "fqdn2")
(add-validate-listener "single")
(add-validate-listener "multi")
(add-validate-listener "issuer") (add-validate-listener "issuer")
(add-validate-listener "auth")) (add-validate-listener "auth"))

View file

@ -1,10 +1,10 @@
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: CERTNAME name: c4k-common-cert
namespace: default namespace: default
spec: spec:
secretName: CERTNAME secretName: c4k-common-cert
commonName: FQDN commonName: FQDN
duration: 2160h # 90d duration: 2160h # 90d
renewBefore: 360h # 15d renewBefore: 360h # 15d

View file

@ -1,7 +1,7 @@
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: http-ingress name: c4k-common-http-ingress
namespace: default namespace: default
annotations: annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.entrypoints: web

View file

@ -1,7 +1,7 @@
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: https-ingress-gitea name: c4k-common-https-ingress
namespace: default namespace: default
annotations: annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
@ -10,7 +10,7 @@ spec:
tls: tls:
- hosts: - hosts:
- FQDN - FQDN
secretName: CERTNAME secretName: c4k-common-cert
rules: rules:
- host: FQDN - host: FQDN
http: http:

View file

@ -8,96 +8,111 @@
[dda.c4k-website.website :as cut] [dda.c4k-website.website :as cut]
[dda.c4k-website.core :as cutc])) [dda.c4k-website.core :as cutc]))
(st/instrument `cut/generate-single-certificate) (st/instrument `cut/generate-http-ingress)
(st/instrument `cut/generate-single-ingress) (st/instrument `cut/generate-https-ingress)
(st/instrument `cut/generate-single-nginx-configmap) (st/instrument `cut/generate-nginx-configmap)
(st/instrument `cut/generate-multi-certificate) (st/instrument `cut/generate-nginx-deployment)
(st/instrument `cut/generate-multi-ingress) (st/instrument `cut/generate-nginx-service)
(st/instrument `cut/generate-multi-nginx-configmap)
(st/instrument `cut/generate-website-content-volume) (st/instrument `cut/generate-website-content-volume)
(st/instrument `cut/generate-website-certificate)
(st/instrument `cut/generate-website-build-cron)
(st/instrument `cut/generate-website-build-deployment)
(st/instrument `cut/generate-website-build-secret)
(deftest should-generate-certificate (deftest should-generate-http-ingress
(is (= {:name-c2 "prod", :name-c1 "staging"}
(th/map-diff (cut/generate-single-certificate {:fqdn "test.de"
:fqdn1 "test.org"
:single "fqdn1"
:fqdn2 "bla.com"
:multi ["fqdn1", "fqdn"]})
(cut/generate-single-certificate {:fqdn "test.com"
:fqdn1 "test.org"
:issuer "prod"
:single "fqdn1"
:fqdn2 "bla.com"
:multi ["fqdn1", "fqdn"]})))))
(deftest should-generate-ingress
(is (= {:apiVersion "networking.k8s.io/v1", (is (= {:apiVersion "networking.k8s.io/v1",
:kind "Ingress", :kind "Ingress",
:metadata :metadata
{:name "test-de-ingress", {:name "test-io-http-ingress",
:namespace "default", :namespace "default",
:annotations :annotations
{:ingress.kubernetes.io/ssl-redirect "true", #:traefik.ingress.kubernetes.io{:router.entrypoints "web",
:traefik.ingress.kubernetes.io/router.middlewares "default-redirect-https@kubernetescrd"}}, :router.middlewares "default-redirect-https@kubernetescrd"}},
:spec :spec
{:tls [{:hosts ["test.de"], :secretName "test-de-cert"}], {:rules
:rules
[{:host "test.de", [{:host "test.de",
:http {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-de-service", :port {:number 80}}}}]}}]}} :http
(cut/generate-single-ingress {:fqdn "test.de" {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
:fqdn1 "test.org" {:host "www.test.de",
:fqdn2 "bla.com" :http
:multi ["fqdn1", "fqdn"] {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
:single "fqdn"})))) {:host "test-it.de",
:http
{:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
{:host "www.test-it.de",
:http
{:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}]}}
(cut/generate-website-http-ingress {:uname "test.io"
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
(deftest should-generate-ingress (deftest should-generate-https-ingress
(is (= {:apiVersion "networking.k8s.io/v1", (is (= {:apiVersion "networking.k8s.io/v1",
:kind "Ingress", :kind "Ingress",
:metadata :metadata
{:name "test-de-ingress", {:name "test-io-https-ingress",
:namespace "default", :namespace "default",
:annotations :annotations #:traefik.ingress.kubernetes.io{:router.entrypoints "websecure", :router.tls "true"}},
{:ingress.kubernetes.io/ssl-redirect "true",
:traefik.ingress.kubernetes.io/router.middlewares "default-redirect-https@kubernetescrd"}},
:spec :spec
{:tls [{:hosts ["test.de"], :secretName "test-de-cert"}], {:tls [{:hosts ["test.de" "www.test.de" "test-it.de" "www.test-it.de"], :secretName "test-io-cert"}],
:rules :rules
[{:host "test.de", [{:host "test.de",
:http {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-de-service", :port {:number 80}}}}]}}]}} :http
(cut/generate-single-ingress {:fqdn "test.de" {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
:fqdn1 "test.org" {:host "www.test.de",
:fqdn2 "bla.com" :http
:multi ["fqdn1", "fqdn"] {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
:single "fqdn"})))) {:host "test-it.de",
:http
{:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}
{:host "www.test-it.de",
:http
{:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}]}}
(cut/generate-website-https-ingress {:uname "test.io"
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
(deftest should-generate-website-certificate
(is (= {:name-c1 "prod", :name-c2 "staging"}
(th/map-diff (cut/generate-website-certificate {:uname "test.io"
:gitea-host "gitea.evilorg"
:gitea-repo "none"
:branchname "mablain"
:issuer "prod"
:fqdns ["test.org" "test.de"]})
(cut/generate-website-certificate {:uname "test.io"
:gitea-host "gitea.evilorg"
:gitea-repo "none"
:branchname "mablain"
:issuer "staging"
:fqdns ["test.org" "test.de"]})))))
(deftest should-generate-nginx-configmap (deftest should-generate-nginx-configmap
(is (= {:website.conf-c1 "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n listen 443 ssl;\n ssl_certificate /etc/certs/tls.crt;\n ssl_certificate_key /etc/certs/tls.key;\n server_name test.de; \n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';\n add_header Content-Security-Policy \"default-src 'self'; font-src *;img-src * data:; script-src *; style-src *\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n", (is (= {:website.conf-c1 "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n listen 443 ssl;\n ssl_certificate /etc/certs/tls.crt;\n ssl_certificate_key /etc/certs/tls.key;\n server_name test.de www.test.de test-it.de www.test-it.de; \n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';\n add_header Content-Security-Policy \"default-src 'self'; font-src *;img-src * data:; script-src *; style-src *\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n",
:website.conf-c2 "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n listen 443 ssl;\n ssl_certificate /etc/certs/tls.crt;\n ssl_certificate_key /etc/certs/tls.key;\n server_name test.com; \n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';\n add_header Content-Security-Policy \"default-src 'self'; font-src *;img-src * data:; script-src *; style-src *\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n", :website.conf-c2 "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n listen 443 ssl;\n ssl_certificate /etc/certs/tls.crt;\n ssl_certificate_key /etc/certs/tls.key;\n server_name example.de www.example.de example-by.de www.example-by.de; \n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';\n add_header Content-Security-Policy \"default-src 'self'; font-src *;img-src * data:; script-src *; style-src *\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n",
:name-c1 "test-de-configmap", :name-c1 "test-io-configmap",
:name-c2 "test-com-configmap"} :name-c2 "example-io-configmap"}
(th/map-diff (cut/generate-single-nginx-configmap {:fqdn "test.de" (th/map-diff (cut/generate-nginx-configmap {:uname "test.io",
:fqdn1 "test.org" :gitea-host "gitea.evilorg",
:single "fqdn" :gitea-repo "none",
:fqdn2 "bla.com" :branchname "mablain",
:multi ["fqdn1", "fqdn"]}) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
(cut/generate-single-nginx-configmap {:fqdn "test.org" (cut/generate-nginx-configmap {:uname "example.io",
:fqdn1 "test.com" :gitea-host "gitea.evilorg",
:single "fqdn1" :gitea-repo "none",
:fqdn2 "bla.com" :branchname "mablain",
:multi ["fqdn1", "fqdn"]}))))) :fqdns ["example.de" "www.example.de" "example-by.de" "www.example-by.de"]})))))
(deftest should-generate-nginx-deployment (deftest should-generate-nginx-deployment
(is (= {:apiVersion "apps/v1", (is (= {:apiVersion "apps/v1",
:kind "Deployment", :kind "Deployment",
:metadata {:name "test-de-deployment"}, :metadata {:name "test-io-deployment"},
:spec :spec
{:replicas 1, {:replicas 1,
:selector {:matchLabels {:app "test-de-nginx"}}, :selector {:matchLabels {:app "test-io-nginx"}},
:template :template
{:metadata {:labels {:app "test-de-nginx"}}, {:metadata {:labels {:app "test-io-nginx"}},
:spec :spec
{:containers {:containers
[{:name "test-de-nginx", [{:name "test-io-nginx",
:image "nginx:latest", :image "nginx:latest",
:imagePullPolicy "IfNotPresent", :imagePullPolicy "IfNotPresent",
:ports [{:containerPort 80}], :ports [{:containerPort 80}],
@ -109,42 +124,42 @@
:volumes :volumes
[{:name "nginx-config-volume", [{:name "nginx-config-volume",
:configMap :configMap
{:name "test-de-configmap", {:name "test-io-configmap",
:items :items
[{:key "nginx.conf", :path "nginx.conf"} [{:key "nginx.conf", :path "nginx.conf"}
{:key "website.conf", :path "conf.d/website.conf"} {:key "website.conf", :path "conf.d/website.conf"}
{:key "mime.types", :path "mime.types"}]}} {:key "mime.types", :path "mime.types"}]}}
{:name "log", :emptyDir {}} {:name "log", :emptyDir {}}
{:name "website-content-volume", :persistentVolumeClaim {:claimName "test-de-content-volume"}} {:name "website-content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}
{:name "website-cert", {:name "website-cert",
:secret :secret
{:secretName "test-de-cert", :items [{:key "tls.crt", :path "tls.crt"} {:key "tls.key", :path "tls.key"}]}}]}}}} {:secretName "test-io-cert", :items [{:key "tls.crt", :path "tls.crt"} {:key "tls.key", :path "tls.key"}]}}]}}}}
(cut/generate-nginx-deployment {:fqdn "test.de" (cut/generate-nginx-deployment {:uname "test.io",
:fqdn1 "test.com" :gitea-host "gitea.evilorg",
:fqdn2 "test.io" :gitea-repo "none",
:single "fqdn2" :branchname "mablain",
:multi ["fqdn1", "fqdn2"]})))) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
(deftest should-generate-nginx-service (deftest should-generate-nginx-service
(is (= {:name-c1 "test-de-service", (is (= {:name-c1 "test-io-service",
:name-c2 "test-com-service", :name-c2 "test-org-service",
:app-c1 "test-de-nginx", :app-c1 "test-io-nginx",
:app-c2 "test-com-nginx"} :app-c2 "test-org-nginx"}
(th/map-diff (cut/generate-nginx-service (cutc/set-multi-fqdn {:fqdn "test.de" (th/map-diff (cut/generate-nginx-service {:uname "test.io",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn", "fqdn"]})) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
(cut/generate-nginx-service (cutc/set-multi-fqdn {:fqdn "test.com" (cut/generate-nginx-service {:uname "test.org",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn", "fqdn"]})))))) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
(deftest should-generate-website-build-cron (deftest should-generate-website-build-cron
(is (= {:apiVersion "batch/v1beta1", (is (= {:apiVersion "batch/v1beta1",
:kind "CronJob", :kind "CronJob",
:metadata {:name "test-de-build-cron", :labels {:app.kubernetes.part-of "website"}}, :metadata {:name "test-io-build-cron", :labels {:app.kubernetes.part-of "website"}},
:spec :spec
{:schedule "1,7,14,21,28,35,42,49,54,59 * * * *", {:schedule "1,7,14,21,28,35,42,49,54,59 * * * *",
:successfulJobsHistoryLimit 1, :successfulJobsHistoryLimit 1,
@ -155,81 +170,77 @@
{:spec {:spec
{:containers {:containers
[{:image "domaindrivenarchitecture/c4k-website-build", [{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-de-build-app", :name "test-io-build-app",
:imagePullPolicy "IfNotPresent", :imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"], :command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-de-secret"}}], :envFrom [{:secretRef {:name "test-io-secret"}}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}], :volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-de-content-volume"}}], :volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}],
:restartPolicy "OnFailure"}}}}}} :restartPolicy "OnFailure"}}}}}}
(cut/generate-website-build-cron {:fqdn "test.de" (cut/generate-website-build-cron {:uname "test.io",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn1", "fqdn"]})))) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
(deftest should-generate-website-build-deployment (deftest should-generate-website-build-deployment
(is (= {:apiVersion "apps/v1", (is (= {:apiVersion "apps/v1",
:kind "Deployment", :kind "Deployment",
:metadata {:name "test-de-build-deployment"}, :metadata {:name "test-io-build-deployment"},
:spec :spec
{:replicas 0, {:replicas 0,
:selector {:matchLabels {:app "test-de-builder"}}, :selector {:matchLabels {:app "test-io-builder"}},
:strategy {:type "Recreate"}, :strategy {:type "Recreate"},
:template :template
{:metadata {:metadata
{:labels {:app "test-de-builder", :app.kubernetes.io/name "test-de-builder", :app.kubernetes.io/part-of "website"}}, {:labels {:app "test-io-builder", :app.kubernetes.io/name "test-io-builder", :app.kubernetes.io/part-of "website"}},
:spec :spec
{:containers {:containers
[{:image "domaindrivenarchitecture/c4k-website-build", [{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-de-build-app", :name "test-io-build-app",
:imagePullPolicy "IfNotPresent", :imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"], :command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-de-secret"}}], :envFrom [{:secretRef {:name "test-io-secret"}}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}], :volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-de-content-volume"}}]}}}} :volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}}
(cut/generate-website-build-deployment {:fqdn "test.de" (cut/generate-website-build-deployment {:uname "test.io",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn1", "fqdn"]})))) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
(deftest should-generate-website-build-secret (deftest should-generate-website-build-secret
(is (= {:name-c1 "test-de-secret", (is (= {:name-c1 "test-io-secret",
:name-c2 "test-com-secret", :name-c2 "test-org-secret",
:AUTHTOKEN-c1 (b64/encode "token1"), :AUTHTOKEN-c1 (b64/encode "token1"),
:AUTHTOKEN-c2 (b64/encode "token2"), :AUTHTOKEN-c2 (b64/encode "token2"),
:GITREPOURL-c1 (b64/encode "test.de/user/repo.git"), :GITREPOURL-c1 (b64/encode "https://gitlab.org/api/v1/repos/dumpty/websitebau/archive/testname.zip"),
:GITREPOURL-c2 (b64/encode "test.com/user/repo.git")} :GITREPOURL-c2 (b64/encode "https://github.com/api/v1/repos/humpty/websitedachs/archive/testname.zip")}
(th/map-diff (cut/generate-website-build-secret {:fqdn "test.de" (th/map-diff (cut/generate-website-build-secret {:uname "test.io",
:fqdn1 "bla.de" :authtoken "token1",
:fqdn2 "bla.com" :gitea-host "gitlab.org",
:single "fqdn1" :gitea-repo "websitebau",
:multi ["fqdn1", "fqdn"] :username "dumpty",
:authtoken "token1" :branchname "testname"})
:gitrepourl "test.de/user/repo.git" (cut/generate-website-build-secret {:uname "test.org",
:singlegitrepourl "test.com/user/otherrepo.git"}) :authtoken "token2",
(cut/generate-website-build-secret {:fqdn "test.com" :gitea-host "github.com",
:fqdn1 "bla.de" :gitea-repo "websitedachs",
:fqdn2 "bla.com" :username "humpty",
:single "fqdn1" :branchname "testname"})))))
:multi ["fqdn1", "fqdn"]
:authtoken "token2"
:gitrepourl "test.com/user/repo.git"
:singlegitrepourl "test.com/user/otherrepo.git"})))))
(deftest should-generate-website-content-volume (deftest should-generate-website-content-volume
(is (= {:name-c1 "test-de-content-volume", (is (= {:name-c1 "test-io-content-volume",
:name-c2 "test-com-content-volume", :name-c2 "test-org-content-volume",
:app-c1 "test-de-nginx", :app-c1 "test-io-nginx",
:app-c2 "test-com-nginx"} :app-c2 "test-org-nginx"}
(th/map-diff (cut/generate-website-content-volume {:fqdn "test.de" (th/map-diff (cut/generate-website-content-volume {:uname "test.io",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn1", "fqdn"]}) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
(cut/generate-website-content-volume {:fqdn "test.com" (cut/generate-website-content-volume {:uname "test.org",
:fqdn1 "bla.de" :gitea-host "gitea.evilorg",
:fqdn2 "bla.com" :gitea-repo "none",
:single "fqdn1" :branchname "mablain",
:multi ["fqdn1", "fqdn"]}))))) :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))