...
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled

This commit is contained in:
Your Name
2025-05-24 11:15:23 +12:00
parent e1c631dc72
commit 0934179053
17 changed files with 523 additions and 366 deletions

View File

@ -74,7 +74,7 @@ namespace dropshell
return true; // nothing to back up.
}
std::string user = server_env.get_user_for_service(server, service);
std::string user = server_env.get_user_for_service(service);
// Check if basic installed stuff is in place.
std::string remote_service_template_path = remotepath(server, user).service_template(service);
@ -135,7 +135,7 @@ namespace dropshell
}
// Copy backup file from server to local
if (!shared_commands::scp_file_from_remote(server_env, remote_backup_file_path, local_backup_file_path, false))
if (!shared_commands::scp_file_from_remote(server_env, remote_backup_file_path, local_backup_file_path, false, sinfo.user))
{
error << "Failed to copy backup file from server" << std::endl;
return false;

View File

@ -67,96 +67,177 @@ namespace dropshell
namespace shared_commands
{
bool print_readme(const template_info &tinfo, std::string server, std::string service)
{
std::vector<std::string> variants_to_try = {"README.txt", "readme.txt", "ReadMe.txt", "README", "readme", "README.md", "readme.md"};
std::filesystem::path readme_path = tinfo.local_template_path();
for (const auto &variant : variants_to_try)
bool print_readme(const template_info &tinfo, std::string server, std::string service)
{
if (std::filesystem::exists(readme_path / variant))
std::vector<std::string> variants_to_try = {"README.txt", "readme.txt", "ReadMe.txt", "README", "readme", "README.md", "readme.md"};
std::filesystem::path readme_path = tinfo.local_template_path();
for (const auto &variant : variants_to_try)
{
readme_path = readme_path / variant;
break;
if (std::filesystem::exists(readme_path / variant))
{
readme_path = readme_path / variant;
break;
}
}
}
if (!std::filesystem::exists(readme_path))
return false;
if (!std::filesystem::exists(readme_path))
return false;
std::map<std::string, std::string> all_env_vars;
get_all_service_env_vars(server, service, all_env_vars);
all_env_vars["LOCAL_CONFIG_PATH"] = localpath::service(server, service);
all_env_vars["LOCAL_TEMPLATE_PATH"] = tinfo.local_template_path().string();
std::map<std::string, std::string> all_env_vars;
get_all_service_env_vars(server, service, all_env_vars);
all_env_vars["LOCAL_CONFIG_PATH"] = localpath::service(server, service);
all_env_vars["LOCAL_TEMPLATE_PATH"] = tinfo.local_template_path().string();
info << std::endl;
std::ifstream readme_file(readme_path);
std::string line;
while (std::getline(readme_file, line))
{
rawout << substitute_provided_key_value_pairs(line, all_env_vars) << std::endl;
}
return true;
}
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name)
{
if (server_name.empty() || template_name.empty() || service_name.empty())
return false;
std::string service_dir = localpath::service(server_name, service_name);
if (service_dir.empty())
{
error << "Couldn't locate server " << server_name << " in any config directory" << std::endl;
info << "Please check the server name is correct and try again" << std::endl;
info << "You can list all servers with 'dropshell servers'" << std::endl;
info << "You can create a new server with 'dropshell create-server " << server_name << "'" << std::endl;
return false;
}
if (std::filesystem::exists(service_dir))
{
error << "Service already exists: " << service_name << std::endl;
debug << "Current service path: " << service_dir << std::endl;
return false;
}
template_info tinfo = gTemplateManager().get_template_info(template_name);
if (!tinfo.is_set())
{
error << "Template '" << template_name << "' not found" << std::endl;
info << "Please check the template name is correct and try again" << std::endl;
info << "You can list all templates with 'dropshell templates'" << std::endl;
info << "You can create a new template with 'dropshell create-template " << template_name << "'" << std::endl;
return false;
}
// check template is all good.
if (!gTemplateManager().test_template(tinfo.local_template_path()))
{
error << "Template '" << template_name << "' is not valid" << std::endl;
return false;
}
// create the service directory
std::filesystem::create_directory(service_dir);
// copy the template config files to the service directory
recursive_copy(tinfo.local_template_path() / "config", service_dir);
info << "Service " << service_name << " created successfully" << std::endl;
if (!print_readme(tinfo, server_name, service_name))
{
info << std::endl;
info << "To complete the installation, please:" << std::endl;
info << "1. edit the service config file: dropshell edit " << server_name << " " << service_name << std::endl;
info << "2. install the remote service: dropshell install " << server_name << " " << service_name << std::endl;
std::ifstream readme_file(readme_path);
std::string line;
while (std::getline(readme_file, line))
{
rawout << substitute_provided_key_value_pairs(line, all_env_vars) << std::endl;
}
return true;
}
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, std::string user_override/*=""*/)
{
if (server_name.empty() || template_name.empty() || service_name.empty())
return false;
server_config server_info(server_name);
if (!server_info.is_valid())
{
error << "Server " << server_name << " is not valid" << std::endl;
return false;
}
std::string service_dir = localpath::service(server_name, service_name);
if (service_dir.empty())
{
error << "Couldn't locate server " << server_name << " in any config directory" << std::endl;
info << "Please check the server name is correct and try again" << std::endl;
info << "You can list all servers with 'dropshell servers'" << std::endl;
info << "You can create a new server with 'dropshell create-server " << server_name << "'" << std::endl;
return false;
}
if (std::filesystem::exists(service_dir))
{
error << "Service already exists: " << service_name << std::endl;
debug << "Current service path: " << service_dir << std::endl;
return false;
}
template_info tinfo = gTemplateManager().get_template_info(template_name);
if (!tinfo.is_set())
{
error << "Template '" << template_name << "' not found" << std::endl;
info << "Please check the template name is correct and try again" << std::endl;
info << "You can list all templates with 'dropshell templates'" << std::endl;
info << "You can create a new template with 'dropshell create-template " << template_name << "'" << std::endl;
return false;
}
// check template is all good.
if (!gTemplateManager().test_template(tinfo.local_template_path()))
{
error << "Template '" << template_name << "' is not valid" << std::endl;
return false;
}
// create the service directory
std::filesystem::create_directory(service_dir);
// copy the template config files to the service directory
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::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();
// modify the SSH_USER to be nice.
// everything is created, so we can get the service info.
LocalServiceInfo service_info = get_service_info(server_name, service_name);
std::string sshuser = "root";
if (!user_override.empty())
sshuser = user_override;
else
if (!service_info.requires_host_root)
{ // find a non-root user.
auto users = server_info.get_users();
auto it = std::find_if(users.begin(), users.end(), [&sshuser](const UserConfig &user)
{ return user.user != "root"; });
if (it != users.end())
sshuser = it->user;
}
if (sshuser == "root" && !server_info.hasRootUser())
{
error << "Server " << server_name << " does not have a root user, but the service " << service_name << " requires it." << std::endl;
return false;
}
if (sshuser != "root" && service_info.requires_host_root)
{
error << "The service " << service_name << " requires a root user, but a non-root user was specified." << std::endl;
return false;
}
if (!server_info.hasUser(sshuser))
{
error << "User " << sshuser << "is not available on server " << server_name << std::endl;
return false;
}
info << "Setting SSH_USER to " << sshuser << " in 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";
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::string line;
while (std::getline(template_service_env_file_in, line))
{
if (line.find("SSH_USER") != std::string::npos)
line = "SSH_USER=" + sshuser;
service_env_file_out << line << std::endl;
}
template_service_env_file_in.close();
service_env_file_out.close();
}
// check docker.
if (service_info.requires_docker)
{
if (!server_info.hasDocker())
{
error << "Server " << server_name << " does not have docker, but the service " << service_name << " requires it." << std::endl;
return false;
}
if (service_info.requires_docker_root)
{
if (!server_info.hasRootDocker())
{
error << "Server " << server_name << " does not have a root docker, but the service " << service_name << " requires it." << std::endl;
return false;
}
}
}
info << "Service " << service_name << " created successfully" << std::endl;
if (!print_readme(tinfo, server_name, service_name))
{
info << std::endl;
info << "To complete the installation, please:" << std::endl;
info << "1. edit the service config file: dropshell edit " << server_name << " " << service_name << std::endl;
info << "2. install the remote service: dropshell install " << server_name << " " << service_name << std::endl;
}
return true;
}
return true;
}
} // namespace shared_commands

View File

@ -63,7 +63,7 @@ namespace dropshell
if (!SIvalid(service_info))
error << "Invalid service: " << service << std::endl;
std::string user = server_env.get_user_for_service(server, service);
std::string user = server_env.get_user_for_service(service);
if (server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))
{
// run the nuke script on the remote server if it exists.

View File

@ -88,7 +88,7 @@ namespace dropshell
}
// Create service directory
std::string user = server_env.get_user_for_service(server, service);
std::string user = server_env.get_user_for_service(service);
std::string remote_service_path = remotepath(server,user).service(service);
std::string mkdir_cmd = "mkdir -p " + quote(remote_service_path);
if (!execute_ssh_command(server_env.get_SSH_INFO(user), sCommand("", mkdir_cmd, {}), cMode::Silent))
@ -109,7 +109,7 @@ namespace dropshell
debug << "Copying: [LOCAL] " << tinfo.local_template_path() << std::endl
<< std::string(8, ' ') << "[REMOTE] " << remotepath(server,user).service_template(service) << "/" << std::endl;
if (!shared_commands::rsync_tree_to_remote(tinfo.local_template_path().string(), remotepath(server,user).service_template(service),
server_env, false))
server_env, false, service_info.user))
{
std::cerr << "Failed to copy template files using rsync" << std::endl;
return false;
@ -119,7 +119,7 @@ namespace dropshell
debug << "Copying: [LOCAL] " << localpath::service(server, service) << std::endl
<< std::string(8, ' ') << "[REMOTE] " << remotepath(server,user).service_config(service) << std::endl;
if (!shared_commands::rsync_tree_to_remote(localpath::service(server, service), remotepath(server,user).service_config(service),
server_env, false))
server_env, false, service_info.user))
{
std::cerr << "Failed to copy service files using rsync" << std::endl;
return false;
@ -273,7 +273,7 @@ namespace dropshell
// now create the agent.
// copy across from the local agent files.
info << "Copying local agent files to remote server... " << std::flush;
shared_commands::rsync_tree_to_remote(localpath::agent_remote(), agent_path, server, false);
shared_commands::rsync_tree_to_remote(localpath::agent_remote(), agent_path, server, false, user.user);
info << "done." << std::endl;
// run the agent installer. Can't use BB64 yet, as we're installing it on the remote server.

View File

@ -183,7 +183,7 @@ namespace dropshell
{ // create the new service
info << "3) Creating new service..." << std::endl;
if (!shared_commands::create_service(server, service_info.template_name, service))
if (!shared_commands::create_service(server, service_info.template_name, service, service_info.user))
return 1;
}
@ -196,14 +196,14 @@ namespace dropshell
{ // restore service from backup
info << "5) Restoring service data from backup..." << std::endl;
std::string user = server_env.get_user_for_service(server, service);
std::string user = server_env.get_user_for_service(service);
std::string remote_backups_dir = remotepath(server, user).backups();
std::string remote_backup_file_path = remote_backups_dir + "/" + backup_details->get_filename();
debug << "Copying backup file from local to server: " << local_backup_file_path << " -> " << remote_backup_file_path << std::endl;
// Copy backup file from local to server
if (!shared_commands::scp_file_to_remote(server_env, local_backup_file_path, remote_backup_file_path, false))
if (!shared_commands::scp_file_to_remote(server_env, local_backup_file_path, remote_backup_file_path, false, service_info.user))
{
error << "Failed to copy backup file from local to server" << std::endl;
return 1;

View File

@ -55,13 +55,14 @@ namespace dropshell
const std::string &local_path,
const std::string &remote_path,
const server_config &server_env,
bool silent)
bool silent,
std::string user)
{
ASSERT(!local_path.empty() && !remote_path.empty(), "Local or remote path not specified. Can't rsync.");
std::string rsync_cmd = "rsync --delete --mkpath -zrpc -e 'ssh -p " + server_env.get_SSH_PORT() + "' " +
quote(local_path + "/") + " " +
quote(server_env.get_SSH_UNPRIVILEGED_USER() + "@" + server_env.get_SSH_HOST() + ":" +
quote(user + "@" + server_env.get_SSH_HOST() + ":" +
remote_path + "/");
return execute_local_command("", rsync_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
}
@ -222,7 +223,7 @@ namespace dropshell
return HealthStatus::ERROR;
}
std::string user = env.get_user_for_service(server, service);
std::string user = env.get_user_for_service(service);
if (!env.check_remote_dir_exists(remotepath(server,user).service(service), user))
{
@ -308,7 +309,7 @@ namespace dropshell
// ------------------------------------------------------------------------------------------------
// scp_file_to_remote : SHARED COMMAND
// ------------------------------------------------------------------------------------------------
bool scp_file_to_remote(const server_config &server_env, const std::string &local_path, const std::string &remote_path, bool silent)
bool scp_file_to_remote(const server_config &server_env, const std::string &local_path, const std::string &remote_path, bool silent, std::string user)
{
if (!server_env.is_valid())
{
@ -316,14 +317,14 @@ namespace dropshell
return false;
}
ASSERT(!remote_path.empty() && !local_path.empty(), "Remote or local path not specified. Can't scp.");
std::string scp_cmd = "scp -P " + server_env.get_SSH_PORT() + " " + quote(local_path) + " " + server_env.get_SSH_UNPRIVILEGED_USER() + "@" + server_env.get_SSH_HOST() + ":" + quote(remote_path) + (silent ? " > /dev/null 2>&1" : "");
std::string scp_cmd = "scp -P " + server_env.get_SSH_PORT() + " " + quote(local_path) + " " + user + "@" + server_env.get_SSH_HOST() + ":" + quote(remote_path) + (silent ? " > /dev/null 2>&1" : "");
return execute_local_command("", scp_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
}
// ------------------------------------------------------------------------------------------------
// scp_file_from_remote : SHARED COMMAND
// ------------------------------------------------------------------------------------------------
bool scp_file_from_remote(const server_config &server_env, const std::string &remote_path, const std::string &local_path, bool silent)
bool scp_file_from_remote(const server_config &server_env, const std::string &remote_path, const std::string &local_path, bool silent, std::string user)
{
if (!server_env.is_valid())
{
@ -331,7 +332,7 @@ namespace dropshell
return false;
}
ASSERT(!remote_path.empty() && !local_path.empty(), "Remote or local path not specified. Can't scp.");
std::string scp_cmd = "scp -P " + server_env.get_SSH_PORT() + " " + server_env.get_SSH_UNPRIVILEGED_USER() + "@" + server_env.get_SSH_HOST() + ":" + quote(remote_path) + " " + quote(local_path) + (silent ? " > /dev/null 2>&1" : "");
std::string scp_cmd = "scp -P " + server_env.get_SSH_PORT() + " " + user + "@" + server_env.get_SSH_HOST() + ":" + quote(remote_path) + " " + quote(local_path) + (silent ? " > /dev/null 2>&1" : "");
return execute_local_command("", scp_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
}

View File

@ -44,7 +44,8 @@ namespace dropshell
const std::string &local_path,
const std::string &remote_path,
const server_config &server_env,
bool silent);
bool silent,
std::string user);
std::string get_arch();
@ -80,8 +81,8 @@ namespace dropshell
std::string mDatetime;
};
bool scp_file_to_remote(const server_config &server_env, const std::string &local_path, const std::string &remote_path, bool silent);
bool scp_file_from_remote(const server_config &server_env, const std::string &remote_path, const std::string &local_path, bool silent);
bool scp_file_to_remote(const server_config &server_env, const std::string &local_path, const std::string &remote_path, bool silent, std::string user);
bool scp_file_from_remote(const server_config &server_env, const std::string &remote_path, const std::string &local_path, bool silent, std::string user);
// defined in backupdata.cpp, used by restoredata.cpp.
bool backupdata_service(const server_config &server_env, const std::string& service);
@ -96,7 +97,7 @@ namespace dropshell
bool install_service(const server_config &server_env, const std::string &service);
// defined in create-service.cpp
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name);
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, std::string user_override="");
} // namespace shared_commands
} // namespace dropshell

View File

@ -48,7 +48,7 @@ namespace dropshell
std::string server = server_env.get_server_name();
maketitle("Uninstalling " + service + " on " + server);
std::string user = server_env.get_user_for_service(server, service);
std::string user = server_env.get_user_for_service(service);
// 2. Check if service directory exists on server
if (!server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))