dropshell release 2025.0524.1149
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 17s
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 17s
This commit is contained in:
parent
0934179053
commit
763293c7d0
@ -1,5 +1,5 @@
|
|||||||
SSH_ADDRESS=localhost
|
SSH_ADDRESS=localhost
|
||||||
SSH_PORT=22
|
SSH_PORT=22
|
||||||
SSH_USER=$(whoami)
|
SSH_UNPRIVILEGED_USER=$(whoami)
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace dropshell
|
|||||||
recursive_copy(tinfo.local_template_path() / "config", service_dir);
|
recursive_copy(tinfo.local_template_path() / "config", service_dir);
|
||||||
|
|
||||||
// append TEMPLATE_HASH to the .template_info.env file
|
// append TEMPLATE_HASH to the .template_info.env file
|
||||||
std::string template_info_env_file = service_dir + "/.template_info.env";
|
std::string template_info_env_file = service_dir + "/" + filenames::template_info_env;
|
||||||
std::ofstream template_info_env_file_out(template_info_env_file);
|
std::ofstream template_info_env_file_out(template_info_env_file);
|
||||||
template_info_env_file_out << "TEMPLATE_HASH=" << tinfo.hash() << std::endl;
|
template_info_env_file_out << "TEMPLATE_HASH=" << tinfo.hash() << std::endl;
|
||||||
template_info_env_file_out.close();
|
template_info_env_file_out.close();
|
||||||
@ -191,12 +191,12 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
info << "Setting SSH_USER to " << sshuser << " in service.env file" << std::endl;
|
info << "Setting SSH_USER to " << sshuser << " in the " << filenames::service_env << " file" << std::endl;
|
||||||
{ // edit the service.env file to set the SSH_USER.
|
{ // edit the service.env file to set the SSH_USER.
|
||||||
std::string template_service_env_file = tinfo.local_template_path() / "config" / "service.env";
|
std::string template_service_env_file = tinfo.local_template_path() / "config" / filenames::service_env;
|
||||||
ASSERT(std::filesystem::exists(template_service_env_file), "Template service env file not found: " + template_service_env_file);
|
ASSERT(std::filesystem::exists(template_service_env_file), "Template service env file not found: " + template_service_env_file);
|
||||||
std::ifstream template_service_env_file_in(template_service_env_file);
|
std::ifstream template_service_env_file_in(template_service_env_file);
|
||||||
std::ofstream service_env_file_out(service_dir + "/service.env");
|
std::ofstream service_env_file_out(localfile::template_info_env(server_name, service_name));
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(template_service_env_file_in, line))
|
while (std::getline(template_service_env_file_in, line))
|
||||||
{
|
{
|
||||||
@ -239,6 +239,23 @@ namespace dropshell
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool merge_updated_service_template(const std::string &server_name, const std::string &service_name)
|
||||||
|
{
|
||||||
|
LocalServiceInfo service_info = get_service_info(server_name, service_name);
|
||||||
|
ASSERT(SIvalid(service_info), "Service info is not valid for " + service_name + " on " + server_name);
|
||||||
|
|
||||||
|
template_info tinfo = gTemplateManager().get_template_info(service_info.template_name);
|
||||||
|
ASSERT(tinfo.is_set(), "Failed to load template " + service_info.template_name);
|
||||||
|
|
||||||
|
// copy across .template_info.env file
|
||||||
|
std::string template_service_env_file = "";
|
||||||
|
std::string target_service_env_file = localfile::template_info_env(server_name, service_name);
|
||||||
|
ASSERT(std::filesystem::exists(template_service_env_file), "Template service env file not found: " + template_service_env_file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shared_commands
|
} // namespace shared_commands
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
@ -70,6 +70,15 @@ namespace dropshell
|
|||||||
if (!SIvalid(service_info))
|
if (!SIvalid(service_info))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!service_info.service_template_hash_match)
|
||||||
|
{
|
||||||
|
warning << "Service " << service << " is using an old template. Updating. " << std::endl;
|
||||||
|
if (!merge_updated_service_template(server_env.get_server_name(), service))
|
||||||
|
{
|
||||||
|
error << "Failed to merge updated service template. " << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
maketitle("Installing " + service + " (" + service_info.template_name + ") on " + server);
|
maketitle("Installing " + service + " (" + service_info.template_name + ") on " + server);
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ namespace dropshell
|
|||||||
|
|
||||||
// defined in create-service.cpp
|
// defined in create-service.cpp
|
||||||
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, std::string user_override="");
|
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, std::string user_override="");
|
||||||
|
bool merge_updated_service_template(const std::string &server_name, const std::string &service_name);
|
||||||
|
|
||||||
} // namespace shared_commands
|
} // namespace shared_commands
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
||||||
|
@ -28,23 +28,22 @@ namespace dropshell
|
|||||||
if (server_name.empty())
|
if (server_name.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Construct the full path to server.json
|
std::string server_json_path = localfile::server_json(server_name);
|
||||||
std::string server_env_path = localfile::server_json(server_name);
|
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
if (!std::filesystem::exists(server_env_path))
|
if (!std::filesystem::exists(server_json_path))
|
||||||
{
|
{
|
||||||
std::cerr << "Server environment file not found: " + server_env_path << " for server " << server_name << std::endl;
|
std::cerr << "Server environment file not found: " + server_json_path << " for server " << server_name << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Use envmanager to handle the environment file
|
// Use envmanager to handle the environment file
|
||||||
nlohmann::json server_env_json = nlohmann::json::parse(std::ifstream(server_env_path));
|
nlohmann::json server_env_json = nlohmann::json::parse(std::ifstream(server_json_path));
|
||||||
if (server_env_json.empty())
|
if (server_env_json.empty())
|
||||||
{
|
{
|
||||||
error << "Failed to parse server environment file at "<< server_env_path << std::endl;
|
error << "Failed to parse server environment file at "<< server_json_path << std::endl;
|
||||||
info << "The returned json was empty." << std::endl;
|
info << "The returned json was empty." << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,7 +95,7 @@ namespace dropshell
|
|||||||
|
|
||||||
if (mUsers.empty())
|
if (mUsers.empty())
|
||||||
{
|
{
|
||||||
error << "No users defined in server configuration " << server_env_path << std::endl;
|
error << "No users defined in server configuration " << server_json_path << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
error << "Failed to parse " << server_env_path << std::endl;
|
error << "Failed to parse " << server_json_path << std::endl;
|
||||||
error << "Error: " << e.what() << std::endl;
|
error << "Error: " << e.what() << std::endl;
|
||||||
|
|
||||||
mValid = false;
|
mValid = false;
|
||||||
@ -334,30 +333,10 @@ namespace dropshell
|
|||||||
argstr += " " + quote(dequote(trim(arg)));
|
argstr += " " + quote(dequote(trim(arg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env_vars.find("RUNAS") == env_vars.end())
|
|
||||||
{
|
|
||||||
error << "Error: RUNAS is not set in .template_info.env for the service." << std::endl;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
std::string runas = env_vars.find("RUNAS")->second;
|
|
||||||
if (runas != "root" && runas != "user")
|
|
||||||
{
|
|
||||||
error << "Error: RUNAS is not set to root or user in .template_info.env for the service." << std::endl;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
bool run_as_root = runas == "root";
|
|
||||||
|
|
||||||
if (run_as_root && !hasRootUser())
|
|
||||||
{
|
|
||||||
error << "Error: The service " << service_name << " is set to run as root on the remote server, but the server environment does not allow root services." << std::endl;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
sCommand sc(
|
sCommand sc(
|
||||||
remote_service_template_path,
|
remote_service_template_path,
|
||||||
quote(script_path) + argstr + (silent ? " > /dev/null 2>&1" : ""),
|
quote(script_path) + argstr + (silent ? " > /dev/null 2>&1" : ""),
|
||||||
env_vars,
|
env_vars);
|
||||||
run_as_root);
|
|
||||||
|
|
||||||
if (sc.empty())
|
if (sc.empty())
|
||||||
{
|
{
|
||||||
@ -427,7 +406,7 @@ namespace dropshell
|
|||||||
|
|
||||||
// 3. create a template server.env file in the server directory
|
// 3. create a template server.env file in the server directory
|
||||||
std::string user = getenv("USER");
|
std::string user = getenv("USER");
|
||||||
std::string server_env_path = server_dir + "/server.json";
|
std::string server_env_path = server_dir + "/" + filenames::server_json;
|
||||||
std::ofstream server_env_file(server_env_path);
|
std::ofstream server_env_file(server_env_path);
|
||||||
server_env_file << "{" << std::endl;
|
server_env_file << "{" << std::endl;
|
||||||
server_env_file << " \"SSH_HOST\": \"" << server_name << "\"," << std::endl;
|
server_env_file << " \"SSH_HOST\": \"" << server_name << "\"," << std::endl;
|
||||||
|
@ -67,7 +67,7 @@ namespace dropshell
|
|||||||
auto it = variables.find(variable_name);
|
auto it = variables.find(variable_name);
|
||||||
if (it == variables.end())
|
if (it == variables.end())
|
||||||
{
|
{
|
||||||
error << "Variable " << variable_name << " not found in the service .template_info.env file" << std::endl;
|
error << "Variable " << variable_name << " not found in the service " << filenames::template_info_env << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return it->second == "true";
|
return it->second == "true";
|
||||||
@ -237,7 +237,7 @@ namespace dropshell
|
|||||||
if (user.empty())
|
if (user.empty())
|
||||||
{
|
{
|
||||||
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
info << "This variable definition is always required, and usually set int he service.env file." << std::endl;
|
info << "This variable definition is always required, and usually set in the "<<filenames::service_env << " file." << std::endl;
|
||||||
info << "Please check " << localfile::service_env(server_name, service_name) << std::endl;
|
info << "Please check " << localfile::service_env(server_name, service_name) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ namespace dropshell
|
|||||||
{
|
{
|
||||||
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
info << "The TEMPLATE variable is required to determine the template name." << std::endl;
|
info << "The TEMPLATE variable is required to determine the template name." << std::endl;
|
||||||
info << "Please check the service.env file and the .template_info.env file in:" << std::endl;
|
info << "Please check the " << filenames::service_env << " file and the "<< filenames::template_info_env << " file in:" << std::endl;
|
||||||
info << " " << localpath::service(server_name, service_name) << std::endl
|
info << " " << localpath::service(server_name, service_name) << std::endl
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -220,9 +220,9 @@
|
|||||||
// modify the TEMPLATE=example line in the .template_info.env file to TEMPLATE=<template_name>
|
// modify the TEMPLATE=example line in the .template_info.env file to TEMPLATE=<template_name>
|
||||||
std::string search_string = "TEMPLATE=";
|
std::string search_string = "TEMPLATE=";
|
||||||
std::string replacement_line = "TEMPLATE=" + template_name;
|
std::string replacement_line = "TEMPLATE=" + template_name;
|
||||||
std::string service_env_path = new_template_path + "/config/.template_info.env";
|
std::string service_env_path = new_template_path + "/config/" + filenames::template_info_env;
|
||||||
if (!replace_line_in_file(service_env_path, search_string, replacement_line)) {
|
if (!replace_line_in_file(service_env_path, search_string, replacement_line)) {
|
||||||
std::cerr << "Error: Failed to replace TEMPLATE= line in the .template_info.env file" << std::endl;
|
std::cerr << "Error: Failed to replace TEMPLATE= line in the " << filenames::template_info_env <<" file" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,8 +306,8 @@
|
|||||||
std::string template_name = std::filesystem::path(template_path).filename().string();
|
std::string template_name = std::filesystem::path(template_path).filename().string();
|
||||||
|
|
||||||
std::vector<std::string> required_files = {
|
std::vector<std::string> required_files = {
|
||||||
"config/service.env",
|
"config/" + filenames::service_env,
|
||||||
"config/.template_info.env",
|
"config/" + filenames::template_info_env,
|
||||||
"install.sh",
|
"install.sh",
|
||||||
"uninstall.sh"
|
"uninstall.sh"
|
||||||
};
|
};
|
||||||
@ -331,8 +331,8 @@
|
|||||||
// check TEMPLATE= line.
|
// check TEMPLATE= line.
|
||||||
std::map<std::string, std::string> all_env_vars;
|
std::map<std::string, std::string> all_env_vars;
|
||||||
std::vector<std::string> env_files = {
|
std::vector<std::string> env_files = {
|
||||||
"config/service.env",
|
"config/" + filenames::service_env,
|
||||||
"config/.template_info.env"
|
"config/" + filenames::template_info_env
|
||||||
};
|
};
|
||||||
for (const auto& file : env_files) {
|
for (const auto& file : env_files) {
|
||||||
{ // load service.env from the service on this machine.
|
{ // load service.env from the service on this machine.
|
||||||
|
@ -19,7 +19,7 @@ namespace localfile {
|
|||||||
// Try ~/.config/dropshell/dropshell.json
|
// Try ~/.config/dropshell/dropshell.json
|
||||||
std::string homedir = localpath::current_user_home();
|
std::string homedir = localpath::current_user_home();
|
||||||
if (!homedir.empty()) {
|
if (!homedir.empty()) {
|
||||||
fs::path user_path = fs::path(homedir) / ".config" / "dropshell" / "dropshell.json";
|
fs::path user_path = fs::path(homedir) / ".config" / "dropshell" / filenames::dropshell_json;
|
||||||
return user_path.string();
|
return user_path.string();
|
||||||
}
|
}
|
||||||
return std::string();
|
return std::string();
|
||||||
@ -27,18 +27,18 @@ namespace localfile {
|
|||||||
|
|
||||||
std::string server_json(const std::string &server_name) {
|
std::string server_json(const std::string &server_name) {
|
||||||
std::string serverpath = localpath::server(server_name);
|
std::string serverpath = localpath::server(server_name);
|
||||||
return (serverpath.empty() ? "" : (fs::path(serverpath) / "server.json").string());
|
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 service_env(const std::string &server_name, const std::string &service_name) {
|
||||||
std::string servicepath = localpath::service(server_name, service_name);
|
std::string servicepath = localpath::service(server_name, service_name);
|
||||||
return (servicepath.empty() ? "" : (fs::path(servicepath) / "service.env").string());
|
return (servicepath.empty() ? "" : (fs::path(servicepath) / filenames::service_env).string());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string template_info_env(const std::string &server_name, const std::string &service_name)
|
std::string template_info_env(const std::string &server_name, const std::string &service_name)
|
||||||
{
|
{
|
||||||
std::string servicepath = localpath::service(server_name, service_name);
|
std::string servicepath = localpath::service(server_name, service_name);
|
||||||
return (servicepath.empty() ? "" : (fs::path(servicepath) / ".template_info.env").string());
|
return (servicepath.empty() ? "" : (fs::path(servicepath) / filenames::template_info_env).string());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string template_example()
|
std::string template_example()
|
||||||
@ -165,7 +165,7 @@ namespace localpath {
|
|||||||
|
|
||||||
std::string remotefile::service_env(const std::string &service_name) const
|
std::string remotefile::service_env(const std::string &service_name) const
|
||||||
{
|
{
|
||||||
return remotepath(mServer_name,mUser).service_config(service_name) + "/service.env";
|
return remotepath(mServer_name,mUser).service_config(service_name) + "/" + filenames::service_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -218,12 +218,6 @@ namespace localpath {
|
|||||||
return (dsp.empty() ? "" : (dsp + "/agent"));
|
return (dsp.empty() ? "" : (dsp + "/agent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::string remotepath::service_env(const std::string &service_name) const
|
|
||||||
// {
|
|
||||||
// std::string service_path = service_config(service_name);
|
|
||||||
// return (service_path.empty() ? "" : (service_path + "/service.env"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
// Utility functions
|
// Utility functions
|
||||||
|
@ -44,7 +44,13 @@ namespace dropshell {
|
|||||||
// |-- .template_info.env
|
// |-- .template_info.env
|
||||||
// |-- (...other config files for specific server&service...)
|
// |-- (...other config files for specific server&service...)
|
||||||
|
|
||||||
|
namespace filenames {
|
||||||
|
static const std::string template_info_env = ".template_info.env";
|
||||||
|
static const std::string service_env = "service.env";
|
||||||
|
static const std::string readme = "README.txt";
|
||||||
|
static const std::string server_json = "server.json";
|
||||||
|
static const std::string dropshell_json = "dropshell.json";
|
||||||
|
} // namespace filenames.
|
||||||
|
|
||||||
namespace localfile {
|
namespace localfile {
|
||||||
// ~/.config/dropshell/dropshell.json
|
// ~/.config/dropshell/dropshell.json
|
||||||
|
@ -54,13 +54,12 @@ bool execute_ssh_command(const sSSHInfo & ssh_info, const sCommand & remote_comm
|
|||||||
// class to hold a command to run on the remote server.
|
// class to hold a command to run on the remote server.
|
||||||
class sCommand {
|
class sCommand {
|
||||||
public:
|
public:
|
||||||
sCommand(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars, bool requires_root = false) :
|
sCommand(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars) :
|
||||||
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars), mRequiresRoot(requires_root) {}
|
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars) {}
|
||||||
|
|
||||||
std::string get_directory_to_run_in() const { return mDir; }
|
std::string get_directory_to_run_in() const { return mDir; }
|
||||||
std::string get_command_to_run() const { return mCmd; }
|
std::string get_command_to_run() const { return mCmd; }
|
||||||
const std::map<std::string, std::string>& get_env_vars() const { return mVars; }
|
const std::map<std::string, std::string>& get_env_vars() const { return mVars; }
|
||||||
bool requires_root() const { return mRequiresRoot; }
|
|
||||||
|
|
||||||
void add_env_var(const std::string& key, const std::string& value) { mVars[key] = value; }
|
void add_env_var(const std::string& key, const std::string& value) { mVars[key] = value; }
|
||||||
|
|
||||||
@ -72,7 +71,6 @@ class sCommand {
|
|||||||
std::string makesafecmd(std::string bb64path, const std::string& command) const;
|
std::string makesafecmd(std::string bb64path, const std::string& command) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mRequiresRoot;
|
|
||||||
std::string mDir;
|
std::string mDir;
|
||||||
std::string mCmd;
|
std::string mCmd;
|
||||||
std::map<std::string, std::string> mVars;
|
std::map<std::string, std::string> mVars;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user