This commit is contained in:
parent
e1c631dc72
commit
0934179053
@ -23,7 +23,6 @@ SCRIPT_DIR="$(dirname "$0")"
|
|||||||
# // |-- service.env (actual service config)
|
# // |-- service.env (actual service config)
|
||||||
# // |-- .template_info.env
|
# // |-- .template_info.env
|
||||||
# // |-- template
|
# // |-- template
|
||||||
# // |-- _default.env
|
|
||||||
# // |-- (script files)
|
# // |-- (script files)
|
||||||
# // |-- config
|
# // |-- config
|
||||||
# // |-- service.env (default service config)
|
# // |-- service.env (default service config)
|
||||||
@ -66,7 +65,6 @@ function run_command() {
|
|||||||
CURRENT_OUTPUT=$(
|
CURRENT_OUTPUT=$(
|
||||||
set -a
|
set -a
|
||||||
|
|
||||||
load_dotenv "${service_path}/template/_default.env"
|
|
||||||
load_dotenv "${service_path}/config/service.env"
|
load_dotenv "${service_path}/config/service.env"
|
||||||
load_dotenv "${service_path}/config/.template_info.env"
|
load_dotenv "${service_path}/config/.template_info.env"
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ namespace dropshell
|
|||||||
return true; // nothing to back up.
|
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.
|
// Check if basic installed stuff is in place.
|
||||||
std::string remote_service_template_path = remotepath(server, user).service_template(service);
|
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
|
// 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;
|
error << "Failed to copy backup file from server" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -67,7 +67,6 @@ namespace dropshell
|
|||||||
namespace shared_commands
|
namespace shared_commands
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
bool print_readme(const template_info &tinfo, std::string server, std::string service)
|
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::vector<std::string> variants_to_try = {"README.txt", "readme.txt", "ReadMe.txt", "README", "readme", "README.md", "readme.md"};
|
||||||
@ -99,12 +98,18 @@ namespace dropshell
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|
||||||
{
|
{
|
||||||
if (server_name.empty() || template_name.empty() || service_name.empty())
|
if (server_name.empty() || template_name.empty() || service_name.empty())
|
||||||
return false;
|
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);
|
std::string service_dir = localpath::service(server_name, service_name);
|
||||||
|
|
||||||
if (service_dir.empty())
|
if (service_dir.empty())
|
||||||
@ -146,6 +151,82 @@ namespace dropshell
|
|||||||
// copy the template config files to the service directory
|
// copy the template config files to the service directory
|
||||||
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
|
||||||
|
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;
|
info << "Service " << service_name << " created successfully" << std::endl;
|
||||||
|
|
||||||
if (!print_readme(tinfo, server_name, service_name))
|
if (!print_readme(tinfo, server_name, service_name))
|
||||||
|
@ -63,7 +63,7 @@ namespace dropshell
|
|||||||
if (!SIvalid(service_info))
|
if (!SIvalid(service_info))
|
||||||
error << "Invalid service: " << service << std::endl;
|
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))
|
if (server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))
|
||||||
{
|
{
|
||||||
// run the nuke script on the remote server if it exists.
|
// run the nuke script on the remote server if it exists.
|
||||||
|
@ -88,7 +88,7 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create service directory
|
// 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 remote_service_path = remotepath(server,user).service(service);
|
||||||
std::string mkdir_cmd = "mkdir -p " + quote(remote_service_path);
|
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))
|
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
|
debug << "Copying: [LOCAL] " << tinfo.local_template_path() << std::endl
|
||||||
<< std::string(8, ' ') << "[REMOTE] " << remotepath(server,user).service_template(service) << "/" << 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),
|
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;
|
std::cerr << "Failed to copy template files using rsync" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -119,7 +119,7 @@ namespace dropshell
|
|||||||
debug << "Copying: [LOCAL] " << localpath::service(server, service) << std::endl
|
debug << "Copying: [LOCAL] " << localpath::service(server, service) << std::endl
|
||||||
<< std::string(8, ' ') << "[REMOTE] " << remotepath(server,user).service_config(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),
|
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;
|
std::cerr << "Failed to copy service files using rsync" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -273,7 +273,7 @@ namespace dropshell
|
|||||||
// now create the agent.
|
// now create the agent.
|
||||||
// copy across from the local agent files.
|
// copy across from the local agent files.
|
||||||
info << "Copying local agent files to remote server... " << std::flush;
|
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;
|
info << "done." << std::endl;
|
||||||
|
|
||||||
// run the agent installer. Can't use BB64 yet, as we're installing it on the remote server.
|
// run the agent installer. Can't use BB64 yet, as we're installing it on the remote server.
|
||||||
|
@ -183,7 +183,7 @@ namespace dropshell
|
|||||||
|
|
||||||
{ // create the new service
|
{ // create the new service
|
||||||
info << "3) Creating new service..." << std::endl;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,14 +196,14 @@ namespace dropshell
|
|||||||
|
|
||||||
{ // restore service from backup
|
{ // restore service from backup
|
||||||
info << "5) Restoring service data from backup..." << std::endl;
|
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_backups_dir = remotepath(server, user).backups();
|
||||||
std::string remote_backup_file_path = remote_backups_dir + "/" + backup_details->get_filename();
|
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;
|
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
|
// 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;
|
error << "Failed to copy backup file from local to server" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -55,13 +55,14 @@ namespace dropshell
|
|||||||
const std::string &local_path,
|
const std::string &local_path,
|
||||||
const std::string &remote_path,
|
const std::string &remote_path,
|
||||||
const server_config &server_env,
|
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.");
|
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() + "' " +
|
std::string rsync_cmd = "rsync --delete --mkpath -zrpc -e 'ssh -p " + server_env.get_SSH_PORT() + "' " +
|
||||||
quote(local_path + "/") + " " +
|
quote(local_path + "/") + " " +
|
||||||
quote(server_env.get_SSH_UNPRIVILEGED_USER() + "@" + server_env.get_SSH_HOST() + ":" +
|
quote(user + "@" + server_env.get_SSH_HOST() + ":" +
|
||||||
remote_path + "/");
|
remote_path + "/");
|
||||||
return execute_local_command("", rsync_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
|
return execute_local_command("", rsync_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
|
||||||
}
|
}
|
||||||
@ -222,7 +223,7 @@ namespace dropshell
|
|||||||
return HealthStatus::ERROR;
|
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))
|
if (!env.check_remote_dir_exists(remotepath(server,user).service(service), user))
|
||||||
{
|
{
|
||||||
@ -308,7 +309,7 @@ namespace dropshell
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// scp_file_to_remote : SHARED COMMAND
|
// 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())
|
if (!server_env.is_valid())
|
||||||
{
|
{
|
||||||
@ -316,14 +317,14 @@ namespace dropshell
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(!remote_path.empty() && !local_path.empty(), "Remote or local path not specified. Can't scp.");
|
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));
|
return execute_local_command("", scp_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// scp_file_from_remote : SHARED COMMAND
|
// 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())
|
if (!server_env.is_valid())
|
||||||
{
|
{
|
||||||
@ -331,7 +332,7 @@ namespace dropshell
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(!remote_path.empty() && !local_path.empty(), "Remote or local path not specified. Can't scp.");
|
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));
|
return execute_local_command("", scp_cmd, {}, nullptr, (silent ? cMode::Silent : cMode::Defaults));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@ namespace dropshell
|
|||||||
const std::string &local_path,
|
const std::string &local_path,
|
||||||
const std::string &remote_path,
|
const std::string &remote_path,
|
||||||
const server_config &server_env,
|
const server_config &server_env,
|
||||||
bool silent);
|
bool silent,
|
||||||
|
std::string user);
|
||||||
|
|
||||||
std::string get_arch();
|
std::string get_arch();
|
||||||
|
|
||||||
@ -80,8 +81,8 @@ namespace dropshell
|
|||||||
std::string mDatetime;
|
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_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);
|
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.
|
// defined in backupdata.cpp, used by restoredata.cpp.
|
||||||
bool backupdata_service(const server_config &server_env, const std::string& service);
|
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);
|
bool install_service(const server_config &server_env, const std::string &service);
|
||||||
|
|
||||||
// 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);
|
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 shared_commands
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
||||||
|
@ -48,7 +48,7 @@ namespace dropshell
|
|||||||
std::string server = server_env.get_server_name();
|
std::string server = server_env.get_server_name();
|
||||||
maketitle("Uninstalling " + service + " on " + server);
|
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
|
// 2. Check if service directory exists on server
|
||||||
if (!server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))
|
if (!server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))
|
||||||
|
@ -49,7 +49,7 @@ namespace dropshell
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the variables from the json
|
// get the variables from the json, converting everything to strings.
|
||||||
for (const auto &var : server_env_json.items())
|
for (const auto &var : server_env_json.items())
|
||||||
{
|
{
|
||||||
std::string value;
|
std::string value;
|
||||||
@ -111,35 +111,19 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool server_config::create_server_json_file(const std::string &server_env_path, const std::string &SSH_HOST, const std::string &SSH_PORT, const std::vector<UserConfig> &users)
|
std::string server_config::get_SSH_HOST() const
|
||||||
{
|
{
|
||||||
nlohmann::json server_env_json;
|
return get_variable("SSH_HOST");
|
||||||
server_env_json["SSH_HOST"] = SSH_HOST;
|
}
|
||||||
server_env_json["SSH_PORT"] = std::stoi(SSH_PORT);
|
|
||||||
|
|
||||||
// Create users array
|
std::string server_config::get_SSH_PORT() const
|
||||||
nlohmann::json users_array = nlohmann::json::array();
|
|
||||||
for (const auto &user : users)
|
|
||||||
{
|
{
|
||||||
nlohmann::json user_json;
|
return get_variable("SSH_PORT");
|
||||||
user_json["USER"] = user.user;
|
|
||||||
user_json["DIR"] = user.dir;
|
|
||||||
users_array.push_back(user_json);
|
|
||||||
}
|
}
|
||||||
server_env_json["SSH_USERS"] = users_array;
|
|
||||||
|
|
||||||
try
|
std::vector<UserConfig> server_config::get_users() const
|
||||||
{
|
{
|
||||||
std::ofstream server_env_file(server_env_path);
|
return mUsers;
|
||||||
server_env_file << server_env_json.dump(4);
|
|
||||||
server_env_file.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to create server environment file: " + std::string(e.what()) << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string server_config::get_user_dir(const std::string &user) const
|
std::string server_config::get_user_dir(const std::string &user) const
|
||||||
@ -154,22 +138,24 @@ namespace dropshell
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string server_config::get_user_for_service(const std::string &server, const std::string &service)
|
std::string server_config::get_server_name() const
|
||||||
|
{
|
||||||
|
return mServerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string server_config::get_user_for_service(const std::string &service) const
|
||||||
|
{
|
||||||
|
return dropshell::get_user_for_service(mServerName, service);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_user_for_service(const std::string &server, const std::string &service)
|
||||||
{
|
{
|
||||||
auto services_info = get_server_services_info(server);
|
auto services_info = get_server_services_info(server);
|
||||||
if (std::find_if(services_info.begin(), services_info.end(),
|
|
||||||
[&service](const LocalServiceInfo &si)
|
|
||||||
{ return si.service_name == service; }) != services_info.end())
|
|
||||||
{
|
|
||||||
// found a service with matching name.
|
|
||||||
auto it = std::find_if(services_info.begin(), services_info.end(),
|
auto it = std::find_if(services_info.begin(), services_info.end(),
|
||||||
[&service](const LocalServiceInfo &si)
|
[&service](const LocalServiceInfo &si)
|
||||||
{ return si.service_name == service; });
|
{ return si.service_name == service; });
|
||||||
if (it != services_info.end())
|
if (it != services_info.end() && SIvalid(*it))
|
||||||
{
|
|
||||||
return it->user;
|
return it->user;
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +170,31 @@ namespace dropshell
|
|||||||
return sSSHInfo(get_SSH_HOST(), it->user, get_SSH_PORT(), get_server_name(), it->dir);
|
return sSSHInfo(get_SSH_HOST(), it->user, get_SSH_PORT(), get_server_name(), it->dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool server_config::hasRootUser() const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(mUsers.begin(), mUsers.end(),[](const UserConfig &u)
|
||||||
|
{ return u.user == "root"; });
|
||||||
|
return it != mUsers.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool server_config::hasDocker() const
|
||||||
|
{
|
||||||
|
return get_variable("HAS_DOCKER") == "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool server_config::hasRootDocker() const
|
||||||
|
{
|
||||||
|
return get_variable("DOCKER_ROOTLESS") == "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool server_config::hasUser(const std::string &user) const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(mUsers.begin(), mUsers.end(),
|
||||||
|
[&user](const UserConfig &u)
|
||||||
|
{ return u.user == user; });
|
||||||
|
return it != mUsers.end();
|
||||||
|
}
|
||||||
|
|
||||||
bool server_config::check_remote_dir_exists(const std::string &dir_path, std::string user) const
|
bool server_config::check_remote_dir_exists(const std::string &dir_path, std::string user) const
|
||||||
{
|
{
|
||||||
sCommand scommand("", "test -d " + quote(dir_path), {});
|
sCommand scommand("", "test -d " + quote(dir_path), {});
|
||||||
@ -255,7 +266,7 @@ namespace dropshell
|
|||||||
bool silent,
|
bool silent,
|
||||||
std::map<std::string, std::string> extra_env_vars) const
|
std::map<std::string, std::string> extra_env_vars) const
|
||||||
{
|
{
|
||||||
std::string user = get_user_for_service(mServerName, service_name);
|
std::string user = get_user_for_service(service_name);
|
||||||
auto scommand = construct_standard_template_run_cmd(service_name, command, args, silent);
|
auto scommand = construct_standard_template_run_cmd(service_name, command, args, silent);
|
||||||
if (!scommand.has_value())
|
if (!scommand.has_value())
|
||||||
return false;
|
return false;
|
||||||
@ -278,7 +289,7 @@ namespace dropshell
|
|||||||
bool silent,
|
bool silent,
|
||||||
std::map<std::string, std::string> extra_env_vars) const
|
std::map<std::string, std::string> extra_env_vars) const
|
||||||
{
|
{
|
||||||
std::string user = get_user_for_service(mServerName, service_name);
|
std::string user = get_user_for_service(service_name);
|
||||||
auto scommand = construct_standard_template_run_cmd(service_name, command, args, false);
|
auto scommand = construct_standard_template_run_cmd(service_name, command, args, false);
|
||||||
if (!scommand.has_value())
|
if (!scommand.has_value())
|
||||||
return false;
|
return false;
|
||||||
@ -305,7 +316,7 @@ namespace dropshell
|
|||||||
if (command.empty())
|
if (command.empty())
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
std::string user = get_user_for_service(mServerName, service_name);
|
std::string user = get_user_for_service(service_name);
|
||||||
|
|
||||||
std::string remote_service_template_path = remotepath(mServerName, user).service_template(service_name);
|
std::string remote_service_template_path = remotepath(mServerName, user).service_template(service_name);
|
||||||
std::string script_path = remote_service_template_path + "/" + command + ".sh";
|
std::string script_path = remote_service_template_path + "/" + command + ".sh";
|
||||||
@ -336,9 +347,9 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
bool run_as_root = runas == "root";
|
bool run_as_root = runas == "root";
|
||||||
|
|
||||||
if (run_as_root && !get_ALLOW_ROOT_SERVICES())
|
if (run_as_root && !hasRootUser())
|
||||||
{
|
{
|
||||||
error << "Error: The service " << service_name << " is set to run as root, but the server environment does not allow root services." << std::endl;
|
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;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,30 +37,33 @@ namespace dropshell
|
|||||||
public:
|
public:
|
||||||
server_config(const std::string &server_name);
|
server_config(const std::string &server_name);
|
||||||
|
|
||||||
static bool create_server_json_file(
|
bool is_valid() const { return mValid; }
|
||||||
const std::string &server_env_path,
|
|
||||||
const std::string &SSH_HOST,
|
|
||||||
const std::string &SSH_PORT,
|
|
||||||
const std::vector<UserConfig> &users);
|
|
||||||
|
|
||||||
std::string get_variable(const std::string &name) const;
|
|
||||||
|
|
||||||
// trivial getters.
|
// trivial getters.
|
||||||
const std::map<std::string, std::string> &get_variables() const { return mVariables; }
|
const std::map<std::string, std::string> &get_variables() const { return mVariables; }
|
||||||
std::string get_SSH_HOST() const { return get_variable("SSH_HOST"); }
|
std::string get_variable(const std::string &name) const;
|
||||||
std::string get_SSH_PORT() const { return get_variable("SSH_PORT"); }
|
|
||||||
std::string get_SSH_UNPRIVILEGED_USER() const { return get_variable("SSH_UNPRIVILEGED_USER"); }
|
|
||||||
bool get_ALLOW_ROOT_SERVICES() const { return get_variable("ALLOW_ROOT_SERVICES") == "true"; }
|
|
||||||
std::vector<UserConfig> get_users() const { return mUsers; }
|
|
||||||
std::string get_user_dir(const std::string &user) const;
|
|
||||||
bool is_valid() const { return mValid; }
|
|
||||||
std::string get_server_name() const { return mServerName; }
|
|
||||||
|
|
||||||
static std::string get_user_for_service(const std::string &server, const std::string &service);
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// getters
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
std::string get_SSH_HOST() const;
|
||||||
|
std::string get_SSH_PORT() const;
|
||||||
|
std::vector<UserConfig> get_users() const;
|
||||||
|
std::string get_user_dir(const std::string &user) const;
|
||||||
|
std::string get_server_name() const;
|
||||||
|
std::string get_user_for_service(const std::string &service) const;
|
||||||
|
|
||||||
sSSHInfo get_SSH_INFO(std::string user) const;
|
sSSHInfo get_SSH_INFO(std::string user) const;
|
||||||
|
|
||||||
|
// server capabilities
|
||||||
|
bool hasRootUser() const;
|
||||||
|
bool hasDocker() const;
|
||||||
|
bool hasRootDocker() const;
|
||||||
|
|
||||||
// helper functions
|
// helper functions
|
||||||
|
bool hasUser(const std::string &user) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool check_remote_dir_exists(const std::string &dir_path, std::string user) const;
|
bool check_remote_dir_exists(const std::string &dir_path, std::string user) const;
|
||||||
bool check_remote_file_exists(const std::string &file_path, std::string user) const;
|
bool check_remote_file_exists(const std::string &file_path, std::string user) const;
|
||||||
@ -84,8 +87,12 @@ namespace dropshell
|
|||||||
bool mValid;
|
bool mValid;
|
||||||
}; // class server_config
|
}; // class server_config
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<server_config> get_configured_servers();
|
std::vector<server_config> get_configured_servers();
|
||||||
|
|
||||||
|
std::string get_user_for_service(const std::string &server, const std::string &service);
|
||||||
|
|
||||||
bool create_server(const std::string &server_name);
|
bool create_server(const std::string &server_name);
|
||||||
|
|
||||||
void get_all_used_commands(std::set<std::string> &commands);
|
void get_all_used_commands(std::set<std::string> &commands);
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
#include "templates.hpp"
|
#include "templates.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
#include "servers.hpp"
|
|
||||||
#include "servers.hpp"
|
|
||||||
#include "assert.hpp"
|
#include "assert.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -13,9 +11,12 @@
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell
|
||||||
|
{
|
||||||
|
|
||||||
bool SIvalid(const LocalServiceInfo& service_info) {
|
#pragma TODO : Smart test that the service is fully valid.
|
||||||
|
bool SIvalid(const LocalServiceInfo &service_info)
|
||||||
|
{
|
||||||
return !service_info.service_name.empty() &&
|
return !service_info.service_name.empty() &&
|
||||||
!service_info.template_name.empty() &&
|
!service_info.template_name.empty() &&
|
||||||
!service_info.local_service_path.empty() &&
|
!service_info.local_service_path.empty() &&
|
||||||
@ -23,24 +24,29 @@ namespace dropshell {
|
|||||||
!service_info.user.empty();
|
!service_info.user.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LocalServiceInfo> get_server_services_info(const std::string& server_name) {
|
std::vector<LocalServiceInfo> get_server_services_info(const std::string &server_name)
|
||||||
|
{
|
||||||
std::vector<LocalServiceInfo> services;
|
std::vector<LocalServiceInfo> services;
|
||||||
|
|
||||||
if (server_name.empty())
|
if (server_name.empty())
|
||||||
return services;
|
return services;
|
||||||
|
|
||||||
std::vector<std::string> local_server_definition_paths = gConfig().get_local_server_definition_paths();
|
std::vector<std::string> local_server_definition_paths = gConfig().get_local_server_definition_paths();
|
||||||
if (local_server_definition_paths.empty()) {
|
if (local_server_definition_paths.empty())
|
||||||
|
{
|
||||||
std::cerr << "Error: No local server definition paths found" << std::endl;
|
std::cerr << "Error: No local server definition paths found" << std::endl;
|
||||||
std::cerr << "Run 'dropshell edit' to configure DropShell" << std::endl;
|
std::cerr << "Run 'dropshell edit' to configure DropShell" << std::endl;
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& server_definition_path : local_server_definition_paths) {
|
for (const auto &server_definition_path : local_server_definition_paths)
|
||||||
|
{
|
||||||
fs::path serverpath = server_definition_path + "/" + server_name;
|
fs::path serverpath = server_definition_path + "/" + server_name;
|
||||||
if (fs::exists(serverpath)) // service is on that server...
|
if (fs::exists(serverpath)) // service is on that server...
|
||||||
for (const auto& entry : fs::directory_iterator(serverpath)) {
|
for (const auto &entry : fs::directory_iterator(serverpath))
|
||||||
if (fs::is_directory(entry)) {
|
{
|
||||||
|
if (fs::is_directory(entry))
|
||||||
|
{
|
||||||
std::string dirname = entry.path().filename().string();
|
std::string dirname = entry.path().filename().string();
|
||||||
if (dirname.empty() || dirname[0] == '.' || dirname[0] == '_')
|
if (dirname.empty() || dirname[0] == '.' || dirname[0] == '_')
|
||||||
continue;
|
continue;
|
||||||
@ -54,11 +60,21 @@ std::vector<LocalServiceInfo> get_server_services_info(const std::string& server
|
|||||||
}
|
}
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_bool_variable(const std::map<std::string, std::string> &variables, const std::string &variable_name)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return it->second == "true";
|
||||||
|
}
|
||||||
|
|
||||||
LocalServiceInfo get_service_info(const std::string &server_name, const std::string &service_name)
|
LocalServiceInfo get_service_info(const std::string &server_name, const std::string &service_name)
|
||||||
{
|
{
|
||||||
LocalServiceInfo service;
|
LocalServiceInfo service;
|
||||||
|
|
||||||
if (server_name.empty() || service_name.empty())
|
if (server_name.empty() || service_name.empty())
|
||||||
@ -82,50 +98,81 @@ LocalServiceInfo get_service_info(const std::string &server_name, const std::str
|
|||||||
if (!get_all_service_env_vars(server_name, service_name, variables))
|
if (!get_all_service_env_vars(server_name, service_name, variables))
|
||||||
return LocalServiceInfo();
|
return LocalServiceInfo();
|
||||||
|
|
||||||
// confirm TEMPLATE is defined.
|
{ // confirm TEMPLATE is defined.
|
||||||
auto it = variables.find("TEMPLATE");
|
auto it = variables.find("TEMPLATE");
|
||||||
if (it == variables.end()) {
|
if (it == variables.end())
|
||||||
std::cerr << "Error: TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
{
|
||||||
|
error << "Error: TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
return LocalServiceInfo();
|
return LocalServiceInfo();
|
||||||
}
|
}
|
||||||
service.template_name = it->second;
|
service.template_name = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
template_info tinfo = gTemplateManager().get_template_info(service.template_name);
|
template_info tinfo = gTemplateManager().get_template_info(service.template_name);
|
||||||
if (!tinfo.is_set()) {
|
if (!tinfo.is_set())
|
||||||
std::cerr << "Error: Template '" << service.template_name << "' not found" << std::endl;
|
{
|
||||||
|
error << "Template specified '" << service.template_name << "' could not be found" << std::endl;
|
||||||
return LocalServiceInfo();
|
return LocalServiceInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the template path
|
// find the template path
|
||||||
service.local_template_path = tinfo.local_template_path();
|
service.local_template_path = tinfo.local_template_path();
|
||||||
|
|
||||||
return service;
|
{ // set the user.
|
||||||
}
|
auto it = variables.find("SSH_USER");
|
||||||
|
if (it == variables.end())
|
||||||
|
{
|
||||||
|
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
|
return LocalServiceInfo();
|
||||||
|
}
|
||||||
|
service.user = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
std::set<std::string> get_used_commands(const std::string &server_name, const std::string &service_name)
|
// set the host root and docker requirements.
|
||||||
{
|
service.requires_host_root = get_bool_variable(variables, "REQUIRES_HOST_ROOT");
|
||||||
|
service.requires_docker = get_bool_variable(variables, "REQUIRES_DOCKER");
|
||||||
|
service.requires_docker_root = get_bool_variable(variables, "REQUIRES_DOCKER_ROOT");
|
||||||
|
|
||||||
|
{ // determine if the service template hash matches the template hash.
|
||||||
|
auto it = variables.find("TEMPLATE_HASH");
|
||||||
|
if (it == variables.end())
|
||||||
|
{
|
||||||
|
error << "TEMPLATE_HASH variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
|
return LocalServiceInfo();
|
||||||
|
}
|
||||||
|
uint64_t service_template_hash = std::stoull(it->second);
|
||||||
|
service.service_template_hash_match = (service_template_hash == tinfo.hash());
|
||||||
|
}
|
||||||
|
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::string> get_used_commands(const std::string &server_name, const std::string &service_name)
|
||||||
|
{
|
||||||
std::set<std::string> commands;
|
std::set<std::string> commands;
|
||||||
|
|
||||||
if (server_name.empty() || service_name.empty())
|
if (server_name.empty() || service_name.empty())
|
||||||
return commands;
|
return commands;
|
||||||
|
|
||||||
auto service_info = get_service_info(server_name, service_name);
|
auto service_info = get_service_info(server_name, service_name);
|
||||||
if (service_info.local_template_path.empty()) {
|
if (service_info.local_template_path.empty())
|
||||||
|
{
|
||||||
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate over all files in the template path, and add the command name to the set.
|
// iterate over all files in the template path, and add the command name to the set.
|
||||||
// commands are .sh files that don't begin with _
|
// commands are .sh files that don't begin with _
|
||||||
for (const auto& entry : fs::directory_iterator(service_info.local_template_path)) {
|
for (const auto &entry : fs::directory_iterator(service_info.local_template_path))
|
||||||
|
{
|
||||||
if (fs::is_regular_file(entry) && entry.path().extension() == ".sh" && (entry.path().filename().string().rfind("_", 0) != 0))
|
if (fs::is_regular_file(entry) && entry.path().extension() == ".sh" && (entry.path().filename().string().rfind("_", 0) != 0))
|
||||||
commands.insert(entry.path().stem().string());
|
commands.insert(entry.path().stem().string());
|
||||||
}
|
}
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<std::string> list_backups(const std::string &server_name, const std::string &service_name)
|
std::set<std::string> list_backups(const std::string &server_name, const std::string &service_name)
|
||||||
{
|
{
|
||||||
std::set<std::string> backups;
|
std::set<std::string> backups;
|
||||||
|
|
||||||
if (server_name.empty() || service_name.empty())
|
if (server_name.empty() || service_name.empty())
|
||||||
@ -133,7 +180,8 @@ std::set<std::string> list_backups(const std::string &server_name, const std::st
|
|||||||
|
|
||||||
// need to find the template for the service.
|
// need to find the template for the service.
|
||||||
auto service_info = get_service_info(server_name, service_name);
|
auto service_info = get_service_info(server_name, service_name);
|
||||||
if (service_info.local_template_path.empty()) {
|
if (service_info.local_template_path.empty())
|
||||||
|
{
|
||||||
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
||||||
return backups;
|
return backups;
|
||||||
}
|
}
|
||||||
@ -142,8 +190,10 @@ std::set<std::string> list_backups(const std::string &server_name, const std::st
|
|||||||
if (backups_dir.empty())
|
if (backups_dir.empty())
|
||||||
return backups;
|
return backups;
|
||||||
|
|
||||||
if (fs::exists(backups_dir)) {
|
if (fs::exists(backups_dir))
|
||||||
for (const auto& entry : fs::directory_iterator(backups_dir)) {
|
{
|
||||||
|
for (const auto &entry : fs::directory_iterator(backups_dir))
|
||||||
|
{
|
||||||
if (fs::is_regular_file(entry) && entry.path().extension() == ".tgz")
|
if (fs::is_regular_file(entry) && entry.path().extension() == ".tgz")
|
||||||
if (entry.path().filename().string().find(service_info.template_name) != std::string::npos)
|
if (entry.path().filename().string().find(service_info.template_name) != std::string::npos)
|
||||||
{
|
{
|
||||||
@ -152,12 +202,10 @@ std::set<std::string> list_backups(const std::string &server_name, const std::st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return backups;
|
return backups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_all_service_env_vars(const std::string &server_name, const std::string &service_name, std::map<std::string, std::string> &all_env_vars)
|
||||||
|
{
|
||||||
bool get_all_service_env_vars(const std::string &server_name, const std::string &service_name, std::map<std::string, std::string> & all_env_vars)
|
|
||||||
{
|
|
||||||
all_env_vars.clear();
|
all_env_vars.clear();
|
||||||
|
|
||||||
if (localpath::service(server_name, service_name).empty() || !fs::exists(localpath::service(server_name, service_name)))
|
if (localpath::service(server_name, service_name).empty() || !fs::exists(localpath::service(server_name, service_name)))
|
||||||
@ -166,25 +214,11 @@ bool get_all_service_env_vars(const std::string &server_name, const std::string
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
server_config server_info(server_name);
|
|
||||||
if (server_info.get_SSH_HOST().empty())
|
|
||||||
std::cerr << "Error: Server " << server_name << " not found - ssh_host empty, so HOST_NAME not set" << std::endl;
|
|
||||||
|
|
||||||
std::string user = server_config::get_user_for_service(server_name, service_name);
|
|
||||||
|
|
||||||
// add in some handy variables.
|
|
||||||
// if we change these, we also need to update agent/_allservicesstatus.sh
|
|
||||||
all_env_vars["CONFIG_PATH"] = remotepath(server_name,user).service_config(service_name);
|
|
||||||
all_env_vars["SERVER"] = server_name;
|
|
||||||
all_env_vars["SERVICE"] = service_name;
|
|
||||||
all_env_vars["AGENT_PATH"] = remotepath(server_name,user).agent();
|
|
||||||
all_env_vars["HOST_NAME"] = server_info.get_SSH_HOST();
|
|
||||||
all_env_vars["DOCKER_CLI_HINTS"] = "false"; // turn off docker junk.
|
|
||||||
all_env_vars["SSH_USER"] = user;
|
|
||||||
|
|
||||||
// Lambda function to load environment variables from a file
|
// Lambda function to load environment variables from a file
|
||||||
auto load_env_file = [&all_env_vars](const std::string& file) {
|
auto load_env_file = [&all_env_vars](const std::string &file)
|
||||||
if (!file.empty() && std::filesystem::exists(file)) {
|
{
|
||||||
|
if (!file.empty() && std::filesystem::exists(file))
|
||||||
|
{
|
||||||
std::map<std::string, std::string> env_vars;
|
std::map<std::string, std::string> env_vars;
|
||||||
envmanager env_manager(file);
|
envmanager env_manager(file);
|
||||||
env_manager.load();
|
env_manager.load();
|
||||||
@ -199,29 +233,42 @@ bool get_all_service_env_vars(const std::string &server_name, const std::string
|
|||||||
load_env_file(localfile::service_env(server_name, service_name));
|
load_env_file(localfile::service_env(server_name, service_name));
|
||||||
load_env_file(localfile::template_info_env(server_name, service_name));
|
load_env_file(localfile::template_info_env(server_name, service_name));
|
||||||
|
|
||||||
|
std::string user = all_env_vars["SSH_USER"];
|
||||||
|
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 << "Please check " << localfile::service_env(server_name, service_name) << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add in some handy variables.
|
||||||
|
// if we change these, we also need to update agent/_allservicesstatus.sh
|
||||||
|
all_env_vars["CONFIG_PATH"] = remotepath(server_name, user).service_config(service_name);
|
||||||
|
all_env_vars["SERVER"] = server_name;
|
||||||
|
all_env_vars["SERVICE"] = service_name;
|
||||||
|
all_env_vars["AGENT_PATH"] = remotepath(server_name, user).agent();
|
||||||
|
all_env_vars["DOCKER_CLI_HINTS"] = "false"; // turn off docker junk.
|
||||||
|
|
||||||
// determine template name.
|
// determine template name.
|
||||||
auto it = all_env_vars.find("TEMPLATE");
|
auto it = all_env_vars.find("TEMPLATE");
|
||||||
if (it == all_env_vars.end()) {
|
if (it == all_env_vars.end())
|
||||||
|
{
|
||||||
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 service.env file and the .template_info.env file in:" << std::endl;
|
||||||
info << " " << localpath::service(server_name, service_name) << std::endl << std::endl;
|
info << " " << localpath::service(server_name, service_name) << std::endl
|
||||||
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
template_info tinfo = gTemplateManager().get_template_info(it->second);
|
template_info tinfo = gTemplateManager().get_template_info(it->second);
|
||||||
if (!tinfo.is_set()) {
|
if (!tinfo.is_set())
|
||||||
|
{
|
||||||
std::cerr << "Error: Template '" << it->second << "' not found" << std::endl;
|
std::cerr << "Error: Template '" << it->second << "' not found" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string default_env_file = tinfo.local_template_path()/"_default.env";
|
return true;
|
||||||
if (!fs::exists(default_env_file)) {
|
|
||||||
std::cerr << "Error: Template default env file '" << default_env_file << "' not found" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_env_file(default_env_file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
||||||
|
@ -14,6 +14,10 @@ namespace dropshell {
|
|||||||
std::string local_service_path;
|
std::string local_service_path;
|
||||||
std::string local_template_path;
|
std::string local_template_path;
|
||||||
std::string user;
|
std::string user;
|
||||||
|
bool requires_host_root;
|
||||||
|
bool requires_docker;
|
||||||
|
bool requires_docker_root;
|
||||||
|
bool service_template_hash_match;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SIvalid(const LocalServiceInfo& service_info);
|
bool SIvalid(const LocalServiceInfo& service_info);
|
||||||
@ -28,6 +32,7 @@ namespace dropshell {
|
|||||||
|
|
||||||
// list all backups for a given service (across all servers)
|
// list all backups for a given service (across all servers)
|
||||||
std::set<std::string> list_backups(const std::string& server_name, const std::string& service_name);
|
std::set<std::string> list_backups(const std::string& server_name, const std::string& service_name);
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
#include "templates.hpp"
|
#include "templates.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "utils/hash.hpp"
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
|
|
||||||
@ -307,7 +308,6 @@
|
|||||||
std::vector<std::string> required_files = {
|
std::vector<std::string> required_files = {
|
||||||
"config/service.env",
|
"config/service.env",
|
||||||
"config/.template_info.env",
|
"config/.template_info.env",
|
||||||
"_default.env",
|
|
||||||
"install.sh",
|
"install.sh",
|
||||||
"uninstall.sh"
|
"uninstall.sh"
|
||||||
};
|
};
|
||||||
@ -376,8 +376,16 @@
|
|||||||
mLocationID(location_id),
|
mLocationID(location_id),
|
||||||
mTemplateLocalPath(local_template_path),
|
mTemplateLocalPath(local_template_path),
|
||||||
mTemplateValid(template_manager::test_template(local_template_path.string())),
|
mTemplateValid(template_manager::test_template(local_template_path.string())),
|
||||||
mIsSet(!template_name.empty() && !location_id.empty() && !local_template_path.empty())
|
mIsSet(!template_name.empty() && !location_id.empty() && !local_template_path.empty()),\
|
||||||
|
mHash(0)
|
||||||
{
|
{
|
||||||
|
if (!std::filesystem::exists(local_template_path))
|
||||||
|
{
|
||||||
|
error << "Template path does not exist: " << local_template_path << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mHash = hash_directory_recursive(local_template_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
||||||
|
@ -26,12 +26,15 @@ class template_info {
|
|||||||
std::string locationID() const { return mLocationID; }
|
std::string locationID() const { return mLocationID; }
|
||||||
std::filesystem::path local_template_path() const { return mTemplateLocalPath; }
|
std::filesystem::path local_template_path() const { return mTemplateLocalPath; }
|
||||||
bool template_valid() const { return mTemplateValid; }
|
bool template_valid() const { return mTemplateValid; }
|
||||||
|
uint64_t hash() const { return mHash; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mTemplateName;
|
std::string mTemplateName;
|
||||||
std::string mLocationID;
|
std::string mLocationID;
|
||||||
std::filesystem::path mTemplateLocalPath; // source or cache.
|
std::filesystem::path mTemplateLocalPath; // source or cache.
|
||||||
bool mTemplateValid;
|
bool mTemplateValid;
|
||||||
bool mIsSet;
|
bool mIsSet;
|
||||||
|
uint64_t mHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
class template_source_interface {
|
class template_source_interface {
|
||||||
|
@ -154,7 +154,6 @@ namespace localpath {
|
|||||||
// |-- config
|
// |-- config
|
||||||
// |-- service.env (actual service config)
|
// |-- service.env (actual service config)
|
||||||
// |-- template
|
// |-- template
|
||||||
// |-- _default.env
|
|
||||||
// |-- (script files)
|
// |-- (script files)
|
||||||
// |-- config
|
// |-- config
|
||||||
// |-- service.env (default service config)
|
// |-- service.env (default service config)
|
||||||
|
@ -30,13 +30,10 @@ namespace dropshell {
|
|||||||
// | |-- <template_name>.json
|
// | |-- <template_name>.json
|
||||||
// | |-- <template_name>
|
// | |-- <template_name>
|
||||||
// | |-- (...script files...)
|
// | |-- (...script files...)
|
||||||
// | |-- _default.env
|
|
||||||
// | |-- config
|
// | |-- config
|
||||||
// | |-- service.env
|
// | |-- service.env
|
||||||
// | |-- .template_info.env
|
// | |-- .template_info.env
|
||||||
// | |-- (...other service config files...)
|
// | |-- (...other service config files...)
|
||||||
// |-- remote_versions
|
|
||||||
// | |-- server_name-service_name.json
|
|
||||||
|
|
||||||
// server_definition_path
|
// server_definition_path
|
||||||
// |-- <server_name>
|
// |-- <server_name>
|
||||||
@ -92,7 +89,6 @@ namespace dropshell {
|
|||||||
// |-- service.env (actual service config)
|
// |-- service.env (actual service config)
|
||||||
// |-- .template_info.env
|
// |-- .template_info.env
|
||||||
// |-- template
|
// |-- template
|
||||||
// |-- _default.env
|
|
||||||
// |-- (script files)
|
// |-- (script files)
|
||||||
// |-- config
|
// |-- config
|
||||||
// |-- service.env (default service config)
|
// |-- service.env (default service config)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user