Compare commits
6 commits
main
...
backup-mon
Author | SHA1 | Date | |
---|---|---|---|
2c3a0aa8a9 | |||
2e39383a04 | |||
0d9324017d | |||
e0e59e2620 | |||
c18a4c9a8b | |||
2fb682e94b |
14 changed files with 103 additions and 132 deletions
10
deps.edn
10
deps.edn
|
@ -9,9 +9,12 @@
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
:deps
|
:deps
|
||||||
{;; Application
|
{;; Application
|
||||||
org.clojure/clojure {:mvn/version "1.11.4"}
|
;;org.clojure/clojure {:mvn/version "1.11.4"}
|
||||||
org.clojure/spec.alpha {:mvn/version "0.5.238"}
|
org.clojure/spec.alpha {:mvn/version "0.5.238"}
|
||||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}}
|
;; org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha"
|
||||||
|
;; :git/sha "644a7fc216e43d5da87b07471b0f87d874107d1a"}
|
||||||
|
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
||||||
|
babashka/babashka.curl {:mvn/version "0.1.2"}}
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
|
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
|
@ -26,7 +29,8 @@
|
||||||
;; call with :watch? true to start file watcher and re-run tests on saved changes
|
;; call with :watch? true to start file watcher and re-run tests on saved changes
|
||||||
:test/run
|
:test/run
|
||||||
{:extra-paths ["test"]
|
{:extra-paths ["test"]
|
||||||
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}
|
||||||
|
expound/expound {:mvn/version "0.9.0"}}
|
||||||
:main-opts ["-m" "kaocha.runner"]
|
:main-opts ["-m" "kaocha.runner"]
|
||||||
:exec-fn kaocha.runner/exec-fn
|
:exec-fn kaocha.runner/exec-fn
|
||||||
:exec-args {:randomize? false
|
:exec-args {:randomize? false
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
# Credential Rotation
|
|
||||||
|
|
||||||
## Example Data
|
|
||||||
|
|
||||||
Default
|
|
||||||
|
|
||||||
```json
|
|
||||||
[{
|
|
||||||
"current": true,
|
|
||||||
"id": "521e0760",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:08:16"
|
|
||||||
}]
|
|
||||||
```
|
|
||||||
|
|
||||||
Add another password
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"current": true,
|
|
||||||
"id": "521e0760",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:08:16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"current": false,
|
|
||||||
"id": "b67161fb",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:16:54"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Change current password
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"current": false,
|
|
||||||
"id": "521e0760",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:08:16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"current": true,
|
|
||||||
"id": "b67161fb",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:16:54"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Remove old password
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"current": true,
|
|
||||||
"id": "b67161fb",
|
|
||||||
"userName": "root",
|
|
||||||
"hostName": "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
"created": "2024-10-18 13:16:54"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
Steps need to be validated and performed seperately and work independently of each other.
|
|
||||||
To avoid problems where the program is shut down mid-transition.
|
|
||||||
|
|
||||||
### Stages
|
|
||||||
|
|
||||||
#### Initial State
|
|
||||||
|
|
||||||
Validation:
|
|
||||||
|
|
||||||
- Detect change requested: new password file environment is set
|
|
||||||
|
|
||||||
Steps to perform:
|
|
||||||
|
|
||||||
- Add new password
|
|
||||||
- `restic -r <repo> key add --new-password-file <file>`
|
|
||||||
|
|
||||||
#### New password has been added
|
|
||||||
|
|
||||||
Validation:
|
|
||||||
|
|
||||||
- List of passwords has 2 entries
|
|
||||||
- The password with the newer timestamp is not set as "current"
|
|
||||||
|
|
||||||
Steps to perform:
|
|
||||||
|
|
||||||
- Extract id of new password
|
|
||||||
- Extract id of old password
|
|
||||||
- Remove old password in favour of new one
|
|
||||||
- `restic -r <repo> key remove --key-hint <new-id> <old-id>`
|
|
||||||
- Unset new password file environment
|
|
|
@ -3,6 +3,7 @@
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
(s/def ::command (s/cat
|
(s/def ::command (s/cat
|
||||||
|
:opts (s/? map?)
|
||||||
:app string?
|
:app string?
|
||||||
:params (s/* string?)))
|
:params (s/* string?)))
|
||||||
(s/def ::commands (s/coll-of ::command))
|
(s/def ::commands (s/coll-of ::command))
|
||||||
|
|
11
src/dda/backup/monitoring.clj
Normal file
11
src/dda/backup/monitoring.clj
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
(ns dda.backup.monitoring
|
||||||
|
(:require
|
||||||
|
[dda.backup.monitoring.domain :as d]
|
||||||
|
[orchestra.core :refer [defn-spec]]))
|
||||||
|
|
||||||
|
(defn-spec send-monitoring any?
|
||||||
|
[config ::d/monitoring-config]
|
||||||
|
(curl/post
|
||||||
|
"http://pushgateway:9091/metrics/job/backup"
|
||||||
|
{:headers {"Content-Type" "application/json; schema=\"prometheus/telemetry\"; version=\"0.0.2\""}
|
||||||
|
:body (d/monitoring-data config)}))
|
43
src/dda/backup/monitoring/domain.clj
Normal file
43
src/dda/backup/monitoring/domain.clj
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
(ns dda.backup.monitoring.domain
|
||||||
|
(:require
|
||||||
|
[dda.backup.restic.domain :as rd]
|
||||||
|
[dda.backup.monitoring.element :as e]
|
||||||
|
[orchestra.core :refer [defn-spec]]
|
||||||
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(s/def ::type #{"gauge"})
|
||||||
|
(s/def ::value (s/+ ::e/metric-element))
|
||||||
|
(s/def ::metric (s/keys :req-un [::type
|
||||||
|
::value]))
|
||||||
|
(s/def ::backup-size (s/spec ::e/value))
|
||||||
|
|
||||||
|
(s/def ::docstring string?)
|
||||||
|
(s/def ::__name__ string?)
|
||||||
|
(s/def ::baseLabels (s/keys :req-un [::__name__]))
|
||||||
|
|
||||||
|
(s/def ::monitoring-data (s/keys :req-un [::baseLabels
|
||||||
|
::docstring
|
||||||
|
::metric]))
|
||||||
|
|
||||||
|
(s/def ::monitoring-data-seq (s/+ ::monitoring-data))
|
||||||
|
|
||||||
|
(s/def ::fqdn string?)
|
||||||
|
|
||||||
|
|
||||||
|
(s/def ::monitoring-config
|
||||||
|
(s/keys :req-un [::fqdn
|
||||||
|
::backup-size
|
||||||
|
::rd/restic-repository
|
||||||
|
::rd/backup-path]))
|
||||||
|
|
||||||
|
(defn-spec monitoring-data ::monitoring-data-seq
|
||||||
|
[config ::monitoring-config]
|
||||||
|
(let [{:keys [fqdn backup-size restic-repository backup-path]} config]
|
||||||
|
[{:baseLabels {:__name__ "backup_size"},
|
||||||
|
:docstring "Backup size in MB",
|
||||||
|
:metric {:type "gauge",
|
||||||
|
:value [{:labels
|
||||||
|
{:app_name "c4k-forgejo"
|
||||||
|
:fqdn fqdn
|
||||||
|
:restic_repo (str restic-repository "/" backup-path)},
|
||||||
|
:value backup-size}]}}]))
|
7
src/dda/backup/monitoring/element.clj
Normal file
7
src/dda/backup/monitoring/element.clj
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
(ns dda.backup.monitoring.element
|
||||||
|
(:require
|
||||||
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(s/def ::labels map?)
|
||||||
|
(s/def ::value pos?)
|
||||||
|
(s/def ::metric-element (s/keys :req-un [::labels ::value]))
|
|
@ -30,9 +30,11 @@
|
||||||
(s/merge ::pg-config
|
(s/merge ::pg-config
|
||||||
::rd/restic-config))
|
::rd/restic-config))
|
||||||
|
|
||||||
|
(s/def ::pg-command (s/* string?))
|
||||||
|
|
||||||
(defn-spec psql-command ::cd/command
|
(defn-spec psql-command ::cd/command
|
||||||
[config ::pg-config
|
[config ::pg-config
|
||||||
command ::cd/command]
|
command ::pg-command]
|
||||||
(let [{:keys [pg-host pg-port pg-db pg-user]} config]
|
(let [{:keys [pg-host pg-port pg-db pg-user]} config]
|
||||||
(into
|
(into
|
||||||
["psql" "-d" pg-db "-h" pg-host "-p" (str pg-port) "-U" pg-user
|
["psql" "-d" pg-db "-h" pg-host "-p" (str pg-port) "-U" pg-user
|
||||||
|
@ -41,7 +43,7 @@
|
||||||
|
|
||||||
(defn-spec pgdumpall-command ::cd/command
|
(defn-spec pgdumpall-command ::cd/command
|
||||||
[config ::pg-role-dump-config
|
[config ::pg-role-dump-config
|
||||||
command ::cd/command]
|
command ::pg-command]
|
||||||
(let [{:keys [pg-host pg-port pg-user pg-role-prefix]} config]
|
(let [{:keys [pg-host pg-port pg-user pg-role-prefix]} config]
|
||||||
(into
|
(into
|
||||||
[]
|
[]
|
||||||
|
@ -54,7 +56,7 @@
|
||||||
|
|
||||||
(defn-spec pgdump-command ::cd/command
|
(defn-spec pgdump-command ::cd/command
|
||||||
[config ::pg-db-dump-config
|
[config ::pg-db-dump-config
|
||||||
command ::cd/command]
|
command ::pg-command]
|
||||||
(let [{:keys [pg-host pg-port pg-db pg-user]} config]
|
(let [{:keys [pg-host pg-port pg-db pg-user]} config]
|
||||||
(into
|
(into
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
(ns dda.backup.backup.domain-test
|
(ns dda.backup.backup.domain-test
|
||||||
(:require
|
(:require
|
||||||
[clojure.test :refer [deftest is are testing run-tests]]
|
[clojure.test :refer [deftest is are testing run-tests]]
|
||||||
[clojure.spec.test.alpha :as st]
|
|
||||||
[dda.backup.backup.domain :as cut]))
|
[dda.backup.backup.domain :as cut]))
|
||||||
|
|
||||||
(st/instrument `cut/backup-files-command)
|
|
||||||
(st/instrument `cut/backup-role-command)
|
|
||||||
(st/instrument `cut/backup-db-command)
|
|
||||||
|
|
||||||
(deftest should-calculate-backup-files-command
|
(deftest should-calculate-backup-files-command
|
||||||
(is (= [[{:dir "dir-to-backup"}
|
(is (= [[{:dir "dir-to-backup"}
|
||||||
"restic"
|
"restic"
|
||||||
|
|
|
@ -6,7 +6,13 @@
|
||||||
|
|
||||||
(deftest should-verify-command
|
(deftest should-verify-command
|
||||||
(is (= {:app "restic", :params ["-r" "repo/dir" "-v" "init" "--cacert" "ca"]}
|
(is (= {:app "restic", :params ["-r" "repo/dir" "-v" "init" "--cacert" "ca"]}
|
||||||
(s/conform ::cut/command ["restic" "-r" "repo/dir" "-v" "init" "--cacert" "ca"]))))
|
(s/conform ::cut/command ["restic" "-r" "repo/dir" "-v" "init" "--cacert" "ca"])))
|
||||||
|
(is (= {:app "restic"}
|
||||||
|
(s/conform ::cut/command ["restic"])))
|
||||||
|
(is (= {:opts {:dir "dir"} :app "restic", :params ["-r" "repo/dir" "-v" "init" "--cacert" "ca"]}
|
||||||
|
(s/conform ::cut/command [{:dir "dir"} "restic" "-r" "repo/dir" "-v" "init" "--cacert" "ca"])))
|
||||||
|
(is (= {:opts {:dir "dir"} :app "restic"}
|
||||||
|
(s/conform ::cut/command [{:dir "dir"} "restic"]))))
|
||||||
|
|
||||||
(deftest should-verify-commands
|
(deftest should-verify-commands
|
||||||
(is (= [{:app "ls"}
|
(is (= [{:app "ls"}
|
||||||
|
|
19
test/dda/backup/monitoring/domain_test.clj
Normal file
19
test/dda/backup/monitoring/domain_test.clj
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
(ns dda.backup.monitoring.domain-test
|
||||||
|
(:require
|
||||||
|
[clojure.test :refer [deftest is are testing run-tests]]
|
||||||
|
[dda.backup.monitoring.domain :as cut]))
|
||||||
|
|
||||||
|
(deftest should-generate-monitoring-data
|
||||||
|
(is (= [{:baseLabels {:__name__ "backup_size"},
|
||||||
|
:docstring "Backup size in MB",
|
||||||
|
:metric {:type "gauge",
|
||||||
|
:value [{:labels
|
||||||
|
{:app_name "c4k-forgejo"
|
||||||
|
:fqdn "repo.prod.meissa.de"
|
||||||
|
:restic_repo "repo/dir-at-repo"},
|
||||||
|
:value 123}]}}]
|
||||||
|
(cut/monitoring-data {:fqdn "repo.prod.meissa.de"
|
||||||
|
:restic-repository "repo"
|
||||||
|
:backup-path "dir-at-repo"
|
||||||
|
:backup-size 123}))))
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
(ns dda.backup.postgresql.domain-test
|
(ns dda.backup.postgresql.domain-test
|
||||||
(:require
|
(:require
|
||||||
[clojure.test :refer [deftest is are testing run-tests]]
|
[clojure.test :refer [deftest is are testing run-tests]]
|
||||||
[clojure.spec.test.alpha :as st]
|
|
||||||
[dda.backup.postgresql.domain :as cut]))
|
[dda.backup.postgresql.domain :as cut]))
|
||||||
|
|
||||||
(st/instrument `cut/pgpass)
|
|
||||||
(st/instrument `cut/db-drop-command)
|
|
||||||
(st/instrument `cut/db-create-command)
|
|
||||||
|
|
||||||
(deftest should-calculate-pgpass
|
(deftest should-calculate-pgpass
|
||||||
(is (= "localhost:5432:mydb:user:password\nlocalhost:5432:template1:user:password\n"
|
(is (= "localhost:5432:mydb:user:password\nlocalhost:5432:template1:user:password\n"
|
||||||
(cut/pgpass {:restic-repository "repo"
|
(cut/pgpass {:restic-repository "repo"
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
(ns dda.backup.restic.domain-test
|
(ns dda.backup.restic.domain-test
|
||||||
(:require
|
(:require
|
||||||
[clojure.test :refer [deftest is are testing run-tests]]
|
[clojure.test :refer [deftest is are testing run-tests]]
|
||||||
[clojure.spec.test.alpha :as st]
|
|
||||||
[dda.backup.restic.domain :as cut]))
|
[dda.backup.restic.domain :as cut]))
|
||||||
|
|
||||||
(st/instrument `cut/repo-command)
|
|
||||||
(st/instrument `cut/init-repo-command)
|
|
||||||
(st/instrument `cut/unlock-repo-command)
|
|
||||||
(st/instrument `cut/forget-command)
|
|
||||||
|
|
||||||
(deftest should-calculate-repo-command
|
(deftest should-calculate-repo-command
|
||||||
(is (= [{:dir "dir"}
|
(is (= [{:dir "dir"}
|
||||||
"restic"
|
"restic"
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
(ns dda.backup.restore.domain-test
|
(ns dda.backup.restore.domain-test
|
||||||
(:require
|
(:require
|
||||||
[clojure.test :refer [deftest is are testing run-tests]]
|
[clojure.test :refer [deftest is are testing run-tests]]
|
||||||
[clojure.spec.test.alpha :as st]
|
|
||||||
[dda.backup.restore.domain :as cut]))
|
[dda.backup.restore.domain :as cut]))
|
||||||
|
|
||||||
(st/instrument `cut/restore-dir-command)
|
|
||||||
(st/instrument `cut/restore-db-command)
|
|
||||||
|
|
||||||
(deftest should-calculate-restore-dir
|
(deftest should-calculate-restore-dir
|
||||||
(is (= [["rm" "-rf" "dir-to-backup"]
|
(is (= [["rm" "-rf" "dir-to-backup"]
|
||||||
["restic"
|
["restic"
|
||||||
|
|
|
@ -10,4 +10,6 @@
|
||||||
|
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
|
|
||||||
#kaocha/v1 {}
|
#kaocha/v1 {:plugins [:orchestra]
|
||||||
|
:reporter kaocha.report/documentation}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue