Contabo API - automated snapshot creation
Using VPS instances provided by Contabo could be quite easy and not that expensive, but keep in mind to always have some backup at hand and to always keep at least a single snapshot of each instance (a single snapshot is included in the standard plan).
Not forgetting this layer of data preservation could help a lot and speed up recovery processes, so ... why not having this procedures fully automated and run by some Linux system ?
Let's have a look at a possible script ...
#!/bin/bash
# !!! CONFIGURATION SECTION !!!
# list of "INSTANCE ID":::"CLIENT ID":::"CLIENT KEY":::"API ID":::"API PWD":::"SNAPSHOT INTERVAL":::"URL TO CHECK,URL TO CHECK,..."
# --> item separatore is " "
# --> value separator is ":::"
INSTANCES="your.instance:::your.clientid:::your.clientsecret:::your.apiusername:::your.apipassword:::14:::https://your.website1.com,https://your.website2.com"
# !!! PROCEDURES SECTION !!!
export LANG=""
# --> NO CHANGES AFTER THIS COMMENT ... UNLESS YOU KNOW WHAT YOUR ARE DOING
# status of snapshot creations
CONTABO_OUTPUT=""
# preliminary check to see if 'cut' is present (and also to check if "which" is available) ...
which cut 2>/dev/null >/dev/null || exit 1
# check required programs and set variables
# list of "VARNAME":"PROGRAM NAME":"ALTERNATIVE PROGRAM NAME"
# --> item separator is " "
# --> value separator is ":"
PROGRAMS="AWKBIN:awk UUIDBIN:uuid CUTBIN:cut SEDBIN:sed CATBIN:cat JQBIN:jq WGETBIN:wget CURLBIN:curl GREPBIN:grep HEADBIN:head TRBIN:tr SLEEPBIN:sleep DATEBIN:date DATEDIFFBIN:dateutils.ddiff:datediff"
for PROGRAM in $PROGRAMS ;
do
VAR="$( echo $PROGRAM | cut -d: -f1 2>/dev/null )"
PRG="$( echo $PROGRAM | cut -d: -f2 2>/dev/null )"
ALT="$( echo $PROGRAM | cut -d: -f3 2>/dev/null )"
_PR="$( which $PRG 2>/dev/null )"
[[ "${_PR}" == "" && "$ALT" != "" ]] && _PR="$( which $ALT 2>/dev/null )"
[ "${_PR}" = "" ] && exit 2
declare $VAR="${_PR}"
done
# loop over instances
for INSTANCE in $INSTANCES ;
do
ID="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $1}' )"
CLIENT_ID="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $2}' )"
CLIENT_KEY="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $3}' )"
API_ID="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $4}' )"
API_PWD="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $5}' )"
INTERVAL="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $6}' )"
URLS="$( echo "$INSTANCE" | $AWKBIN -F::: '{ print $7}' | $TRBIN ',' ' ' )"
OUTPUT_ID=$( echo $ID | $TRBIN '-' '_' )
declare CONTABO_OUTPUT_${OUTPUT_ID}=""
OK=1
for URL in $URLS ;
do
$SLEEPBIN 1
if [ "$( $WGETBIN -qO- --server-response "$URL" 2>&1 | $GREPBIN ' HTTP/' | $HEADBIN -n1 | $GREPBIN ' 200 OK' )" = "" ]; then
OK=""
fi
done
if [ "$OK" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: URLs NOT OK"
continue
fi
ATOKEN=$( $CURLBIN -d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_KEY}" \
-d 'grant_type=password' \
--data-urlencode "username=${API_ID}" \
--data-urlencode "password=${API_PWD}" \
'https://auth.contabo.com/auth/realms/contabo/protocol/openid-connect/token' 2>/dev/null \
| $JQBIN -r '.access_token' 2>/dev/null )
if [ "$ATOKEN" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: TOKEN KO"
continue
fi
INSTANCE=$( $CURLBIN -X GET -H "Authorization: Bearer $ATOKEN" -H "x-request-id: ${ID}" "https://api.contabo.com/v1/compute/instances" 2>/dev/null \
| $JQBIN 2>/dev/null | $GREPBIN "instanceId" | $CUTBIN -d: -f2 | $SEDBIN -e 's/,//' | $SEDBIN -e 's/ //g' )
if [ "$INSTANCE" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: INSTANCE KO"
continue
fi
IDTRACE=$( $UUIDBIN )
SNAPSHOT=$( $CURLBIN -X GET "https://api.contabo.com/v1/compute/instances/${INSTANCE}/snapshots" \
-H 'Content-Type: application/json' -H "Authorization: Bearer ${ATOKEN}" \
-H "x-request-id: $( $UUIDBIN )" -H "x-trace-id: ${IDTRACE}" 2>/dev/null )
if [ "$SNAPSHOT" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: SNAPSHOTS UNAVAILABLE"
continue
fi
S_DATE=$( echo $SNAPSHOT | $JQBIN -r .data[0].createdDate | $GREPBIN -iv "null" )
S_ID=$( echo $SNAPSHOT | $JQBIN -r .data[0].snapshotId | $GREPBIN -iv "null" )
CREATE=""
if [[ "${S_DATE}" != "" && "${S_ID}" != "" ]]; then
DAYS=$( $DATEDIFFBIN --format="%d" $S_DATE now 2>/dev/null )
if [ "$DAYS" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: UNABLE TO GET LAST SNAPSHOT DATE"
continue
fi
[ $DAYS -gt $INTERVAL ] && CREATE=1
[ $DAYS -gt $INTERVAL ] || declare CONTABO_OUTPUT_${OUTPUT_ID}="WARNING: NO SNAPSHOT REQUIRED ($DAYS DAYS OLD)"
else
CREATE="1"
fi
if [ "$CREATE" = "1" ]; then
DELOK=$( $CURLBIN -i -X DELETE "https://api.contabo.com/v1/compute/instances/${INSTANCE}/snapshots/${S_ID}" \
-H 'Content-Type: application/json' -H "Authorization: Bearer ${ATOKEN}" -H "x-request-id: $( $UUIDBIN )" -H "x-trace-id: ${IDTRACE}" -d '{}' 2>/dev/null \
| $GREPBIN -e '^HTTP/' | $GREPBIN ' 20' )
if [ "$DELOK" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: UNABLE TO DELETE OLD SNAPSHOT"
continue
fi
fi
if [ "$CREATE" = "1" ]; then
NEWDATE=$( $DATEBIN +%Y%m%d )
OK=$( $CURLBIN -i -X POST "https://api.contabo.com/v1/compute/instances/${INSTANCE}/snapshots" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ATOKEN}" \
-H "x-request-id: $( $UUIDBIN )" -H "x-trace-id: ${IDTRACE}" \
-d "{\"name\":\"$NEWDATE\",\"description\":\"$NEWDATE\"}" \
2>/dev/null | $GREPBIN -e '^HTTP/' | $GREPBIN -E ' (20|30)' )
if [ "$OK" = "" ]; then
declare CONTABO_OUTPUT_${OUTPUT_ID}="ERROR: UNABLE TO CREATE NEW SNAPSHOT"
continue
fi
declare CONTABO_OUTPUT_${OUTPUT_ID}="SUCCESS: SNAPSHOT CREATED"
fi
done
set | $GREPBIN CONTABO_OUTPUT | $GREPBIN -v 'CONTABO_OUTPUT=' | $SEDBIN -e 's/^CONTABO_OUTPUT_/INSTANCE /g' | $SEDBIN -e 's/=/ = /g' | $TRBIN '_' '-'
exit 0