switch to common backup

This commit is contained in:
Michael Jerger 2025-04-16 18:11:03 +02:00
parent 217a1bf51c
commit 9d48bbb8fb
10 changed files with 12 additions and 283 deletions

1
.gitignore vendored
View file

@ -28,3 +28,4 @@ public/js/
.eastwood
.envrc
out*.*

View file

@ -5,7 +5,7 @@
:url "https://www.apache.org/licenses/LICENSE-2.0.html"}
:dependencies [[org.clojure/clojure "1.12.0" :scope "provided"]
[org.clojure/tools.reader "1.5.2"]
[org.domaindrivenarchitecture/c4k-common-clj "10.0.0"]
[org.domaindrivenarchitecture/c4k-common-clj "11.0.0-SNAPSHOT"]
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
:target-path "target/%s/"
:source-paths ["src/main/cljc"

View file

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

View file

@ -1,52 +0,0 @@
(ns dda.c4k-forgejo.backup
(:require
[clojure.spec.alpha :as s]
#?(:clj [orchestra.core :refer [defn-spec]]
:cljs [orchestra.core :refer-macros [defn-spec]])
[dda.c4k-common.yaml :as yaml]
[dda.c4k-common.base64 :as b64]
[dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as p]
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
(s/def ::aws-access-key-id p/bash-env-string?)
(s/def ::aws-secret-access-key p/bash-env-string?)
(s/def ::restic-password p/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
(defmethod yaml/load-resource :backup [resource-name]
(get (inline-resources "backup") resource-name)))
(defn-spec generate-config p/map-or-seq?
[my-conf ::config]
(let [{:keys [restic-repository]} my-conf]
(->
(yaml/from-string (yaml/load-resource "backup/config.yaml"))
(cm/replace-key-value :restic-repository restic-repository))))
(defn-spec generate-cron p/map-or-seq?
[]
(yaml/from-string (yaml/load-resource "backup/cron.yaml")))
(defn-spec generate-backup-restore-deployment p/map-or-seq?
[my-conf ::config]
(yaml/from-string (yaml/load-resource "backup/backup-restore-deployment.yaml")))
(defn-spec generate-secret p/map-or-seq?
[auth ::auth]
(let [{:keys [aws-access-key-id aws-secret-access-key
restic-password restic-new-password]} auth]
(as-> (yaml/from-string (yaml/load-resource "backup/secret.yaml")) res
(cm/replace-key-value res :aws-access-key-id (b64/encode aws-access-key-id))
(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

@ -7,8 +7,8 @@
[dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as p]
[dda.c4k-common.monitoring :as mon]
[dda.c4k-common.backup :as backup]
[dda.c4k-forgejo.forgejo :as forgejo]
[dda.c4k-forgejo.backup :as backup]
[dda.c4k-common.postgres :as postgres]
[dda.c4k-common.namespace :as ns]))
@ -21,6 +21,12 @@
:pvc-storage-class-name :local-path
:postgres-image "postgres:14"
:postgres-size :2gb
:backup-image "domaindrivenarchitecture/c4k-forgejo-backup"
:app-name "forgejo"
:backup-postgres true
:backup-volume-mount {:mount-name "forgejo-data-volume"
:pvc-name "forgejo-data-pvc"
:mount-path "/var/backups"}
:max-rate 10,
:max-concurrent-requests 5})
@ -67,9 +73,7 @@
(forgejo/generate-appini-env resolved-config)]
(forgejo/generate-ratelimit-ingress-and-cert resolved-config) ; this function has a vector as output
(when (contains? resolved-config :restic-repository)
[(backup/generate-config resolved-config)
(backup/generate-cron)
(backup/generate-backup-restore-deployment resolved-config)])
(backup/config-objects resolved-config))
(when (contains? resolved-config :mon-cfg)
(mon/generate-config)))))))
@ -84,6 +88,6 @@
[(postgres/generate-secret resolved-config auth)
(forgejo/generate-secrets auth)]
(when (contains? resolved-config :restic-repository)
[(backup/generate-secret auth)])
(backup/auth-objects resolved-config auth))
(when (contains? resolved-config :mon-cfg)
(mon/generate-auth (:mon-cfg resolved-config) (:mon-auth auth))))))))

View file

@ -1,74 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backup-restore
namespace: forgejo
spec:
replicas: 0
selector:
matchLabels:
app: backup-restore
strategy:
type: Recreate
template:
metadata:
labels:
app: backup-restore
app.kubernetes.io/name: backup-restore
app.kubernetes.io/part-of: forgejo
spec:
containers:
- image: domaindrivenarchitecture/c4k-forgejo-backup
name: backup-app
imagePullPolicy: IfNotPresent
command: ["wait.bb"]
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-db
- name: POSTGRES_HOST
value: "postgresql-service:5432"
- name: POSTGRES_SERVICE
value: "postgresql-service"
- name: POSTGRES_PORT
value: "5432"
- name: AWS_DEFAULT_REGION
value: eu-central-1
- name: AWS_ACCESS_KEY_ID_FILE
value: /var/run/secrets/backup-secrets/aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY_FILE
value: /var/run/secrets/backup-secrets/aws-secret-access-key
- name: RESTIC_REPOSITORY
valueFrom:
configMapKeyRef:
name: backup-config
key: restic-repository
- name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password
- name: RESTIC_NEW_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-new-password
volumeMounts:
- name: forgejo-data-volume
mountPath: /var/backups
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
volumes:
- name: forgejo-data-volume
persistentVolumeClaim:
claimName: forgejo-data-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret

View file

@ -1,10 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: backup-config
namespace: forgejo
labels:
app.kubernetes.io/name: backup
app.kubernetes.io/part-of: forgejo
data:
restic-repository: restic-repository

View file

@ -1,71 +0,0 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: forgejo-backup
namespace: forgejo
labels:
app.kubernetes.part-of: forgejo
spec:
schedule: "10 23 * * *"
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: backup-app
image: domaindrivenarchitecture/c4k-forgejo-backup
imagePullPolicy: IfNotPresent
command: ["backup.bb"]
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-db
- name: POSTGRES_HOST
value: "postgresql-service:5432"
- name: POSTGRES_SERVICE
value: "postgresql-service"
- name: POSTGRES_PORT
value: "5432"
- name: AWS_DEFAULT_REGION
value: eu-central-1
- name: AWS_ACCESS_KEY_ID_FILE
value: /var/run/secrets/backup-secrets/aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY_FILE
value: /var/run/secrets/backup-secrets/aws-secret-access-key
- name: RESTIC_REPOSITORY
valueFrom:
configMapKeyRef:
name: backup-config
key: restic-repository
- name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password
- name: CERTIFICATE_FILE
value: ""
volumeMounts:
- name: forgejo-data-volume
mountPath: /var/backups
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
volumes:
- name: forgejo-data-volume
persistentVolumeClaim:
claimName: forgejo-data-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret
restartPolicy: OnFailure

View file

@ -1,10 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: backup-secret
namespace: forgejo
type: Opaque
data:
aws-access-key-id: aws-access-key-id
aws-secret-access-key: aws-secret-access-key
restic-password: restic-password

View file

@ -1,59 +0,0 @@
(ns dda.c4k-forgejo.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-forgejo.backup :as cut]))
(st/instrument `cut/generate-secret)
(st/instrument `cut/generate-config)
(deftest should-generate-secret
(is (= {:apiVersion "v1",
:kind "Secret",
:metadata {:name "backup-secret", :namespace "forgejo"},
: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 "forgejo"},
:type "Opaque",
:data
{:aws-access-key-id "YXdzLWlk",
:aws-secret-access-key "YXdzLXNlY3JldA==",
:restic-password "b2xk",
:restic-new-password "bmV3"}}
(cut/generate-secret {:aws-access-key-id "aws-id"
:aws-secret-access-key "aws-secret"
:restic-password "old"
:restic-new-password "new"}))))
(deftest should-generate-backup-config
(testing "federated"
(is (= {:apiVersion "v1",
:kind "ConfigMap",
:metadata
{:name "backup-config",
:namespace "forgejo",
:labels
#:app.kubernetes.io{:name "backup", :part-of "forgejo"}},
:data {:restic-repository "s3:s3.amazonaws.com/backup/federated-repo"}}
(cut/generate-config
{:restic-repository "s3:s3.amazonaws.com/backup/federated-repo"}))))
(testing "non-federated"
(is (= {:apiVersion "v1",
:kind "ConfigMap",
:metadata
{:name "backup-config",
:namespace "forgejo",
:labels
#:app.kubernetes.io{:name "backup", :part-of "forgejo"}},
:data {:restic-repository "s3:s3.amazonaws.com/backup/repo"}}
(cut/generate-config
{:restic-repository "s3:s3.amazonaws.com/backup/repo"})))))