From c03fe11fe5dda73ebaadf7a18f266d2438e0587f Mon Sep 17 00:00:00 2001 From: James Tufarelli Date: Mon, 23 Oct 2023 14:22:07 -0700 Subject: [PATCH] Remove ENV variables from Dockerfile --- Dockerfile | 37 -------- pkg/entry.sh | 152 ++++----------------------------- pkg/env.sh | 224 +++++++++++++++++++++++++++++++++++++++++++++++++ pkg/utils.sh | 50 +++++++++++ tests/tests.sh | 4 - 5 files changed, 292 insertions(+), 175 deletions(-) create mode 100644 pkg/env.sh create mode 100644 pkg/utils.sh diff --git a/Dockerfile b/Dockerfile index 66975709..e5e0f56c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,42 +40,5 @@ RUN mv app/entry.sh /entry.sh ARG NAUTICAL_VERSION="main" ENV NAUTICAL_VERSION=${NAUTICAL_VERSION} -# Set default timezone -ENV TZ=Etc/UTC - -# Default = Every day at 4am -ENV CRON_SCHEDULE="0 4 * * *" - -# Default enable the report file -ENV REPORT_FILE="true" - -# Run the backup immediately on start -ENV BACKUP_ON_START="false" - -# Use the default rsync args "-raq" (recursive, archive, quiet) -ENV USE_DEFAULT_RSYNC_ARGS="true" - -# Apply custom rsync args (in addition to the default args) -ENV RSYNC_CUSTOM_ARGS="" - -# Require the Docker Label `nautical-backup.enable=true` to be present on each contianer or it will be skipped. -ENV REQUIRE_LABEL="false" - -# Set the default log level to INFO -ENV LOG_LEVEL="INFO" - -# Set the default log level for the repot file to INFO -ENV REPORT_FILE_LOG_LEVEL="INFO" - -# Only write to the report file when backups run, not on initialization -ENV REPORT_FILE_ON_BACKUP_ONLY="true" - -# Mirrior the source directory name to the destination directory name -# When true, and an source dir override is applied, then the destination directory will be same same as the new source directory -ENV KEEP_SRC_DIR_NAME="true" - -# Usually combined with BACKUP_ON_START. Essentially, this just exists the container after 1 run. -ENV EXIT_AFTER_INIT="false" - # Run the entry script and pass all variables to it ENTRYPOINT [ "bash", "-c", "exec ./entry.sh \"${@}\"", "--"] diff --git a/pkg/entry.sh b/pkg/entry.sh index f3002bd3..cb3d4ea7 100644 --- a/pkg/entry.sh +++ b/pkg/entry.sh @@ -1,11 +1,15 @@ #!/bin/bash -source /app/logger.sh # Use the logger script -create_new_report_file - -logThis "Nautical Backup Version: $NAUTICAL_VERSION" "INFO" "init" -logThis "Built for the platform: $TARGETPLATFORM" "DEBUG" "init" -logThis "Using log level: $LOG_LEVEL" "DEBUG" "init" +if [ "$TEST_MODE" == "true" ]; then + echo "Running in test mode" + source "$(dirname $0)"/logger.sh # Use the logger script + source "$(dirname $0)"/utils.sh + source "$(dirname $0)"/env.sh +else + source /app/logger.sh # Use the logger script + source /app/utils.sh + source app/env.sh +fi # Echo the CRON schedule for logging/debugging logThis "Installing CRON schedule: $CRON_SCHEDULE in TZ: $TZ" "DEBUG" "init" @@ -19,143 +23,23 @@ sed -i '/\/app\/backup.sh/d' tempcron # Add the new cron job to the file echo "$CRON_SCHEDULE bash /app/backup.sh" >>tempcron -# Install the new cron jobs -crontab tempcron -rm tempcron - -# Variables -export SOURCE_LOCATION=/app/source # Do not include a trailing slash -export DEST_LOCATION=/app/destination # Do not include a trailing slash - -logThis "Verifying source directory..." "DEBUG" "init" -if [ ! -d "$SOURCE_LOCATION" ]; then - logThis "Error: Source directory $SOURCE_LOCATION does not exist." "ERROR" "init" - exit 1 -elif [ ! -r "$SOURCE_LOCATION" ]; then - logThis "Error: No read access to source directory $SOURCE_LOCATION." "ERROR" "init" - exit 1 -fi - -logThis "Verifying destination directory..." "DEBUG" "init" -if [ ! -d "$DEST_LOCATION" ]; then - logThis "Error: Destination directory $DEST_LOCATION does not exist." "ERROR" "init" - exit 1 -elif [ ! -r "$DEST_LOCATION" ]; then - logThis "Error: No read access to destination directory $DEST_LOCATION." "ERROR" "init" - exit 1 -elif [ ! -w "$DEST_LOCATION" ]; then - logThis "Error: No write access to destination directory $DEST_LOCATION." "ERROR" "init" - exit 1 -fi - -CONTAINER_SKIP_LIST=() # Containers to skips - -# Function to populate the skip list array -process_csv() { - local -n skip_list_ref=$1 # Use nameref to update the array passed as argument - local skip_var=$2 # The environment variable containing the skip list - - if [ ! -z "$skip_var" ]; then - # Remove quotes and leading/trailing whitespaces - local cleaned_skip_var=$(echo "$skip_var" | sed "s/'//g;s/\"//g" | tr -d ' ') - - # Split by commas into an array - IFS=',' read -ra ADDITIONAL_SKIPS <<<"$cleaned_skip_var" - - # Add to the existing skip list - skip_list_ref=("${skip_list_ref[@]}" "${ADDITIONAL_SKIPS[@]}") - fi -} - -# Declare the CONTAINER_SKIP_LIST array -CONTAINER_SKIP_LIST=() -SKIP_STOPPING_LIST=() - -# Populate the skip list -process_csv CONTAINER_SKIP_LIST "$SKIP_CONTAINERS" -process_csv SKIP_STOPPING_LIST "$SKIP_STOPPING" - -if [ ! -z "$SKIP_CONTAINERS" ]; then - logThis "SKIP_CONTAINERS: ${CONTAINER_SKIP_LIST[@]}" "DEBUG" "init" -fi - -if [ ! -z "$SKIP_STOPPING" ]; then - logThis "SKIP_STOPPING: ${SKIP_STOPPING_LIST[@]}" "DEBUG" "init" -fi - -# Get the container ID of the current container -export SELF_CONTAINER_ID=$(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1) -# Add the self container ID to the default skips -CONTAINER_SKIP_LIST+=("$SELF_CONTAINER_ID") - -CONTAINER_SKIP_LIST_STR=$( - IFS=, - echo "${CONTAINER_SKIP_LIST[*]}" -) # Convert the array to a string -export CONTAINER_SKIP_LIST_STR # Export the string +# Install the new cron jobs and remove the tempcron file +crontab tempcron && rm tempcron -SKIP_STOPPING_STR=$( - IFS=, - echo "${SKIP_STOPPING[*]}" -) # Convert the array to a string -export SKIP_STOPPING_STR # Export the string - -# Assuming OVERRIDE_SOURCE_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..." -if [ ! -z "$OVERRIDE_SOURCE_DIR" ]; then - logThis "OVERRIDE_SOURCE_DIR: ${OVERRIDE_SOURCE_DIR}" "DEBUG" "init" -fi -export OVERRIDE_SOURCE_DIR - -# Assuming OVERRIDE_DEST_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..." -if [ ! -z "$OVERRIDE_DEST_DIR" ]; then - logThis "OVERRIDE_DEST_DIR: ${OVERRIDE_DEST_DIR}" "DEBUG" "init" -fi -export OVERRIDE_DEST_DIR - -if [ ! -z "$REPORT_FILE" ]; then - logThis "REPORT_FILE: $REPORT_FILE" "DEBUG" "init" -fi - -# Set rsync custom arguments if specified -if [ ! -z "$RSYNC_CUSTOM_ARGS" ]; then - logThis "RSYNC_CUSTOM_ARGS: $RSYNC_CUSTOM_ARGS" "DEBUG" "init" -fi - -if [ ! -z "$LOG_RSYNC_COMMANDS" ]; then - logThis "LOG_RSYNC_COMMANDS: $LOG_RSYNC_COMMANDS" "DEBUG" "init" -fi - -if [ ! -z "$USE_DEFAULT_RSYNC_ARGS" ]; then - logThis "USE_DEFAULT_RSYNC_ARGS: $USE_DEFAULT_RSYNC_ARGS" "DEBUG" "init" -fi - -if [ ! -z "$REQUIRE_LABEL" ]; then - logThis "REQUIRE_LABEL: $REQUIRE_LABEL" "DEBUG" "init" -fi - -if [ ! -z "$KEEP_SRC_DIR_NAME" ]; then - logThis "KEEP_SRC_DIR_NAME: $KEEP_SRC_DIR_NAME" "DEBUG" "init" -fi - -if [ ! -z "$LOG_LEVEL" ]; then - logThis "LOG_LEVEL: $LOG_LEVEL" "DEBUG" "init" -fi - -if [ ! -z "$REPORT_FILE_LOG_LEVEL" ]; then - logThis "REPORT_FILE_LOG_LEVEL: $REPORT_FILE_LOG_LEVEL" "DEBUG" "init" -fi +# Verify the source and destination locations +verify_source_location $SOURCE_LOCATION +verify_destination_location $DEST_LOCATION if [ "$BACKUP_ON_START" = "true" ]; then - logThis "BACKUP_ON_START: $BACKUP_ON_START" "DEBUG" "init" + echo "Starting backup since BACKUP_ON_START is true" "INFO" "init" bash ./app/backup.sh fi if [ "$EXIT_AFTER_INIT" = "true" ]; then - logThis "EXIT_AFTER_INIT: $EXIT_AFTER_INIT" "DEBUG" "init" + echo "Exiting since EXIT_AFTER_INITis true" "INFO" "init" exit 0 fi logThis "Initialization complete. Awaiting CRON schedule: $CRON_SCHEDULE" "INFO" "init" -# Start cron and keep container running -/usr/sbin/crond -f -l 8 +/usr/sbin/crond -f -l 8 # Start cron and keep container running diff --git a/pkg/env.sh b/pkg/env.sh new file mode 100644 index 00000000..b40acfbb --- /dev/null +++ b/pkg/env.sh @@ -0,0 +1,224 @@ +#!/bin/bash + +if [ "$TEST_MODE" == "true" ]; then + echo "Running in test mode" + source "$(dirname $0)"/logger.sh # Use the logger script + source "$(dirname $0)"/utils.sh # Use the logger script +else + source /app/logger.sh # Use the logger script + source /app/utils.sh # Use the logger script +fi + +create_new_report_file + +logThis "Nautical Backup Version: $NAUTICAL_VERSION" "INFO" "init" +logThis "Built for the platform: $TARGETPLATFORM" "DEBUG" "init" + +# ------ Default Variable Values ------ # + +# Set default timezone +DEFAULT_TZ=Etc/UTC + +# Default = Every day at 4am +DEFAULT_CRON_SCHEDULE="0 4 * * *" + +# Default enable the report file +DEFAULT_REPORT_FILE="true" + +# Run the backup immediately on start +DEFAULT_BACKUP_ON_START="false" + +# Use the default rsync args "-raq" (recursive, archive, quiet) +DEFAULT_USE_DEFAULT_RSYNC_ARGS="true" + +# Require the Docker Label `nautical-backup.enable=true` to be present on each contianer or it will be skipped. +DEFAULT_REQUIRE_LABEL="false" + +# Set the default log level to INFO +DEFAULT_LOG_LEVEL="INFO" + +# Set the default log level for the repot file to INFO +DEFAULT_REPORT_FILE_LOG_LEVEL="INFO" + +# Only write to the report file when backups run, not on initialization +DEFAULT_REPORT_FILE_ON_BACKUP_ONLY="true" + +# Mirrior the source directory name to the destination directory name +# When true, and an source dir override is applied, then the destination directory will be same same as the new source directory +DEFAULT_KEEP_SRC_DIR_NAME="true" + +# Usually combined with BACKUP_ON_START. Essentially, this just exists the container after 1 run. +DEFAULT_EXIT_AFTER_INIT="false" + +# Log the rsync commands to the console (and/or report file) +DEFAULT_LOG_RSYNC_COMMANDS="false" + +# Do not include a trailing slash +DEFAULT_SOURCE_LOCATION="/app/source" +DEFAULT_DEST_LOCATION=/app/destination +# Test directories +DEFAULT_TEST_SOURCE_LOCATION="source" +DEFAULT_TEST_DEST_LOCATION="destination" + +# ------ Default Empty Values------ # + +DEFAULT_SKIP_CONTAINERS="" + +DEFAULT_SKIP_STOPPING="" + +# Apply custom rsync args (in addition to the default args) +DEFAULT_RSYNC_CUSTOM_ARGS="" + +# Assuming OVERRIDE_SOURCE_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..." +DEFAULT_OVERRIDE_SOURCE_DIR="" + +# Assuming OVERRIDE_DEST_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..." +DEFAULT_OVERRIDE_DEST_DIR="" + +logThis "Perparing enviornment variables..." "DEBUG" "init" + +if [ -z "$TZ" ]; then + TZ=$DEFAULT_TZ +fi +logThis "TZ: $TZ" "DEBUG" "init" +export TZ + +if [ -z "$CRON_SCHEDULE" ]; then + CRON_SCHEDULE=$DEFAULT_CRON_SCHEDULE +fi +logThis "CRON_SCHEDULE: $CRON_SCHEDULE" "DEBUG" "init" +export CRON_SCHEDULE + +if [ -z "$REPORT_FILE" ]; then + REPORT_FILE=$DEFAULT_REPORT_FILE +fi +logThis "REPORT_FILE: $REPORT_FILE" "DEBUG" "init" +export REPORT_FILE + +if [ -z "$BACKUP_ON_START" ]; then + BACKUP_ON_START=$DEFAULT_BACKUP_ON_START +fi +logThis "BACKUP_ON_START: $BACKUP_ON_START" "DEBUG" "init" +export BACKUP_ON_START + +if [ -z "$USE_DEFAULT_RSYNC_ARGS" ]; then + USE_DEFAULT_RSYNC_ARGS=$DEFAULT_USE_DEFAULT_RSYNC_ARGS +fi +logThis "USE_DEFAULT_RSYNC_ARGS: $USE_DEFAULT_RSYNC_ARGS" "DEBUG" "init" +export USE_DEFAULT_RSYNC_ARGS + +if [ -z "$REQUIRE_LABEL" ]; then + REQUIRE_LABEL=$DEFAULT_REQUIRE_LABEL +fi +logThis "REQUIRE_LABEL: $REQUIRE_LABEL" "DEBUG" "init" +export REQUIRE_LABEL + +if [ -z "$LOG_LEVEL" ]; then + LOG_LEVEL=$DEFAULT_LOG_LEVEL +fi +logThis "LOG_LEVEL: $LOG_LEVEL" "DEBUG" "init" +export LOG_LEVEL + +if [ -z "$REPORT_FILE_LOG_LEVEL" ]; then + REPORT_FILE_LOG_LEVEL=$DEFAULT_REPORT_FILE_LOG_LEVEL +fi +logThis "REPORT_FILE_LOG_LEVEL: $REPORT_FILE_LOG_LEVEL" "DEBUG" "init" +export REPORT_FILE_LOG_LEVEL + +if [ -z "$REPORT_FILE_ON_BACKUP_ONLY" ]; then + REPORT_FILE_ON_BACKUP_ONLY=$DEFAULT_REPORT_FILE_ON_BACKUP_ONLY +fi +logThis "REPORT_FILE_ON_BACKUP_ONLY: $REPORT_FILE_ON_BACKUP_ONLY" "DEBUG" "init" +export REPORT_FILE_ON_BACKUP_ONLY + +if [ -z "$KEEP_SRC_DIR_NAME" ]; then + KEEP_SRC_DIR_NAME=$DEFAULT_KEEP_SRC_DIR_NAME +fi +logThis "KEEP_SRC_DIR_NAME: $KEEP_SRC_DIR_NAME" "DEBUG" "init" +export KEEP_SRC_DIR_NAME + +if [ -z "$EXIT_AFTER_INIT" ]; then + EXIT_AFTER_INIT=$DEFAULT_EXIT_AFTER_INIT +fi +logThis "EXIT_AFTER_INIT: $EXIT_AFTER_INIT" "DEBUG" "init" +export EXIT_AFTER_INIT + +if [ -z "$LOG_RSYNC_COMMANDS" ]; then + LOG_RSYNC_COMMANDS=$DEFAULT_LOG_RSYNC_COMMANDS +else + logThis "LOG_RSYNC_COMMANDS: $LOG_RSYNC_COMMANDS" "DEBUG" "init" +fi +export LOG_RSYNC_COMMANDS + +# ------ Default Empty Values ------ # + +if [ -z "$SKIP_CONTAINERS" ]; then + SKIP_CONTAINERS=$DEFAULT_SKIP_CONTAINERS +else + logThis "SKIP_CONTAINERS: ${CONTAINER_SKIP_LIST[@]}" "DEBUG" "init" +fi + +if [ -z "$SKIP_STOPPING" ]; then + SKIP_STOPPING=$DEFAULT_SKIP_STOPPING +else + logThis "SKIP_STOPPING: ${SKIP_STOPPING_LIST[@]}" "DEBUG" "init" +fi + +if [ -z "$RSYNC_CUSTOM_ARGS" ]; then + RSYNC_CUSTOM_ARGS=$DEFAULT_RSYNC_CUSTOM_ARGS +else + logThis "RSYNC_CUSTOM_ARGS: $RSYNC_CUSTOM_ARGS" "DEBUG" "init" +fi +export RSYNC_CUSTOM_ARGS + +if [ -z "$OVERRIDE_SOURCE_DIR" ]; then + OVERRIDE_SOURCE_DIR=$DEFAULT_OVERRIDE_SOURCE_DIR +else + logThis "OVERRIDE_SOURCE_DIR: $OVERRIDE_SOURCE_DIR" "DEBUG" "init" +fi +export OVERRIDE_SOURCE_DIR + +if [ ! -z "$OVERRIDE_DEST_DIR" ]; then + OVERRIDE_DEST_DIR=$DEFAULT_OVERRIDE_DEST_DIR +else + logThis "OVERRIDE_DEST_DIR: $OVERRIDE_DEST_DIR" "DEBUG" "init" + +fi +export OVERRIDE_DEST_DIR + +# ----- Variables Requiring Logic ----- # + +if [ "$TEST_MODE" == "true" ]; then + SOURCE_LOCATION=$DEFAULT_TEST_SOURCE_LOCATION + DEST_LOCATION=$DEFAULT_TEST_DEST_LOCATION +else + SOURCE_LOCATION=$DEFAULT_SOURCE_LOCATION + DEST_LOCATION=$DEFAULT_DEST_LOCATION +fi +export SOURCE_LOCATION +export DEST_LOCATION + +# Declare the CONTAINER_SKIP_LIST array +CONTAINER_SKIP_LIST=() +SKIP_STOPPING_LIST=() + +# Populate the skip list +process_csv CONTAINER_SKIP_LIST "$SKIP_CONTAINERS" +process_csv SKIP_STOPPING_LIST "$SKIP_STOPPING" + +# Get the container ID of the current container +export SELF_CONTAINER_ID=$(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1) +# Add the self container ID to the default skips +CONTAINER_SKIP_LIST+=("$SELF_CONTAINER_ID") + +CONTAINER_SKIP_LIST_STR=$( + IFS=, + echo "${CONTAINER_SKIP_LIST[*]}" +) # Convert the array to a string +export CONTAINER_SKIP_LIST_STR # Export the string + +SKIP_STOPPING_STR=$( + IFS=, + echo "${SKIP_STOPPING[*]}" +) # Convert the array to a string +export SKIP_STOPPING_STR # Export the string diff --git a/pkg/utils.sh b/pkg/utils.sh new file mode 100644 index 00000000..4a87633f --- /dev/null +++ b/pkg/utils.sh @@ -0,0 +1,50 @@ +if [ "$TEST_MODE" == "true" ]; then + echo "Running in test mode" + source "$(dirname $0)"/logger.sh # Use the logger script +else + source /app/logger.sh # Use the logger script +fi + +# Function to populate a list array +process_csv() { + local -n skip_list_ref=$1 # Use nameref to update the array passed as argument + local skip_var=$2 # The environment variable containing the skip list + + if [ ! -z "$skip_var" ]; then + # Remove quotes and leading/trailing whitespaces + local cleaned_skip_var=$(echo "$skip_var" | sed "s/'//g;s/\"//g" | tr -d ' ') + + # Split by commas into an array + IFS=',' read -ra ADDITIONAL_SKIPS <<<"$cleaned_skip_var" + + # Add to the existing skip list + skip_list_ref=("${skip_list_ref[@]}" "${ADDITIONAL_SKIPS[@]}") + fi +} + +verify_source_location() { + local src_dir=$1 + logThis "Verifying source directory $src_dir..." "DEBUG" "init" + if [ ! -d "$src_dir" ]; then + logThis "Error: Source directory $src_dir does not exist." "ERROR" "init" + exit 1 + elif [ ! -r "$src_dir" ]; then + logThis "Error: No read access to source directory $src_dir." "ERROR" "init" + exit 1 + fi +} + +verify_destination_location() { + local dest_dir=$1 + logThis "Verifying destination directory $dest_dir..." "DEBUG" "init" + if [ ! -d "$dest_dir" ]; then + logThis "Error: Destination directory $dest_dir does not exist." "ERROR" "init" + exit 1 + elif [ ! -r "$dest_dir" ]; then + logThis "Error: No read access to destination directory $dest_dir." "ERROR" "init" + exit 1 + elif [ ! -w "$dest_dir" ]; then + logThis "Error: No write access to destination directory $dest_dir." "ERROR" "init" + exit 1 + fi +} diff --git a/tests/tests.sh b/tests/tests.sh index 82dbbf64..07b861bd 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -1,9 +1,5 @@ #!/bin/bash -# Global variables to control mock behavior -export SOURCE_LOCATION=source # Do not include a trailing slash -export DEST_LOCATION=destination # Do not include a trailing slash - export MOCK_DOCKER_PS_OUTPUT="" RSYNC_COMMANDS_RUN=() DOCKER_COMMANDS_RUN=()