This commit is contained in:
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user