Merge branch 'init-container' into 'main'

Add init-container

See merge request domaindrivenarchitecture/c4k-website!3
This commit is contained in:
Pat Dyn 2022-11-23 10:14:46 +00:00
commit c9b12a6564
9 changed files with 74 additions and 222 deletions

3
.gitignore vendored
View file

@ -27,4 +27,5 @@ public/js/
auth.edn auth.edn
config.edn config.edn
build-and-move-frontend.sh build-and-move-frontend.sh
website.yaml

View file

@ -48,8 +48,9 @@ test-schema:
stage: build_and_test stage: build_and_test
script: script:
- lein uberjar - lein uberjar
- java -jar target/uberjar/c4k-website-standalone.jar valid-config.edn valid-auth.edn | kubeconform --kubernetes-version 1.19.0 --strict --skip Certificate - - java -jar target/uberjar/c4k-website-standalone.jar valid-config.edn valid-auth.edn | kubeconform --kubernetes-version 1.23.0 --strict --skip Certificate -
artifacts: artifacts:
expire_in: 1h
paths: paths:
- target/uberjar - target/uberjar

View file

@ -47,8 +47,7 @@
(website/generate-website-content-volume (flatten-and-reduce-config config)) (website/generate-website-content-volume (flatten-and-reduce-config config))
(website/generate-website-ingress (flatten-and-reduce-config config)) (website/generate-website-ingress (flatten-and-reduce-config config))
(website/generate-website-certificate (flatten-and-reduce-config config)) (website/generate-website-certificate (flatten-and-reduce-config config))
(website/generate-website-build-cron (flatten-and-reduce-config config)) (website/generate-website-build-cron (flatten-and-reduce-config config))
(website/generate-website-initial-build-job (flatten-and-reduce-config config))
(website/generate-website-build-secret (flatten-and-reduce-config config))))))) (website/generate-website-build-secret (flatten-and-reduce-config config)))))))
(defn k8s-objects [config] (defn k8s-objects [config]

View file

@ -77,7 +77,7 @@
(str (replace-dots-by-minus unique-name) "-ingress")) (str (replace-dots-by-minus unique-name) "-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-spec make-gitrepourl string? (defn-spec generate-gitrepourl string?
[host pred/fqdn-string? [host pred/fqdn-string?
repo string? repo string?
user string? user string?
@ -93,6 +93,24 @@
(str/replace % value-to-partly-match value-to-inplace) %) (str/replace % value-to-partly-match value-to-inplace) %)
col)) col))
(defn-spec replace-common-data pred/map-or-seq?
[resource-file string?
config flattened-and-reduced-config?]
(let [{:keys [unique-name sha256sum-output]} config]
(->
(yaml/load-as-edn resource-file)
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name)))))
(defn-spec replace-build-data pred/map-or-seq?
[resource-file string?
config flattened-and-reduced-config?]
(let [{:keys [sha256sum-output]} config]
(->
(replace-common-data resource-file config)
(cm/replace-all-matching-values-by-new-value "CHECK_SUM" (get-hash-from-sha256sum-output sha256sum-output))
(cm/replace-all-matching-values-by-new-value "SCRIPT_FILE" (get-file-name-from-sha256sum-output sha256sum-output)))))
#?(:cljs #?(:cljs
(defmethod yaml/load-resource :website [resource-name] (defmethod yaml/load-resource :website [resource-name]
(case resource-name (case resource-name
@ -100,8 +118,6 @@
"website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml") "website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml")
"website/nginx-service.yaml" (rc/inline "website/nginx-service.yaml") "website/nginx-service.yaml" (rc/inline "website/nginx-service.yaml")
"website/website-build-cron.yaml" (rc/inline "website/website-build-cron.yaml") "website/website-build-cron.yaml" (rc/inline "website/website-build-cron.yaml")
"website/website-initial-build-job.yaml" (rc/inline "website/website-initial-build-job.yaml")
"website/website-build-deployment.yaml" (rc/inline "website/website-build-deployment.yaml")
"website/website-build-secret.yaml" (rc/inline "website/website-build-secret.yaml") "website/website-build-secret.yaml" (rc/inline "website/website-build-secret.yaml")
"website/website-content-volume.yaml" (rc/inline "website/website-content-volume.yaml") "website/website-content-volume.yaml" (rc/inline "website/website-content-volume.yaml")
(throw (js/Error. "Undefined Resource!"))))) (throw (js/Error. "Undefined Resource!")))))
@ -126,80 +142,46 @@
(defn-spec generate-nginx-configmap pred/map-or-seq? (defn-spec generate-nginx-configmap pred/map-or-seq?
[config flattened-and-reduced-config?] [config flattened-and-reduced-config?]
(let [{:keys [unique-name fqdns]} config] (let [{:keys [fqdns]} config]
(-> (->
(yaml/load-as-edn "website/nginx-configmap.yaml") (replace-common-data "website/nginx-configmap.yaml" config)
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name))
(#(assoc-in % (#(assoc-in %
[:data :website.conf] [:data :website.conf]
(str/replace (str/replace
(-> % :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 flattened-and-reduced-config?] [config flattened-and-reduced-config?]
(let [{:keys [unique-name]} config] (replace-build-data "website/nginx-deployment.yaml" config))
(->
(yaml/load-as-edn "website/nginx-deployment.yaml")
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name)))))
(defn-spec generate-nginx-service pred/map-or-seq? (defn-spec generate-nginx-service pred/map-or-seq?
[config flattened-and-reduced-config?] [config flattened-and-reduced-config?]
(let [{:keys [unique-name]} config] (replace-common-data "website/nginx-service.yaml" config))
(->
(yaml/load-as-edn "website/nginx-service.yaml")
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name)))))
(defn-spec generate-website-content-volume pred/map-or-seq? (defn-spec generate-website-content-volume pred/map-or-seq?
[config flattened-and-reduced-config?] [config flattened-and-reduced-config?]
(let [{:keys [unique-name volume-size] (let [{:keys [volume-size]
:or {volume-size "3"}} config] :or {volume-size "3"}} config]
(-> (->
(yaml/load-as-edn "website/website-content-volume.yaml") (replace-common-data "website/website-content-volume.yaml" config)
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name))
(cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str volume-size "Gi"))))) (cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str volume-size "Gi")))))
(defn-spec replace-build-data pred/map-or-seq?
[resource-file string?
config flattened-and-reduced-config?]
(let [{:keys [unique-name sha256sum-output]} config]
(->
(yaml/load-as-edn resource-file)
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(cm/replace-all-matching-values-by-new-value "CHECK_SUM" (get-hash-from-sha256sum-output sha256sum-output))
(cm/replace-all-matching-values-by-new-value "SCRIPT_FILE" (get-file-name-from-sha256sum-output sha256sum-output))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name)))))
(defn-spec generate-website-build-cron pred/map-or-seq? (defn-spec generate-website-build-cron pred/map-or-seq?
[config flattened-and-reduced-config?] [config flattened-and-reduced-config?]
(replace-build-data "website/website-build-cron.yaml" config)) (replace-build-data "website/website-build-cron.yaml" config))
(defn-spec generate-website-initial-build-job pred/map-or-seq?
[config flattened-and-reduced-config?]
(replace-build-data "website/website-initial-build-job.yaml" config))
(defn-spec generate-website-build-deployment pred/map-or-seq?
[config flattened-and-reduced-config?]
(replace-build-data "website/website-build-deployment.yaml" config))
(defn-spec generate-website-build-secret pred/map-or-seq? (defn-spec generate-website-build-secret pred/map-or-seq?
[auth flattened-and-reduced-config?] [auth flattened-and-reduced-config?]
(let [{:keys [unique-name (let [{:keys [authtoken
authtoken
gitea-host gitea-host
gitea-repo gitea-repo
username username
branchname]} auth] branchname]} auth]
(-> (->
(yaml/load-as-edn "website/website-build-secret.yaml") (replace-common-data "website/website-build-secret.yaml" auth)
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
(replace-all-matching-subvalues-in-string-start "NAME" (replace-dots-by-minus unique-name))
(cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken)) (cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken))
(cm/replace-all-matching-values-by-new-value "URL" (b64/encode (cm/replace-all-matching-values-by-new-value "URL" (b64/encode
(make-gitrepourl (generate-gitrepourl
gitea-host gitea-host
gitea-repo gitea-repo
username username

View file

@ -27,8 +27,24 @@ spec:
- mountPath: /var/log/nginx - mountPath: /var/log/nginx
name: log name: log
- mountPath: /var/www/html/website - mountPath: /var/www/html/website
name: website-content-volume name: content-volume
readOnly: true readOnly: true
initContainers:
- image: domaindrivenarchitecture/c4k-website-build
name: NAME-init-build-container
imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"]
envFrom:
- secretRef:
name: NAME-secret
env:
- name: SHA256SUM
value: CHECK_SUM
- name: SCRIPTFILE
value: SCRIPT_FILE
volumeMounts:
- name: content-volume
mountPath: /var/www/html/website
volumes: volumes:
- name: nginx-config-volume - name: nginx-config-volume
configMap: configMap:
@ -42,7 +58,7 @@ spec:
path: mime.types path: mime.types
- name: log - name: log
emptyDir: {} emptyDir: {}
- name: website-content-volume - name: content-volume
persistentVolumeClaim: persistentVolumeClaim:
claimName: NAME-content-volume claimName: NAME-content-volume

View file

@ -1,4 +1,4 @@
apiVersion: batch/v1beta1 apiVersion: batch/v1
kind: CronJob kind: CronJob
metadata: metadata:
name: NAME-build-cron name: NAME-build-cron

View file

@ -1,40 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: NAME-build-deployment
labels:
app.kubernetes.part-of: NAME-website
spec:
replicas: 0
selector:
matchLabels:
app: NAME-builder
strategy:
type: Recreate
template:
metadata:
labels:
app: NAME-builder
app.kubernetes.io/name: NAME-builder
app.kubernetes.io/part-of: website
spec:
containers:
- image: domaindrivenarchitecture/c4k-website-build
name: NAME-build-app
imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"]
envFrom:
- secretRef:
name: NAME-secret
env:
- name: SHA256SUM
value: CHECK_SUM
- name: SCRIPTFILE
value: SCRIPT_FILE
volumeMounts:
- name: content-volume
mountPath: /var/www/html/website
volumes:
- name: content-volume
persistentVolumeClaim:
claimName: NAME-content-volume

View file

@ -1,31 +0,0 @@
apiVersion: batch/v1
kind: Job
metadata:
name: NAME-initial-build-job
labels:
app.kubernetes.part-of: NAME-website
spec:
template:
spec:
containers:
- image: domaindrivenarchitecture/c4k-website-build
name: NAME-build-app
imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"]
envFrom:
- secretRef:
name: NAME-secret
env:
- name: SHA256SUM
value: CHECK_SUM
- name: SCRIPTFILE
value: SCRIPT_FILE
volumeMounts:
- name: content-volume
mountPath: /var/www/html/website
volumes:
- name: content-volume
persistentVolumeClaim:
claimName: NAME-content-volume
restartPolicy: OnFailure

View file

@ -15,7 +15,6 @@
(st/instrument `cut/generate-website-ingress) (st/instrument `cut/generate-website-ingress)
(st/instrument `cut/generate-website-certificate) (st/instrument `cut/generate-website-certificate)
(st/instrument `cut/generate-website-build-cron) (st/instrument `cut/generate-website-build-cron)
(st/instrument `cut/generate-website-build-deployment)
(st/instrument `cut/generate-website-build-secret) (st/instrument `cut/generate-website-build-secret)
(deftest should-be-valid-website-auth-spec (deftest should-be-valid-website-auth-spec
@ -82,8 +81,7 @@
(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-io-deployment", :metadata {:name "test-io-deployment", :labels {:app.kubernetes.part-of "test-io-website"}},
:labels {:app.kubernetes.part-of "test-io-website"}},
:spec :spec
{:replicas 1, {:replicas 1,
:selector {:matchLabels {:app "test-io-nginx"}}, :selector {:matchLabels {:app "test-io-nginx"}},
@ -98,7 +96,15 @@
:volumeMounts :volumeMounts
[{:mountPath "/etc/nginx", :readOnly true, :name "nginx-config-volume"} [{:mountPath "/etc/nginx", :readOnly true, :name "nginx-config-volume"}
{:mountPath "/var/log/nginx", :name "log"} {:mountPath "/var/log/nginx", :name "log"}
{:mountPath "/var/www/html/website", :name "website-content-volume", :readOnly true}]}], {:mountPath "/var/www/html/website", :name "content-volume", :readOnly true}]}],
:initContainers
[{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-io-init-build-container",
:imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-io-secret"}}],
:env [{:name "SHA256SUM", :value "123456789ab123cd345de"} {:name "SCRIPTFILE", :value "script-file-name.sh"}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes :volumes
[{:name "nginx-config-volume", [{:name "nginx-config-volume",
:configMap :configMap
@ -108,14 +114,16 @@
{: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-io-content-volume"}}]}}}} {:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}}
(cut/generate-nginx-deployment {:unique-name "test.io", (cut/generate-nginx-deployment {:authtoken "abedjgbasdodj",
:gitea-host "gitea.evilorg", :gitea-host "gitlab.de",
:gitea-repo "none", :username "someuser",
:branchname "mablain", :fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"] :gitea-repo "repo",
:username "someuser" :sha256sum-output "123456789ab123cd345de script-file-name.sh",
:authtoken "abedjgbasdodj"})))) :issuer "staging",
:branchname "main",
:unique-name "test.io"}))))
(deftest should-generate-nginx-service (deftest should-generate-nginx-service
(is (= {:name-c1 "test-io-service", (is (= {:name-c1 "test-io-service",
@ -140,7 +148,7 @@
:authtoken "abedjgbasdodj"}))))) :authtoken "abedjgbasdodj"})))))
(deftest should-generate-website-build-cron (deftest should-generate-website-build-cron
(is (= {:apiVersion "batch/v1beta1", (is (= {:apiVersion "batch/v1",
:kind "CronJob", :kind "CronJob",
:metadata {:name "test-io-build-cron", :labels {:app.kubernetes.part-of "test-io-website"}}, :metadata {:name "test-io-build-cron", :labels {:app.kubernetes.part-of "test-io-website"}},
:spec :spec
@ -171,90 +179,6 @@
:branchname "main", :branchname "main",
:unique-name "test.io"})))) :unique-name "test.io"}))))
(deftest should-generate-website-build-deployment
(is (= {:apiVersion "apps/v1",
:kind "Deployment",
:metadata {:name "test-io-build-deployment", :labels {:app.kubernetes.part-of "test-io-website"}},
:spec
{:replicas 0,
:selector {:matchLabels {:app "test-io-builder"}},
:strategy {:type "Recreate"},
:template
{:metadata
{:labels {:app "test-io-builder", :app.kubernetes.io/name "test-io-builder", :app.kubernetes.io/part-of "website"}},
:spec
{:containers
[{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-io-build-app",
:imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-io-secret"}}],
:env [{:name "SHA256SUM", :value "123456789ab123cd345de"} {:name "SCRIPTFILE", :value "script-file-name.sh"}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}}
(cut/generate-website-build-deployment {:authtoken "abedjgbasdodj",
:gitea-host "gitlab.de",
:username "someuser",
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
:gitea-repo "repo",
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
:issuer "staging",
:branchname "main",
:unique-name "test.io"}))))
(deftest should-generate-website-initial-build-job
(is (= {:apiVersion "batch/v1",
:kind "Job",
:metadata {:name "test-io-initial-build-job", :labels {:app.kubernetes.part-of "test-io-website"}},
:spec
{:template
{:spec
{:containers
[{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-io-build-app",
:imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-io-secret"}}],
:env [{:name "SHA256SUM", :value "123456789ab123cd345de"} {:name "SCRIPTFILE", :value "script-file-name.sh"}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}],
:restartPolicy "OnFailure"}}}}
(cut/generate-website-initial-build-job {:authtoken "abedjgbasdodj",
:gitea-host "gitlab.de",
:username "someuser",
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
:gitea-repo "repo",
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
:issuer "staging",
:branchname "main",
:unique-name "test.io"}))))
(deftest should-generate-website-initial-build-job-without-script-file
(is (= {:apiVersion "batch/v1",
:kind "Job",
:metadata {:name "test-io-initial-build-job", :labels {:app.kubernetes.part-of "test-io-website"}},
:spec
{:template
{:spec
{:containers
[{:image "domaindrivenarchitecture/c4k-website-build",
:name "test-io-build-app",
:imagePullPolicy "IfNotPresent",
:command ["/entrypoint.sh"],
:envFrom [{:secretRef {:name "test-io-secret"}}],
:env [{:name "SHA256SUM", :value nil} {:name "SCRIPTFILE", :value nil}],
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}],
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}],
:restartPolicy "OnFailure"}}}}
(cut/generate-website-initial-build-job {:authtoken "abedjgbasdodj",
:gitea-host "gitlab.de",
:username "someuser",
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
:gitea-repo "repo",
:issuer "staging",
:branchname "main",
:unique-name "test.io"}))))
(deftest should-generate-website-build-secret (deftest should-generate-website-build-secret
(is (= {:name-c1 "test-io-secret", (is (= {:name-c1 "test-io-secret",
:name-c2 "test-org-secret", :name-c2 "test-org-secret",