Major refactor

This commit is contained in:
Your Name 2025-04-28 20:39:49 +12:00
parent bd043eaed8
commit 1d6986cda0
8 changed files with 177 additions and 233 deletions

View File

@ -10,9 +10,9 @@
namespace dropshell {
config *get_global_config() {
static config *gConfig = new config();
return gConfig;
config & gConfig() {
static config *globalConfig = new config();
return *globalConfig;
}
@ -22,7 +22,7 @@ config::~config() {
}
bool config::load_config() {
std::string config_path = get_local_dropshell_config_file();
std::string config_path = localfile::dropshell_conf();
if (config_path.empty() || !std::filesystem::exists(config_path))
return false;
@ -56,10 +56,10 @@ void config::save_config()
return;
}
std::string parent_path = get_local_dropshell_config_parent_path();
std::string parent_path = dropshell::get_parent(localfile::dropshell_conf());
std::filesystem::create_directories(parent_path);
std::string config_path = get_local_dropshell_config_file();
std::string config_path = localfile::dropshell_conf();
envmanager config_env(config_path);
config_env.set_variable("local.config.directories", multi2string(mLocalConfigPaths));

View File

@ -25,6 +25,6 @@ class config {
};
config *get_global_config();
config & gConfig();
} // namespace dropshell

View File

@ -1,4 +1,4 @@
#include "server_env.hpp"
#include "server_env_manager.hpp"
#include "utils/envmanager.hpp"
#include "utils/directories.hpp"
#include "utils/utils.hpp"
@ -12,15 +12,12 @@
namespace dropshell {
server_env::server_env(const std::string& server_name) : mValid(false), mServer_name(server_name) {
server_env_manager::server_env_manager(const std::string& server_name) : mValid(false), mServer_name(server_name) {
if (server_name.empty())
{
std::cerr << "Warning: Server name is empty, passed to server_env constructor." << std::endl;
return;
}
// Construct the full path to server.env
std::string env_path = get_local_server_env_path(server_name);
std::string env_path = localfile::server_env(server_name);
// Check if file exists
if (!std::filesystem::exists(env_path)) {
@ -54,7 +51,7 @@ server_env::server_env(const std::string& server_name) : mValid(false), mServer_
}
}
std::string server_env::get_variable(const std::string& name) const {
std::string server_env_manager::get_variable(const std::string& name) const {
if (!m_env_manager) {
return "";
}
@ -62,17 +59,17 @@ std::string server_env::get_variable(const std::string& name) const {
}
// Helper method implementations
std::string server_env::construct_ssh_cmd() const {
std::string server_env_manager::construct_ssh_cmd() const {
std::stringstream ssh_cmd;
ssh_cmd << "ssh -p " << get_SSH_PORT() << " "
<< get_SSH_USER() << "@" << get_SSH_HOST();
return ssh_cmd.str();
}
std::string server_env::construct_standard_command_run_cmd(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
std::string server_env_manager::construct_standard_command_run_cmd(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
{
std::string remote_service_template_path = get_remote_service_template_path(mServer_name,service_name);
std::string remote_service_config_path = get_remote_service_config_path(mServer_name,service_name);
std::string remote_service_template_path = remotepath::service_template(mServer_name,service_name);
std::string remote_service_config_path = remotepath::service_config(mServer_name,service_name);
std::string script_path = remote_service_template_path + "/" + command + ".sh";
@ -89,19 +86,19 @@ std::string server_env::construct_standard_command_run_cmd(const std::string &se
return run_cmd;
}
void server_env::get_all_service_env_vars(const std::string &service_name, std::map<std::string, std::string> & all_env_vars) const
void server_env_manager::get_all_service_env_vars(const std::string &service_name, std::map<std::string, std::string> & all_env_vars) const
{
all_env_vars.clear();
// add in some handy variables.
all_env_vars["CONFIG_PATH"] = get_remote_service_config_path(mServer_name,service_name);
all_env_vars["CONFIG_PATH"] = remotepath::service_config(mServer_name,service_name);
all_env_vars["SERVER"] = mServer_name;
all_env_vars["SERVICE"] = service_name;
{ // load service.env from the service on this machine.
std::map<std::string, std::string> env_vars;
envmanager env_manager(get_local_service_env_path(mServer_name,service_name));
envmanager env_manager(localfile::service_env(mServer_name,service_name));
env_manager.load();
env_manager.get_all_variables(env_vars);
all_env_vars.merge(env_vars);
@ -123,18 +120,18 @@ void server_env::get_all_service_env_vars(const std::string &service_name, std::
}
bool server_env::check_remote_dir_exists(const std::string &dir_path) const
bool server_env_manager::check_remote_dir_exists(const std::string &dir_path) const
{
sCommand scommand("test -d " + quote(dir_path));
return execute_ssh_command(scommand);
}
bool server_env::check_remote_file_exists(const std::string& file_path) const {
bool server_env_manager::check_remote_file_exists(const std::string& file_path) const {
sCommand scommand("test -f " + quote(file_path));
return execute_ssh_command(scommand);
}
bool server_env::check_remote_items_exist(const std::vector<std::string> &file_paths) const
bool server_env_manager::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;
@ -154,34 +151,34 @@ bool server_env::check_remote_items_exist(const std::vector<std::string> &file_p
return true;
}
bool server_env::execute_ssh_command(const sCommand& command) const {
bool server_env_manager::execute_ssh_command(const sCommand& command) const {
std::string full_cmd = construct_ssh_cmd() + " " + quote(command.construct_safecmd());
return execute_local_command(full_cmd);
}
bool server_env::execute_ssh_command_and_capture_output(const sCommand& command, std::string &output) const
bool server_env_manager::execute_ssh_command_and_capture_output(const sCommand& command, std::string &output) const
{
std::string full_cmd = construct_ssh_cmd() + " " + quote(command.construct_safecmd());
return execute_local_command_and_capture_output(full_cmd, output);
}
bool server_env::run_remote_template_command(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
bool server_env_manager::run_remote_template_command(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
{
std::string full_cmd = construct_standard_command_run_cmd(service_name, command, args, silent);
return execute_ssh_command(full_cmd);
}
bool server_env::run_remote_template_command_and_capture_output(const std::string &service_name, const std::string &command, std::vector<std::string> args, std::string &output, bool silent) const
bool server_env_manager::run_remote_template_command_and_capture_output(const std::string &service_name, const std::string &command, std::vector<std::string> args, std::string &output, bool silent) const
{
std::string full_cmd = construct_standard_command_run_cmd(service_name, command, args, silent);
return execute_ssh_command_and_capture_output(full_cmd, output);
}
bool server_env::execute_local_command(const sCommand& command) {
bool server_env_manager::execute_local_command(const sCommand& command) {
return (system(command.construct_safecmd().c_str()) == 0);
}
bool server_env::execute_local_command_and_capture_output(const sCommand& command, std::string &output)
bool server_env_manager::execute_local_command_and_capture_output(const sCommand& command, std::string &output)
{
std::string full_cmd = command.construct_safecmd() + " 2>&1";
FILE *pipe = popen(full_cmd.c_str(), "r");

View File

@ -11,6 +11,7 @@
#include "utils/envmanager.hpp"
namespace dropshell {
// class to hold a command to run on the remote server.
class sCommand {
public:
sCommand(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars) :
@ -41,9 +42,9 @@ class sCommand {
// SSH_PORT
// the following replacements are made in the values:
// ${USER} -> the username of the user running dropshell
class server_env {
class server_env_manager {
public:
server_env(const std::string& server_name);
server_env_manager(const std::string& server_name);
std::string get_variable(const std::string& name) const;
// trivial getters.

View File

@ -1,5 +1,5 @@
#include "servers.hpp"
#include "server_env.hpp"
#include "server_env_manager.hpp"
#include "service_runner.hpp"
#include "utils/tableprint.hpp"
#include "utils/envmanager.hpp"
@ -18,19 +18,19 @@ namespace dropshell {
std::vector<ServerInfo> get_configured_servers() {
std::vector<ServerInfo> servers;
std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
std::vector<std::string> local_config_directories = gConfig().get_local_config_directories();
if (local_config_directories.empty())
return servers;
for (int i = 0; i < local_config_directories.size(); i++) {
std::string servers_dir = get_local_config_servers_path(i);
std::string servers_dir = localpath::config_servers(i);
if (!servers_dir.empty() && std::filesystem::exists(servers_dir)) {
for (const auto& entry : std::filesystem::directory_iterator(servers_dir)) {
if (std::filesystem::is_directory(entry)) {
std::string server_name = entry.path().filename().string();
server_env env(server_name);
server_env_manager env(server_name);
if (!env.is_valid()) {
std::cerr << "Error: Invalid server environment file: " << entry.path().string() << std::endl;
continue;
@ -75,7 +75,7 @@ void list_servers() {
}
void show_server_details(const std::string& server_name) {
server_env env(server_name);
server_env_manager env(server_name);
if (!env.is_valid()) {
std::cerr << "Error: Invalid server environment file: " << server_name << std::endl;
return;
@ -146,7 +146,7 @@ void show_server_details(const std::string& server_name) {
void create_server(const std::string &server_name)
{
// 1. check if server name already exists
std::string server_existing_dir = get_local_server_path(server_name);
std::string server_existing_dir = localpath::server(server_name);
if (!server_existing_dir.empty()) {
std::cerr << "Error: Server name already exists: " << server_name << std::endl;
std::cerr << "Current server path: " << server_existing_dir << std::endl;
@ -154,7 +154,7 @@ void create_server(const std::string &server_name)
}
// 2. create a new directory in the user config directory
std::string config_servers_dir = get_local_config_servers_path(0);
std::string config_servers_dir = localpath::config_servers();
std::string server_dir = config_servers_dir + "/" + server_name;
std::filesystem::create_directory(server_dir);

View File

@ -9,7 +9,7 @@
#include <string>
#include <vector>
#include <memory>
#include "server_env.hpp"
#include "server_env_manager.hpp"
#include "services.hpp"
#include "utils/utils.hpp"
#include "utils/assert.hpp"
@ -93,7 +93,7 @@ class service_runner {
private:
std::string m_server_name;
server_env m_server_env;
server_env_manager m_server_env;
ServiceInfo m_service_info;
bool mValid;

View File

@ -1,6 +1,6 @@
#include "directories.hpp"
#include "config.hpp"
#include "server_env.hpp"
#include "server_env_manager.hpp"
#include <iostream>
#include <string>
#include <filesystem>
@ -10,135 +10,88 @@ namespace fs = std::filesystem;
namespace dropshell {
std::string get_local_dropshell_config_parent_path()
{
namespace localfile {
std::string dropshell_conf() {
// Try ~/.config/dropshell/dropshell.conf
const char* home = std::getenv("HOME");
if (home) {
fs::path user_path = fs::path(home) / ".config" / "dropshell";
fs::path user_path = fs::path(home) / ".config" / "dropshell" / "dropshell.conf";
return user_path.string();
}
std::cerr << "Warning: Couldn't determine user directory" << std::endl;
return std::string();
}
std::string get_local_dropshell_config_file()
{
std::string parent_path = get_local_dropshell_config_parent_path();
if (parent_path.empty())
return std::string();
return parent_path + "/dropshell.conf";
}
std::string get_local_system_templates_path()
{
return "/opt/dropshell/templates";
}
std::string get_local_backup_path()
{
config *cfg = get_global_config();
if (!cfg)
return std::string();
return cfg->get_local_backup_path();
}
int getNumConfigDirectories()
{
config *cfg = get_global_config();
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
return local_config_directories.size();
}
std::string get_primary_local_config_path()
{
return get_local_config_path(0);
}
std::string get_local_config_path(int index)
{
config *cfg = get_global_config();
if (!cfg)
return std::string();
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
if (index < 0 || index >= local_config_directories.size())
return std::string();
return local_config_directories[index];
}
std::string get_local_config_templates_path(int index)
{
std::string config_path = get_local_config_path(index);
if (config_path.empty())
return std::string();
return config_path + "/templates";
}
std::string get_local_config_servers_path(int index)
{
std::string config_path = get_local_config_path(index);
if (config_path.empty())
return std::string();
return config_path + "/servers";
}
std::string get_local_server_path(const std::string &server_name)
{
config *cfg = get_global_config();
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
for (auto &dir : local_config_directories) {
std::string server_path = dir + "/servers/" + server_name;
if (fs::exists(server_path)) {
return server_path;
}
}
return std::string();
}
std::string get_local_server_env_path(const std::string &server_name)
{
if (server_name.empty())
return std::string();
std::string serverpath = get_local_server_path(server_name);
if (serverpath.empty())
return std::string();
return (fs::path(serverpath) / "server.env").string();
}
std::string server_env(const std::string &server_name) {
if (server_name.empty())
return std::string();
std::string serverpath = localpath::server(server_name);
if (serverpath.empty())
return std::string();
return (fs::path(serverpath) / "server.env").string();
}
std::string get_local_service_path(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string service_env(const std::string &server_name, const std::string &service_name) {
if (server_name.empty() || service_name.empty())
return std::string();
std::string servicepath = localpath::service(server_name, service_name);
if (servicepath.empty())
return std::string();
return (fs::path(servicepath) / "service.env").string();
}
std::string serverpath = get_local_server_path(server_name);
if (serverpath.empty())
return std::string();
return (fs::path(serverpath) / service_name).string();
}
std::string service_hash(const std::string &server_name, const std::string &service_name) {
std::string config_path = localpath::config();
if (server_name.empty() || service_name.empty() || config_path.empty())
return std::string();
return (fs::path(config_path) / ".remote_versions" / server_name / (service_name + ".hash.env")).string();
}
std::string get_local_service_env_path(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string servicepath = get_local_service_path(server_name, service_name);
if (servicepath.empty())
return std::string();
return (fs::path(servicepath) / "service.env").string();
}
} // namespace localfile
std::string get_local_service_hash_path(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string config_path = get_primary_local_config_path();
if (config_path.empty())
return std::string();
// ------------------------------------------------------------------------------------------
namespace localpath {
// /opt/dropshell/templates
std::string system_templates() {
return "/opt/dropshell/templates";
}
// configured by user - defaults to first config_path/backups.
std::string backups_path() {
return gConfig().get_local_backup_path();
}
int num_config_directories() {
return gConfig().get_local_config_directories().size();
}
std::string config(int index) {
return (num_config_directories()>index) ? gConfig().get_local_config_directories()[index] : "";
}
std::string config_templates(int index) {
return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/templates") : "";
}
std::string config_servers(int index) {
return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/servers") : "";
}
std::string server(const std::string &server_name) {
for (auto &dir : gConfig().get_local_config_directories())
if (fs::exists(dir + "/servers/" + server_name))
return dir + "/servers/" + server_name;
return "";
}
std::string service(const std::string &server_name, const std::string &service_name) {
std::string serverpath = localpath::server(server_name);
return (serverpath.empty() ? "" : (serverpath+"/"+service_name));
}
} // namespace localpath
return (fs::path(config_path) / ".remote_versions" / server_name / (service_name + ".hash.env")).string();
}
// ------------------------------------------------------------------------------------------
@ -152,74 +105,53 @@ std::string get_local_service_hash_path(const std::string &server_name, const st
// |-- (script files)
// |-- backups
std::string get_remote_DROPSHELL_path(const std::string &server_name)
{
if (server_name.empty())
return std::string();
server_env env(server_name);
if (!env.is_valid())
return std::string();
return env.get_DROPSHELL_DIR();
namespace remotepath {
std::string DROPSHELL_DIR(const std::string &server_name)
{
return server_env_manager(server_name).get_DROPSHELL_DIR();
}
std::string get_remote_services_path(const std::string &server_name)
std::string services(const std::string &server_name)
{
if (server_name.empty())
return std::string();
std::string dropshell_path = get_remote_DROPSHELL_path(server_name);
if (dropshell_path.empty())
return std::string();
return (fs::path(dropshell_path) / "services").string();
std::string dsp = DROPSHELL_DIR(server_name);
return (dsp.empty() ? "" : (dsp + "/services"));
}
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name)
std::string service(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string services_path = get_remote_services_path(server_name);
if (services_path.empty())
return std::string();
return (fs::path(services_path) / service_name).string();
std::string services_path = services(server_name);
return (services_path.empty() ? "" : (services_path + "/" + service_name));
}
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name)
std::string service_config(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string service_path = get_remote_service_path(server_name, service_name);
if (service_path.empty())
return std::string();
return (fs::path(service_path) / "config").string();
std::string service_path = service(server_name, service_name);
return (service_path.empty() ? "" : (service_path + "/config"));
}
std::string get_remote_service_template_path(const std::string &server_name, const std::string &service_name)
std::string service_template(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string service_path = get_remote_service_path(server_name, service_name);
if (service_path.empty())
return std::string();
return (fs::path(service_path) / "template").string();
std::string service_path = service(server_name, service_name);
return (service_path.empty() ? "" : (service_path + "/template"));
}
std::string get_remote_backups_path(const std::string &server_name)
std::string backups(const std::string &server_name)
{
if (server_name.empty())
return std::string();
std::string dropshell_path = get_remote_DROPSHELL_path(server_name);
if (dropshell_path.empty())
return std::string();
return (fs::path(dropshell_path) / "backups").string();
std::string dsp = DROPSHELL_DIR(server_name);
return (dsp.empty() ? "" : (dsp + "/backups"));
}
std::string get_remote_service_env_file(const std::string &server_name, const std::string &service_name)
std::string service_env(const std::string &server_name, const std::string &service_name)
{
if (server_name.empty() || service_name.empty())
return std::string();
std::string service_path = get_remote_service_config_path(server_name, service_name);
if (service_path.empty())
return std::string();
return (fs::path(service_path) / "service.env").string();
std::string service_path = service_config(server_name, service_name);
return (service_path.empty() ? "" : (service_path + "/service.env"));
}
} // namespace remotepath
std::string get_parent(std::string path)
{
if (path.empty())
return std::string();
return fs::path(path).parent_path().string();
}
} // namespace dropshell

View File

@ -5,13 +5,9 @@
namespace dropshell {
// local paths - return empty string on failure
std::string get_local_dropshell_config_parent_path();
std::string get_local_dropshell_config_file();
std::string get_local_system_templates_path();
std::string get_local_backup_path();
// all functions return empty string on failure
//------------------------------------------------------------------------------------------------
// local user config directories
// config_path
// |-- servers
@ -30,23 +26,32 @@ namespace dropshell {
// |-- .remote_versions
// | |-- server_name
// | |-- service_name.hash.env
namespace localfile {
// ~/.config/dropshell/dropshell.conf
std::string dropshell_conf();
std::string server_env(const std::string &server_name);
std::string service_env(const std::string &server_name, const std::string &service_name);
std::string service_hash(const std::string &server_name, const std::string &service_name);
} // namespace localfile
std::string get_primary_local_config_path();
namespace localpath {
// /opt/dropshell/templates
std::string system_templates();
// configured by user - defaults to first config_path/backups.
std::string backups_path();
int num_config_directories();
std::string config(int index=0);
std::string config_templates(int index=0);
std::string config_servers(int index=0);
std::string server(const std::string &server_name);
std::string service(const std::string &server_name, const std::string &service_name);
} // namespace local
int getNumConfigDirectories();
std::string get_local_config_path(int index);
std::string get_local_config_templates_path(int index);
std::string get_local_config_servers_path(int index);
std::string get_local_server_path(const std::string &server_name);
std::string get_local_server_env_path(const std::string &server_name);
std::string get_local_service_path(const std::string &server_name, const std::string &service_name);
std::string get_local_service_env_path(const std::string &server_name, const std::string &service_name);
std::string get_local_service_hash_path(const std::string &server_name, const std::string &service_name);
//------------------------------------------------------------------------------------------------
// remote paths
// DROPSHELL_DIR
// |-- backups
@ -59,14 +64,23 @@ namespace dropshell {
// |-- example
// |-- service.env
// |-- (other config files for specific server&service)
std::string get_remote_DROPSHELL_path(const std::string &server_name);
std::string get_remote_services_path(const std::string &server_name);
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name);
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name);
std::string get_remote_service_template_path(const std::string &server_name, const std::string &service_name);
std::string get_remote_backups_path(const std::string &server_name);
namespace remotefile {
std::string service_env(const std::string &server_name, const std::string &service_name);
} // namespace remotefile
namespace remotepath {
std::string DROPSHELL_DIR(const std::string &server_name);
std::string services(const std::string &server_name);
std::string service(const std::string &server_name, const std::string &service_name);
std::string service_config(const std::string &server_name, const std::string &service_name);
std::string service_template(const std::string &server_name, const std::string &service_name);
std::string backups(const std::string &server_name);
} // namespace remotepath
//------------------------------------------------------------------------------------------------
// utility functions
std::string get_parent(std::string path);
std::string get_remote_service_env_file(const std::string &server_name, const std::string &service_name);
} // namespace dropshell
#endif