Skip to content

Commit

Permalink
Merge pull request #116 from i5okie/feature/mongo6
Browse files Browse the repository at this point in the history
Upgrade MongoDB Plugin and Dockerfile for compatibility with MongoDB Version 6+
  • Loading branch information
WadeBarnes authored Nov 28, 2023
2 parents 1eb1c52 + 2586094 commit 621bb53
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 43 deletions.
13 changes: 10 additions & 3 deletions docker/Dockerfile_Mongo
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# This image provides a mongo installation from which to run backups
FROM registry.access.redhat.com/rhscl/mongodb-36-rhel7
FROM mongodb/mongodb-community-server:6.0.6-ubi8

ARG uid=998
ARG user=mongod

# Change timezone to PST for convenience
ENV TZ=PST8PDT
Expand All @@ -23,6 +26,10 @@ ADD https://github.com/$SOURCE_REPO/go-crond/releases/download/$GOCROND_VERSION/
USER root

RUN chmod +x /usr/bin/go-crond
RUN chown -R $user:root /data/db && \
chmod -R ug+rw /data/db

RUN usermod -a -G 0 $user
# ========================================================================================================

# ========================================================================================================
Expand All @@ -32,7 +39,7 @@ RUN echo $TZ > /etc/timezone
# ========================================================================================================

# Important - Reset to the base image's user account.
USER 26
USER $uid

# Set the default CMD.
CMD sh /backup.sh
CMD bash /backup.sh
4 changes: 2 additions & 2 deletions docker/backup.container.utils
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function isPostgres(){

function isMongo(){
(
if isInstalled "mongo"; then
if isInstalled "mongosh"; then
return 0
else
return 1
Expand Down Expand Up @@ -79,4 +79,4 @@ function isForContainerType(){
fi
)
}
# ======================================================================================
# ======================================================================================
16 changes: 11 additions & 5 deletions docker/backup.misc.utils
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ function getElapsedTime(){
}

function getElapsedTimeFromDuration(){
(
local duration=${1}
local elapsedTime="$(($duration/3600))h:$(($duration%3600/60))m:$(($duration%60))s"
local duration_ns=${1}

local hours=$((duration_ns / 3600000000000))
local minutes=$(( (duration_ns % 3600000000000) / 60000000000 ))
local seconds=$(( (duration_ns % 60000000000) / 1000000000 ))
local milliseconds=$(( (duration_ns % 1000000000) / 1000000 ))
local microseconds=$(( (duration_ns % 1000000) / 1000 ))
local nanoseconds=$(( duration_ns % 1000 ))

local elapsedTime="${hours}h:${minutes}m:${seconds}s:${milliseconds}ms:${microseconds}µs:${nanoseconds}ns"
echo ${elapsedTime}
)
}
# ======================================================================================
# ======================================================================================
92 changes: 70 additions & 22 deletions docker/backup.mongo.plugin
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Mongo Backup and Restore Functions:
# - Dynamically loaded as a plug-in
# -----------------------------------------------------------------------------------------------------------------
export serverDataDirectory="/var/lib/mongodb/data"
export serverDataDirectory="/data/db"

function onBackupDatabase(){
(
Expand Down Expand Up @@ -69,6 +69,52 @@ function onRestoreDatabase(){
)
}

function onDatabaseInit() {
local OPTIND
local unset flags
while getopts : FLAG; do
case $FLAG in
? ) flags+="-${OPTARG} ";;
esac
done
shift $((OPTIND-1))

# Retrieve database details
local _databaseSpec=${1}
local _database=$(getDatabaseName "${_databaseSpec}")
local _username=$(getUsername "${_databaseSpec}")
local _password=$(getPassword "${_databaseSpec}")

# Check if the database already exists
if mongosh --quiet --eval "db.getMongo().getDBNames().indexOf('$_database') >= 0"; then
echoYellow "Database '$_database' already exists, skipping initialization."
return 0
fi

# Initialize the database by creating the user with the roles
mongosh "$_database" --quiet --eval "
db.createUser({
user: '$_username',
pwd: '$_password',
roles: [
{ role: 'dbOwner', db: '$_database' },
{ role: 'readWrite', db: '$_database' },
{ role: 'clusterAdmin', db: 'admin' }
]
});
"

# Check the exit status of the createUser command
if [ $? -eq 0 ]; then
echoGreen "Database '$_database' initialized successfully."
return 0
else
echoRed "Failed to initialize database '$_database'."
return 1
fi
}


function onStartServer(){
(
local OPTIND
Expand All @@ -82,12 +128,13 @@ function onStartServer(){

_databaseSpec=${1}

_hostname=$(getHostname ${flags} ${_databaseSpec})

# Start a local MongoDb instance
MONGODB_DATABASE=$(getDatabaseName "${_databaseSpec}") \
MONGODB_USER=$(getUsername "${_databaseSpec}") \
MONGODB_PASSWORD=$(getPassword "${_databaseSpec}") \
MONGODB_ADMIN_PASSWORD=$(getPassword "${_databaseSpec}") \
run-mongod >/dev/null 2>&1 &
mongod --bind_ip $_hostname > /dev/null 2>&1 &

# Initialize database if necessary
onDatabaseInit "${_databaseSpec}"
)
}

Expand All @@ -104,21 +151,18 @@ function onStopServer(){

_databaseSpec=${1}

_port=$(getPort ${_databaseSpec})
_portArg=${_port:+"--port ${_port}"}
_username=admin
_password=$(getPassword ${_databaseSpec})
_hostname=$(getHostname ${flags} ${_databaseSpec})

_authDbArg=${MONGODB_AUTHENTICATION_DATABASE:+"--authenticationDatabase ${MONGODB_AUTHENTICATION_DATABASE}"}
mongo admin ${_authDbArg} ${_portArg} -u "${_username}" -p "${_password}" --quiet --eval "db.shutdownServer()"
mongosh ${_hostname}/admin --quiet --eval "db.shutdownServer()" > /dev/null 2>&1

# Wait for server to stop ...
local startTime=${SECONDS}
local startTime=$(date +%s%N)

printf "waiting for server to stop"
while onPingDbServer ${@}; do
while onPingDbServer -l ${@}; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${DATABASE_SERVER_TIMEOUT} )); then
local duration_ns=$(($(date +%s%N) - $startTime))
if (( ${duration_ns} >= ${DATABASE_SERVER_TIMEOUT_NS} )); then
echoRed "\nThe server failed to stop within $(getElapsedTimeFromDuration ${duration})."
echoRed "Killing the mongod process ...\n"
pkill -INT mongod
Expand Down Expand Up @@ -163,10 +207,14 @@ function onPingDbServer(){

_dbAddressArg=${_hostname}${_port:+:${_port}}${_database:+/${_database}}
_authDbArg=${MONGODB_AUTHENTICATION_DATABASE:+"--authenticationDatabase ${MONGODB_AUTHENTICATION_DATABASE}"}
if mongo ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval='quit()' >/dev/null 2>&1; then
return 0
else

mongosh ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval='db.runCommand("ping").ok' > /dev/null 2>&1
local mongoshExitCode=$?

if (( ${mongoshExitCode} != 0 )); then
return 1
else
return 0
fi
)
}
Expand All @@ -193,7 +241,7 @@ function onVerifyBackup(){

_dbAddressArg=${_hostname}${_port:+:${_port}}${_database:+/${_database}}
_authDbArg=${MONGODB_AUTHENTICATION_DATABASE:+"--authenticationDatabase ${MONGODB_AUTHENTICATION_DATABASE}"}
collections=$(mongo ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval 'var dbs = [];dbs = db.getCollectionNames();for (i in dbs){ print(db.dbs[i]);}';)
collections=$(mongosh ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval 'var dbs = [];dbs = db.getCollectionNames();for (i in dbs){ print(db.dbs[i]);}';)
rtnCd=${?}

# Get the size of the restored database
Expand Down Expand Up @@ -241,11 +289,11 @@ function onGetDbSize(){

_dbAddressArg=${_hostname}${_port:+:${_port}}${_database:+/${_database}}
_authDbArg=${MONGODB_AUTHENTICATION_DATABASE:+"--authenticationDatabase ${MONGODB_AUTHENTICATION_DATABASE}"}
size=$(mongo ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval 'printjson(db.stats().fsTotalSize)')
size=$(mongosh ${_dbAddressArg} ${_authDbArg} -u "${_username}" -p "${_password}" --quiet --eval 'printjson(db.stats().fsTotalSize)')
rtnCd=${?}

echo ${size}
return ${rtnCd}
)
}
# =================================================================================================================
# =================================================================================================================
3 changes: 2 additions & 1 deletion docker/backup.settings
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@ export CONTAINER_TYPE="$(getContainerType)"

# Other:
export DATABASE_SERVER_TIMEOUT=${DATABASE_SERVER_TIMEOUT:-120}
# ======================================================================================
export DATABASE_SERVER_TIMEOUT_NS=$((DATABASE_SERVER_TIMEOUT * 1000000000))
# ======================================================================================
20 changes: 10 additions & 10 deletions docker/backup.utils
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ function restoreDatabase(){
echo -e "\n"
fi

local startTime=${SECONDS}
local startTime=$(date +%s%N)
onRestoreDatabase ${flags} "${_databaseSpec}" "${_fileName}" "${_adminPassword}"
_rtnCd=${?}

local endTime=${SECONDS}
local endTime=$(date +%s%N)
if (( ${_rtnCd} == 0 )); then
echoGreen "\nRestore complete - Elapsed time: $(getElapsedTime ${startTime} ${endTime})\n"
else
Expand All @@ -92,11 +92,11 @@ function runBackups(){

for database in ${databases}; do
if isForContainerType ${database}; then
local startTime=${SECONDS}
local startTime=$(date +%s%N)
filename=$(generateFilename "${backupDir}" "${database}")
backupDatabase "${database}" "${filename}"
rtnCd=${?}
local endTime=${SECONDS}
local endTime=$(date +%s%N)
local elapsedTime="\n\nElapsed time: $(getElapsedTime ${startTime} ${endTime}) - Status Code: ${rtnCd}"

if (( ${rtnCd} == 0 )); then
Expand Down Expand Up @@ -124,13 +124,13 @@ function startServer(){
onStartServer ${@}

# Wait for server to start ...
local startTime=${SECONDS}
local startTime=$(date +%s%N)
rtnCd=0
printf "waiting for server to start"
while ! pingDbServer ${@}; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${DATABASE_SERVER_TIMEOUT} )); then
local duration_ns=$(($(date +%s%N) - $startTime))
if (( ${duration_ns} >= ${DATABASE_SERVER_TIMEOUT_NS} )); then
echoRed "\nThe server failed to start within $(getElapsedTimeFromDuration ${duration}).\n"
rtnCd=1
break
Expand Down Expand Up @@ -231,7 +231,7 @@ function verifyBackup(){
# Make sure things have been cleaned up before we start ...
cleanUp

local startTime=${SECONDS}
local startTime=$(date +%s%N)
startServer -l "${_databaseSpec}"
rtnCd=${?}

Expand Down Expand Up @@ -262,10 +262,10 @@ function verifyBackup(){
fi

# Stop the database server and clean up ...
stopServer "${_databaseSpec}"
stopServer -l "${_databaseSpec}"
cleanUp

local endTime=${SECONDS}
local endTime=$(date +%s%N)
local elapsedTime="\n\nElapsed time: $(getElapsedTime ${startTime} ${endTime}) - Status Code: ${rtnCd}"

if (( ${rtnCd} == 0 )); then
Expand Down

0 comments on commit 621bb53

Please sign in to comment.