diff --git a/infrastructure/backup/build.py b/infrastructure/backup/build.py index 252752b..b403ddb 100644 --- a/infrastructure/backup/build.py +++ b/infrastructure/backup/build.py @@ -6,7 +6,7 @@ from ddadevops import * name = "c4k-cloud" MODULE = "backup" PROJECT_ROOT_PATH = "../.." -version = "10.4.3-dev" +version = "10.4.5-dev" @init diff --git a/infrastructure/nextcloud/build.py b/infrastructure/nextcloud/build.py index 36af428..5141386 100644 --- a/infrastructure/nextcloud/build.py +++ b/infrastructure/nextcloud/build.py @@ -6,7 +6,7 @@ from ddadevops import * name = 'c4k-cloud' MODULE = 'not_set' PROJECT_ROOT_PATH = '../..' -version = "10.4.3-dev" +version = "10.4.5-dev" @init def initialize(project): diff --git a/package.json b/package.json index 521e0a4..4d6b720 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "c4k-nextcloud", "description": "Generate c4k yaml for a nextcloud deployment.", "author": "meissa GmbH", - "version": "10.4.3-SNAPSHOT", + "version": "10.4.5-SNAPSHOT", "homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-nextcloud#readme", "repository": "https://www.npmjs.com/package/c4k-nextcloud", "license": "APACHE2", diff --git a/project.clj b/project.clj index 370029e..f1cefec 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject org.domaindrivenarchitecture/c4k-nextcloud "10.4.3-SNAPSHOT" +(defproject org.domaindrivenarchitecture/c4k-nextcloud "10.4.5-SNAPSHOT" :description "nextcloud c4k-installation package" :url "https://domaindrivenarchitecture.org" :license {:name "Apache License, Version 2.0" diff --git a/src/main/clj/dda/c4k_nextcloud/uberjar.clj b/src/main/clj/dda/c4k_nextcloud/uberjar.clj index f4aa154..7439461 100644 --- a/src/main/clj/dda/c4k_nextcloud/uberjar.clj +++ b/src/main/clj/dda/c4k_nextcloud/uberjar.clj @@ -2,14 +2,13 @@ (:gen-class) (:require [dda.c4k-common.uberjar :as uberjar] - [dda.c4k-nextcloud.nextcloud :as nextcloud] [dda.c4k-nextcloud.core :as core])) (defn -main [& cmd-args] (uberjar/main-cm "c4k-nextcloud" - nextcloud/config? - nextcloud/auth? + core/config? + core/auth? core/config-defaults core/config-objects core/auth-objects diff --git a/src/main/cljc/dda/c4k_nextcloud/backup.cljc b/src/main/cljc/dda/c4k_nextcloud/backup.cljc index a985295..b2ebe44 100644 --- a/src/main/cljc/dda/c4k_nextcloud/backup.cljc +++ b/src/main/cljc/dda/c4k_nextcloud/backup.cljc @@ -1,6 +1,8 @@ (ns dda.c4k-nextcloud.backup (:require [clojure.spec.alpha :as s] + #?(:clj [orchestra.core :refer [defn-spec]] + :cljs [orchestra.core :refer-macros [defn-spec]]) [dda.c4k-common.yaml :as yaml] [dda.c4k-common.base64 :as b64] [dda.c4k-common.common :as cm] @@ -13,27 +15,36 @@ (s/def ::restic-new-password cp/bash-env-string?) (s/def ::restic-repository cp/bash-env-string?) +(s/def ::config (s/keys :req-un [::restic-repository])) + +(s/def ::auth (s/keys :req-un [::restic-password ::aws-access-key-id ::aws-secret-access-key])) + + #?(:cljs (defmethod yaml/load-resource :backup [resource-name] (get (inline-resources "backup") resource-name))) -(defn generate-config [my-conf] +(defn-spec generate-config map? + [my-conf ::config] (let [{:keys [restic-repository]} my-conf] (-> (yaml/load-as-edn "backup/config.yaml") (cm/replace-key-value :restic-repository restic-repository)))) -(defn generate-cron [] +(defn-spec generate-cron map? + [] (yaml/from-string (yaml/load-resource "backup/cron.yaml"))) -(defn generate-backup-restore-deployment [my-conf] +(defn-spec generate-backup-restore-deployment map? + [my-conf ::config] (let [backup-restore-yaml (yaml/load-as-edn "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] +(defn-spec generate-secret map? + [my-auth ::auth] (let [{:keys [aws-access-key-id aws-secret-access-key restic-password]} my-auth] (-> (yaml/load-as-edn "backup/secret.yaml") diff --git a/src/main/cljc/dda/c4k_nextcloud/core.cljc b/src/main/cljc/dda/c4k_nextcloud/core.cljc index 32dd2d1..a003ec4 100644 --- a/src/main/cljc/dda/c4k_nextcloud/core.cljc +++ b/src/main/cljc/dda/c4k_nextcloud/core.cljc @@ -1,5 +1,6 @@ (ns dda.c4k-nextcloud.core (:require + [clojure.spec.alpha :as s] #?(:clj [orchestra.core :refer [defn-spec]] :cljs [orchestra.core :refer-macros [defn-spec]]) [dda.c4k-common.common :as cm] @@ -16,8 +17,15 @@ :pvc-storage-class-name "hcloud-volumes-encrypted" :pv-storage-size-gb 200}) +(def config? (s/merge ::nextcloud/config + ::backup/config)) + +(def auth? (s/merge ::nextcloud/auth + ::backup/auth)) + + (defn-spec config-objects cp/map-or-seq? - [config nextcloud/config?] + [config config?] (let [resolved-config (merge config-defaults config)] (map yaml/to-string (filter @@ -40,8 +48,8 @@ (mon/generate-config))))))) (defn-spec auth-objects cp/map-or-seq? - [config nextcloud/config? - auth nextcloud/auth?] + [config config? + auth auth?] (let [resolved-config (merge config-defaults config)] (map yaml/to-string (filter diff --git a/src/main/cljc/dda/c4k_nextcloud/nextcloud.cljc b/src/main/cljc/dda/c4k_nextcloud/nextcloud.cljc index 0f40ba4..930d093 100644 --- a/src/main/cljc/dda/c4k_nextcloud/nextcloud.cljc +++ b/src/main/cljc/dda/c4k_nextcloud/nextcloud.cljc @@ -14,23 +14,20 @@ (s/def ::fqdn cp/fqdn-string?) (s/def ::issuer cp/letsencrypt-issuer?) -(s/def ::restic-repository string?) (s/def ::nextcloud-admin-user cp/bash-env-string?) (s/def ::nextcloud-admin-password cp/bash-env-string?) (s/def ::pvc-storage-class-name cp/pvc-storage-class-name?) (s/def ::pv-storage-size-gb pos?) -(def config? (s/keys :req-un [::fqdn] +(s/def ::config (s/keys :req-un [::fqdn] :opt-un [::issuer - ::restic-repository ::pv-storage-size-gb ::pvc-storage-class-name ::mon/mon-cfg])) -(def auth? (s/keys :req-un [::postgres/postgres-db-user ::postgres/postgres-db-password +(s/def ::auth (s/keys :req-un [::postgres/postgres-db-user ::postgres/postgres-db-password ::nextcloud-admin-user ::nextcloud-admin-password - ::aws-access-key-id ::aws-secret-access-key - ::restic-password] + ::aws-access-key-id ::aws-secret-access-key] :opt-un [::mon/mon-auth])) #?(:cljs @@ -38,13 +35,13 @@ (get (inline-resources "nextcloud") resource-name))) (defn-spec generate-deployment cp/map-or-seq? - [config config?] + [config ::config] (let [{:keys [fqdn]} config] (-> (yaml/load-as-edn "nextcloud/deployment.yaml") (cm/replace-all-matching "fqdn" fqdn)))) (defn-spec generate-ingress-and-cert cp/map-or-seq? - [config config?] + [config ::config] (ing/generate-ingress-and-cert (merge {:service-name "cloud-service" @@ -64,7 +61,7 @@ (yaml/load-as-edn "nextcloud/service.yaml")) (defn-spec generate-secret cp/map-or-seq? - [auth auth?] + [auth ::auth] (let [{:keys [nextcloud-admin-user nextcloud-admin-password]} auth] (-> (yaml/load-as-edn "nextcloud/secret.yaml") diff --git a/src/main/cljs/dda/c4k_nextcloud/browser.cljs b/src/main/cljs/dda/c4k_nextcloud/browser.cljs index cb151c1..66443f6 100644 --- a/src/main/cljs/dda/c4k_nextcloud/browser.cljs +++ b/src/main/cljs/dda/c4k_nextcloud/browser.cljs @@ -2,28 +2,27 @@ (:require [clojure.tools.reader.edn :as edn] [dda.c4k-common.common :as cm] - [dda.c4k-common.monitoring :as mon] [dda.c4k-nextcloud.core :as core] - [dda.c4k-nextcloud.nextcloud :as nextcloud] - [dda.c4k-common.browser :as br] - [dda.c4k-common.postgres :as pgc])) + [dda.c4k-common.browser :as br])) (defn generate-content [] (cm/concat-vec [(assoc (br/generate-needs-validation) :content (cm/concat-vec - (br/generate-group "domain" - (cm/concat-vec (br/generate-input-field "fqdn" "Your fqdn:" "nextcloud-neu.prod.meissa-gmbh.de") - (br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "") - (br/generate-input-field "pv-storage-size-gb" "(Optional) Your nextcloud storage size in GB" "8") - (br/generate-input-field "pvc-storage-class-name" "(Optional) Your storage class type (manual / local-path):" "local-path") - (br/generate-input-field "postgres-data-volume-path" "(Optional) Your postgres-data-volume-path:" "/var/postgres") - (br/generate-input-field "restic-repository" "(Optional) Your restic-repository:" "restic-repository") - (br/generate-input-field "mon-cluster-name" "(Optional) monitoring cluster name:" "keycloak") - (br/generate-input-field "mon-cluster-stage" "(Optional) monitoring cluster stage:" "test") - (br/generate-input-field "mon-cloud-url" "(Optional) grafana cloud url:" "https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push"))) - (br/generate-group "credentials" + (br/generate-group "config" + (br/generate-text-area "config" "Your config.edn:" "{:fqdn \"cloud.your.domain\" + :issuer \"staging\" + :pv-storage-size-gb \"400\" + :pvc-storage-class-name \"local-path\" + :postgres-data-volume-path \"/var/postgres\" + :restic-repository \"s3://yourbucket/your-repo\" + :restic-password \"restic-password\"} + :mon-cfg {:cluster-name \"cloud\" + :cluster-stage \"test\" + :cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}" + "5")) + (br/generate-group "auth" (br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"nextcloud\" :postgres-db-password \"nextcloud-db-password\" :nextcloud-admin-password \"nextcloud-admin-password\" @@ -45,41 +44,9 @@ :content (generate-content)}) -(defn config-from-document [] - (let [pv-storage-size-gb (br/get-content-from-element "pv-storage-size-gb" :optional true) - pvc-storage-class-name (br/get-content-from-element "pvc-storage-class-name" :optional true) - postgres-data-volume-path (br/get-content-from-element "postgres-data-volume-path" :optional true) - restic-repository (br/get-content-from-element "restic-repository" :optional true) - issuer (br/get-content-from-element "issuer" :optional true) - mon-cluster-name (br/get-content-from-element "mon-cluster-name" :optional true) - mon-cluster-stage (br/get-content-from-element "mon-cluster-stage" :optional true) - mon-cloud-url (br/get-content-from-element "mon-cloud-url" :optional true)] - (merge - {:fqdn (br/get-content-from-element "fqdn")} - (when (and (some? pv-storage-size-gb) (some? pvc-storage-class-name)) - {:pv-storage-size-gb pv-storage-size-gb :pvc-storage-class-name pvc-storage-class-name}) - (when (some? postgres-data-volume-path) - {:postgres-data-volume-path postgres-data-volume-path}) - (when (some? restic-repository) - {:restic-repository restic-repository}) - (when (some? issuer) - {:issuer issuer}) - (when (some? mon-cluster-name) - {:mon-cfg {:cluster-name mon-cluster-name - :cluster-stage (keyword mon-cluster-stage) - :grafana-cloud-url mon-cloud-url}})))) - (defn validate-all! [] - (br/validate! "fqdn" ::nextcloud/fqdn) - (br/validate! "pv-storage-size-gb" ::nextcloud/pv-storage-size-gb :optional true) - (br/validate! "pvc-storage-class-name" ::nextcloud/pvc-storage-class-name :optional true) - (br/validate! "postgres-data-volume-path" ::pgc/postgres-data-volume-path :optional true) - (br/validate! "restic-repository" ::nextcloud/restic-repository :optional true) - (br/validate! "issuer" ::nextcloud/issuer :optional true) - (br/validate! "mon-cluster-name" ::mon/cluster-name :optional true) - (br/validate! "mon-cluster-stage" ::mon/cluster-stage :optional true) - (br/validate! "mon-cloud-url" ::mon/grafana-cloud-url :optional true) - (br/validate! "auth" nextcloud/auth? :deserializer edn/read-string) + (br/validate! "config" core/config? :deserializer edn/read-string) + (br/validate! "auth" core/auth? :deserializer edn/read-string) (br/set-validated!)) (defn add-validate-listener [name] @@ -92,19 +59,14 @@ (.getElementById "generate-button") (.addEventListener "click" #(do (validate-all!) - (-> (cm/generate-common - (config-from-document) + (-> (cm/generate-cm + (br/get-content-from-element "config" :deserializer edn/read-string) (br/get-content-from-element "auth" :deserializer edn/read-string) - {} - core/k8s-objects) + core/config-defaults + core/config-objects + core/auth-objects + false + false) (br/set-output!))))) - (add-validate-listener "fqdn") - (add-validate-listener "pv-storage-size-gb") - (add-validate-listener "pvc-storage-class-name") - (add-validate-listener "postgres-data-volume-path") - (add-validate-listener "restic-repository") - (add-validate-listener "issuer") - (add-validate-listener "mon-cluster-name") - (add-validate-listener "mon-cluster-stage") - (add-validate-listener "mon-cloud-url") + (add-validate-listener "config") (add-validate-listener "auth")) diff --git a/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc b/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc index aa013cf..4f651b7 100644 --- a/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc +++ b/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc @@ -2,8 +2,12 @@ (: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-nextcloud.backup :as cut])) +(st/instrument `cut/generate-secret) +(st/instrument `cut/generate-config) +(st/instrument `cut/generate-cron) (deftest should-generate-secret (is (= {:apiVersion "v1" diff --git a/src/test/cljc/dda/c4k_nextcloud/core_test.cljc b/src/test/cljc/dda/c4k_nextcloud/core_test.cljc new file mode 100644 index 0000000..7b84ec7 --- /dev/null +++ b/src/test/cljc/dda/c4k_nextcloud/core_test.cljc @@ -0,0 +1,19 @@ +(ns dda.c4k-nextcloud.core-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.alpha :as s] + [dda.c4k-common.yaml :as yaml] + [dda.c4k-nextcloud.core :as cut] + #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]]))) + + +#?(:cljs + (defmethod yaml/load-resource :nextcloud-test [resource-name] + (get (inline-resources "nextcloud-test") resource-name))) + +(deftest validate-valid-resources + (is (s/valid? cut/config? (yaml/load-as-edn "nextcloud-test/valid-config.yaml"))) + (is (s/valid? cut/auth? (yaml/load-as-edn "nextcloud-test/valid-auth.yaml"))) + (is (not (s/valid? cut/config? (yaml/load-as-edn "nextcloud-test/invalid-config.yaml")))) + (is (not (s/valid? cut/auth? (yaml/load-as-edn "nextcloud-test/invalid-auth.yaml"))))) diff --git a/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc b/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc index daa7f45..52c93fc 100644 --- a/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc +++ b/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc @@ -2,24 +2,20 @@ (:require #?(:clj [clojure.test :refer [deftest is are testing run-tests]] :cljs [cljs.test :refer-macros [deftest is are testing run-tests]]) - [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [dda.c4k-common.yaml :as yaml] [dda.c4k-nextcloud.nextcloud :as cut] #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]]))) -(st/instrument) +(st/instrument `cut/generate-secret) +(st/instrument `cut/generate-ingress-and-cert) +(st/instrument `cut/generate-pvc) +(st/instrument `cut/generate-deployment) #?(:cljs (defmethod yaml/load-resource :nextcloud-test [resource-name] (get (inline-resources "nextcloud-test") resource-name))) -(deftest validate-valid-resources - (is (s/valid? cut/config? (yaml/load-as-edn "nextcloud-test/valid-config.yaml"))) - (is (s/valid? cut/auth? (yaml/load-as-edn "nextcloud-test/valid-auth.yaml"))) - (is (not (s/valid? cut/config? (yaml/load-as-edn "nextcloud-test/invalid-config.yaml")))) - (is (not (s/valid? cut/auth? (yaml/load-as-edn "nextcloud-test/invalid-auth.yaml"))))) - (deftest should-generate-secret (is (= {:apiVersion "v1" :kind "Secret" @@ -95,7 +91,7 @@ {:metadata {:labels {:app "cloud-app", :app.kubernetes.io/name "cloud-pod", :app.kubernetes.io/application "cloud", :redeploy "v3"}} :spec {:containers - [{:image "domaindrivenarchitecture/c4k-cloud:10.4.0" + [{:image "domaindrivenarchitecture/c4k-cloud:10.4.2" :name "cloud-app" :imagePullPolicy "IfNotPresent" :ports [{:containerPort 80}]