Refactor! Compiles...

This commit is contained in:
Your Name
2025-04-26 21:53:15 +12:00
parent bc0edf8e91
commit 3c03c2a536
11 changed files with 211 additions and 223 deletions

View File

@ -19,26 +19,16 @@ namespace fs = std::filesystem;
namespace dropshell {
service_runner::service_runner() : m_server_name(""), m_server_env(nullptr) {}
bool service_runner::init(const std::string& server_name, const std::string& service_name) {
service_runner::service_runner(const std::string& server_name, const std::string& service_name) :
m_server_env(server_name), m_server_name(server_name), mValid(false)
{
if (server_name.empty() || service_name.empty())
return false;
return;
// Initialize server environment
try {
m_server_env = std::make_unique<server_env>(server_name);
if (!m_server_env->is_valid()) {
std::cerr << "Error: Invalid server environment" << std::endl;
m_server_env.reset();
return false;
}
} catch (const std::exception& e) {
std::cerr << "Error: Failed to initialize server environment: " << e.what() << std::endl;
return false;
}
if (!m_server_env.is_valid())
return;
m_server_name = server_name;
m_service_info = get_service_info(server_name, service_name);
mRemote_service_path = get_remote_service_path(m_server_name, m_service_info.service_name);
@ -46,101 +36,13 @@ bool service_runner::init(const std::string& server_name, const std::string& ser
mRemote_service_template_path = get_remote_service_template_path(m_server_name, m_service_info.service_name);
mRemote_service_env_file = get_remote_service_env_file(m_server_name, m_service_info.service_name);
return !m_service_info.path.empty();
}
// Helper method implementations
std::string service_runner::construct_ssh_cmd(const server_env &env) {
std::stringstream ssh_cmd;
ssh_cmd << "ssh -p " << env.get_SSH_PORT() << " "
<< env.get_SSH_USER() << "@" << env.get_SSH_HOST() << " ";
return ssh_cmd.str();
}
std::string service_runner::construct_ssh_cmd() const
{
if (!m_server_env)
return std::string();
return construct_ssh_cmd(*m_server_env);
}
std::string service_runner::construct_standard_command_run_cmd(const std::string &command) const
{
std::string script_path = mRemote_service_template_path + "/" + command + ".sh";
std::string run_cmd = "'cd " + quote(mRemote_service_template_path) +
" && /bin/bash "+quote(script_path)+" "+quote(mRemote_service_config_path)+"'";
return run_cmd;
}
bool service_runner::check_remote_dir_exists(const std::string &dir_path) const
{
std::string check_dir_cmd = construct_ssh_cmd() + "'test -d " + quote(dir_path) + "'";
if (system(check_dir_cmd.c_str()) != 0) {
std::cerr << "Error: Directory not found on remote server:" << fs::path(dir_path).filename().string() << std::endl;
return false;
}
return true;
}
bool service_runner::check_remote_file_exists(const std::string& file_path) const {
std::string check_cmd = construct_ssh_cmd() + "'test -f " + quote(file_path) + "'";
if (system(check_cmd.c_str()) != 0) {
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 += quote(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 true;
}
bool service_runner::execute_ssh_command(const std::string& command, const std::string& error_msg) const {
std::string full_cmd = construct_ssh_cmd() + command;
return execute_local_command(full_cmd, error_msg);
}
bool service_runner::execute_local_command(const std::string& command, const std::string& error_msg) const {
bool okay = (system(command.c_str()) == 0);
if (!okay && !error_msg.empty())
std::cerr << "Error: " << error_msg << std::endl;
return okay;
}
bool service_runner::execute_local_command_and_capture_output(const std::string &command, std::string &output)
{
std::string full_cmd = command + " 2>&1";
FILE *pipe = popen(full_cmd.c_str(), "r");
if (!pipe) {
std::cerr << "Error: Failed to execute command: " << command << std::endl;
return false;
}
char buffer[128];
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
output += buffer;
}
pclose(pipe);
return true;
mValid = !m_service_info.local_template_path.empty();
}
bool service_runner::install() {
maketitle("Installing " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name);
if (!m_server_env) return false; // should never hit this.
if (!m_server_env.is_valid()) return false; // should never hit this.
// Check if template exists
template_info tinfo;
@ -149,23 +51,23 @@ bool service_runner::install() {
// Create service directory
std::string mkdir_cmd = "'mkdir -p " + quote(mRemote_service_path) + "'";
if (!execute_ssh_command(mkdir_cmd, "Failed to create service directory"))
if (!m_server_env.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 (!m_server_env.execute_ssh_command(check_rsync_cmd, "rsync is not installed on the remote host"))
return false;
// Copy template files
{
std::cout << "Copying template files from [LOCAL] " << tinfo.path << std::endl << std::string(24,' ')<<"to [REMOTE] " << mRemote_service_template_path << "/" << std::endl;
std::string rsync_cmd = "rsync --delete -zrpc -e 'ssh -p " + m_server_env->get_SSH_PORT() + "' " +
quote(tinfo.path + "/") + " "+
m_server_env->get_SSH_USER() + "@" + m_server_env->get_SSH_HOST() + ":" +
std::cout << "Copying template files from [LOCAL] " << tinfo.local_template_path << std::endl << std::string(24,' ')<<"to [REMOTE] " << mRemote_service_template_path << "/" << std::endl;
std::string rsync_cmd = "rsync --delete -zrpc -e 'ssh -p " + m_server_env.get_SSH_PORT() + "' " +
quote(tinfo.local_template_path + "/") + " "+
m_server_env.get_SSH_USER() + "@" + m_server_env.get_SSH_HOST() + ":" +
quote(mRemote_service_template_path+"/");
//std::cout << std::endl << rsync_cmd << std::endl << std::endl;
execute_local_command(rsync_cmd,"Failed to copy template files");
m_server_env.execute_local_command(rsync_cmd,"Failed to copy template files");
}
// Copy service files (including service.env)
@ -176,17 +78,17 @@ bool service_runner::install() {
return false;
}
std::cout << "Copying service files from [LOCAL] " << local_service_path << std::endl <<std::string(24,' ')<<"to [REMOTE] " << mRemote_service_config_path << std::endl;
std::string rsync_cmd = "rsync --delete -zrpc -e 'ssh -p " + m_server_env->get_SSH_PORT() + "' " +
std::string rsync_cmd = "rsync --delete -zrpc -e 'ssh -p " + m_server_env.get_SSH_PORT() + "' " +
quote(local_service_path + "/") + " "+
m_server_env->get_SSH_USER() + "@" + m_server_env->get_SSH_HOST() + ":" +
m_server_env.get_SSH_USER() + "@" + m_server_env.get_SSH_HOST() + ":" +
quote(mRemote_service_config_path + "/");
execute_local_command(rsync_cmd,"Failed to copy service files");
m_server_env.execute_local_command(rsync_cmd,"Failed to copy service files");
}
// Run install script
{
std::string install_cmd = construct_standard_command_run_cmd("install");
bool ok= execute_ssh_command(install_cmd, "Failed to run install script");
std::string install_cmd = m_server_env.construct_standard_command_run_cmd(m_service_info.service_name, "install");
bool ok= m_server_env.execute_ssh_command(install_cmd, "Failed to run install script");
if (!ok)
return false;
}
@ -199,21 +101,21 @@ 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) return false; // should never hit this.
if (!m_server_env.is_valid()) return false; // should never hit this.
// 2. Check if service directory exists on server
if (!check_remote_dir_exists(mRemote_service_path)) {
if (!m_server_env.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);
bool script_exists = m_server_env.check_remote_file_exists(uninstall_script);
if (script_exists) {
std::string uninstall_cmd = construct_standard_command_run_cmd("uninstall");
if (!execute_ssh_command(uninstall_cmd, "Failed to run uninstall script")) {
std::string uninstall_cmd = m_server_env.construct_standard_command_run_cmd(m_service_info.service_name, "uninstall");
if (!m_server_env.execute_ssh_command(uninstall_cmd, "Failed to run uninstall script")) {
std::cerr << "Warning: Uninstall script failed, but continuing with directory removal" << std::endl;
}
} else {
@ -223,7 +125,7 @@ bool service_runner::uninstall() {
// 4. Remove the service directory from the server
std::string rm_cmd = "'rm -rf " + quote(mRemote_service_path) + "'";
if (!execute_ssh_command(rm_cmd, "Failed to remove service directory")) {
if (!m_server_env.execute_ssh_command(rm_cmd, "Failed to remove service directory")) {
return false;
}
@ -236,7 +138,7 @@ bool service_runner::uninstall() {
// Run a command on the service.
// ------------------------------------------------------------------------------------------------
bool service_runner::run_command(const std::string& command) {
if (!m_server_env) {
if (!m_server_env.is_valid()) {
std::cerr << "Error: Server service not initialized" << std::endl;
return false;
}
@ -264,17 +166,17 @@ bool service_runner::run_command(const std::string& command) {
std::string script_path = mRemote_service_template_path + "/" + command + ".sh";
// Check if service directory exists
if (!check_remote_dir_exists(mRemote_service_path)) {
if (!m_server_env.check_remote_dir_exists(mRemote_service_path)) {
return false;
}
// Check if command script exists
if (!check_remote_file_exists(script_path)) {
if (!m_server_env.check_remote_file_exists(script_path)) {
return false;
}
// Check if env file exists
if (!check_remote_file_exists(mRemote_service_env_file)) {
if (!m_server_env.check_remote_file_exists(mRemote_service_env_file)) {
return false;
}
@ -286,8 +188,8 @@ bool service_runner::run_command(const std::string& command) {
}
// Run the generic command
std::string run_cmd = construct_standard_command_run_cmd(command);
return execute_ssh_command(run_cmd, "Command returned error code: " + script_path);
std::string run_cmd = m_server_env.construct_standard_command_run_cmd(m_service_info.service_name, command);
return m_server_env.execute_ssh_command(run_cmd, "Command returned error code: " + script_path);
}
@ -316,11 +218,11 @@ std::map<std::string, ServiceStatus> service_runner::get_all_services_status(std
}
std::string script_path = remote_service_template_path + "/" + command + ".sh";
std::string ssh_cmd = construct_ssh_cmd(env) + "'cd " + quote(remote_service_template_path) +
std::string ssh_cmd = env.construct_ssh_cmd() + "'cd " + quote(remote_service_template_path) +
" && /bin/bash "+quote(script_path)+" "+quote(remote_service_config_path)+"'";
std::string output;
if (!execute_local_command_and_capture_output(ssh_cmd, output))
if (!env.execute_local_command_and_capture_output(ssh_cmd, output))
return status;
std::stringstream ss(output);
@ -359,7 +261,7 @@ std::map<std::string, ServiceStatus> service_runner::get_all_services_status(std
HealthStatus service_runner::is_healthy()
{
if (!m_server_env) {
if (!m_server_env.is_valid()) {
std::cerr << "Error: Server service not initialized" << std::endl;
return HealthStatus::ERROR;
}
@ -372,14 +274,14 @@ HealthStatus service_runner::is_healthy()
}
std::string script_path = mRemote_service_template_path + "/" + command + ".sh";
if (!check_remote_file_exists(script_path)) {
if (!m_server_env.check_remote_file_exists(script_path)) {
std::cerr << "Service is not installed: " << m_service_info.service_name << std::endl;
return HealthStatus::NOTINSTALLED;
}
// Run status script, does not display output.
std::string run_cmd = construct_standard_command_run_cmd("status");
bool ok = execute_ssh_command(run_cmd, "");
std::string run_cmd = m_server_env.construct_standard_command_run_cmd(m_service_info.service_name, "status");
bool ok = m_server_env.execute_ssh_command(run_cmd, "");
if (!ok)
return HealthStatus::UNHEALTHY;
@ -506,7 +408,7 @@ void service_runner::interactive_ssh_service()
return;
}
std::string command = construct_standard_command_run_cmd("ssh");
std::string command = m_server_env.construct_standard_command_run_cmd(m_service_info.service_name, "ssh");
interactive_ssh(m_server_name, "/bin/bash -c '"+command+"'");
}