diff --git a/get-all-apps.sh b/get-all-apps.sh new file mode 100755 index 0000000..8826d1d --- /dev/null +++ b/get-all-apps.sh @@ -0,0 +1,6 @@ +#! /usr/bin/env bash +k3s crictl pods --namespace ix -s Ready \ + | sed 1d | grep -v svclb- \ + | sed -E 's/[[:space:]]([0-9]*|About)[a-z0-9 ]{5,12}ago[[:space:]]//' \ + | awk '{ print $4 }' \ + | sed 's/^ix-//' | sort -u diff --git a/tcdbbackup.sh b/tcdbbackup.sh index f95eb62..808041a 100755 --- a/tcdbbackup.sh +++ b/tcdbbackup.sh @@ -1,10 +1,24 @@ -#!/bin/bash +#! /usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +USER_HOME=$HOME +[[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")" +. ${SHRC_D:-$SCRIPT_DIR}/01_util.functions + +set -e + # create backup folder folder="./dumps/" mkdir -p "$folder" # get namespaces with postgres database pod -namespaces=$(k3s kubectl get pods -A | grep postgres | awk '{print $1}') +json_results=$( + # While tcdbinfo lists all SQL databases, we want only postgresql + # in this script. + "${SCRIPT_DIR}/tcdbinfo.sh" --json "${@}" \ + | jq -s '.[] | select( .protocol = "postgresql" )' +) + +namespaces=$(<<<"$json_results" jq -sr '.[] | .name') for ns in $namespaces; do # extract application name @@ -18,7 +32,10 @@ for ns in $namespaces; do k3s kubectl scale deploy "$app" -n "$ns" --replicas=0 while true; do k3s kubectl get pods -n "$ns" | grep -i -q terminating || break; done; - k3s kubectl exec -n "$ns" -c "$app"-postgresql "$app"-postgresql-0 -- bash -c 'PGPASSWORD=$POSTGRES_PASSWORD pg_dump -Fc -U $POSTGRES_USER -d $POSTGRES_DB -f /tmp/'$file + k3s kubectl exec -n "$ns" -c "$app"-postgresql "$app"-postgresql-0 -- bash -c " + PGPASSWORD=\$POSTGRES_PASSWORD $( # Does not affect the output + ) pg_dump -Fc -U \$POSTGRES_USER -d \$POSTGRES_DB -f /tmp/$file + " k3s kubectl cp -n "$ns" -c "$app"-postgresql "$app-postgresql-0:tmp/$file" $folder$file # Scale deployment back up diff --git a/work-the-pvc b/work-the-pvc new file mode 100755 index 0000000..56c4483 --- /dev/null +++ b/work-the-pvc @@ -0,0 +1,145 @@ +#! /usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +USER_HOME=$HOME +[[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")" +. ${SHRC_D:-$SCRIPT_DIR}/01_util.functions + +set -e + +JSON=0 +if [[ $# -gt 0 && "$1" =~ ^-- ]]; then + if [[ "$1" == "--help" ]]; then + cat < + sudo ./$(basename $0) [] + +NOTE: + DBG=' ' will add debug output + without ZFS_DO=' ' zfs operations will not happen. + +Description: + + a simple match pattern, that will list any matching pvc names + + + Must match a unique pvc name, most commonly these are + -config or -data. + + +   zfs path to the dataset contianing the restore data + + (optional) + default value for this is: + \${ZFS_POOL\}/backup/tmp-\${APP_NAME\}-\${PVC\} + + available variables are: + NAME,APP_NAME,PVC,ZFS_POOL + +Examples: + + List all PVCs ending with either '-data' or '-config': + sudo ./$(basename $0) '-(data|config)$' + + Replace gitea-data's pvc with the one stored in tank/backup/gitea/pvc-backup + preserving the current gitea-data pvc in the default location: + tank/backup/tmp-gitea-data-pvc-... : + sudo ./$(basename $0) 'gitea-data' 'tank/backup/gitea/pvc-backup' + +USAGE + exit 0 + elif [[ "$1" == "--json" ]]; then + JSON=1 + fi + shift +fi + +require_root + +PVCS="$( + k3s kubectl get persistentvolume --output json \ + | jq ' + .items[] + | select( .spec.claimRef.name | test("'"${1}"'") ) + | { + name: .spec.claimRef.name + ,app: .spec.claimRef.namespace | sub("ix-"; "") + ,pvc: .spec.csi.volumeHandle + ,zfs_pvc: "\( + .spec.csi.volumeAttributes."openebs.io/poolname" + )/\( + .spec.csi.volumeHandle + )" + ,zfs_pool: + .spec.csi.volumeAttributes."openebs.io/poolname" + | split("/")[0] + #,raw: . + } + ' +)" + +DISPLAY_ONLY=0 +LEN="$(jq -s 'length' <<<"$PVCS")" +if [[ $# -eq 1 || "$LEN" -ne 1 ]]; then + DISPLAY_ONLY=1 +fi +if [[ "$LEN" -eq 0 ]]; then + PVCS='"ERROR: EMPTY query results"' +fi +if [[ "${DISPLAY_ONLY}" != 0 ]]; then + jq -r <<<"$PVCS" + exit 0 +fi + +ENV="$( + <<<"$PVCS" jq -r "[ + \"NAME='\(.name)'\" + ,\"APP_NAME='\(.app)'\" + ,\"PVC='\(.pvc)'\" + ,\"ZFS_PVC='\(.zfs_pvc)'\" + ,\"ZFS_POOL='\(.zfs_pool)'\" + ] | join (\"\n\") + " +)" +${DBG:-:} echo "$ENV" 1>&2 +eval $ENV + +TMP_DEST="${3:-\${ZFS_POOL\}/backup/tmp-\${APP_NAME\}-\${PVC\}}" +${DBG:-:} echo "$TMP_DEST" 1>&2 +eval "TMP_DEST=\"${TMP_DEST}\"" +${DBG:-:} echo "$TMP_DEST" 1>&2 + +if [[ -z "$(type -fp zfs)" ]]; then + printf "ERROR: zfs is not a valid command (is your PATH correct?)\n" 1>&2 + exit 2 +fi + +VALIDATE=() +zfs list -Ho name "$ZFS_PVC" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}" + "ZFS_PVC '$ZFS_PVC' cannot be found") +zfs list -Ho name "${2}" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}" + "Restore source '${2}' cannot be found") || true +zfs list -Ho name "${TMP_DEST%/*}" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}" + "Parent of temp-dset '${TMP_DEST%/*}' cannot be found") +zfs list -Ho name "$TMP_DEST" >/dev/null 2>&1 && VALIDATE=( "${VALIDATE[@]}" + "Temp dest '${TMP_DEST}' already exists") || true + +if [[ ${#VALIDATE[@]} -ne 0 ]]; then + ${DBG:-:} echo "" 1>&2 + printf 'ERROR: %s\n' "${VALIDATE[@]}" 1>&2 + exit 1 +fi + +printf '%s\n' \ + "Performing the following actions:" \ + " zfs rename '$ZFS_PVC' '${TMP_DEST}'" \ + " zfs rename '${2}' '$ZFS_PVC'" \ + '' '' \ + 'To revert these changes manualy run:' \ + " sudo zfs rename '$ZFS_PVC' '${2}' " \ + " sudo zfs rename '${TMP_DEST}' '$ZFS_PVC' " \ + '' '' + +${ZFS_DO:-:} zfs rename "$ZFS_PVC" "${TMP_DEST}" +${ZFS_DO:-:} zfs rename "${2}" "$ZFS_PVC"