Merge branch 'main' of ssh://repo.prod.meissa.de:2222/meissa/c4k-taiga

This commit is contained in:
Michael Jerger 2025-01-24 15:06:40 +01:00
commit 46c49a3317
65 changed files with 626 additions and 522 deletions

5
.gitignore vendored
View file

@ -27,8 +27,7 @@ public/js/
*.iml *.iml
.idea/ .idea/
auth.edn
config.edn
build-and-move-frontend.sh build-and-move-frontend.sh
website.yaml website.yaml
.envrc

View file

@ -2,7 +2,7 @@
[![Clojars Project](https://img.shields.io/clojars/v/org.domaindrivenarchitecture/c4k-taiga.svg)](https://clojars.org/org.domaindrivenarchitecture/c4k-taiga) [![pipeline status](https://gitlab.com/domaindrivenarchitecture/c4k-taiga/badges/master/pipeline.svg)](https://gitlab.com/domaindrivenarchitecture/c4k-taiga/-/commits/main) [![Clojars Project](https://img.shields.io/clojars/v/org.domaindrivenarchitecture/c4k-taiga.svg)](https://clojars.org/org.domaindrivenarchitecture/c4k-taiga) [![pipeline status](https://gitlab.com/domaindrivenarchitecture/c4k-taiga/badges/master/pipeline.svg)](https://gitlab.com/domaindrivenarchitecture/c4k-taiga/-/commits/main)
[<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa-gmbh.de/img/community/Mastodon_Logotype.svg" width=20 alt="team@social.meissa-gmbh.de"> team@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@team) | [taiga & Blog](https://domaindrivenarchitecture.org) [<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa.de/images/parts/contact/mastodon36_hue9b2464f10b18e134322af482b9c915e_5501_filter_14705073121015236177.png" width=20 alt="M"> meissa@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@meissa) | [Blog](https://domaindrivenarchitecture.org) | [Website](https://meissa.de)
## Purpose ## Purpose
@ -63,10 +63,18 @@ To set up you need:
Apply this file on your cluster with `kubectl apply -f application.yaml`. Apply this file on your cluster with `kubectl apply -f application.yaml`.
Done. Done.
## Setup
`python manage.py createsuperuser --noinput`
## Administration ## Administration
You can access the administration of the taiga installation via: your.taiga.url/admin/ You can access the administration of the taiga installation via: your.taiga.url/admin/
In order to login, you first have to create a superuser.
1. Connect to taiga-back pod: `kubectl exec -it taiga-back-deployment-... -- bash`
2. `source /opt/venv/bin/activate && python manage.py createsuperuser --noinput`
## Backup ## Backup
You need some form of cloud storage like AWS buckets and the respective access credentials You need some form of cloud storage like AWS buckets and the respective access credentials
@ -90,7 +98,7 @@ For more details about our repository model see: https://repo.prod.meissa.de/mei
## License ## License
Copyright © 2022 meissa GmbH Copyright © 2024, 2025 meissa GmbH
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License") Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE) Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)

View file

@ -152,6 +152,7 @@ def upload_clj(project):
@task @task
def inst(project): def inst(project):
run("lein uberjar", shell=True, check=True)
package_uberjar(project) package_uberjar(project)
package_native(project) package_native(project)
run( run(

View file

@ -1,14 +1,20 @@
from os import environ from os import environ
from datetime import datetime
from pybuilder.core import task, init from pybuilder.core import task, init
from ddadevops import * from ddadevops import *
name = "c4k-taiga-backup" name = "c4k-taiga"
MODULE = "docker" MODULE = "backup"
PROJECT_ROOT_PATH = "../.." PROJECT_ROOT_PATH = "../.."
version = "1.2.5-dev"
@init @init
def initialize(project): def initialize(project):
image_tag = version
if "dev" in image_tag:
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
input = { input = {
"name": name, "name": name,
"module": MODULE, "module": MODULE,
@ -16,9 +22,11 @@ def initialize(project):
"project_root_path": PROJECT_ROOT_PATH, "project_root_path": PROJECT_ROOT_PATH,
"build_types": ["IMAGE"], "build_types": ["IMAGE"],
"mixin_types": [], "mixin_types": [],
"image_naming": "NAME_AND_MODULE",
"image_tag": f"{image_tag}",
} }
project.build_depends_on("ddadevops>=4.0.0-dev") project.build_depends_on("ddadevops>=4.7.0")
build = DevopsImageBuild(project, input) build = DevopsImageBuild(project, input)
build.initialize_build_dir() build.initialize_build_dir()
@ -29,21 +37,18 @@ def image(project):
build = get_devops_build(project) build = get_devops_build(project)
build.image() build.image()
@task @task
def drun(project): def drun(project):
build = get_devops_build(project) build = get_devops_build(project)
build.drun() build.drun()
@task
def test(project):
build = get_devops_build(project)
build.test()
@task @task
def publish(project): def publish(project):
build = get_devops_build(project) build = get_devops_build(project)
build.dockerhub_login() build.dockerhub_login()
build.dockerhub_publish() build.dockerhub_publish()
@task
def test(project):
build = get_devops_build(project)
build.test()

View file

@ -1,5 +1,5 @@
FROM domaindrivenarchitecture/dda-backup:latest FROM domaindrivenarchitecture/dda-backup:5.3.0
# Prepare Entrypoint Script # Prepare Entrypoint Script
ADD resources /tmp ADD resources /tmp
RUN /tmp/install.sh RUN /tmp/install.bb

View file

@ -0,0 +1,29 @@
#!/usr/bin/env bb
(require
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.restic :as rc]
'[dda.backup.postgresql :as pg]
'[dda.backup.backup :as bak])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(defn prepare!
[]
(bc/create-aws-credentials! (:aws-config config))
(pg/create-pg-pass! (:db-config config)))
(defn restic-repo-init!
[]
(rc/init! (:file-config config))
(rc/init! (:db-config config)))
(defn restic-backup!
[]
(bak/backup-file! (:file-config config))
(bak/backup-db! (:db-config config)))
(prepare!)
(restic-repo-init!)
(restic-backup!)

View file

@ -1,17 +0,0 @@
#!/bin/bash
function main() {
file_env AWS_ACCESS_KEY_ID
file_env AWS_SECRET_ACCESS_KEY
file_env RESTIC_DAYS_TO_KEEP 30
file_env RESTIC_MONTHS_TO_KEEP 12
backup-db-dump
backup-directory "/media"
}
source /usr/local/lib/functions.sh
source /usr/local/lib/pg-functions.sh
source /usr/local/lib/file-functions.sh
main

View file

@ -0,0 +1,4 @@
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
orchestra/orchestra {:mvn/version "2021.01.01-1"}
aero/aero {:mvn/version "1.1.6"}
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}

View file

@ -0,0 +1,3 @@
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
orchestra/orchestra {:mvn/version "2021.01.01-1"}
org.domaindrivenarchitecture/dda-build {:mvn/version "0.2.0"}}}

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bb
(require
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.restic :as rc])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(def file-pw-change-config (merge (:file-config config)
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
(def db-pw-change-config (merge (:db-config config)
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
(defn prepare!
[]
(bc/create-aws-credentials! (:aws-config config)))
(defn change-password!
[]
(rc/change-password! file-pw-change-config)
(rc/change-password! db-pw-change-config))
(prepare!)
(change-password!)

View file

@ -0,0 +1,24 @@
{:restic-repo {:password-file #env-or-file "RESTIC_PASSWORD_FILE"
:restic-repository #env-or-file "RESTIC_REPOSITORY"}
:file-config #merge [#ref [:restic-repo]
{:backup-path "files"
:execution-directory "/media"
:files ["."]}]
:file-restore-config #merge [#ref [:restic-repo]
{:backup-path "files"
:restore-target-directory "/media/"
:clean-up-elements ["user"]}]
:db-config #merge [#ref [:restic-repo] {:backup-path "pg-database"
:pg-host #env-or-file "POSTGRES_SERVICE"
:pg-port #env-or-file "POSTGRES_PORT"
:pg-db #env-or-file "POSTGRES_DB"
:pg-user #env-or-file "POSTGRES_USER"
:pg-password #env-or-file "POSTGRES_PASSWORD"}]
:aws-config {:aws-access-key-id #env-or-file "AWS_ACCESS_KEY_ID"
:aws-secret-access-key #env-or-file "AWS_SECRET_ACCESS_KEY"}
:dry-run {:dry-run true :debug true}}

View file

@ -1,13 +0,0 @@
#!/bin/bash
function main() {
create-pg-pass
while true; do
sleep 1m
done
}
source /usr/local/lib/functions.sh
source /usr/local/lib/pg-functions.sh
main

View file

@ -1,11 +0,0 @@
#!/bin/bash
function main() {
create-pg-pass
/usr/local/bin/backup.sh
}
source /usr/local/lib/functions.sh
source /usr/local/lib/pg-functions.sh
main

View file

@ -0,0 +1,3 @@
#!/usr/bin/env bb
(println "initialized")

View file

@ -1,14 +0,0 @@
#!/bin/bash
function main() {
file_env AWS_ACCESS_KEY_ID
file_env AWS_SECRET_ACCESS_KEY
init-database-repo
init-file-repo
}
source /usr/local/lib/functions.sh
source /usr/local/lib/pg-functions.sh
source /usr/local/lib/file-functions.sh
main

View file

@ -0,0 +1,18 @@
#!/usr/bin/env bb
(require
'[dda.image.ubuntu :as ub]
'[dda.image.install :as in])
(ub/upgrade-system!)
(in/install! "bb-backup.edn" :target-name "bb.edn" :mod "0440")
(in/install! "config.edn" :mod "0440")
(in/install! "init.bb")
(in/install! "backup.bb")
(in/install! "restore.bb")
(in/install! "list-snapshots.bb")
(in/install! "change-password.bb")
(in/install! "restore.bb")
(in/install! "wait.bb")
(ub/cleanup-container!)

View file

@ -1,21 +0,0 @@
#!/bin/bash
set -exo pipefail
function main()
{
{
install -m 0700 /tmp/entrypoint.sh /
install -m 0700 /tmp/entrypoint-start-and-wait.sh /
install -m 0700 /tmp/init.sh /usr/local/bin/
install -m 0700 /tmp/backup.sh /usr/local/bin/
install -m 0700 /tmp/restore.sh /usr/local/bin/
install -m 0700 /tmp/restic-snapshots.sh /usr/local/bin/
cleanupDocker
} > /dev/null
}
source /tmp/install_functions_debian.sh
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bb
(require
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.restic :as rc])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(defn prepare!
[]
(bc/create-aws-credentials! (:aws-config config)))
(defn list-snapshots!
[]
(rc/list-snapshots! (:file-config config))
(rc/list-snapshots! (:db-config config)))
(prepare!)
(list-snapshots!)

View file

@ -1,14 +0,0 @@
#!/bin/bash
function main() {
file_env AWS_ACCESS_KEY_ID
file_env AWS_SECRET_ACCESS_KEY
restic -r ${RESTIC_REPOSITORY}/files snapshots
restic -r ${RESTIC_REPOSITORY}/pg-database snapshots
}
source /usr/local/lib/functions.sh
source /usr/local/lib/file-functions.sh
main

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bb
(require
'[babashka.tasks :as t]
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.postgresql :as pg]
'[dda.backup.restore :as rs])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(defn prepare!
[]
(bc/create-aws-credentials! (:aws-config config))
(pg/create-pg-pass! (:db-config config)))
(defn restic-restore!
[]
(pg/drop-create-db! (:db-config config))
(rs/restore-db! (:db-config config))
(rs/restore-file! (:file-restore-config config))
(t/shell "chown -R 999:999 /media"))
(prepare!)
(restic-restore!)

View file

@ -1,29 +0,0 @@
#!/bin/bash
function main() {
file_env AWS_ACCESS_KEY_ID
file_env AWS_SECRET_ACCESS_KEY
file_env POSTGRES_DB
file_env POSTGRES_PASSWORD
file_env POSTGRES_USER
# Restore latest snapshot into /var/backups/restore
restore-directory '/var/backups/restore'
mv /var/backups/restore/* /media
# adjust file permissions for the taiga user
chown -R 999:999 /media
# Restore db
drop-create-db
restore-db
}
source /usr/local/lib/functions.sh
source /usr/local/lib/pg-functions.sh
source /usr/local/lib/file-functions.sh
main

View file

@ -0,0 +1,19 @@
#!/usr/bin/env bb
(require
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.postgresql :as pg])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(defn prepare!
[]
(bc/create-aws-credentials! (:aws-config config))
(pg/create-pg-pass! (:db-config config)))
(defn wait! []
(while true
(Thread/sleep 1000)))
(prepare!)
(wait!)

View file

@ -0,0 +1,4 @@
FROM c4k-taiga-backup:latest
ADD resources /tmp/
RUN RESTIC_PASSWORD_FILE=/tmp/file_password RESTIC_NEW_PASSWORD_FILE=/tmp/new_file_password RESTIC_REPOSITORY=restic-repo POSTGRES_SERVICE=dummy POSTGRES_PORT=dummy POSTGRES_DB=dummy POSTGRES_USER=dummy POSTGRES_PASSWORD=dummy AWS_ACCESS_KEY_ID=dummy AWS_SECRET_ACCESS_KEY=dummy /tmp/test.bb

View file

@ -0,0 +1,4 @@
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
orchestra/orchestra {:mvn/version "2021.01.01-1"}
aero/aero {:mvn/version "1.1.6"}
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}

View file

@ -0,0 +1 @@
oldPassword

View file

@ -0,0 +1 @@
newPassword

View file

@ -0,0 +1,59 @@
#!/usr/bin/env bb
(require '[babashka.tasks :as tasks]
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.restic :as rc]
'[dda.backup.postgresql :as pg]
'[dda.backup.backup :as bak]
'[dda.backup.restore :as rs])
(def config (cfg/read-config "/usr/local/bin/config.edn"))
(def file-pw-change-config (merge (:file-config config)
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
(defn prepare!
[]
(tasks/shell "mkdir" "-p" "/var/backups/")
(spit "/var/backups/file" "I was here")
(tasks/shell "mkdir" "-p" "/var/restore"))
(defn restic-repo-init!
[]
(rc/init! (:file-config config))
(rc/init! (merge (:db-config config)
(:dry-run config))))
(defn restic-backup!
[]
(bak/backup-file! (:file-config config))
(bak/backup-db! (merge (:db-config config)
(:dry-run config))))
(defn list-snapshots!
[]
(rc/list-snapshots! (:file-config config))
(rc/list-snapshots! (merge (:db-config config)
(:dry-run config))))
(defn restic-restore!
[]
(pg/drop-create-db! (merge (:db-config config)
(:dry-run config)))
(rs/restore-db! (merge (:db-config config)
(:dry-run config)))
(rs/restore-file! (merge (:file-restore-config config)
(:dry-run config))))
(defn change-password!
[]
(println "change-password!")
(rc/change-password! file-pw-change-config))
(prepare!)
(restic-repo-init!)
(restic-backup!)
(list-snapshots!)
(restic-restore!)
(change-password!)

View file

@ -2,7 +2,7 @@
"name": "c4k-taiga", "name": "c4k-taiga",
"description": "Generate c4k yaml for a taiga project management deployment.", "description": "Generate c4k yaml for a taiga project management deployment.",
"author": "meissa GmbH", "author": "meissa GmbH",
"version": "1.1.3-SNAPSHOT", "version": "1.2.5-SNAPSHOT",
"homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga#readme", "homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga#readme",
"repository": "https://www.npmjs.com/package/c4k-taiga", "repository": "https://www.npmjs.com/package/c4k-taiga",
"license": "APACHE2", "license": "APACHE2",
@ -23,11 +23,11 @@
"url": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga/issues" "url": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga/issues"
}, },
"dependencies": { "dependencies": {
"js-base64": "^3.7.5", "js-base64": "^3.7.7",
"js-yaml": "^4.0.0" "js-yaml": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"shadow-cljs": "^2.11.18", "shadow-cljs": "^2.28.20",
"source-map-support": "^0.5.19" "source-map-support": "^0.5.21"
} }
} }

View file

@ -1,11 +1,11 @@
(defproject org.domaindrivenarchitecture/c4k-taiga "1.1.3-SNAPSHOT" (defproject org.domaindrivenarchitecture/c4k-taiga "1.2.5-SNAPSHOT"
:description "taiga c4k-installation package" :description "taiga c4k-installation package"
:url "https://domaindrivenarchitecture.org" :url "https://domaindrivenarchitecture.org"
:license {:name "Apache License, Version 2.0" :license {:name "Apache License, Version 2.0"
:url "https://www.apache.org/licenses/LICENSE-2.0.html"} :url "https://www.apache.org/licenses/LICENSE-2.0.html"}
:dependencies [[org.clojure/clojure "1.11.1"] :dependencies [[org.clojure/clojure "1.12.0"]
[org.clojure/tools.reader "1.4.0"] [org.clojure/tools.reader "1.5.0"]
[org.domaindrivenarchitecture/c4k-common-clj "6.1.3"] [org.domaindrivenarchitecture/c4k-common-clj "9.0.1"]
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]] [hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
:target-path "target/%s/" :target-path "target/%s/"
:source-paths ["src/main/cljc" :source-paths ["src/main/cljc"
@ -23,9 +23,9 @@
:main dda.c4k-taiga.uberjar :main dda.c4k-taiga.uberjar
:uberjar-name "c4k-taiga-standalone.jar" :uberjar-name "c4k-taiga-standalone.jar"
:dependencies [[org.clojure/tools.cli "1.1.230"] :dependencies [[org.clojure/tools.cli "1.1.230"]
[ch.qos.logback/logback-classic "1.5.0" [ch.qos.logback/logback-classic "1.5.16"
:exclusions [com.sun.mail/javax.mail]] :exclusions [com.sun.mail/javax.mail]]
[org.slf4j/jcl-over-slf4j "2.0.12"] [org.slf4j/jcl-over-slf4j "2.0.16"]
[com.github.clj-easy/graal-build-time "1.0.5"]]}} [com.github.clj-easy/graal-build-time "1.0.5"]]}}
:release-tasks [["test"] :release-tasks [["test"]
["vcs" "assert-committed"] ["vcs" "assert-committed"]

View file

@ -4,7 +4,7 @@
"src/test/cljc" "src/test/cljc"
"src/test/cljs" "src/test/cljs"
"src/test/resources"] "src/test/resources"]
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "6.1.3"] :dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "9.0.1"]
[hickory "0.7.1"]] [hickory "0.7.1"]]
:builds {:frontend {:target :browser :builds {:frontend {:target :browser
:modules {:main {:init-fn dda.c4k-taiga.browser/init}} :modules {:main {:init-fn dda.c4k-taiga.browser/init}}

View file

@ -4,12 +4,12 @@
[dda.c4k-common.uberjar :as uberjar] [dda.c4k-common.uberjar :as uberjar]
[dda.c4k-taiga.core :as core])) [dda.c4k-taiga.core :as core]))
(defn -main [& cmd-args] (defn -main [& cmd-args]
(uberjar/main-common (uberjar/main-cm
"c4k-taiga" "c4k-taiga"
core/config? core/config?
core/auth? core/auth?
core/config-defaults core/defaults
core/k8s-objects core/config-objects
core/auth-objects
cmd-args)) cmd-args))

View file

@ -1,45 +1,52 @@
(ns dda.c4k-taiga.backup (ns dda.c4k-taiga.backup
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
#?(:cljs [shadow.resource :as rc]) #?(:clj [orchestra.core :refer [defn-spec]]
[dda.c4k-common.yaml :as yaml] :cljs [orchestra.core :refer-macros [defn-spec]])
[dda.c4k-common.base64 :as b64] [dda.c4k-common.yaml :as yaml]
[dda.c4k-common.common :as cm] [dda.c4k-common.base64 :as b64]
[dda.c4k-common.predicate :as pd])) [dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as p]
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
(s/def ::aws-access-key-id pd/bash-env-string?) (s/def ::aws-access-key-id p/bash-env-string?)
(s/def ::aws-secret-access-key pd/bash-env-string?) (s/def ::aws-secret-access-key p/bash-env-string?)
(s/def ::restic-password pd/bash-env-string?) (s/def ::restic-password p/bash-env-string?)
(s/def ::restic-repository pd/bash-env-string?) (s/def ::restic-new-password p/bash-env-string?)
(s/def ::restic-repository p/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]
:opt-un [::restic-new-password]))
#?(:cljs #?(:cljs
(defmethod yaml/load-resource :backup [resource-name] (defmethod yaml/load-resource :backup [resource-name]
(case resource-name (get (inline-resources "backup") resource-name)))
"backup/config.yaml" (rc/inline "backup/config.yaml")
"backup/cron.yaml" (rc/inline "backup/cron.yaml")
"backup/secret.yaml" (rc/inline "backup/secret.yaml")
"backup/backup-restore-deployment.yaml" (rc/inline "backup/backup-restore-deployment.yaml")
(throw (js/Error. "Undefined Resource!")))))
(defn generate-config [my-conf] (defn-spec generate-config p/map-or-seq?
[my-conf ::config]
(let [{:keys [restic-repository]} my-conf] (let [{:keys [restic-repository]} my-conf]
(-> (->
(yaml/load-as-edn "backup/config.yaml") (yaml/load-as-edn "backup/config.yaml")
(cm/replace-key-value :restic-repository restic-repository)))) (cm/replace-key-value :restic-repository restic-repository))))
(defn generate-cron [] (defn-spec generate-cron p/map-or-seq?
(yaml/load-as-edn "backup/cron.yaml")) []
(yaml/load-as-edn "backup/cron.yaml"))
(defn generate-backup-restore-deployment [my-conf] (defn-spec generate-backup-restore-deployment p/map-or-seq?
(let [backup-restore-yaml (yaml/load-as-edn "backup/backup-restore-deployment.yaml")] [my-conf ::config]
(if (and (contains? my-conf :local-integration-test) (= true (:local-integration-test my-conf))) (yaml/load-as-edn "backup/backup-restore-deployment.yaml"))
(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 p/map-or-seq?
(let [{:keys [aws-access-key-id aws-secret-access-key restic-password]} my-auth] [auth ::auth]
(-> (let [{:keys [aws-access-key-id aws-secret-access-key
(yaml/load-as-edn "backup/secret.yaml") restic-password restic-new-password]} auth]
(cm/replace-key-value :aws-access-key-id (b64/encode aws-access-key-id)) (as-> (yaml/load-as-edn "backup/secret.yaml") res
(cm/replace-key-value :aws-secret-access-key (b64/encode aws-secret-access-key)) (cm/replace-key-value res :aws-access-key-id (b64/encode aws-access-key-id))
(cm/replace-key-value :restic-password (b64/encode restic-password))))) (cm/replace-key-value res :aws-secret-access-key (b64/encode aws-secret-access-key))
(cm/replace-key-value res :restic-password (b64/encode restic-password))
(if (contains? auth :restic-new-password)
(assoc-in res [:data :restic-new-password] (b64/encode restic-new-password))
res))))

View file

@ -9,57 +9,103 @@
[dda.c4k-common.monitoring :as mon] [dda.c4k-common.monitoring :as mon]
[dda.c4k-taiga.taiga :as taiga] [dda.c4k-taiga.taiga :as taiga]
[dda.c4k-taiga.backup :as backup] [dda.c4k-taiga.backup :as backup]
[dda.c4k-common.postgres :as postgres])) [dda.c4k-common.postgres :as postgres]
[dda.c4k-common.namespace :as ns]))
(def default-storage-class :local-path) (def defaults {:namespace "taiga"
:issuer "staging"
:storage-class-name "local-path"
:pv-storage-size-gb "5"
:storage-media-size "5"
:storage-static-size "5"
:storage-async-rabbitmq-size "5"
:storage-events-rabbitmq-size "5"
:public-register-enabled "false"
:enable-telemetry "false"})
(def config? taiga/config?) (def config? (s/merge
(def auth? taiga/auth?) ::backup/config
(s/keys :req-un [::taiga/fqdn]
:opt-un [::taiga/issuer
::taiga/storage-class-name
::taiga/storage-media-size
::taiga/storage-static-size
::taiga/storage-async-rabbitmq-size
::taiga/storage-events-rabbitmq-size
::taiga/public-register-enabled
::taiga/enable-telemetry
::postgres/pv-storage-size-gb
::mon/mon-cfg])))
(def config-defaults taiga/config-defaults) (def auth? (s/merge
::backup/auth
(s/keys :req-un [::postgres/postgres-db-user
::postgres/postgres-db-password
::taiga/taiga-secret-key
::taiga/mailer-pw
::taiga/mailer-user
::taiga/django-superuser-email
::taiga/django-superuser-password
::taiga/django-superuser-username
::taiga/rabbitmq-erlang-cookie
::taiga/rabbitmq-pw
::taiga/rabbitmq-user
::mon/mon-auth])))
(defn-spec k8s-objects cp/map-or-seq? (defn-spec config-objects cp/map-or-seq?
[config taiga/config? [config config?]
auth taiga/auth?] (let [resolved-config (merge defaults config)]
(cm/concat-vec (cm/concat-vec
(map yaml/to-string (map yaml/to-string
(filter (filter
#(not (nil? %)) #(not (nil? %))
(cm/concat-vec (cm/concat-vec
[(postgres/generate-config {:postgres-size :8gb :db-name "taiga"}) (ns/generate resolved-config)
(postgres/generate-secret auth) (postgres/generate-config (merge resolved-config
(postgres/generate-pvc {:pv-storage-size-gb 50 {:postgres-size :8gb :db-name "taiga"
:pvc-storage-class-name default-storage-class}) :pv-storage-size-gb 50}))
(postgres/generate-deployment) [(taiga/generate-async-deployment)
(postgres/generate-service) (taiga/generate-async-rabbitmq-deployment)
(taiga/generate-async-deployment) (taiga/generate-async-rabbitmq-service)
(taiga/generate-async-rabbitmq-deployment) (taiga/generate-async-service)
(taiga/generate-async-rabbitmq-service) (taiga/generate-back-deployment)
(taiga/generate-async-service) (taiga/generate-back-service)
(taiga/generate-back-deployment) (taiga/generate-configmap resolved-config)
(taiga/generate-back-service) (taiga/generate-pvc-taiga-media-data resolved-config)
(taiga/generate-configmap config) (taiga/generate-pvc-taiga-static-data resolved-config)
(taiga/generate-pvc-taiga-media-data config) (taiga/generate-events-deployment)
(taiga/generate-pvc-taiga-static-data config) (taiga/generate-events-rabbitmq-deployment)
(taiga/generate-events-deployment) (taiga/generate-events-rabbitmq-service)
(taiga/generate-events-rabbitmq-deployment) (taiga/generate-events-service)
(taiga/generate-events-rabbitmq-service) (taiga/generate-front-deployment)
(taiga/generate-events-service) (taiga/generate-front-service)
(taiga/generate-front-deployment) (taiga/generate-gateway-configmap)
(taiga/generate-front-service) (taiga/generate-gateway-deployment)
(taiga/generate-gateway-configmap) (taiga/generate-gateway-service)
(taiga/generate-gateway-deployment) (taiga/generate-protected-deployment)
(taiga/generate-gateway-service) (taiga/generate-protected-service)
(taiga/generate-protected-deployment) (taiga/generate-rabbitmq-pvc-async resolved-config)
(taiga/generate-protected-service) (taiga/generate-rabbitmq-pvc-events resolved-config)]
(taiga/generate-rabbitmq-pvc-async config) (taiga/generate-ingress-and-cert resolved-config)
(taiga/generate-rabbitmq-pvc-events config) (when (contains? resolved-config :restic-repository)
(taiga/generate-secret auth)] [(backup/generate-config resolved-config)
(taiga/generate-ingress-and-cert config) (backup/generate-cron)
(when (contains? config :restic-repository) (backup/generate-backup-restore-deployment resolved-config)])
[(backup/generate-config config) (when (:contains? resolved-config :mon-cfg)
(backup/generate-secret auth) (mon/generate-config))))))))
(backup/generate-cron)
(backup/generate-backup-restore-deployment config)]) (defn-spec auth-objects cp/map-or-seq?
(when (:contains? config :mon-cfg) [config config?
(mon/generate (:mon-cfg config) (:mon-auth auth)))))))) auth auth?]
(let [resolved-config (merge defaults config)]
(cm/concat-vec
(map yaml/to-string
(filter
#(not (nil? %))
(cm/concat-vec
(postgres/generate-auth resolved-config auth)
[(taiga/generate-secret auth)]
(when (contains? resolved-config :restic-repository)
[(backup/generate-secret auth)])
(when (:contains? resolved-config :mon-cfg)
(mon/generate-auth (:mon-cfg resolved-config) (:mon-auth auth)))))))))

View file

@ -1,35 +1,16 @@
(ns dda.c4k-taiga.taiga (ns dda.c4k-taiga.taiga
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
#?(:cljs [shadow.resource :as rc])
#?(:clj [orchestra.core :refer [defn-spec]] #?(:clj [orchestra.core :refer [defn-spec]]
:cljs [orchestra.core :refer-macros [defn-spec]]) :cljs [orchestra.core :refer-macros [defn-spec]])
#?(:clj [clojure.edn :as edn]
:cljs [cljs.reader :as edn])
[dda.c4k-common.yaml :as yaml] [dda.c4k-common.yaml :as yaml]
[dda.c4k-common.common :as cm]
[dda.c4k-common.base64 :as b64]
[dda.c4k-common.predicate :as cp]
[dda.c4k-common.monitoring :as mon]
[dda.c4k-common.postgres :as postgres]
[dda.c4k-common.ingress :as ing] [dda.c4k-common.ingress :as ing]
[clojure.string :as str] [dda.c4k-common.base64 :as b64]
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]]))) [dda.c4k-common.predicate :as p]
[dda.c4k-common.common :as cm]
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
(s/def ::taiga-secret-key p/bash-env-string?)
(def config-defaults {:issuer "staging"
:storage-class-name "local-path"
:pv-storage-size-gb "5" ;; ToDo: check sensible defaults
:storage-media-size "5"
:storage-static-size "5"
:storage-async-rabbitmq-size "5"
:storage-events-rabbitmq-size "5"
:public-register-enabled "false"
:enable-telemetry "false"})
(s/def ::mon-cfg ::mon/mon-cfg)
(s/def ::mon-auth ::mon/mon-auth)
(s/def ::taiga-secret-key cp/bash-env-string?)
(s/def ::mailer-user string?) (s/def ::mailer-user string?)
(s/def ::mailer-pw string?) (s/def ::mailer-pw string?)
(s/def ::django-superuser-username string?) (s/def ::django-superuser-username string?)
@ -39,9 +20,9 @@
(s/def ::rabbitmq-pw string?) (s/def ::rabbitmq-pw string?)
(s/def ::rabbitmq-erlang-cookie string?) (s/def ::rabbitmq-erlang-cookie string?)
(s/def ::issuer cp/letsencrypt-issuer?) (s/def ::issuer p/letsencrypt-issuer?)
(s/def ::fqdn cp/fqdn-string?) (s/def ::fqdn p/fqdn-string?)
(s/def ::public-register-enabled string?) ;; ToDo maybe check for boolean string (s/def ::public-register-enabled string?)
(s/def ::enable-telemetry string?) (s/def ::enable-telemetry string?)
(s/def ::storage-class-name string?) (s/def ::storage-class-name string?)
(s/def ::storage-media-size pos?) (s/def ::storage-media-size pos?)
@ -49,37 +30,34 @@
(s/def ::storage-async-rabbitmq-size pos?) (s/def ::storage-async-rabbitmq-size pos?)
(s/def ::storage-events-rabbitmq-size pos?) (s/def ::storage-events-rabbitmq-size pos?)
(def auth? (s/keys :req-un [::postgres/postgres-db-user (s/def ::auth (s/keys :req-un [::taiga-secret-key
::postgres/postgres-db-password ::mailer-pw
::taiga-secret-key ::mailer-user
::mailer-pw ::django-superuser-email
::mailer-user ::django-superuser-password
::django-superuser-email ::django-superuser-username
::django-superuser-password ::rabbitmq-erlang-cookie
::django-superuser-username ::rabbitmq-pw
::rabbitmq-erlang-cookie ::rabbitmq-user]
::rabbitmq-pw :opt-un [::mon-auth]))
::rabbitmq-user]
:opt-un [::mon-auth]))
(def config? (s/keys :req-un [::fqdn] (s/def ::config (s/keys :req-un [::fqdn]
:opt-un [::issuer :opt-un [::issuer
::storage-class-name ::storage-class-name
::storage-media-size ::storage-media-size
::storage-static-size ::storage-static-size
::storage-async-rabbitmq-size ::storage-async-rabbitmq-size
::storage-events-rabbitmq-size ::storage-events-rabbitmq-size
::postgres/pv-storage-size-gb ::public-register-enabled
::public-register-enabled ::enable-telemetry
::enable-telemetry ::mon-cfg]))
::mon-cfg]))
#?(:cljs #?(:cljs
(defmethod yaml/load-resource :taiga [resource-name] (defmethod yaml/load-resource :taiga [resource-name]
(get (inline-resources "taiga") resource-name))) (get (inline-resources "taiga") resource-name)))
(defn-spec generate-ingress-and-cert cp/map-or-seq? (defn-spec generate-ingress-and-cert p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [fqdn]} config] (let [{:keys [fqdn]} config]
(ing/generate-ingress-and-cert (ing/generate-ingress-and-cert
(merge (merge
@ -88,85 +66,85 @@
:fqdns [fqdn]} :fqdns [fqdn]}
config)))) config))))
(defn-spec generate-async-deployment cp/map-or-seq? [] (defn-spec generate-async-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/async-deployment.yaml")) (yaml/load-as-edn "taiga/async-deployment.yaml"))
(defn-spec generate-async-service cp/map-or-seq? [] (defn-spec generate-async-service p/map-or-seq? []
(yaml/load-as-edn "taiga/async-service.yaml")) (yaml/load-as-edn "taiga/async-service.yaml"))
(defn-spec generate-async-rabbitmq-deployment cp/map-or-seq? [] (defn-spec generate-async-rabbitmq-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/async-rabbitmq-deployment.yaml")) (yaml/load-as-edn "taiga/async-rabbitmq-deployment.yaml"))
(defn-spec generate-events-rabbitmq-service cp/map-or-seq? [] (defn-spec generate-events-rabbitmq-service p/map-or-seq? []
(yaml/load-as-edn "taiga/events-rabbitmq-service.yaml")) (yaml/load-as-edn "taiga/events-rabbitmq-service.yaml"))
(defn-spec generate-async-rabbitmq-service cp/map-or-seq? [] (defn-spec generate-async-rabbitmq-service p/map-or-seq? []
(yaml/load-as-edn "taiga/async-rabbitmq-service.yaml")) (yaml/load-as-edn "taiga/async-rabbitmq-service.yaml"))
(defn-spec generate-back-deployment cp/map-or-seq? [] (defn-spec generate-back-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/back-deployment.yaml")) (yaml/load-as-edn "taiga/back-deployment.yaml"))
(defn-spec generate-back-service cp/map-or-seq? [] (defn-spec generate-back-service p/map-or-seq? []
(yaml/load-as-edn "taiga/back-service.yaml")) (yaml/load-as-edn "taiga/back-service.yaml"))
(defn-spec generate-events-rabbitmq-deployment cp/map-or-seq? [] (defn-spec generate-events-rabbitmq-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/events-rabbitmq-deployment.yaml")) (yaml/load-as-edn "taiga/events-rabbitmq-deployment.yaml"))
(defn-spec generate-events-deployment cp/map-or-seq? [] (defn-spec generate-events-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/events-deployment.yaml")) (yaml/load-as-edn "taiga/events-deployment.yaml"))
(defn-spec generate-events-service cp/map-or-seq? [] (defn-spec generate-events-service p/map-or-seq? []
(yaml/load-as-edn "taiga/events-service.yaml")) (yaml/load-as-edn "taiga/events-service.yaml"))
(defn-spec generate-front-deployment cp/map-or-seq? [] (defn-spec generate-front-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/front-deployment.yaml")) (yaml/load-as-edn "taiga/front-deployment.yaml"))
(defn-spec generate-front-service cp/map-or-seq? [] (defn-spec generate-front-service p/map-or-seq? []
(yaml/load-as-edn "taiga/front-service.yaml")) (yaml/load-as-edn "taiga/front-service.yaml"))
(defn-spec generate-gateway-configmap cp/map-or-seq? [] (defn-spec generate-gateway-configmap p/map-or-seq? []
(yaml/load-as-edn "taiga/gateway-configmap.yaml")) (yaml/load-as-edn "taiga/gateway-configmap.yaml"))
(defn-spec generate-gateway-deployment cp/map-or-seq? [] (defn-spec generate-gateway-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/gateway-deployment.yaml")) (yaml/load-as-edn "taiga/gateway-deployment.yaml"))
(defn-spec generate-gateway-service cp/map-or-seq? [] (defn-spec generate-gateway-service p/map-or-seq? []
(yaml/load-as-edn "taiga/gateway-service.yaml")) (yaml/load-as-edn "taiga/gateway-service.yaml"))
(defn-spec generate-protected-deployment cp/map-or-seq? [] (defn-spec generate-protected-deployment p/map-or-seq? []
(yaml/load-as-edn "taiga/protected-deployment.yaml")) (yaml/load-as-edn "taiga/protected-deployment.yaml"))
(defn-spec generate-protected-service cp/map-or-seq? [] (defn-spec generate-protected-service p/map-or-seq? []
(yaml/load-as-edn "taiga/protected-service.yaml")) (yaml/load-as-edn "taiga/protected-service.yaml"))
(defn-spec generate-configmap cp/map-or-seq? (defn-spec generate-configmap p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [fqdn enable-telemetry public-register-enabled]} (merge config-defaults config)] (let [{:keys [fqdn enable-telemetry public-register-enabled]} config]
(-> (yaml/load-as-edn "taiga/configmap.yaml") (-> (yaml/load-as-edn "taiga/configmap.yaml")
(cm/replace-key-value :TAIGA_SITES_DOMAIN fqdn) (cm/replace-key-value :TAIGA_SITES_DOMAIN fqdn)
(cm/replace-key-value :TAIGA_URL (str "https://" fqdn)) (cm/replace-key-value :TAIGA_URL (str "https://" fqdn))
(cm/replace-key-value :TAIGA_WEBSOCKETS_URL (str "wss://" fqdn)) (cm/replace-key-value :TAIGA_WEBSOCKETS_URL (str "wss://" fqdn))
(cm/replace-key-value :ENABLE_TELEMETRY enable-telemetry) (cm/replace-key-value :ENABLE_TELEMETRY enable-telemetry)
(cm/replace-key-value :PUBLIC_REGISTER_ENABLED public-register-enabled)))) (cm/replace-key-value :PUBLIC_REGISTER_ENABLED public-register-enabled))))
(defn-spec generate-pvc-taiga-media-data cp/map-or-seq? (defn-spec generate-pvc-taiga-media-data p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [storage-class-name storage-media-size]} (merge config-defaults config)] (let [{:keys [storage-class-name storage-media-size]} config]
(-> (->
(yaml/load-as-edn "taiga/pvc-taiga-media-data.yaml") (yaml/load-as-edn "taiga/pvc-taiga-media-data.yaml")
(assoc-in [:spec :storageClassName] storage-class-name) (assoc-in [:spec :storageClassName] storage-class-name)
(assoc-in [:spec :resources :requests :storage] (str storage-media-size "Gi"))))) (assoc-in [:spec :resources :requests :storage] (str storage-media-size "Gi")))))
(defn-spec generate-pvc-taiga-static-data cp/map-or-seq? (defn-spec generate-pvc-taiga-static-data p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [storage-class-name storage-static-size]} (merge config-defaults config)] (let [{:keys [storage-class-name storage-static-size]} config]
(-> (->
(yaml/load-as-edn "taiga/pvc-taiga-static-data.yaml") (yaml/load-as-edn "taiga/pvc-taiga-static-data.yaml")
(assoc-in [:spec :storageClassName] storage-class-name) (assoc-in [:spec :storageClassName] storage-class-name)
(assoc-in [:spec :resources :requests :storage] (str storage-static-size "Gi"))))) (assoc-in [:spec :resources :requests :storage] (str storage-static-size "Gi")))))
(defn-spec generate-secret cp/map-or-seq? (defn-spec generate-secret p/map-or-seq?
[auth auth?] [auth ::auth]
(let [{:keys [taiga-secret-key (let [{:keys [taiga-secret-key
mailer-user mailer-pw mailer-user mailer-pw
rabbitmq-user rabbitmq-pw rabbitmq-erlang-cookie rabbitmq-user rabbitmq-pw rabbitmq-erlang-cookie
@ -183,18 +161,18 @@
(cm/replace-key-value :DJANGO_SUPERUSER_PASSWORD (b64/encode django-superuser-password)) (cm/replace-key-value :DJANGO_SUPERUSER_PASSWORD (b64/encode django-superuser-password))
(cm/replace-key-value :DJANGO_SUPERUSER_EMAIL (b64/encode django-superuser-email))))) (cm/replace-key-value :DJANGO_SUPERUSER_EMAIL (b64/encode django-superuser-email)))))
(defn-spec generate-rabbitmq-pvc-async cp/map-or-seq? (defn-spec generate-rabbitmq-pvc-async p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [storage-class-name storage-async-rabbitmq-size]} (merge config-defaults config)] (let [{:keys [storage-class-name storage-async-rabbitmq-size]} config]
(-> (->
(yaml/load-as-edn "taiga/rabbitmq-pvc-async.yaml") (yaml/load-as-edn "taiga/rabbitmq-pvc-async.yaml")
(assoc-in [:spec :storageClassName] storage-class-name) (assoc-in [:spec :storageClassName] storage-class-name)
(assoc-in [:spec :resources :requests :storage] (str storage-async-rabbitmq-size "Gi"))))) (assoc-in [:spec :resources :requests :storage] (str storage-async-rabbitmq-size "Gi")))))
(defn-spec generate-rabbitmq-pvc-events cp/map-or-seq? (defn-spec generate-rabbitmq-pvc-events p/map-or-seq?
[config config?] [config ::config]
(let [{:keys [storage-class-name storage-events-rabbitmq-size]} (merge config-defaults config)] (let [{:keys [storage-class-name storage-events-rabbitmq-size]} config]
(-> (->
(yaml/load-as-edn "taiga/rabbitmq-pvc-events.yaml") (yaml/load-as-edn "taiga/rabbitmq-pvc-events.yaml")
(assoc-in [:spec :storageClassName] storage-class-name) (assoc-in [:spec :storageClassName] storage-class-name)
(assoc-in [:spec :resources :requests :storage] (str storage-events-rabbitmq-size "Gi"))))) (assoc-in [:spec :resources :requests :storage] (str storage-events-rabbitmq-size "Gi")))))

View file

@ -1,14 +1,9 @@
(ns dda.c4k-taiga.browser (ns dda.c4k-taiga.browser
(:require (:require
[clojure.string :as st]
[clojure.tools.reader.edn :as edn] [clojure.tools.reader.edn :as edn]
[dda.c4k-common.monitoring :as mon]
[dda.c4k-taiga.core :as core] [dda.c4k-taiga.core :as core]
[dda.c4k-taiga.taiga :as taiga]
[dda.c4k-common.common :as cm] [dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as cp] [dda.c4k-common.browser :as br]))
[dda.c4k-common.browser :as br]
[dda.c4k-common.postgres :as postgres]))
(defn generate-content [] (defn generate-content []
(cm/concat-vec (cm/concat-vec
@ -16,40 +11,33 @@
(br/generate-needs-validation) :content (br/generate-needs-validation) :content
(cm/concat-vec (cm/concat-vec
(br/generate-group (br/generate-group
"domain" "config"
(cm/concat-vec (br/generate-text-area "config" "Your config.edn:" "{:fqdn \"cloud.your.domain\"
(br/generate-input-field "fqdn" "The fully qualified domain name of your Taiga Instance:" "taiga.example.com") :issuer \"staging\"
(br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "staging") :restic-repository \"s3://yourbucket/your-repo\"
(br/generate-input-field "mon-cluster-name" "(Optional) monitoring cluster name:" "taiga") :mon-cfg {:cluster-name \"cloud\"
(br/generate-input-field "mon-cluster-stage" "(Optional) monitoring cluster stage:" "test") :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"))) :cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
"5"))
(br/generate-group (br/generate-group
"options" "auth"
(cm/concat-vec (br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"taiga\"
(br/generate-input-field "public-register-enabled" "(Optional) Allow public registration?" "false") :postgres-db-password \"db-password\"
(br/generate-input-field "enable-telemetry" "(Optional) Allow anonymous collection of usage data?" "false") :mailer-user \"mail[at]example.com\"
(br/generate-input-field "pv-storage-size-gb" "(Optional) The volume size of your postgres DB:" "5") :mailer-pw \"change-me\"
(br/generate-input-field "storage-class-name" "(Optional) Name of storage class:" "local-path") :django-superuser-username \"admin\"
(br/generate-input-field "storage-media-size" "(Optional) The size of your media storage:" "5") :django-superuser-password \"change-me\"
(br/generate-input-field "storage-static-size" "(Optional) The size of your static data storage:" "5") :django-superuser-email \"mail[at]example.com\"
(br/generate-input-field "storage-async-rabbitmq-size" "(Optional) The size of your rabbitmq async storage:" "5") :rabbitmq-user \"user\"
(br/generate-input-field "storage-events-rabbitmq-size" "(Optional) The size of your rabbitmq events storage:" "5"))) :rabbitmq-pw \"change-me\"
(br/generate-group :rabbitmq-erlang-cookie \"change-me\"
"credentials" :taiga-secret-key \"change-me\"
(cm/concat-vec :aws-access-key-id \"aws-id\"
(br/generate-input-field "postgres-db-user" "Your postgres user:" "postgres") :aws-secret-access-key \"aws-secret\"
(br/generate-input-field "postgres-db-password" "Your postgres password:" "change-me") :restic-password \"restic-password\"}
(br/generate-input-field "mailer-user" "Allow taiga access to a mail account:" "mail[at]example.com") :mon-auth {:grafana-cloud-user \"your-user-id\"
(br/generate-input-field "mailer-pw" "Allow taiga access to a mail account:" "change-me") :grafana-cloud-password \"your-cloud-password\"}"
(br/generate-input-field "django-superuser-username" "The superusers username:" "admin") "5"))
(br/generate-input-field "django-superuser-password" "The superusers password:" "change-me")
(br/generate-input-field "django-superuser-email" "The superusers email:" "mail[at]example.com")
(br/generate-input-field "rabbitmq-user" "User for rabbitmq:" "user")
(br/generate-input-field "rabbitmq-pw" "Password for the rabbitmq user:" "change-me")
(br/generate-input-field "rabbitmq-erlang-cookie" "Random hash shared among all rabbitmq pods:" "change-me")
(br/generate-input-field "taiga-secret-key" "Random key shared among all taiga pods:" "change-me")
(br/generate-input-field "grafana-cloud-user" "Your grafana user name:" "user")
(br/generate-input-field "grafana-cloud-password" "Your grafana password:" "change-me")))
[(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-taiga-output" "Your c4k deployment.yaml:" "15"))) (br/generate-output "c4k-taiga-output" "Your c4k deployment.yaml:" "15")))
@ -61,94 +49,9 @@
:content :content
(generate-content)}) (generate-content)})
(defn auth-from-document []
(let [postgres-db-user (br/get-content-from-element "postgres-db-user" )
postgres-db-password (br/get-content-from-element "postgres-db-password" )
mailer-user (br/get-content-from-element "mailer-user" )
mailer-pw (br/get-content-from-element "mailer-pw" )
django-superuser-username (br/get-content-from-element "django-superuser-username" )
django-superuser-password (br/get-content-from-element "django-superuser-password" )
django-superuser-email (br/get-content-from-element "django-superuser-email" )
rabbitmq-user (br/get-content-from-element "rabbitmq-user" )
rabbitmq-pw (br/get-content-from-element "rabbitmq-pw" )
rabbitmq-erlang-cookie (br/get-content-from-element "rabbitmq-erlang-cookie" )
taiga-secret-key (br/get-content-from-element "taiga-secret-key" )
grafana-cloud-user (br/get-content-from-element "grafana-cloud-user" :optional true)
grafana-cloud-password (br/get-content-from-element "grafana-cloud-password" :optional true)]
(merge
{:postgres-db-user postgres-db-user}
{:postgres-db-password postgres-db-password}
{:mailer-user mailer-user}
{:mailer-pw mailer-pw}
{:django-superuser-username django-superuser-username}
{:django-superuser-password django-superuser-password}
{:django-superuser-email django-superuser-email}
{:rabbitmq-user rabbitmq-user}
{:rabbitmq-pw rabbitmq-pw}
{:rabbitmq-erlang-cookie rabbitmq-erlang-cookie}
{:taiga-secret-key taiga-secret-key}
(when (some? grafana-cloud-user)
{:mon-auth {:grafana-cloud-user grafana-cloud-user
:grafana-cloud-password grafana-cloud-password}}))))
(defn config-from-document []
(let [issuer (br/get-content-from-element "issuer" :optional true)
fqdn (br/get-content-from-element "fqdn" :deserializer edn/read-string)
public-register-enabled (br/get-content-from-element "public-register-enabled" :deserializer edn/read-string)
enable-telemetry (br/get-content-from-element "enable-telemetry" :deserializer edn/read-string)
pv-storage-size-gb (br/get-content-from-element "pv-storage-size-gb" :deserializer edn/read-string)
storage-class-name (br/get-content-from-element "storage-class-name" :deserializer edn/read-string)
storage-media-size (br/get-content-from-element "storage-media-size" :deserializer edn/read-string)
storage-static-size (br/get-content-from-element "storage-static-size" :deserializer edn/read-string)
storage-async-rabbitmq-size (br/get-content-from-element "storage-async-rabbitmq-size" :deserializer edn/read-string)
storage-events-rabbitmq-size (br/get-content-from-element "storage-events-rabbitmq-size" :deserializer edn/read-string)
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 fqdn}
{:public-register-enabled public-register-enabled}
{:enable-telemetry enable-telemetry}
{:pv-storage-size-gb pv-storage-size-gb}
{:storage-class-name storage-class-name}
{:storage-media-size storage-media-size}
{:storage-static-size storage-static-size}
{:storage-async-rabbitmq-size storage-async-rabbitmq-size}
{:storage-events-rabbitmq-size storage-events-rabbitmq-size}
(when (not (st/blank? 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! [] (defn validate-all! []
(br/validate! "fqdn" ::taiga/fqdn ) (br/validate! "config" core/config? :deserializer edn/read-string)
(br/validate! "issuer" ::taiga/issuer :optional true) (br/validate! "auth" core/auth? :deserializer edn/read-string)
(br/validate! "public-register-enabled" ::taiga/public-register-enabled :optional true)
(br/validate! "enable-telemetry" ::taiga/enable-telemetry :optional true)
(br/validate! "pv-storage-size-gb" ::postgres/pv-storage-size-gb :optional true)
(br/validate! "storage-class-name" ::taiga/storage-class-name :optional true)
(br/validate! "storage-media-size" ::taiga/storage-media-size :optional true)
(br/validate! "storage-static-size" ::taiga/storage-static-size :optional true)
(br/validate! "storage-async-rabbitmq-size" ::taiga/storage-async-rabbitmq-size :optional true)
(br/validate! "storage-events-rabbitmq-size" ::taiga/storage-events-rabbitmq-size :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! "postgres-db-user" ::postgres/postgres-db-user )
(br/validate! "postgres-db-password" ::postgres/postgres-db-password )
(br/validate! "mailer-user" ::taiga/mailer-user )
(br/validate! "mailer-pw" ::taiga/mailer-pw )
(br/validate! "django-superuser-username" ::taiga/django-superuser-username )
(br/validate! "django-superuser-password" ::taiga/django-superuser-password )
(br/validate! "django-superuser-email" ::taiga/django-superuser-email )
(br/validate! "rabbitmq-user" ::taiga/rabbitmq-user )
(br/validate! "rabbitmq-pw" ::taiga/rabbitmq-pw )
(br/validate! "rabbitmq-erlang-cookie" ::taiga/rabbitmq-erlang-cookie )
(br/validate! "taiga-secret-key" ::taiga/taiga-secret-key )
(br/validate! "grafana-cloud-user" ::mon/grafana-cloud-user )
(br/validate! "grafana-cloud-password" ::mon/grafana-cloud-password )
(br/set-form-validated!)) (br/set-form-validated!))
(defn add-validate-listener [name] (defn add-validate-listener [name]
@ -161,35 +64,14 @@
(.getElementById "generate-button") (.getElementById "generate-button")
(.addEventListener "click" (.addEventListener "click"
#(do (validate-all!) #(do (validate-all!)
(-> (cm/generate-common (-> (cm/generate-cm
(config-from-document) (br/get-content-from-element "config" :deserializer edn/read-string)
(auth-from-document) (br/get-content-from-element "auth" :deserializer edn/read-string)
core/config-defaults core/config-defaults
core/k8s-objects) core/config-objects
core/auth-objects
false
false)
(br/set-output!))))) (br/set-output!)))))
(add-validate-listener "fqdn") (add-validate-listener "config")
(add-validate-listener "issuer") (add-validate-listener "authr"))
(add-validate-listener "public-register-enabled")
(add-validate-listener "enable-telemetry")
(add-validate-listener "pv-storage-size-gb")
(add-validate-listener "storage-class-name")
(add-validate-listener "storage-media-size")
(add-validate-listener "storage-static-size")
(add-validate-listener "storage-async-rabbitmq-size")
(add-validate-listener "storage-events-rabbitmq-size")
(add-validate-listener "mon-cluster-name")
(add-validate-listener "mon-cluster-stage")
(add-validate-listener "mon-cloud-url")
(add-validate-listener "postgres-db-user")
(add-validate-listener "postgres-db-password")
(add-validate-listener "mailer-user")
(add-validate-listener "mailer-pw")
(add-validate-listener "django-superuser-username")
(add-validate-listener "django-superuser-password")
(add-validate-listener "django-superuser-email")
(add-validate-listener "rabbitmq-user")
(add-validate-listener "rabbitmq-pw")
(add-validate-listener "rabbitmq-erlang-cookie")
(add-validate-listener "taiga-secret-key")
(add-validate-listener "grafana-cloud-user")
(add-validate-listener "grafana-cloud-password"))

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: backup-restore name: backup-restore
namespace: taiga
spec: spec:
replicas: 0 replicas: 0
selector: selector:
@ -20,7 +21,7 @@ spec:
- image: domaindrivenarchitecture/c4k-taiga-backup - image: domaindrivenarchitecture/c4k-taiga-backup
name: backup-app name: backup-app
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/entrypoint-start-and-wait.sh"] command: ["wait.bb"]
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
valueFrom: valueFrom:
@ -56,8 +57,8 @@ spec:
key: restic-repository key: restic-repository
- name: RESTIC_PASSWORD_FILE - name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password value: /var/run/secrets/backup-secrets/restic-password
- name: CERTIFICATE_FILE - name: RESTIC_NEW_PASSWORD_FILE
value: "" value: /var/run/secrets/backup-secrets/restic-new-password
volumeMounts: volumeMounts:
- name: taiga-media - name: taiga-media
mountPath: /media mountPath: /media

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: backup-config name: backup-config
namespace: taiga
labels: labels:
app.kubernetes.io/name: backup app.kubernetes.io/name: backup
app.kubernetes.io/part-of: taiga app.kubernetes.io/part-of: taiga

View file

@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob kind: CronJob
metadata: metadata:
name: taiga-backup name: taiga-backup
namespace: taiga
labels: labels:
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga
spec: spec:
@ -16,7 +17,7 @@ spec:
- name: backup-app - name: backup-app
image: domaindrivenarchitecture/c4k-taiga-backup image: domaindrivenarchitecture/c4k-taiga-backup
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"] command: ["backup.bb"]
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
valueFrom: valueFrom:
@ -52,8 +53,6 @@ spec:
key: restic-repository key: restic-repository
- name: RESTIC_PASSWORD_FILE - name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password value: /var/run/secrets/backup-secrets/restic-password
- name: CERTIFICATE_FILE
value: ""
volumeMounts: volumeMounts:
- name: taiga-media - name: taiga-media
mountPath: /media mountPath: /media

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: backup-secret name: backup-secret
namespace: taiga
type: Opaque type: Opaque
data: data:
aws-access-key-id: aws-access-key-id aws-access-key-id: aws-access-key-id

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-async-deployment name: taiga-async-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async app.kubernetes.io/component: taiga-async

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-async-rabbitmq-deployment name: taiga-async-rabbitmq-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async-rabbitmq app.kubernetes.io/component: taiga-async-rabbitmq

View file

@ -2,10 +2,11 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-async-rabbitmq name: taiga-async-rabbitmq
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async-rabbitmq app.kubernetes.io/component: taiga-async-rabbitmq
namespace: default namespace: taiga
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,10 +2,11 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-async name: taiga-async
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async app.kubernetes.io/component: taiga-async
namespace: default namespace: taiga
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-back-deployment name: taiga-back-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-back app.kubernetes.io/component: taiga-back
@ -20,7 +21,7 @@ spec:
image: taigaio/taiga-back:latest image: taigaio/taiga-back:latest
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/bin/bash"] command: ["/bin/bash"]
args: ["-c", "source /opt/venv/bin/activate && CELERY_ENABLE=true python manage.py migrate && sleep 15 && python manage.py createsuperuser --noinput"] args: ["-c", "source /opt/venv/bin/activate && CELERY_ENABLE=true python manage.py migrate && sleep 15"]
ports: ports:
- name: http - name: http
containerPort: 8000 containerPort: 8000

View file

@ -2,10 +2,10 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-back name: taiga-back
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-back app.kubernetes.io/component: taiga-back
namespace: default
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: taiga-configmap name: taiga-configmap
namespace: default namespace: taiga
data: data:
# These environment variables will be used by taiga-back and taiga-async. # These environment variables will be used by taiga-back and taiga-async.
# Database settings handled in deployment # Database settings handled in deployment

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-events-deployment name: taiga-events-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-events app.kubernetes.io/component: taiga-events

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-events-rabbitmq-deployment name: taiga-events-rabbitmq-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-events-rabbitmq app.kubernetes.io/component: taiga-events-rabbitmq

View file

@ -2,10 +2,11 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-events-rabbitmq name: taiga-events-rabbitmq
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-events-rabbitmq app.kubernetes.io/component: taiga-events-rabbitmq
namespace: default namespace: taiga
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,10 +2,10 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-events name: taiga-events
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-events app.kubernetes.io/component: taiga-events
namespace: default
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-front-deployment name: taiga-front-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-front app.kubernetes.io/component: taiga-front

View file

@ -2,10 +2,10 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-front name: taiga-front
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-front app.kubernetes.io/component: taiga-front
namespace: default
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: taiga-gateway-configmap name: taiga-gateway-configmap
namespace: taiga
data: data:
default.conf: | default.conf: |
server { server {

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-gateway-deployment name: taiga-gateway-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-gateway app.kubernetes.io/component: taiga-gateway

View file

@ -2,10 +2,10 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-gateway name: taiga-gateway
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-gateway app.kubernetes.io/component: taiga-gateway
namespace: default
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: taiga-protected-deployment name: taiga-protected-deployment
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-protected app.kubernetes.io/component: taiga-protected

View file

@ -2,10 +2,10 @@ kind: Service
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: taiga-protected name: taiga-protected
namespace: taiga
labels: labels:
app.kubernetes.part-of: c4k-taiga app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-protected app.kubernetes.io/component: taiga-protected
namespace: default
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: taiga-media-data name: taiga-media-data
namespace: default namespace: taiga
labels: labels:
app: taiga app: taiga
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: taiga-static-data name: taiga-static-data
namespace: default namespace: taiga
labels: labels:
app: taiga app: taiga
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: taiga-async-rabbitmq-data name: taiga-async-rabbitmq-data
namespace: default namespace: taiga
labels: labels:
app: taiga app: taiga
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: taiga-events-rabbitmq-data name: taiga-events-rabbitmq-data
namespace: default namespace: taiga
labels: labels:
app: taiga app: taiga
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: taiga-secret name: taiga-secret
namespace: taiga
labels: labels:
app.kubernetes.part-of: taiga app.kubernetes.part-of: taiga
data: data:

View file

@ -0,0 +1,47 @@
(ns dda.c4k-taiga.backup-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.test.alpha :as st]
[dda.c4k-taiga.backup :as cut]))
(st/instrument `cut/generate-secret)
(st/instrument `cut/generate-config)
(st/instrument `cut/generate-cron)
(deftest should-generate-config
(is (= {:apiVersion "v1"
:kind "ConfigMap"
:metadata {:name "backup-config"
:namespace "taiga"
:labels {:app.kubernetes.io/name "backup"
:app.kubernetes.io/part-of "taiga"}}
:data
{:restic-repository "s3:restic-repository"}}
(cut/generate-config {:restic-repository "s3:restic-repository"}))))
(deftest should-generate-secret
(is (= {:apiVersion "v1"
:kind "Secret"
:metadata {:name "backup-secret", :namespace "taiga"}
:type "Opaque"
:data
{:aws-access-key-id "YXdzLWlk",
:aws-secret-access-key "YXdzLXNlY3JldA==",
:restic-password "cmVzdGljLXB3"}}
(cut/generate-secret {:aws-access-key-id "aws-id"
:aws-secret-access-key "aws-secret"
:restic-password "restic-pw"})))
(is (= {:apiVersion "v1"
:kind "Secret"
:metadata {:name "backup-secret", :namespace "taiga"}
:type "Opaque"
:data
{:aws-access-key-id "YXdzLWlk",
:aws-secret-access-key "YXdzLXNlY3JldA==",
:restic-password "cmVzdGljLXB3"
:restic-new-password "bmV3LXJlc3RpYy1wdw=="}}
(cut/generate-secret {:aws-access-key-id "aws-id"
:aws-secret-access-key "aws-secret"
:restic-password "restic-pw"
:restic-new-password "new-restic-pw"}))))

View file

@ -1,6 +1,6 @@
(ns dda.c4k-taiga.core-test (ns dda.c4k-taiga.core-test
(:require (:require
#?(:cljs [shadow.resource :as rc]) #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])
#?(:clj [clojure.test :refer [deftest is are testing run-tests]] #?(:clj [clojure.test :refer [deftest is are testing run-tests]]
:cljs [cljs.test :refer-macros [deftest is are testing run-tests]]) :cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
@ -8,11 +8,8 @@
[dda.c4k-taiga.core :as cut])) [dda.c4k-taiga.core :as cut]))
#?(:cljs #?(:cljs
(defmethod yaml/load-resource :website-test [resource-name] (defmethod yaml/load-resource :taiga-test [resource-name]
(case resource-name (get (inline-resources "taiga-test") resource-name)))
"taiga-test/valid-config.yaml" (rc/inline "taiga-test/valid-config.yaml")
"taiga-test/valid-auth.yaml" (rc/inline "taiga-test/valid-auth.yaml")
(throw (js/Error. "Undefined Resource!")))))
(deftest validate-valid-resources (deftest validate-valid-resources
(is (s/valid? cut/config? (yaml/load-as-edn "taiga-test/valid-config.yaml"))) (is (s/valid? cut/config? (yaml/load-as-edn "taiga-test/valid-config.yaml")))

View file

@ -1,23 +1,26 @@
(ns dda.c4k-taiga.taiga-test (ns dda.c4k-taiga.taiga-test
(:require (:require
#?(:cljs [shadow.resource :as rc]) #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])
#?(:clj [clojure.test :refer [deftest is are testing run-tests]] #?(:clj [clojure.test :refer [deftest is are testing run-tests]]
:cljs [cljs.test :refer-macros [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-common.yaml :as yaml]
[dda.c4k-taiga.taiga :as cut])) [dda.c4k-taiga.taiga :as cut]))
(st/instrument `cut/generate-configmap)
(st/instrument `cut/generate-pvc-taiga-media-data)
(st/instrument `cut/generate-rabbitmq-pvc-async)
(st/instrument `cut/generate-rabbitmq-pvc-events)
(st/instrument `cut/generate-secret)
#?(:cljs #?(:cljs
(defmethod yaml/load-resource :taiga-test [resource-name] (defmethod yaml/load-resource :taiga-test [resource-name]
(case resource-name (get (inline-resources "taiga-test") resource-name)))
"taiga-test/valid-config.yaml" (rc/inline "taiga-test/valid-config.yaml")
"taiga-test/valid-auth.yaml" (rc/inline "taiga-test/valid-auth.yaml")
(throw (js/Error. "Undefined Resource!")))))
(deftest should-generate-configmap (deftest should-generate-configmap
(is (= {:apiVersion "v1", (is (= {:apiVersion "v1",
:kind "ConfigMap", :kind "ConfigMap",
:metadata {:name "taiga-configmap", :namespace "default"}, :metadata {:name "taiga-configmap", :namespace "taiga"},
:data :data
{:ENABLE_TELEMETRY "false", {:ENABLE_TELEMETRY "false",
:TAIGA_SITES_SCHEME "https", :TAIGA_SITES_SCHEME "https",
@ -39,20 +42,18 @@
:kind "PersistentVolumeClaim", :kind "PersistentVolumeClaim",
:metadata :metadata
{:name "taiga-media-data", {:name "taiga-media-data",
:namespace "default", :namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}}, :labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:spec :spec
{:storageClassName "local-path", {:storageClassName "local-path",
:accessModes ["ReadWriteOnce"], :accessModes ["ReadWriteOnce"],
:resources {:requests {:storage "2Gi"}}}} :resources {:requests {:storage "2Gi"}}}}
(cut/generate-pvc-taiga-media-data (yaml/load-as-edn "taiga-test/valid-config.yaml"))))) (cut/generate-pvc-taiga-media-data (yaml/load-as-edn "taiga-test/valid-config.yaml"))))
(deftest should-generate-pvc-taiga-static-data
(is (= {:apiVersion "v1", (is (= {:apiVersion "v1",
:kind "PersistentVolumeClaim", :kind "PersistentVolumeClaim",
:metadata :metadata
{:name "taiga-static-data", {:name "taiga-static-data",
:namespace "default", :namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}}, :labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:spec :spec
{:storageClassName "local-path", {:storageClassName "local-path",
@ -65,20 +66,20 @@
:kind "PersistentVolumeClaim", :kind "PersistentVolumeClaim",
:metadata :metadata
{:name "taiga-async-rabbitmq-data", {:name "taiga-async-rabbitmq-data",
:namespace "default", :namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}}, :labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:spec :spec
{:storageClassName "local-path", {:storageClassName "local-path",
:accessModes ["ReadWriteOnce"], :accessModes ["ReadWriteOnce"],
:resources {:requests {:storage "4Gi"}}}} :resources {:requests {:storage "4Gi"}}}}
(cut/generate-rabbitmq-pvc-async(yaml/load-as-edn "taiga-test/valid-config.yaml"))))) (cut/generate-rabbitmq-pvc-async (yaml/load-as-edn "taiga-test/valid-config.yaml")))))
(deftest should-generate-rabbitmq-pvc-events (deftest should-generate-rabbitmq-pvc-events
(is (= {:apiVersion "v1", (is (= {:apiVersion "v1",
:kind "PersistentVolumeClaim", :kind "PersistentVolumeClaim",
:metadata :metadata
{:name "taiga-events-rabbitmq-data", {:name "taiga-events-rabbitmq-data",
:namespace "default", :namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}}, :labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:spec :spec
{:storageClassName "local-path", {:storageClassName "local-path",
@ -90,7 +91,7 @@
(is (= {:apiVersion "v1", (is (= {:apiVersion "v1",
:kind "Secret", :kind "Secret",
:metadata :metadata
{:name "taiga-secret", :labels {:app.kubernetes.part-of "taiga"}}, {:name "taiga-secret", :namespace "taiga" :labels {:app.kubernetes.part-of "taiga"}},
:data :data
{:TAIGA_SECRET_KEY "c29tZS1rZXk=", {:TAIGA_SECRET_KEY "c29tZS1rZXk=",
:EMAIL_HOST_USER "bWFpbGVyLXVzZXI=", :EMAIL_HOST_USER "bWFpbGVyLXVzZXI=",