diff --git a/.gitignore b/.gitignore index 7d6320b..687a125 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ public/js/ auth.edn config.edn -build-and-move-frontend.sh \ No newline at end of file +build-and-move-frontend.sh +website.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 460ff60..0da2ecc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,8 +48,9 @@ test-schema: stage: build_and_test script: - 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: + expire_in: 1h paths: - target/uberjar diff --git a/src/main/cljc/dda/c4k_website/core.cljc b/src/main/cljc/dda/c4k_website/core.cljc index 9ebaf88..d4fc44b 100644 --- a/src/main/cljc/dda/c4k_website/core.cljc +++ b/src/main/cljc/dda/c4k_website/core.cljc @@ -47,8 +47,7 @@ (website/generate-website-content-volume (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-build-cron (flatten-and-reduce-config config)) - (website/generate-website-initial-build-job (flatten-and-reduce-config config)) + (website/generate-website-build-cron (flatten-and-reduce-config config)) (website/generate-website-build-secret (flatten-and-reduce-config config))))))) (defn k8s-objects [config] diff --git a/src/main/cljc/dda/c4k_website/website.cljc b/src/main/cljc/dda/c4k_website/website.cljc index 11a3aec..dbe82ac 100644 --- a/src/main/cljc/dda/c4k_website/website.cljc +++ b/src/main/cljc/dda/c4k_website/website.cljc @@ -77,7 +77,7 @@ (str (replace-dots-by-minus unique-name) "-ingress")) ; https://your.gitea.host/api/v1/repos///archive/main.zip -(defn-spec make-gitrepourl string? +(defn-spec generate-gitrepourl string? [host pred/fqdn-string? repo string? user string? @@ -93,6 +93,24 @@ (str/replace % value-to-partly-match value-to-inplace) %) 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 (defmethod yaml/load-resource :website [resource-name] (case resource-name @@ -100,8 +118,6 @@ "website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.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-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-content-volume.yaml" (rc/inline "website/website-content-volume.yaml") (throw (js/Error. "Undefined Resource!"))))) @@ -126,80 +142,46 @@ (defn-spec generate-nginx-configmap pred/map-or-seq? [config flattened-and-reduced-config?] - (let [{:keys [unique-name fqdns]} config] + (let [{:keys [fqdns]} config] (-> - (yaml/load-as-edn "website/nginx-configmap.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)) + (replace-common-data "website/nginx-configmap.yaml" config) (#(assoc-in % [:data :website.conf] (str/replace (-> % :data :website.conf) #"FQDN" (str (str/join " " fqdns) ";"))))))) (defn-spec generate-nginx-deployment pred/map-or-seq? - [config flattened-and-reduced-config?] - (let [{:keys [unique-name]} 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))))) + [config flattened-and-reduced-config?] + (replace-build-data "website/nginx-deployment.yaml" config)) (defn-spec generate-nginx-service pred/map-or-seq? [config flattened-and-reduced-config?] - (let [{:keys [unique-name]} 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))))) + (replace-common-data "website/nginx-service.yaml" config)) (defn-spec generate-website-content-volume pred/map-or-seq? [config flattened-and-reduced-config?] - (let [{:keys [unique-name volume-size] + (let [{:keys [volume-size] :or {volume-size "3"}} config] (-> - (yaml/load-as-edn "website/website-content-volume.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)) + (replace-common-data "website/website-content-volume.yaml" config) (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? [config flattened-and-reduced-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? [auth flattened-and-reduced-config?] - (let [{:keys [unique-name - authtoken + (let [{:keys [authtoken gitea-host gitea-repo username branchname]} auth] (-> - (yaml/load-as-edn "website/website-build-secret.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)) + (replace-common-data "website/website-build-secret.yaml" auth) (cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken)) (cm/replace-all-matching-values-by-new-value "URL" (b64/encode - (make-gitrepourl + (generate-gitrepourl gitea-host gitea-repo username diff --git a/src/main/resources/website/nginx-deployment.yaml b/src/main/resources/website/nginx-deployment.yaml index da96c65..e32a007 100644 --- a/src/main/resources/website/nginx-deployment.yaml +++ b/src/main/resources/website/nginx-deployment.yaml @@ -27,8 +27,24 @@ spec: - mountPath: /var/log/nginx name: log - mountPath: /var/www/html/website - name: website-content-volume + name: content-volume 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: - name: nginx-config-volume configMap: @@ -42,7 +58,7 @@ spec: path: mime.types - name: log emptyDir: {} - - name: website-content-volume + - name: content-volume persistentVolumeClaim: claimName: NAME-content-volume \ No newline at end of file diff --git a/src/main/resources/website/website-build-cron.yaml b/src/main/resources/website/website-build-cron.yaml index 1c2bd00..7bcae2a 100644 --- a/src/main/resources/website/website-build-cron.yaml +++ b/src/main/resources/website/website-build-cron.yaml @@ -1,4 +1,4 @@ -apiVersion: batch/v1beta1 +apiVersion: batch/v1 kind: CronJob metadata: name: NAME-build-cron diff --git a/src/main/resources/website/website-build-deployment.yaml b/src/main/resources/website/website-build-deployment.yaml deleted file mode 100644 index 5b76ce4..0000000 --- a/src/main/resources/website/website-build-deployment.yaml +++ /dev/null @@ -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 diff --git a/src/main/resources/website/website-initial-build-job.yaml b/src/main/resources/website/website-initial-build-job.yaml deleted file mode 100644 index ce44808..0000000 --- a/src/main/resources/website/website-initial-build-job.yaml +++ /dev/null @@ -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 - \ No newline at end of file diff --git a/src/test/cljc/dda/c4k_website/website_test.cljc b/src/test/cljc/dda/c4k_website/website_test.cljc index c3ee7b7..fbb0148 100644 --- a/src/test/cljc/dda/c4k_website/website_test.cljc +++ b/src/test/cljc/dda/c4k_website/website_test.cljc @@ -15,7 +15,6 @@ (st/instrument `cut/generate-website-ingress) (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-be-valid-website-auth-spec @@ -82,8 +81,7 @@ (deftest should-generate-nginx-deployment (is (= {:apiVersion "apps/v1", :kind "Deployment", - :metadata {:name "test-io-deployment", - :labels {:app.kubernetes.part-of "test-io-website"}}, + :metadata {:name "test-io-deployment", :labels {:app.kubernetes.part-of "test-io-website"}}, :spec {:replicas 1, :selector {:matchLabels {:app "test-io-nginx"}}, @@ -98,7 +96,15 @@ :volumeMounts [{:mountPath "/etc/nginx", :readOnly true, :name "nginx-config-volume"} {: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 [{:name "nginx-config-volume", :configMap @@ -108,14 +114,16 @@ {:key "website.conf", :path "conf.d/website.conf"} {:key "mime.types", :path "mime.types"}]}} {:name "log", :emptyDir {}} - {:name "website-content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}} - (cut/generate-nginx-deployment {:unique-name "test.io", - :gitea-host "gitea.evilorg", - :gitea-repo "none", - :branchname "mablain", - :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"] - :username "someuser" - :authtoken "abedjgbasdodj"})))) + {:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}} + (cut/generate-nginx-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-nginx-service (is (= {:name-c1 "test-io-service", @@ -140,7 +148,7 @@ :authtoken "abedjgbasdodj"}))))) (deftest should-generate-website-build-cron - (is (= {:apiVersion "batch/v1beta1", + (is (= {:apiVersion "batch/v1", :kind "CronJob", :metadata {:name "test-io-build-cron", :labels {:app.kubernetes.part-of "test-io-website"}}, :spec @@ -171,90 +179,6 @@ :branchname "main", :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 (is (= {:name-c1 "test-io-secret", :name-c2 "test-org-secret",