From 2f3135053f3afaf20b0a8ff0ccbb29e9e3f08765 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 25 Apr 2025 12:53:03 +1200 Subject: [PATCH] tidy --- src/main.cpp | 49 +---------------- src/service_runner.cpp | 54 +++++++++---------- src/service_runner.hpp | 52 +++++++++--------- templates/example/README.txt | 0 templates/example/_basic.env | 9 ++++ templates/example/_common.sh | 20 ++++++- templates/example/{_backup.sh => backup.sh} | 9 ++++ templates/example/example/service.env | 14 ++--- templates/example/{_install.sh => install.sh} | 6 +++ templates/example/logs.sh | 6 +++ templates/example/{_ports.sh => ports.sh} | 6 +++ templates/example/start.sh | 13 +++++ templates/example/{_status.sh => status.sh} | 8 +++ templates/example/stop.sh | 6 +++ .../example/{_uninstall.sh => uninstall.sh} | 6 +++ templates/watchtower/_common.sh | 23 ++++++-- 16 files changed, 162 insertions(+), 119 deletions(-) create mode 100644 templates/example/README.txt create mode 100644 templates/example/_basic.env rename templates/example/{_backup.sh => backup.sh} (71%) rename templates/example/{_install.sh => install.sh} (85%) rename templates/example/{_ports.sh => ports.sh} (52%) rename templates/example/{_status.sh => status.sh} (65%) rename templates/example/{_uninstall.sh => uninstall.sh} (73%) diff --git a/src/main.cpp b/src/main.cpp index 4019484..fe817c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,7 +128,7 @@ int main(int argc, char* argv[]) { commands.insert("init"); if (cfg->is_config_set()) commands.merge(std::set{ - "servers","templates","install","uninstall","backup" + "servers","templates" }); for (const auto& command : commands) { @@ -188,52 +188,7 @@ int main(int argc, char* argv[]) { dropshell::list_templates(); return 0; } - - if (cmd == "install" || cmd == "uninstall") { - std::string server_name; - std::vector servicelist; - if (!parseargs(safearg(argc, argv, 2), safearg(argc, argv, 3), server_name, servicelist)) { - std::cerr << "Error: " << cmd << " command requires server name and optionally service name" << std::endl; - return 1; - } - for (const auto& service_info : servicelist) { - dropshell::service_runner service; - if (!service.init(server_name, service_info.service_name)) { - std::cerr << "Error: Failed to initialize service" << std::endl; - return 1; - } - bool success = ((cmd=="install") ? service.install() : service.uninstall()); - if (!success) { - std::cerr << "Error: Failed to " << cmd << " service" << std::endl; - return 1; - } - } - return 0; - } - - if (cmd == "backup") { - std::string server_name; - std::vector servicelist; - if (!parseargs(safearg(argc, argv, 2), safearg(argc, argv, 3), server_name, servicelist)) { - std::cerr << "Error: backup command requires server name and optionally service name" << std::endl; - return 1; - } - - for (const auto& service_info : servicelist) { - dropshell::service_runner service; - if (!service.init(server_name, service_info.service_name)) { - std::cerr << "Error: Failed to initialize service" << std::endl; - return 1; - } - if (!service.backup()) { - std::cerr << "Backup failed." << std::endl; - return 1; - } - } - return 0; - } - - + // handle running a command. for (const auto& command : commands) { if (cmd == command) { diff --git a/src/service_runner.cpp b/src/service_runner.cpp index 01338e4..fc7e6a9 100644 --- a/src/service_runner.cpp +++ b/src/service_runner.cpp @@ -112,29 +112,23 @@ void service_runner::maketitle(const std::string& title) const { bool service_runner::install() { maketitle("Installing " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name); - if (!m_server_env) { - std::cerr << "Error: Server service not initialized" << std::endl; - return false; - } + + if (!m_server_env) return false; // should never hit this. // Check if template exists template_info tinfo; - if (!get_template_info(m_service_info.template_name, tinfo)) { - std::cerr << "Error: Template '" << m_service_info.template_name << "' not found" << std::endl; + if (!get_template_info(m_service_info.template_name, tinfo)) return false; - } // Create service directory std::string mkdir_cmd = "'mkdir -p " + mRemote_service_path + "'"; - if (!execute_ssh_command(mkdir_cmd, "Failed to create service directory")) { + if (!execute_ssh_command(mkdir_cmd, "Failed to create service directory")) return false; - } // Check if rsync is installed on remote host std::string check_rsync_cmd = "'which rsync > /dev/null 2>&1'"; - if (!execute_ssh_command(check_rsync_cmd, "rsync is not installed on the remote host")) { + if (!execute_ssh_command(check_rsync_cmd, "rsync is not installed on the remote host")) return false; - } // Copy template files { @@ -178,17 +172,7 @@ bool service_runner::install() { bool service_runner::uninstall() { maketitle("Uninstalling " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name); - if (!m_server_env) { - std::cerr << "Error: Server service not initialized" << std::endl; - return false; - } - - // 1. Check if template exists - template_info tinfo; - if (!get_template_info(m_service_info.template_name, tinfo)) { - std::cerr << "Error: Template '" << m_service_info.template_name << "' not found" << std::endl; - return false; - } + if (!m_server_env) return false; // should never hit this. // 2. Check if service directory exists on server if (!check_remote_dir_exists(mRemote_service_path)) { @@ -226,12 +210,20 @@ bool service_runner::run_command(const std::string& command) { std::cerr << "Error: Server service not initialized" << std::endl; return false; } - + template_info tinfo; + if (!get_template_info(m_service_info.template_name, tinfo)) { + std::cerr << "Error: Template '" << m_service_info.template_name << "' not found" << std::endl; + return false; + } if (!template_command_exists(m_service_info.template_name, command)) { std::cout << "No command script for " << m_service_info.template_name << " : " << command << std::endl; return true; // nothing to run. } + // install doesn't require anything on the server yet. + if (command == "install") + return install(); + std::string script_path = mRemote_service_template_path + "/" + command + ".sh"; // Check if service directory exists @@ -243,13 +235,18 @@ bool service_runner::run_command(const std::string& command) { if (!check_remote_file_exists(script_path)) { return false; } - + // Check if env file exists if (!check_remote_file_exists(mRemote_service_env_file)) { return false; } - - // Run the command + + if (command == "uninstall") + return uninstall(); + if (command == "backup") + return backup(); + + // Run the generic command std::string run_cmd = "'cd " + mRemote_service_template_path + " && /bin/bash " + script_path + " " + mRemote_service_env_file + "'"; return execute_ssh_command(run_cmd, "Command returned error code: " + script_path); @@ -258,10 +255,7 @@ bool service_runner::run_command(const std::string& command) { bool service_runner::backup() { maketitle("Backing up " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name); - if (!m_server_env) { - std::cerr << "Error: Server service not initialized" << std::endl; - return false; - } + if (!m_server_env) return false; // should never hit this. std::string command = "_backup"; diff --git a/src/service_runner.hpp b/src/service_runner.hpp index 328075e..8742675 100644 --- a/src/service_runner.hpp +++ b/src/service_runner.hpp @@ -16,23 +16,6 @@ class service_runner { service_runner(); bool init(const std::string& server_name, const std::string& service_name); - // install the service over ssh, using the credentials from server.env (via server_env.hpp), by: - // 1. check if the server_name exists, and the service_name refers to a valid template - // 2. check if service_name is valid for the server_name - // 3. create the service directory on the server at {DROPSHELL_DIR}/{service_name} - // 3. copy the template files into {DROPSHELL_DIR}/{service_name}/template (from the templates directory for the specified server, using templates.hpp to identify the path) - // 4. copying the local service directory into {DROPSHELL_DIR}/{service_name}/config (from the server directory for the specified server) - // 5. running the install.sh script on the server, passing the {service_name}.env file as an argument - bool install(); - - // uninstall the service over ssh, using the credentials from server.env (via server_env.hpp) - // 1. check if the server_name exists, and the service_name refers to a valid template - // 2. check if service_name is valid for the server_name - // 3. run the uninstall.sh script on the server, passing the {service_name}.env file as an argument - // 4. - // 1. run the uninstall.sh script on the server, passing the {service_name}.env file as an argument - bool uninstall(); - // run a command over ssh, using the credentials from server.env (via server_env.hpp) // first check that the command corresponds to a valid .sh file in the service directory // then run the command, passing the {service_name}.env file as an argument @@ -44,14 +27,6 @@ class service_runner { // checking that the {service_name}.env file exists in the service directory. bool run_command(const std::string& command); - // backup the service over ssh, using the credentials from server.env (via server_env.hpp) - // 1. run backup.sh on the server - // 2. create a backup file with format server-service-datetime.tgz - // 3. store it in the server's DROPSHELL_DIR/backups folder - // 4. copy it to the local user_dir/backups folder - bool backup(); - - // check health of service. Silent. // 1. run status.sh on the server // 2. return the output of the status.sh script @@ -71,6 +46,33 @@ class service_runner { std::string healthtick(); std::string healthmark(); + + + private: + // install the service over ssh, using the credentials from server.env (via server_env.hpp), by: + // 1. check if the server_name exists, and the service_name refers to a valid template + // 2. check if service_name is valid for the server_name + // 3. create the service directory on the server at {DROPSHELL_DIR}/{service_name} + // 3. copy the template files into {DROPSHELL_DIR}/{service_name}/template (from the templates directory for the specified server, using templates.hpp to identify the path) + // 4. copying the local service directory into {DROPSHELL_DIR}/{service_name}/config (from the server directory for the specified server) + // 5. running the install.sh script on the server, passing the {service_name}.env file as an argument + bool install(); + + // uninstall the service over ssh, using the credentials from server.env (via server_env.hpp) + // 1. check if the server_name exists, and the service_name refers to a valid template + // 2. check if service_name is valid for the server_name + // 3. run the uninstall.sh script on the server, passing the {service_name}.env file as an argument + // 4. remove the service directory from the server + bool uninstall(); + + // backup the service over ssh, using the credentials from server.env (via server_env.hpp) + // 1. run backup.sh on the server + // 2. create a backup file with format server-service-datetime.tgz + // 3. store it in the server's DROPSHELL_DIR/backups folder + // 4. copy it to the local user_dir/backups folder + bool backup(); + + private: std::string m_server_name; ServiceInfo m_service_info; diff --git a/templates/example/README.txt b/templates/example/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/templates/example/_basic.env b/templates/example/_basic.env new file mode 100644 index 0000000..a26eeaa --- /dev/null +++ b/templates/example/_basic.env @@ -0,0 +1,9 @@ +# Service settings specific to this server +TEMPLATE=example + +# Application settings +CONTAINER_PORT=8181 + +# Image settings +IMAGE_REGISTRY="gitea.jde.nz" +IMAGE_REPO="example/example" diff --git a/templates/example/_common.sh b/templates/example/_common.sh index e4e0be3..6a5d2cf 100755 --- a/templates/example/_common.sh +++ b/templates/example/_common.sh @@ -1,5 +1,12 @@ #!/bin/bash +# COMMON FUNCTIONS +# JDE +# 2025-04-25 + +# This file is not required if you write your own template. + + # Print error message and exit with code 1 # Usage: die "error message" die() { @@ -13,7 +20,18 @@ die() { load_env() { local script_dir="$(dirname "${BASH_SOURCE[0]}")" local env_file - + + # first load basic.env for the template defaults + if [ -f "$script_dir/_basic.env" ]; then + set -a + source "$script_dir/_basic.env" + set +a + else + echo "Warning: basic.env file not found at $script_dir/_basic.env. Broken template?" + return 1 + fi + + # now load the server specific env file if [ -z "$1" ]; then echo "Usage: $0 [path_to_env_file]" return 1 diff --git a/templates/example/_backup.sh b/templates/example/backup.sh similarity index 71% rename from templates/example/_backup.sh rename to templates/example/backup.sh index d532a1d..ccceb35 100644 --- a/templates/example/_backup.sh +++ b/templates/example/backup.sh @@ -1,4 +1,13 @@ #!/bin/bash + +# BACKUP SCRIPT +# The backup script is OPTIONAL. +# It is used to backup the service on the server. +# It is called with: +# 1) the path to the server specific env file as the frist argument. +# 2) the path to the destination backup file as the second argument. +# If the backup file already exists, the script should exit with a message. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/example/service.env b/templates/example/example/service.env index c358eb2..e93d8b9 100644 --- a/templates/example/example/service.env +++ b/templates/example/example/service.env @@ -1,15 +1,7 @@ -# Service settings -TEMPLATE=example +# Service settings specific to this server +# (can also override anything in the basic.env file in the template to make it specific to this server) -# Application settings -CONTAINER_PORT=8181 HOST_PORT=80 - -# Deployment settings LOCAL_DATA_FOLDER="${HOME}/.example" -CONTAINER_NAME="example" - -# Image settings -IMAGE_REGISTRY="gitea.jde.nz" -IMAGE_REPO="example/example" IMAGE_TAG="latest" + diff --git a/templates/example/_install.sh b/templates/example/install.sh similarity index 85% rename from templates/example/_install.sh rename to templates/example/install.sh index fc2b11a..fcb998d 100755 --- a/templates/example/_install.sh +++ b/templates/example/install.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# INSTALL SCRIPT +# The install script is required for all templates. +# It is used to install the service on the server. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/logs.sh b/templates/example/logs.sh index 915b61c..691e17b 100644 --- a/templates/example/logs.sh +++ b/templates/example/logs.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# LOGS SCRIPT +# The logs script is OPTIONAL. +# It is used to return the logs of the service. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/_ports.sh b/templates/example/ports.sh similarity index 52% rename from templates/example/_ports.sh rename to templates/example/ports.sh index c678af4..9779af4 100644 --- a/templates/example/_ports.sh +++ b/templates/example/ports.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# PORT SCRIPT +# The port script is OPTIONAL. +# It is used to return the ports used by the service. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/start.sh b/templates/example/start.sh index 13cdc83..2e61071 100755 --- a/templates/example/start.sh +++ b/templates/example/start.sh @@ -1,10 +1,23 @@ #!/bin/bash + +# START SCRIPT +# The start script is required for all templates. +# It is used to start the service on the server. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" # Required environment variables check_required_env_vars "CONTAINER_NAME" "HOST_PORT" "CONTAINER_PORT" "LOCAL_DATA_FOLDER" +if [ -d "${LOCAL_DATA_FOLDER}" ]; then + echo "Local data folder ${LOCAL_DATA_FOLDER} exists, skipping data folder creation" +else + echo "Local data folder ${LOCAL_DATA_FOLDER} does not exist, creating..." + mkdir -p "${LOCAL_DATA_FOLDER}" +fi + DOCKER_RUN_CMD="docker run -d \ --restart unless-stopped \ --name ${CONTAINER_NAME} \ diff --git a/templates/example/_status.sh b/templates/example/status.sh similarity index 65% rename from templates/example/_status.sh rename to templates/example/status.sh index e939eb6..82cc387 100644 --- a/templates/example/_status.sh +++ b/templates/example/status.sh @@ -1,4 +1,12 @@ #!/bin/bash + +# STATUS SCRIPT +# The status script is OPTIONAL. +# It is used to return the status of the service (0 is healthy, 1 is unhealthy). +# It is called with the path to the server specific env file as an argument. + + +# This is an example of a status script that checks if the service is running. source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/stop.sh b/templates/example/stop.sh index 42ee835..68030f6 100755 --- a/templates/example/stop.sh +++ b/templates/example/stop.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# STOP SCRIPT +# The stop script is required for all templates. +# It is used to stop the service on the server. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/example/_uninstall.sh b/templates/example/uninstall.sh similarity index 73% rename from templates/example/_uninstall.sh rename to templates/example/uninstall.sh index cbfe0dd..4031c68 100644 --- a/templates/example/_uninstall.sh +++ b/templates/example/uninstall.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# UNINSTALL SCRIPT +# The uninstall script is required for all templates. +# It is used to uninstall the service from the server. +# It is called with the path to the server specific env file as an argument. + source "$(dirname "$0")/_common.sh" load_env "$1" || die "Failed to load environment variables" diff --git a/templates/watchtower/_common.sh b/templates/watchtower/_common.sh index 4459459..a23a529 100755 --- a/templates/watchtower/_common.sh +++ b/templates/watchtower/_common.sh @@ -1,5 +1,9 @@ #!/bin/bash +# COMMON FUNCTIONS +# JDE +# 2025-04-25 + # Print error message and exit with code 1 # Usage: die "error message" die() { @@ -13,7 +17,18 @@ die() { load_env() { local script_dir="$(dirname "${BASH_SOURCE[0]}")" local env_file - + + # first load basic.env for the template defaults + if [ -f "$script_dir/basic.env" ]; then + set -a + source "$script_dir/basic.env" + set +a + else + echo "Warning: basic.env file not found at $script_dir/basic.env. Broken template?" + return 1 + fi + + # now load the server specific env file if [ -z "$1" ]; then echo "Usage: $0 [path_to_env_file]" return 1 @@ -49,9 +64,7 @@ create_and_start_container() { local container_name="$2" if _is_container_exists $container_name; then - if _is_container_running $container_name; then - return 0 - fi + _is_container_running $container_name && return 0 _start_container $container_name else grey_start @@ -164,4 +177,4 @@ check_required_env_vars() { die "Required environment variable $var is not set in your service.env file" fi done -} \ No newline at end of file +}