From 0b157b92c751d965f9dd3241529ea5f15566fa75 Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Sun, 17 May 2020 18:29:31 +0200 Subject: [PATCH] new: [mongo] added regular dump for backup Signed-off-by: Valentin Lab --- mongo/build/Dockerfile | 4 +- mongo/hooks/schedule_command-relation-joined | 43 +++++++++++++++++ mongo/metadata.yml | 9 ++++ mongo/resources/bin/mongo-backup | 49 ++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100755 mongo/hooks/schedule_command-relation-joined create mode 100755 mongo/resources/bin/mongo-backup diff --git a/mongo/build/Dockerfile b/mongo/build/Dockerfile index e108157..7bd8ef4 100644 --- a/mongo/build/Dockerfile +++ b/mongo/build/Dockerfile @@ -2,7 +2,9 @@ ## is a simple copy of alpine:3.9 FROM docker.0k.io/alpine:3.9 as common -RUN apk add --no-cache mongodb +## mongodb-tools is only required because we expect and use mongodump +## XXXvlab: bash is only required by mongo-backup, we could probably only use sh +RUN apk add --no-cache mongodb mongodb-tools bash RUN mkdir -p /var/lib/mongod RUN chown -R mongodb:mongodb /var/lib/mongod diff --git a/mongo/hooks/schedule_command-relation-joined b/mongo/hooks/schedule_command-relation-joined new file mode 100755 index 0000000..eaf0374 --- /dev/null +++ b/mongo/hooks/schedule_command-relation-joined @@ -0,0 +1,43 @@ +#!/bin/bash + +## When writing relation script, remember: +## - they should be idempotents +## - they can be launched while the dockers is already up +## - they are launched from the host +## - the target of the link is launched first, and get a chance to ``relation-set`` +## - both side of the scripts get to use ``relation-get``. + +. lib/common + +set -e + +label=${SERVICE_NAME}-backup +DST=$CONFIGSTORE/$TARGET_SERVICE_NAME/etc/cron/$label +schedule=$(relation-get schedule) + +if ! echo "$schedule" | egrep '^\s*(([0-9/,*-]+\s+){4,4}[0-9/,*-]+|@[a-z]+)\s*$' >/dev/null 2>&1; then + err "Unrecognized schedule '$schedule'." + exit 1 +fi + +exclude_dbs=$(relation-get exclude-dbs 2>/dev/null) || true +exclude_dbs=$(echo "$exclude_dbs" | shyaml get-values 2>/dev/null | + nspc) || true + +## Warning: 'docker -v' will use HOST directory even if launched from +## 'cron' container. +file_put "$DST" <&1 | ts '\%F \%T \%Z' >> /var/log/cron/${label}_script.log +EOF +chmod +x "$DST" diff --git a/mongo/metadata.yml b/mongo/metadata.yml index 83a12bf..1cc47fd 100644 --- a/mongo/metadata.yml +++ b/mongo/metadata.yml @@ -6,3 +6,12 @@ config-resources: - /etc/mongod.conf provides: mongo-database: + +uses: + schedule-command: + constraint: optional + auto: pair + solves: + backup: "Automatic regular backups" + default-options: + schedule: "47 * * * *" ## schedule backup every hour diff --git a/mongo/resources/bin/mongo-backup b/mongo/resources/bin/mongo-backup new file mode 100755 index 0000000..e2d9815 --- /dev/null +++ b/mongo/resources/bin/mongo-backup @@ -0,0 +1,49 @@ +#!/bin/bash + +[ "$MONGO_HOST" ] || { + echo "You must define \$MONGO_HOST variable." >&2 + exit 1 +} + + +mongo_databases() { + echo "show dbs" | mongo --quiet --host "$MONGO_HOST" | cut -f 1 -d " " +} + +dbs=$(mongo_databases) + +BACKUP_ROOT=/var/backups/mongo +mkdir -p "$BACKUP_ROOT" +for db in $dbs; do + if [[ "$db" == "local" || "$db" == "config" ]]; then + continue + fi + for exclude_db in $exclude_dbs; do + if [ "$exclude_db" == "$db" ]; then + echo "No backup for database $db as it is listed in 'exclude-dbs'." + continue 2 + fi + done + + dst="$BACKUP_ROOT/$db" + [ -d "$dst.old" ] && rm -rf "$dst.old" + [ -d "$dst" ] && mv "$dst" "$dst.old" + mkdir -p "$dst.inprogress" + (( start = SECONDS )) + echo "Dumping database $db..." >&2 + mongodump --host "$MONGO_HOST" --db "$db" --out "$dst.inprogress" && + mv "$dst.inprogress/$db/"* "$dst.inprogress/" && + rmdir "$dst.inprogress/$db" + errlvl="${PIPESTATUS[0]}" + (( elapsed = SECONDS - start )) + if [ "$errlvl" != "0" ]; then + echo " !! Error when dumping database $db." >&2 + rm -rf "$dst.inprogress" && + [ -d "$dst.old" ] && rm -rf "$dst.old" + else + mv "$dst.inprogress" "$dst" + [ -d "$dst.old" ] && rm -rf "$dst.old" + printf " ..dumped %-35s (%12s in %10s)\n" "$db" "$(du -sh "$dst" | cut -f 1)" "${elapsed}s" >&2 + fi +done +