dropshell release 2025.0524.1149
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 17s

This commit is contained in:
Your Name 2025-05-24 11:49:24 +12:00
parent 0934179053
commit 763293c7d0
10 changed files with 64 additions and 60 deletions

View File

@ -1,5 +1,5 @@
SSH_ADDRESS=localhost
SSH_PORT=22
SSH_USER=$(whoami)
SSH_UNPRIVILEGED_USER=$(whoami)

View File

@ -152,7 +152,7 @@ namespace dropshell
recursive_copy(tinfo.local_template_path() / "config", service_dir);
// 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);
template_info_env_file_out << "TEMPLATE_HASH=" << tinfo.hash() << std::endl;
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.
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);
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;
while (std::getline(template_service_env_file_in, line))
{
@ -239,6 +239,23 @@ namespace dropshell
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 dropshell

View File

@ -70,6 +70,15 @@ namespace dropshell
if (!SIvalid(service_info))
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);

View File

@ -98,6 +98,7 @@ namespace dropshell
// 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 merge_updated_service_template(const std::string &server_name, const std::string &service_name);
} // namespace shared_commands
} // namespace dropshell

View File

@ -28,23 +28,22 @@ namespace dropshell
if (server_name.empty())
return;
// Construct the full path to server.json
std::string server_env_path = localfile::server_json(server_name);
std::string server_json_path = localfile::server_json(server_name);
// 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;
}
try
{
// 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())
{
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;
return;
}
@ -96,7 +95,7 @@ namespace dropshell
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;
}
@ -104,7 +103,7 @@ namespace dropshell
}
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;
mValid = false;
@ -334,30 +333,10 @@ namespace dropshell
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(
remote_service_template_path,
quote(script_path) + argstr + (silent ? " > /dev/null 2>&1" : ""),
env_vars,
run_as_root);
env_vars);
if (sc.empty())
{
@ -427,7 +406,7 @@ namespace dropshell
// 3. create a template server.env file in the server directory
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);
server_env_file << "{" << std::endl;
server_env_file << " \"SSH_HOST\": \"" << server_name << "\"," << std::endl;

View File

@ -67,7 +67,7 @@ namespace dropshell
auto it = variables.find(variable_name);
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 it->second == "true";
@ -237,7 +237,7 @@ namespace dropshell
if (user.empty())
{
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;
return false;
}
@ -256,7 +256,7 @@ namespace dropshell
{
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 << "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
<< std::endl;
return false;

View File

@ -220,9 +220,9 @@
// modify the TEMPLATE=example line in the .template_info.env file to TEMPLATE=<template_name>
std::string search_string = "TEMPLATE=";
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)) {
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;
}
@ -306,8 +306,8 @@
std::string template_name = std::filesystem::path(template_path).filename().string();
std::vector<std::string> required_files = {
"config/service.env",
"config/.template_info.env",
"config/" + filenames::service_env,
"config/" + filenames::template_info_env,
"install.sh",
"uninstall.sh"
};
@ -331,8 +331,8 @@
// check TEMPLATE= line.
std::map<std::string, std::string> all_env_vars;
std::vector<std::string> env_files = {
"config/service.env",
"config/.template_info.env"
"config/" + filenames::service_env,
"config/" + filenames::template_info_env
};
for (const auto& file : env_files) {
{ // load service.env from the service on this machine.

View File

@ -19,7 +19,7 @@ namespace localfile {
// Try ~/.config/dropshell/dropshell.json
std::string homedir = localpath::current_user_home();
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 std::string();
@ -27,18 +27,18 @@ namespace localfile {
std::string server_json(const std::string &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 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 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()
@ -165,7 +165,7 @@ namespace localpath {
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"));
}
// 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

View File

@ -44,7 +44,13 @@ namespace dropshell {
// |-- .template_info.env
// |-- (...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 {
// ~/.config/dropshell/dropshell.json

View File

@ -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 sCommand {
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) :
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars), mRequiresRoot(requires_root) {}
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) {}
std::string get_directory_to_run_in() const { return mDir; }
std::string get_command_to_run() const { return mCmd; }
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; }
@ -72,7 +71,6 @@ class sCommand {
std::string makesafecmd(std::string bb64path, const std::string& command) const;
private:
bool mRequiresRoot;
std::string mDir;
std::string mCmd;
std::map<std::string, std::string> mVars;