diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/package.json b/package.json new file mode 100644 index 0000000..7c322cb --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "c4k-matomo", + "description": "Generate c4k yaml for a matomo deployment.", + "author": "meissa GmbH", + "version": "1.0.4-SNAPSHOT", + "homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-matomo#readme", + "repository": "https://www.npmjs.com/package/c4k-matomo", + "license": "APACHE2", + "main": "c4k-matomo.js", + "bin": { + "c4k-matomo": "./c4k-matomo.js" + }, + "keywords": [ + "cljs", + "matomo", + "k8s", + "c4k", + "deployment", + "yaml", + "convention4kubernetes" + ], + "bugs": { + "url": "https://gitlab.com/domaindrivenarchitecture/c4k-matomo/issues" + }, + "dependencies": { + "js-base64": "^3.6.1", + "js-yaml": "^4.0.0" + }, + "devDependencies": { + "shadow-cljs": "^2.11.18", + "source-map-support": "^0.5.19" + } +} diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..ac6b3a7 --- /dev/null +++ b/project.clj @@ -0,0 +1,42 @@ +(defproject org.domaindrivenarchitecture/c4k-matomo "1.0.0-SNAPSHOT" + :description "matomo c4k-installation package" + :url "https://domaindrivenarchitecture.org" + :license {:name "Apache License, Version 2.0" + :url "https://www.apache.org/licenses/LICENSE-2.0.html"} + :dependencies [[org.clojure/clojure "1.10.3"] + [org.clojure/tools.reader "1.3.6"] + [org.domaindrivenarchitecture/c4k-common-clj "0.4.0"] + [hickory "0.7.1"]] + :target-path "target/%s/" + :source-paths ["src/main/cljc" + "src/main/clj"] + :resource-paths ["src/main/resources"] + :repositories [["snapshots" :clojars] + ["releases" :clojars]] + :deploy-repositories [["snapshots" :clojars] + ["releases" :clojars]] + :profiles {:test {:test-paths ["src/test/cljc"] + :resource-paths ["src/test/resources"] + :dependencies [[dda/data-test "0.1.1"]]} + :dev {:plugins [[lein-shell "0.5.0"]]} + :uberjar {:aot :all + :main dda.c4k-matomo.uberjar + :uberjar-name "c4k-matomo-standalone.jar" + :dependencies [[org.clojure/tools.cli "1.0.206"] + [ch.qos.logback/logback-classic "1.3.0-alpha4" + :exclusions [com.sun.mail/javax.mail]] + [org.slf4j/jcl-over-slf4j "2.0.0-alpha1"]]}} + :release-tasks [["test"] + ["vcs" "assert-committed"] + ["change" "version" "leiningen.release/bump-version" "release"] + ["vcs" "commit"] + ["vcs" "tag"] + ["change" "version" "leiningen.release/bump-version"]] + :aliases {"native" ["shell" + "native-image" + "--report-unsupported-elements-at-runtime" + "--initialize-at-build-time" + "-jar" "target/uberjar/c4k-matomo-standalone.jar" + "-H:ResourceConfigurationFiles=graalvm-resource-config.json" + "-H:Log=registerResource" + "-H:Name=target/graalvm/${:name}"]}) diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..d00c7d3 --- /dev/null +++ b/public/index.html @@ -0,0 +1,18 @@ + + + + + + c4k-matomo + + + + + + +
+ + + + \ No newline at end of file diff --git a/shadow-cljs.edn b/shadow-cljs.edn new file mode 100644 index 0000000..77e3aed --- /dev/null +++ b/shadow-cljs.edn @@ -0,0 +1,16 @@ +{:source-paths ["src/main/cljc" + "src/main/cljs" + "src/main/resources" + "src/test/cljc" + "src/test/cljs" + "src/test/resources"] + :dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "0.4.3"] + [hickory "0.7.1"]] + :builds {:frontend {:target :browser + :modules {:main {:init-fn dda.c4k-matomo.browser/init}} + :release {} + :compiler-options {:optimizations :advanced}} + :test {:target :node-test + :output-to "target/node-tests.js" + :autorun true + :repl-pprint true}}} \ No newline at end of file diff --git a/src/main/clj/dda/c4k_matomo/uberjar.clj b/src/main/clj/dda/c4k_matomo/uberjar.clj new file mode 100644 index 0000000..6717067 --- /dev/null +++ b/src/main/clj/dda/c4k_matomo/uberjar.clj @@ -0,0 +1,56 @@ +(ns dda.c4k-matomo.uberjar + (:gen-class) + (:require + [clojure.spec.alpha :as s] + [clojure.string :as cs] + [clojure.tools.reader.edn :as edn] + [expound.alpha :as expound] + [dda.c4k-matomo.core :as core])) + +(def usage + "usage: + + c4k-matomo {your configuraton file} {your authorization file}") + +(s/def ::options (s/* #{"-h"})) +(s/def ::filename (s/and string? + #(not (cs/starts-with? % "-")))) +(s/def ::cmd-args (s/cat :options ::options + :args (s/? + (s/cat :config ::filename + :auth ::filename)))) + +(defn expound-config + [config] + (expound/expound ::core/config config)) + +(defn invalid-args-msg + [spec args] + (s/explain spec args) + (println (str "Bad commandline arguments\n" usage))) + +(defn -main [& cmd-args] + (let [parsed-args-cmd (s/conform ::cmd-args cmd-args)] + (if (= ::s/invalid parsed-args-cmd) + (invalid-args-msg ::cmd-args cmd-args) + (let [{:keys [options args]} parsed-args-cmd + {:keys [config auth]} args] + (cond + (some #(= "-h" %) options) + (println usage) + :default + (let [config-str (slurp config) + auth-str (slurp auth) + config-edn (edn/read-string config-str) + auth-edn (edn/read-string auth-str) + config-valid? (s/valid? core/config? config-edn) + auth-valid? (s/valid? core/auth? auth-edn)] + (if (and config-valid? auth-valid?) + (println (core/generate config-edn auth-edn)) + (do + (when (not config-valid?) + (println + (expound/expound-str core/config? config-edn {:print-specs? false}))) + (when (not auth-valid?) + (println + (expound/expound-str core/auth? auth-edn {:print-specs? false}))))))))))) diff --git a/src/main/cljc/dda/c4k_matomo/core.cljc b/src/main/cljc/dda/c4k_matomo/core.cljc new file mode 100644 index 0000000..4a1a539 --- /dev/null +++ b/src/main/cljc/dda/c4k_matomo/core.cljc @@ -0,0 +1,29 @@ +(ns dda.c4k-matomo.core + (:require + [clojure.string :as cs] + [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.postgres :as postgres] + [dda.c4k-matomo.matomo :as matomo])) + +(def config-defaults {:issuer :staging}) + +(def config? (s/keys :req-un [::matomo/fqdn] + :opt-un [])) + +(def auth? (s/keys :req-un [])) + +(defn k8s-objects [config] + (into + [] + (concat []))) + +(defn-spec generate any? + [my-config config? + my-auth auth?] + (let [resulting-config (merge config-defaults my-config my-auth)] + (cs/join + "\n---\n" + (k8s-objects resulting-config)))) diff --git a/src/main/cljc/dda/c4k_matomo/matomo.cljc b/src/main/cljc/dda/c4k_matomo/matomo.cljc new file mode 100644 index 0000000..ae6a3a2 --- /dev/null +++ b/src/main/cljc/dda/c4k_matomo/matomo.cljc @@ -0,0 +1,56 @@ +(ns dda.c4k-matomo.matomo + (:require + [clojure.spec.alpha :as s] + #?(:cljs [shadow.resource :as rc]) + [dda.c4k-common.yaml :as yaml] + [dda.c4k-common.common :as cm])) + +(s/def ::fqdn cm/fqdn-string?) +(s/def ::issuer cm/letsencrypt-issuer?) +(s/def ::matomo-data-volume-path string?) + +#?(:cljs + (defmethod yaml/load-resource :matomo [resource-name] + (case resource-name + ;"matomo/certificate.yaml" (rc/inline "matomo/certificate.yaml") + ;"matomo/deployment.yaml" (rc/inline "matomo/deployment.yaml") + ;"matomo/ingress.yaml" (rc/inline "matomo/ingress.yaml") + ;"matomo/persistent-volume.yaml" (rc/inline "matomo/persistent-volume.yaml") + ;"matomo/pvc.yaml" (rc/inline "matomo/pvc.yaml") + ;"matomo/service.yaml" (rc/inline "matomo/service.yaml") + (throw (js/Error. "Undefined Resource!"))))) + +(defn generate-certificate [config] + (let [{:keys [fqdn issuer]} config + letsencrypt-issuer (str "letsencrypt-" (name issuer) "-issuer")] + (-> + (yaml/from-string (yaml/load-resource "matomo/certificate.yaml")) + (assoc-in [:spec :commonName] fqdn) + (assoc-in [:spec :dnsNames] [fqdn]) + (assoc-in [:spec :issuerRef :name] letsencrypt-issuer)))) + +(defn generate-deployment [config] + (let [{:keys [fqdn]} config] + (-> (yaml/from-string (yaml/load-resource "matomo/deployment.yaml")) + (cm/replace-named-value "FQDN" fqdn)))) + +(defn generate-ingress [config] + (let [{:keys [fqdn issuer] + :or {issuer :staging}} config + letsencrypt-issuer (str "letsencrypt-" (name issuer) "-issuer")] + (-> + (yaml/from-string (yaml/load-resource "matomo/ingress.yaml")) + (assoc-in [:metadata :annotations :cert-manager.io/cluster-issuer] letsencrypt-issuer) + (cm/replace-all-matching-values-by-new-value "fqdn" fqdn)))) + +(defn generate-persistent-volume [config] + (let [{:keys [matomo-data-volume-path]} config] + (-> + (yaml/from-string (yaml/load-resource "matomo/persistent-volume.yaml")) + (assoc-in [:spec :hostPath :path] matomo-data-volume-path)))) + +(defn generate-pvc [] + (yaml/from-string (yaml/load-resource "matomo/pvc.yaml"))) + +(defn generate-service [] + (yaml/from-string (yaml/load-resource "matomo/service.yaml"))) diff --git a/src/main/cljs/dda/c4k_matomo/browser.cljs b/src/main/cljs/dda/c4k_matomo/browser.cljs new file mode 100644 index 0000000..42c6f6f --- /dev/null +++ b/src/main/cljs/dda/c4k_matomo/browser.cljs @@ -0,0 +1,80 @@ +(ns dda.c4k-matomo.browser + (:require + [clojure.tools.reader.edn :as edn] + [dda.c4k-matomo.core :as core] + [dda.c4k-matomo.matomo :as matomo] + [dda.c4k-common.browser :as br] + [dda.c4k-common.postgres :as pgc])) + +(defn generate-content + [] + (into [] (concat [(assoc (br/generate-needs-validation) :content + (into [] (concat (br/generate-input-field "fqdn" "Your fqdn:" "matomo-neu.prod.meissa-gmbh.de") + (br/generate-input-field "matomo-data-volume-path" "(Optional) Your matomo-data-volume-path:" "/var/matomo") + (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 "issuer" "(Optional) Your issuer prod/staging:" "") + [(br/generate-br)] + (br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"matomo\" + :postgres-db-password \"matomo-db-password\" + :aws-access-key-id \"aws-id\" + :aws-secret-access-key \"aws-secret\" + :restic-password \"restic-password\"}" + "5") + [(br/generate-br)] + (br/generate-button "generate-button" "Generate c4k yaml"))))] + (br/generate-output "c4k-nextcloud-output" "Your c4k deployment.yaml:" "25")))) + +(defn generate-content-div + [] + {:type :element + :tag :div + :content + (generate-content)}) + +(defn config-from-document [] + (let [matomo-data-volume-path (br/get-content-from-element "matomo-data-volume-path" :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 :deserializer keyword)] + (merge + {:fqdn (br/get-content-from-element "fqdn")} + (when (some? matomo-data-volume-path) + {:matomo-data-volume-path matomo-data-volume-path}) + (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}) + ))) + +(defn validate-all! [] + (br/validate! "fqdn" ::matomo/fqdn) + (br/validate! "matomo-data-volume-path" ::matomo/matomo-data-volume-path :optional true) + (br/validate! "postgres-data-volume-path" ::pgc/postgres-data-volume-path :optional true) + (br/validate! "issuer" ::matomo/issuer :optional true :deserializer keyword) + (br/validate! "auth" core/auth? :deserializer edn/read-string) + (br/set-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!) + (-> (core/generate + (config-from-document) + (br/get-content-from-element "auth" :deserializer edn/read-string)) + (br/set-output!))))) + (add-validate-listener "fqdn") + (add-validate-listener "matomo-data-volume-path") + (add-validate-listener "postgres-data-volume-path") + (add-validate-listener "restic-repository") + (add-validate-listener "issuer") + (add-validate-listener "auth")) \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..8985f2b --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,50 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + INFO + + + + + logs/pallet.log + + logs/old/pallet.%d{yyyy-MM-dd}.log + 3 + + + %date %level [%thread] %logger{10} %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +