Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
0d8339cfa7 | |||
031a75bba2 | |||
a0fafe6f5c | |||
9d538e39d9 | |||
b434cf7e1f | |||
5e8acf075e | |||
a2fc8d5ab6 | |||
ca770fb93d | |||
46c49a3317 | |||
64f8f80da1 | |||
2bcf68760b |
28 changed files with 1861 additions and 146 deletions
doc
infrastructure/backup
out.ymlpackage.jsonproject.cljsrc
main
clj/dda/c4k_taiga
cljc/dda/c4k_taiga
cljs/dda/c4k_taiga
resources
backup
taiga
async-rabbitmq-deployment.yamlasync-rabbitmq-service.yamlasync-service.yamlconfigmap.yamlevents-rabbitmq-deployment.yamlevents-rabbitmq-service.yamlgateway-configmap.yamlgateway-deployment.yamlpvc-taiga-media-data.yamlpvc-taiga-static-data.yamlrabbitmq-pvc-async.yamlrabbitmq-pvc-events.yamlsecret.yaml
test/cljc/dda/c4k_taiga
|
@ -1,77 +1,9 @@
|
|||
|
||||
# Backup Architecture details
|
||||
|
||||

|
||||
Use process documented at https://repo.prod.meissa.de/meissa/dda-backup/src/branch/main/docs/Backup.md
|
||||
|
||||
* we use restic to produce small & encrypted backups
|
||||
* backup is scheduled at `schedule: "10 23 * * *"`
|
||||
* Cloud stores files on `/var/jira`, these files are backuped. If you create a jira xml backup located in /var/jira this file will also be backed up.
|
||||
* postgres db is backed up as pgdump
|
||||
Parameters are:
|
||||
|
||||
## Manual backup
|
||||
|
||||
1. Scale gateway and front deployment down:
|
||||
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=0`
|
||||
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=0`
|
||||
2. Scale backup-restore deployment up:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=1`
|
||||
3. exec into pod and execute restore pod
|
||||
`kubectl -n taiga exec -it backup-restore -- backup.bb`
|
||||
4. Scale backup-restore deployment down:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=0`
|
||||
1. Scale gateway and front deployment up:
|
||||
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=1`
|
||||
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=1`
|
||||
|
||||
## Manual restore
|
||||
|
||||
1. Scale gateway and front deployment down:
|
||||
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=0`
|
||||
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=0`
|
||||
2. Scale backup-restore deployment up:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=1`
|
||||
3. exec into pod and execute restore pod
|
||||
`kubectl -n taiga exec -it backup-restore -- restore.bb`
|
||||
4. Scale backup-restore deployment down:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=0`
|
||||
5. Scale gateway and front deployment up:
|
||||
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=1`
|
||||
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=1`
|
||||
|
||||
## Change Password
|
||||
|
||||
1. Check restic-new-password env is set in backup deployment
|
||||
```
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backup-restore
|
||||
spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: backup-app
|
||||
env:
|
||||
- name: RESTIC_NEW_PASSWORD_FILE
|
||||
value: /var/run/secrets/backup-secrets/restic-new-password
|
||||
```
|
||||
2. Add restic-new-password to secret
|
||||
```
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: backup-secret
|
||||
data:
|
||||
restic-password: old
|
||||
restic-new-password: new
|
||||
```
|
||||
3. Scale backup-restore deployment up:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=1`
|
||||
4. exec into pod and execute restore pod
|
||||
`kubectl -n taiga exec -it backup-restore -- change-password.bb`
|
||||
5. Scale backup-restore deployment down:
|
||||
`kubectl -n taiga scale deployment backup-restore --replicas=0`
|
||||
6. Replace restic-password with restic-new-password in secret
|
||||
```
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: backup-secret
|
||||
data:
|
||||
restic-password: new
|
||||
```
|
||||
1. **deployment-name**: taiga-front-deployment, taiga-gateway-deployment
|
||||
2. **deployment-namespace**: taiga
|
||||
|
|
BIN
doc/tryItOut.png
BIN
doc/tryItOut.png
Binary file not shown.
Before ![]() (image error) Size: 53 KiB After ![]() (image error) Size: 157 KiB ![]() ![]() |
|
@ -6,7 +6,7 @@ from ddadevops import *
|
|||
name = "c4k-taiga"
|
||||
MODULE = "backup"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "1.2.4"
|
||||
version = "1.2.7-dev"
|
||||
|
||||
|
||||
@init
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "c4k-taiga",
|
||||
"description": "Generate c4k yaml for a taiga project management deployment.",
|
||||
"author": "meissa GmbH",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.7-SNAPSHOT",
|
||||
"homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga#readme",
|
||||
"repository": "https://www.npmjs.com/package/c4k-taiga",
|
||||
"license": "APACHE2",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(defproject org.domaindrivenarchitecture/c4k-taiga "1.2.4"
|
||||
(defproject org.domaindrivenarchitecture/c4k-taiga "1.2.7-SNAPSHOT"
|
||||
:description "taiga c4k-installation package"
|
||||
:url "https://domaindrivenarchitecture.org"
|
||||
:license {:name "Apache License, Version 2.0"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"c4k-taiga"
|
||||
core/config?
|
||||
core/auth?
|
||||
core/defaults
|
||||
core/config-defaults
|
||||
core/config-objects
|
||||
core/auth-objects
|
||||
cmd-args))
|
||||
|
|
|
@ -12,16 +12,16 @@
|
|||
[dda.c4k-common.postgres :as postgres]
|
||||
[dda.c4k-common.namespace :as ns]))
|
||||
|
||||
(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-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? (s/merge
|
||||
::backup/config
|
||||
|
@ -54,7 +54,7 @@
|
|||
|
||||
(defn-spec config-objects cp/map-or-seq?
|
||||
[config config?]
|
||||
(let [resolved-config (merge defaults config)]
|
||||
(let [resolved-config (merge config-defaults config)]
|
||||
(cm/concat-vec
|
||||
(map yaml/to-string
|
||||
(filter
|
||||
|
@ -97,7 +97,7 @@
|
|||
(defn-spec auth-objects cp/map-or-seq?
|
||||
[config config?
|
||||
auth auth?]
|
||||
(let [resolved-config (merge defaults config)]
|
||||
(let [resolved-config (merge config-defaults config)]
|
||||
(cm/concat-vec
|
||||
(map yaml/to-string
|
||||
(filter
|
||||
|
|
|
@ -12,35 +12,39 @@
|
|||
(cm/concat-vec
|
||||
(br/generate-group
|
||||
"config"
|
||||
(br/generate-text-area "config" "Your config.edn:" "{:fqdn \"cloud.your.domain\"
|
||||
:issuer \"staging\"
|
||||
:restic-repository \"s3://yourbucket/your-repo\"
|
||||
:mon-cfg {:cluster-name \"cloud\"
|
||||
:cluster-stage \"test\"
|
||||
:cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
|
||||
"5"))
|
||||
(br/generate-text-area
|
||||
"config" "Your config.edn:"
|
||||
"{:fqdn \"taiga.your.domain\"
|
||||
:issuer \"staging\"
|
||||
:restic-repository \"s3://yourbucket/your-repo\"
|
||||
:mon-cfg {:cluster-name \"taiga\"
|
||||
:cluster-stage \"test\"
|
||||
:grafana-cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
|
||||
"6"))
|
||||
(br/generate-group
|
||||
"auth"
|
||||
(br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"taiga\"
|
||||
:postgres-db-password \"db-password\"
|
||||
:mailer-user \"mail[at]example.com\"
|
||||
:mailer-pw \"change-me\"
|
||||
:django-superuser-username \"admin\"
|
||||
:django-superuser-password \"change-me\"
|
||||
:django-superuser-email \"mail[at]example.com\"
|
||||
:rabbitmq-user \"user\"
|
||||
:rabbitmq-pw \"change-me\"
|
||||
:rabbitmq-erlang-cookie \"change-me\"
|
||||
:taiga-secret-key \"change-me\"
|
||||
:aws-access-key-id \"aws-id\"
|
||||
:aws-secret-access-key \"aws-secret\"
|
||||
:restic-password \"restic-password\"}
|
||||
:mon-auth {:grafana-cloud-user \"your-user-id\"
|
||||
:grafana-cloud-password \"your-cloud-password\"}"
|
||||
"5"))
|
||||
(br/generate-text-area
|
||||
"auth" "Your auth.edn:"
|
||||
"{:postgres-db-user \"taiga\"
|
||||
:postgres-db-password \"db-password\"
|
||||
:mailer-user \"mail[at]example.com\"
|
||||
:mailer-pw \"change-me\"
|
||||
:django-superuser-username \"admin\"
|
||||
:django-superuser-password \"change-me\"
|
||||
:django-superuser-email \"mail[at]example.com\"
|
||||
:rabbitmq-user \"user\"
|
||||
:rabbitmq-pw \"change-me\"
|
||||
:rabbitmq-erlang-cookie \"change-me\"
|
||||
:taiga-secret-key \"change-me\"
|
||||
:aws-access-key-id \"aws-id\"
|
||||
:aws-secret-access-key \"aws-secret\"
|
||||
:restic-password \"restic-password\"
|
||||
:mon-auth {:grafana-cloud-user \"your-user-id\"
|
||||
:grafana-cloud-password \"your-cloud-password\"}}"
|
||||
"16"))
|
||||
[(br/generate-br)]
|
||||
(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:" "25")))
|
||||
|
||||
(defn generate-content-div
|
||||
[]
|
||||
|
@ -66,12 +70,12 @@
|
|||
#(do (validate-all!)
|
||||
(-> (cm/generate-cm
|
||||
(br/get-content-from-element "config" :deserializer edn/read-string)
|
||||
(br/get-content-from-element "auth" :deserializer edn/read-string)
|
||||
core/config-defaults
|
||||
core/config-objects
|
||||
core/auth-objects
|
||||
false
|
||||
false)
|
||||
(br/get-content-from-element "auth" :deserializer edn/read-string)
|
||||
core/config-defaults
|
||||
core/config-objects
|
||||
core/auth-objects
|
||||
false
|
||||
false)
|
||||
(br/set-output!)))))
|
||||
(add-validate-listener "config")
|
||||
(add-validate-listener "authr"))
|
||||
(add-validate-listener "auth"))
|
||||
|
|
|
@ -15,7 +15,7 @@ spec:
|
|||
labels:
|
||||
app: backup-restore
|
||||
app.kubernetes.io/name: backup-restore
|
||||
app.kubernetes.io/part-of: taiga
|
||||
app.kubernetes.io/part-of: c4k-taiga
|
||||
spec:
|
||||
containers:
|
||||
- image: domaindrivenarchitecture/c4k-taiga-backup
|
||||
|
|
|
@ -5,6 +5,6 @@ metadata:
|
|||
namespace: taiga
|
||||
labels:
|
||||
app.kubernetes.io/name: backup
|
||||
app.kubernetes.io/part-of: taiga
|
||||
app.kubernetes.io/part-of: c4k-taiga
|
||||
data:
|
||||
restic-repository: restic-repository
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: taiga-backup
|
||||
namespace: taiga
|
||||
labels:
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
spec:
|
||||
schedule: "10 23 * * *"
|
||||
successfulJobsHistoryLimit: 1
|
||||
|
|
|
@ -48,7 +48,6 @@ spec:
|
|||
configMapKeyRef:
|
||||
name: taiga-configmap
|
||||
key: RABBITMQ_DEFAULT_VHOST
|
||||
|
||||
volumes:
|
||||
- name: taiga-async-rabbitmq-data
|
||||
persistentVolumeClaim:
|
||||
|
|
|
@ -6,7 +6,6 @@ metadata:
|
|||
labels:
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
app.kubernetes.io/component: taiga-async-rabbitmq
|
||||
namespace: taiga
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
|
|
|
@ -6,7 +6,6 @@ metadata:
|
|||
labels:
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
app.kubernetes.io/component: taiga-async
|
||||
namespace: taiga
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
|
|
|
@ -3,6 +3,8 @@ kind: ConfigMap
|
|||
metadata:
|
||||
name: taiga-configmap
|
||||
namespace: taiga
|
||||
labels:
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
data:
|
||||
# These environment variables will be used by taiga-back and taiga-async.
|
||||
# Database settings handled in deployment
|
||||
|
|
|
@ -48,7 +48,6 @@ spec:
|
|||
secretKeyRef:
|
||||
name: taiga-secret
|
||||
key: RABBITMQ_PASS
|
||||
|
||||
volumes:
|
||||
- name: taiga-events-rabbitmq-data
|
||||
persistentVolumeClaim:
|
||||
|
|
|
@ -6,7 +6,6 @@ metadata:
|
|||
labels:
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
app.kubernetes.io/component: taiga-events-rabbitmq
|
||||
namespace: taiga
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
|
|
|
@ -3,6 +3,8 @@ kind: ConfigMap
|
|||
metadata:
|
||||
name: taiga-gateway-configmap
|
||||
namespace: taiga
|
||||
labels:
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
data:
|
||||
default.conf: |
|
||||
server {
|
||||
|
|
|
@ -34,7 +34,6 @@ spec:
|
|||
- name: taiga-media
|
||||
mountPath: /taiga/media
|
||||
readOnly: false
|
||||
|
||||
volumes:
|
||||
- name: taiga-gateway-configmap
|
||||
configMap:
|
||||
|
|
|
@ -4,8 +4,7 @@ metadata:
|
|||
name: taiga-media-data
|
||||
namespace: taiga
|
||||
labels:
|
||||
app: taiga
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
spec:
|
||||
storageClassName: REPLACEME
|
||||
accessModes:
|
||||
|
|
|
@ -4,8 +4,7 @@ metadata:
|
|||
name: taiga-static-data
|
||||
namespace: taiga
|
||||
labels:
|
||||
app: taiga
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
spec:
|
||||
storageClassName: REPLACEME
|
||||
accessModes:
|
||||
|
|
|
@ -4,8 +4,7 @@ metadata:
|
|||
name: taiga-async-rabbitmq-data
|
||||
namespace: taiga
|
||||
labels:
|
||||
app: taiga
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
spec:
|
||||
storageClassName: REPLACEME
|
||||
accessModes:
|
||||
|
|
|
@ -4,8 +4,7 @@ metadata:
|
|||
name: taiga-events-rabbitmq-data
|
||||
namespace: taiga
|
||||
labels:
|
||||
app: taiga
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
spec:
|
||||
storageClassName: REPLACEME
|
||||
accessModes:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: taiga-secret
|
||||
namespace: taiga
|
||||
labels:
|
||||
app.kubernetes.part-of: taiga
|
||||
app.kubernetes.part-of: c4k-taiga
|
||||
data:
|
||||
# Taiga settings
|
||||
TAIGA_SECRET_KEY: TAIGA_SECRET_KEY
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
:metadata {:name "backup-config"
|
||||
:namespace "taiga"
|
||||
:labels {:app.kubernetes.io/name "backup"
|
||||
:app.kubernetes.io/part-of "taiga"}}
|
||||
:app.kubernetes.io/part-of "c4k-taiga"}}
|
||||
:data
|
||||
{:restic-repository "s3:restic-repository"}}
|
||||
(cut/generate-config {:restic-repository "s3:restic-repository"}))))
|
||||
|
|
|
@ -14,3 +14,14 @@
|
|||
(deftest validate-valid-resources
|
||||
(is (s/valid? cut/config? (yaml/load-as-edn "taiga-test/valid-config.yaml")))
|
||||
(is (s/valid? cut/auth? (yaml/load-as-edn "taiga-test/valid-auth.yaml"))))
|
||||
|
||||
(deftest test-whole-generation
|
||||
(is (= 49
|
||||
(count
|
||||
(cut/config-objects
|
||||
(yaml/load-as-edn "taiga-test/valid-config.yaml")))))
|
||||
(is (= 4
|
||||
(count
|
||||
(cut/auth-objects
|
||||
(yaml/load-as-edn "taiga-test/valid-config.yaml")
|
||||
(yaml/load-as-edn "taiga-test/valid-auth.yaml"))))))
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
(deftest should-generate-configmap
|
||||
(is (= {:apiVersion "v1",
|
||||
:kind "ConfigMap",
|
||||
:metadata {:name "taiga-configmap", :namespace "taiga"},
|
||||
:metadata
|
||||
{:name "taiga-configmap", :namespace "taiga"
|
||||
:labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:data
|
||||
{:ENABLE_TELEMETRY "false",
|
||||
:TAIGA_SITES_SCHEME "https",
|
||||
|
@ -43,7 +45,7 @@
|
|||
:metadata
|
||||
{:name "taiga-media-data",
|
||||
:namespace "taiga"
|
||||
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
|
||||
:labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:spec
|
||||
{:storageClassName "local-path",
|
||||
:accessModes ["ReadWriteOnce"],
|
||||
|
@ -54,7 +56,7 @@
|
|||
:metadata
|
||||
{:name "taiga-static-data",
|
||||
:namespace "taiga"
|
||||
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
|
||||
:labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:spec
|
||||
{:storageClassName "local-path",
|
||||
:accessModes ["ReadWriteOnce"],
|
||||
|
@ -67,7 +69,7 @@
|
|||
:metadata
|
||||
{:name "taiga-async-rabbitmq-data",
|
||||
:namespace "taiga"
|
||||
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
|
||||
:labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:spec
|
||||
{:storageClassName "local-path",
|
||||
:accessModes ["ReadWriteOnce"],
|
||||
|
@ -80,7 +82,7 @@
|
|||
:metadata
|
||||
{:name "taiga-events-rabbitmq-data",
|
||||
:namespace "taiga"
|
||||
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
|
||||
:labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:spec
|
||||
{:storageClassName "local-path",
|
||||
:accessModes ["ReadWriteOnce"],
|
||||
|
@ -91,7 +93,7 @@
|
|||
(is (= {:apiVersion "v1",
|
||||
:kind "Secret",
|
||||
:metadata
|
||||
{:name "taiga-secret", :namespace "taiga" :labels {:app.kubernetes.part-of "taiga"}},
|
||||
{:name "taiga-secret", :namespace "taiga" :labels {:app.kubernetes.part-of "c4k-taiga"}},
|
||||
:data
|
||||
{:TAIGA_SECRET_KEY "c29tZS1rZXk=",
|
||||
:EMAIL_HOST_USER "bWFpbGVyLXVzZXI=",
|
||||
|
|
Loading…
Add table
Reference in a new issue