Refact0r
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled

This commit is contained in:
Your Name
2025-05-17 19:40:51 +12:00
parent 203068048d
commit 1d3bb634f0
17 changed files with 608 additions and 499 deletions

View File

@@ -10,7 +10,6 @@
#include "utils/assert.hpp"
#include "config.hpp"
#include "service_runner.hpp"
#include "server_env_manager.hpp"
#include "templates.hpp"
#include "services.hpp"
@@ -19,6 +18,75 @@
#include "command_registry.hpp"
#include "shared_commands.hpp"
namespace dropshell {
class service_runner {
public:
service_runner(const std::string& server_name, const std::string& service_name);
bool isValid() const { return mValid; }
// 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
// do a lot of checks, such as:
// checking that we can ssh to the server.
// checking whether the service directory exists on the server.
// checking that the command exists in the service directory.
// checking that the command is a valid .sh file.
// checking that the {service_name}.env file exists in the service directory.
bool run_command(const std::string& command, std::vector<std::string> additional_args={}, std::map<std::string, std::string> env_vars={});
// check health of service. Silent.
// 1. run status.sh on the server
// 2. return the output of the status.sh script
//HealthStatus is_healthy();
// std::string healthtick();
// std::string healthmark();
public:
// backup and restore
bool backup(bool silent=false);
bool restore(std::string backup_file, bool silent=false);
// nuke the service
bool nuke(bool silent=false); // nukes all data for this service on the remote server
bool fullnuke(); // nuke all data for this service on the remote server, and then nukes all the local service definitionfiles
// launch an interactive ssh session on a server or service
// replaces the current dropshell process with the ssh process
bool interactive_ssh_service();
bool scp_file_to_remote(const std::string& local_path, const std::string& remote_path, bool silent=false);
bool scp_file_from_remote(const std::string& remote_path, const std::string& local_path, bool silent=false);
public:
// utility functions
static std::string get_latest_backup_file(const std::string& server, const std::string& service);
static bool interactive_ssh(const std::string & server_name, const std::string & command);
// static std::map<std::string, ServiceStatus> get_all_services_status(std::string server_name);
private:
std::string mServer;
server_env_manager mServerEnv;
LocalServiceInfo mServiceInfo;
std::string mService;
bool mValid;
// Helper methods
public:
};
} // namespace dropshell
namespace fs = std::filesystem;
namespace dropshell {
@@ -165,58 +233,6 @@ bool service_runner::run_command(const std::string& command, std::vector<std::st
}
std::map<std::string, ServiceStatus> service_runner::get_all_services_status(std::string server_name)
{
std::map<std::string, ServiceStatus> status;
server_env_manager env(server_name);
if (!env.is_valid()) {
std::cerr << "Error: Invalid server environment" << std::endl;
return status;
}
std::string output;
if (!execute_ssh_command(env.get_SSH_INFO(), sCommand(remotepath::agent(server_name), "./_allservicesstatus.sh", {
{"HOST_NAME", server_name},
{"SERVER",server_name},
{"AGENT_PATH", remotepath::agent(server_name)}
}), cMode::CaptureOutput, &output))
return status;
std::stringstream ss(output);
std::string line;
while (std::getline(ss, line)) {
std::string key, value;
std::size_t pos = line.find("=");
if (pos != std::string::npos) {
key = dequote(trim(line.substr(0, pos)));
value = dequote(trim(line.substr(pos + 1)));
// decode key, it's of format SERVICENAME_[HEALTH|PORTS]
std::string service_name = key.substr(0, key.find_last_of("_"));
std::string status_type = key.substr(key.find_last_of("_") + 1);
if (status_type == "HEALTH") { // healthy|unhealthy|unknown
if (value == "healthy")
status[service_name].health = HealthStatus::HEALTHY;
else if (value == "unhealthy")
status[service_name].health = HealthStatus::UNHEALTHY;
else if (value == "unknown")
status[service_name].health = HealthStatus::UNKNOWN;
else
status[service_name].health = HealthStatus::ERROR;
} else if (status_type == "PORTS") { // port1,port2,port3
std::vector<std::string> ports = string2multi(value);
for (const auto& port : ports) {
if (port!="unknown")
status[service_name].ports.push_back(str2int(port));
}
}
}
}
return status;
}
bool service_runner::interactive_ssh(const std::string & server_name, const std::string & command) {
std::string serverpath = localpath::server(server_name);
@@ -342,7 +358,7 @@ bool service_runner::restore(std::string backup_file, bool silent)
return false;
}
cRemoteTempFolder remote_temp_folder(mServerEnv);
shared_commands::cRemoteTempFolder remote_temp_folder(mServerEnv);
mServerEnv.run_remote_template_command(mService, "restore", {}, silent, {{"BACKUP_FILE", remote_backup_file_path}, {"TEMP_DIR", remote_temp_folder.path()}});
} // dtor of remote_temp_folder will clean up the temp folder on the server
@@ -449,7 +465,7 @@ bool service_runner::backup(bool silent) {
ASSERT(3 == count_substring(magic_string, local_backup_file_path), "Invalid backup filename");
{ // Run backup script
cRemoteTempFolder remote_temp_folder(mServerEnv);
shared_commands::cRemoteTempFolder remote_temp_folder(mServerEnv);
if (!mServerEnv.run_remote_template_command(mService, command, {}, silent, {{"BACKUP_FILE", remote_backup_file_path}, {"TEMP_DIR", remote_temp_folder.path()}})) {
std::cerr << "Backup script failed on remote server: " << remote_backup_file_path << std::endl;
return false;
@@ -469,27 +485,6 @@ bool service_runner::backup(bool silent) {
return true;
}
cRemoteTempFolder::cRemoteTempFolder(const server_env_manager &server_env) : mServerEnv(server_env)
{
std::string p = remotepath::temp_files(server_env.get_server_name()) + "/" + random_alphanumeric_string(10);
std::string mkdir_cmd = "mkdir -p " + quote(p);
if (!execute_ssh_command(server_env.get_SSH_INFO(), sCommand("", mkdir_cmd, {}), cMode::Silent))
std::cerr << "Failed to create temp directory on server" << std::endl;
else
mPath = p;
}
cRemoteTempFolder::~cRemoteTempFolder()
{
std::string rm_cmd = "rm -rf " + quote(mPath);
execute_ssh_command(mServerEnv.get_SSH_INFO(), sCommand("", rm_cmd, {}), cMode::Silent);
}
std::string cRemoteTempFolder::path() const
{
return mPath;
}
// Helper function to get the latest backup file for a given server and service
std::string service_runner::get_latest_backup_file(const std::string& server, const std::string& service) {
std::string local_backups_dir = gConfig().get_local_backup_path();