Files
dropshell/source/src/utils/directories.cpp
j 735e2f083a
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 48s
Build-Test-Publish / build (linux/arm64) (push) Successful in 3m44s
Add overrides.env support for per-location service env overrides
2026-03-30 08:04:23 +13:00

284 lines
8.4 KiB
C++

#include "directories.hpp"
#include "config.hpp"
#include "servers.hpp"
#include "output.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
namespace dropshell
{
namespace localfile
{
std::string dropshell_json()
{
return localpath::dropshell_dir() + "/" + filenames::dropshell_json;
}
std::string server_json(const std::string &server_name)
{
std::string serverpath = localpath::server(server_name);
return (serverpath.empty() ? "" : (fs::path(serverpath) / filenames::server_json).string());
}
std::string service_env(const std::string &server_name, const std::string &service_name)
{
std::string servicepath = localpath::service(server_name, service_name);
return (servicepath.empty() ? "" : (fs::path(servicepath) / filenames::service_env).string());
}
std::string bb64()
{
return localpath::agent_local() + "/bb64";
}
std::string agent_hash()
{
return localpath::agent_remote() + "/agent.hash";
}
std::string overrides_env_for_server(const std::string &server_name)
{
std::string serverpath = localpath::server(server_name);
if (serverpath.empty())
return "";
return (fs::path(get_parent(serverpath)) / filenames::overrides_env).string();
}
} // namespace localfile
std::string get_local_agent_hash()
{
std::string hash_file = localfile::agent_hash();
if (!std::filesystem::exists(hash_file))
return "";
std::ifstream f(hash_file);
if (!f.is_open())
return "";
std::string hash;
std::getline(f, hash);
// Trim whitespace
hash.erase(0, hash.find_first_not_of(" \t\n\r"));
hash.erase(hash.find_last_not_of(" \t\n\r") + 1);
return hash;
}
// ------------------------------------------------------------------------------------------
namespace localpath
{
std::string dropshell_dir()
{
return current_user_home() + "/.dropshell";
}
std::string server(const std::string &server_name)
{
for (std::filesystem::path dir : gConfig().get_local_server_definition_paths())
if (fs::exists(dir / server_name))
return dir / 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() || service_name.empty()) ? "" : (serverpath + "/" + service_name));
}
std::string agent_local()
{
return dropshell_dir() + "/agent-local";
}
std::string agent_remote()
{
return dropshell_dir() + "/agent-remote";
}
std::string current_user_home()
{
char *homedir = std::getenv("HOME");
if (homedir)
{
std::filesystem::path homedir_path(homedir);
return fs::canonical(homedir_path).string();
}
warning << "Couldn't determine user directory" << std::endl;
return std::string();
}
std::string user_local_bin()
{
std::string home = current_user_home();
if (home.empty())
return "";
return home + "/.local/bin";
}
std::string backups()
{
if (!gConfig().is_config_set())
return "";
return gConfig().get_backups_path();
}
std::string temp_files()
{
return dropshell_dir() + "/temp_files";
}
std::string template_example()
{
return agent_local() + "/template_example";
}
bool create_directories()
{
std::vector<std::filesystem::path> paths = {
dropshell_dir(),
agent_local(),
agent_remote(),
backups(),
temp_files()};
for (auto &p : gConfig().get_local_server_definition_paths())
paths.push_back(p);
for (auto &p : paths)
if (!p.empty() && !std::filesystem::exists(p))
{
info << "Creating directory: " << p << std::endl;
std::filesystem::create_directories(p);
}
return false;
}
} // namespace localpath
//------------------------------------------------------------------------------------------------
// remote paths
// DROPSHELL_DIR
// |-- server.json
// |-- backups
// |-- temp_files
// |-- agent
// | |-- bb64
// | |-- (other agent files)
// |-- services
// |-- service name
// |-- config
// |-- service.env (actual service config)
// |-- template
// |-- (script files)
// |-- template_info.env
// |-- config
// |-- service.env (default service config)
// |-- (other template/example config files)
remotefile::remotefile(const std::string &server_name, const std::string &user) : mServer_name(server_name), mUser(user) {}
std::string remotefile::service_env(const std::string &service_name) const
{
return remotepath(mServer_name, mUser).service_config(service_name) + "/" + filenames::service_env;
}
std::string remotefile::server_json()
{
return remotepath(mServer_name, mUser).DROPSHELL_DIR() + "/" + filenames::server_json;
}
std::string remotefile::server_info_env()
{
return remotepath(mServer_name, mUser).DROPSHELL_DIR() + "/" + filenames::server_info_env;
}
std::string remotefile::ds_run()
{
return remotepath(mServer_name,mUser).agent() + "/" + filenames::ds_run;
}
remotepath::remotepath(const std::string &server_name, const std::string &user) : mServer_name(server_name), mUser(user) {}
std::string remotepath::DROPSHELL_DIR() const
{
try
{
return ServerConfig(mServer_name).get_user_dir(mUser);
} catch (const std::exception &e)
{
error << "Failed to get remote dropshell directory for " << mServer_name << "@" << mUser << std::endl;
error << "Exception: " << e.what() << std::endl;
return "";
}
}
std::string remotepath::services() const
{
std::string dsp = DROPSHELL_DIR();
return (dsp.empty() ? "" : (dsp + "/services"));
}
std::string remotepath::service(const std::string &service_name) const
{
std::string services_path = services();
return (services_path.empty() ? "" : (services_path + "/" + service_name));
}
std::string remotepath::service_config(const std::string &service_name) const
{
std::string service_path = service(service_name);
return (service_path.empty() ? "" : (service_path + "/config"));
}
std::string remotepath::service_template(const std::string &service_name) const
{
std::string service_path = service(service_name);
return (service_path.empty() ? "" : (service_path + "/template"));
}
std::string remotepath::backups() const
{
std::string dsp = DROPSHELL_DIR();
return (dsp.empty() ? "" : (dsp + "/backups"));
}
std::string remotepath::temp_files() const
{
std::string dsp = DROPSHELL_DIR();
return (dsp.empty() ? "" : (dsp + "/temp_files"));
}
std::string remotepath::agent() const
{
std::string dsp = DROPSHELL_DIR();
return (dsp.empty() ? "" : (dsp + "/agent"));
}
// ------------------------------------------------------------------------------------------
// Utility functions
std::string get_parent(const std::filesystem::path path)
{
if (path.empty())
return std::string();
return path.parent_path().string();
}
std::string get_child(const std::filesystem::path path)
{
if (path.empty())
return std::string();
return path.filename().string();
}
} // namespace dropshell