Watchtower!

This commit is contained in:
Your Name 2025-04-25 11:44:32 +12:00
parent 4c0c052f20
commit 61fabac1f0
5 changed files with 38 additions and 7 deletions

View File

@ -94,12 +94,14 @@ void show_server_details(const std::string& server_name) {
//--------------------- //---------------------
// Check if server is reachable via SSH // Check if server is reachable via SSH
std::string ssh_address = env.get_SSH_HOST(); std::string ssh_address = env.get_SSH_HOST();
std::string ssh_user = env.get_SSH_USER();
std::string ssh_port = env.get_SSH_PORT();
if (!ssh_address.empty()) { if (!ssh_address.empty()) {
std::cout << std::endl << "Server Status:" << std::endl; std::cout << std::endl << "Server Status:" << std::endl;
std::cout << std::string(40, '-') << std::endl; std::cout << std::string(40, '-') << std::endl;
// Try to connect to the server // Try to connect to the server
std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_address + " 'echo connected' 2>/dev/null"; std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_user + "@" + ssh_address + " -p " + ssh_port + " 'echo connected' 2>/dev/null";
int result = system(cmd.c_str()); int result = system(cmd.c_str());
if (result == 0) { if (result == 0) {
std::cout << "Status: Online" << std::endl; std::cout << "Status: Online" << std::endl;

View File

@ -59,7 +59,7 @@ std::string service_runner::construct_ssh_cmd() const {
bool service_runner::check_remote_dir_exists(const std::string& dir_path) const { bool service_runner::check_remote_dir_exists(const std::string& dir_path) const {
std::string check_dir_cmd = construct_ssh_cmd() + "'test -d " + dir_path + "'"; std::string check_dir_cmd = construct_ssh_cmd() + "'test -d " + dir_path + "'";
if (system(check_dir_cmd.c_str()) != 0) { if (system(check_dir_cmd.c_str()) != 0) {
std::cerr << "Error: Directory not found on remote server:" << dir_path << std::endl; std::cerr << "Error: Directory not found on remote server:" << fs::path(dir_path).filename().string() << std::endl;
return false; return false;
} }
return true; return true;
@ -68,7 +68,25 @@ bool service_runner::check_remote_dir_exists(const std::string& dir_path) const
bool service_runner::check_remote_file_exists(const std::string& file_path) const { bool service_runner::check_remote_file_exists(const std::string& file_path) const {
std::string check_cmd = construct_ssh_cmd() + "'test -f " + file_path + "'"; std::string check_cmd = construct_ssh_cmd() + "'test -f " + file_path + "'";
if (system(check_cmd.c_str()) != 0) { if (system(check_cmd.c_str()) != 0) {
std::cerr << "Error: File not found on remote server: " << file_path << std::endl; std::cerr << "Error: File not found on remote server: " << fs::path(file_path).filename().string() << std::endl;
return false;
}
return true;
}
bool service_runner::check_remote_items_exist(const std::vector<std::string> &file_paths) const
{
// convert file_paths to a single string, separated by spaces
std::string file_paths_str;
std::string file_names_str;
for (const auto& file_path : file_paths) {
file_paths_str += file_path + " ";
file_names_str += fs::path(file_path).filename().string() + " ";
}
// check if all items in the vector exist on the remote server, in a single command.
std::string check_cmd = construct_ssh_cmd() + "'for item in " + file_paths_str + "; do test -f $item; done'";
if (system(check_cmd.c_str()) != 0) {
std::cerr << "Error: Required items not found on remote server: " << file_names_str << std::endl;
return false; return false;
} }
return true; return true;
@ -208,8 +226,12 @@ bool service_runner::backup() {
} }
// Check if basic installed stuff is in place. // Check if basic installed stuff is in place.
if (!check_remote_dir_exists(mRemote_service_path) || !check_remote_file_exists(script_path) || !check_remote_file_exists(mRemote_service_env_file)) if (!check_remote_items_exist({mRemote_service_path,script_path,mRemote_service_env_file}))
{
std::cerr << "Error: Required service directories not found on remote server" << std::endl;
std::cerr << "Is the service installed?" << std::endl;
return false; return false;
}
// Create backups directory on server if it doesn't exist // Create backups directory on server if it doesn't exist
std::string server_backups_dir = m_server_env->get_DROPSHELL_DIR() + "/backups"; std::string server_backups_dir = m_server_env->get_DROPSHELL_DIR() + "/backups";
@ -270,11 +292,12 @@ service_runner::HealthStatus service_runner::is_healthy()
std::string script_path = mRemote_service_template_path + "/" + command + ".sh"; std::string script_path = mRemote_service_template_path + "/" + command + ".sh";
if (!check_remote_file_exists(script_path)) { if (!check_remote_file_exists(script_path)) {
std::cerr << "Service is not installed: " << m_service_info.service_name << std::endl;
return HealthStatus::NOTINSTALLED; return HealthStatus::NOTINSTALLED;
} }
// Run status script, does not display output. // Run status script, does not display output.
bool ok = execute_ssh_command("'cd " + mRemote_service_template_path + " && /bin/bash _status.sh " + mRemote_service_env_file + " > /dev/null 2>&1'", ""); bool ok = execute_ssh_command("'cd " + mRemote_service_template_path + " && /bin/bash " + script_path + " " + mRemote_service_env_file + " > /dev/null 2>&1'", "");
if (!ok) if (!ok)
return HealthStatus::UNHEALTHY; return HealthStatus::UNHEALTHY;

View File

@ -77,6 +77,7 @@ class service_runner {
std::string construct_ssh_cmd() const; std::string construct_ssh_cmd() const;
bool check_remote_dir_exists(const std::string& dir_path) const; bool check_remote_dir_exists(const std::string& dir_path) const;
bool check_remote_file_exists(const std::string& file_path) const; bool check_remote_file_exists(const std::string& file_path) const;
bool check_remote_items_exist(const std::vector<std::string>& file_paths) const;
bool execute_ssh_command(const std::string& command, const std::string& error_msg) const; bool execute_ssh_command(const std::string& command, const std::string& error_msg) const;
bool execute_local_command(const std::string& command, const std::string& error_msg) const; bool execute_local_command(const std::string& command, const std::string& error_msg) const;
void maketitle(const std::string& title) const; void maketitle(const std::string& title) const;

View File

@ -3,6 +3,10 @@ TEMPLATE=watchtower
CONTAINER_NAME=watchtower CONTAINER_NAME=watchtower
# Interval in seconds between checks.
# Default is 1800 seconds (30 minutes).
INTERVAL=1800
# Image settings # Image settings
IMAGE_REGISTRY="docker.io" IMAGE_REGISTRY="docker.io"
IMAGE_REPO="containrrr/watchtower" IMAGE_REPO="containrrr/watchtower"

View File

@ -3,13 +3,14 @@ source "$(dirname "$0")/_common.sh"
load_env "$1" || die "Failed to load environment variables" load_env "$1" || die "Failed to load environment variables"
# Required environment variables # Required environment variables
check_required_env_vars "CONTAINER_NAME" check_required_env_vars "CONTAINER_NAME" "INTERVAL"
DOCKER_RUN_CMD="docker run -d \ DOCKER_RUN_CMD="docker run -d \
--restart unless-stopped \ --restart unless-stopped \
--name ${CONTAINER_NAME} \ --name ${CONTAINER_NAME} \
-v /var/run/docker.sock:/var/run/docker.sock \ -v /var/run/docker.sock:/var/run/docker.sock \
${IMAGE_REGISTRY}/${IMAGE_REPO}:${IMAGE_TAG}" ${IMAGE_REGISTRY}/${IMAGE_REPO}:${IMAGE_TAG} \
--interval ${INTERVAL}"
if ! create_and_start_container "$DOCKER_RUN_CMD" "$CONTAINER_NAME"; then if ! create_and_start_container "$DOCKER_RUN_CMD" "$CONTAINER_NAME"; then
echo "RUN_CMD failed:" echo "RUN_CMD failed:"