uninstall!

This commit is contained in:
Your Name 2025-04-25 12:08:37 +12:00
parent 61fabac1f0
commit ed8bc0dca6
6 changed files with 100 additions and 9 deletions

View File

@ -30,6 +30,7 @@ void print_help() {
std::cout << std::endl;
std::cout << " install SERVER [SERVICE] Install/Update service(s)." << std::endl;
std::cout << " backup SERVER [SERVICE] Backup service(s)." << std::endl;
std::cout << " uninstall SERVER [SERVICE] Uninstall service(s)." << std::endl;
std::cout << " COMMAND SERVER [SERVICE] Run a custom command on service(s)." << std::endl;
std::cout << std::endl;
}
@ -120,7 +121,7 @@ int main(int argc, char* argv[]) {
commands.insert("init");
if (cfg->is_config_set())
commands.merge(std::set<std::string>{
"servers","templates","install","backup"
"servers","templates","install","uninstall","backup"
});
for (const auto& command : commands) {
@ -181,11 +182,11 @@ int main(int argc, char* argv[]) {
return 0;
}
if (cmd == "install") {
if (cmd == "install" || cmd == "uninstall") {
std::string server_name;
std::vector<dropshell::ServiceInfo> servicelist;
if (!parseargs(safearg(argc, argv, 2), safearg(argc, argv, 3), server_name, servicelist)) {
std::cerr << "Error: install command requires server name and optionally service name" << std::endl;
std::cerr << "Error: " << cmd << " command requires server name and optionally service name" << std::endl;
return 1;
}
for (const auto& service_info : servicelist) {
@ -194,9 +195,9 @@ int main(int argc, char* argv[]) {
std::cerr << "Error: Failed to initialize service" << std::endl;
return 1;
}
if (!service.install()) {
std::cerr << "Error: Failed to install service" << std::endl;
bool success = ((cmd=="install") ? service.install() : service.uninstall());
if (!success) {
std::cerr << "Error: Failed to " << cmd << " service" << std::endl;
return 1;
}
}

View File

@ -175,6 +175,52 @@ bool service_runner::install() {
return true;
}
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;
}
// 2. Check if service directory exists on server
if (!check_remote_dir_exists(mRemote_service_path)) {
std::cerr << "Service is not installed: " << m_service_info.service_name << std::endl;
return true; // Nothing to uninstall
}
// 3. Run uninstall script if it exists
std::string uninstall_script = mRemote_service_template_path + "/_uninstall.sh";
bool script_exists = check_remote_file_exists(uninstall_script);
if (script_exists) {
std::string uninstall_cmd = "'cd " + mRemote_service_template_path +
" && /bin/bash _uninstall.sh " + mRemote_service_env_file + "'";
if (!execute_ssh_command(uninstall_cmd, "Failed to run uninstall script")) {
std::cerr << "Warning: Uninstall script failed, but continuing with directory removal" << std::endl;
}
} else {
std::cerr << "Warning: No uninstall script found. Unable to uninstall service." << std::endl;
return false;
}
// 4. Remove the service directory from the server
std::string rm_cmd = "'rm -rf " + mRemote_service_path + "'";
if (!execute_ssh_command(rm_cmd, "Failed to remove service directory")) {
return false;
}
std::cout << "Service " << m_service_info.service_name << " successfully uninstalled from " << m_server_name << std::endl;
return true;
}
bool service_runner::run_command(const std::string& command) {
if (!m_server_env) {
std::cerr << "Error: Server service not initialized" << std::endl;

View File

@ -20,11 +20,19 @@ class service_runner {
// 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 that service directory/template (from the templates directory for the specified server, using templates.hpp to identify the path)
// 4. copying the {service_name}.env file to the service directory (from the server directory for the specified server)
// 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

View File

@ -3,11 +3,19 @@ source "$(dirname "$0")/_common.sh"
load_env "$1" || die "Failed to load environment variables"
# Required environment variables
check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG"
check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG" "LOCAL_DATA_FOLDER"
# Test Docker
_check_docker_installed || die "Docker test failed, aborting installation..."
# Create local data folder if it doesn't exist
if [ -d "${LOCAL_DATA_FOLDER}" ]; then
echo "Local data folder ${LOCAL_DATA_FOLDER} exists, using existing data."
else
echo "Local data folder ${LOCAL_DATA_FOLDER} does not exist, creating..."
mkdir -p "${LOCAL_DATA_FOLDER}"
fi
# check can pull image on remote host and exit if fails
docker pull "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG" || die "Failed to pull image $IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"

View File

@ -0,0 +1,14 @@
#!/bin/bash
source "$(dirname "$0")/_common.sh"
load_env "$1" || die "Failed to load environment variables"
# Required environment variables
check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG"
_remove_container $CONTAINER_NAME || die "Failed to remove container ${CONTAINER_NAME}"
# remove the image
docker rmi "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG" || echo "Failed to remove image $IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
echo "Uninstallation of ${CONTAINER_NAME} complete."
echo "Leaving local data folder ${LOCAL_DATA_FOLDER} in place."

View File

@ -0,0 +1,14 @@
#!/bin/bash
source "$(dirname "$0")/_common.sh"
load_env "$1" || die "Failed to load environment variables"
# Required environment variables
check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG"
_remove_container $CONTAINER_NAME || die "Failed to remove container ${CONTAINER_NAME}"
# remove the image
docker rmi "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG" || echo "Failed to remove image $IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
echo "Uninstallation of ${CONTAINER_NAME} complete."