247 lines
8.8 KiB
C++
247 lines
8.8 KiB
C++
#include "services.hpp"
|
|
#include "utils/envmanager.hpp"
|
|
#include "utils/directories.hpp"
|
|
#include "templates.hpp"
|
|
#include "config.hpp"
|
|
#include "utils/utils.hpp"
|
|
#include "server_env_manager.hpp"
|
|
#include <iostream>
|
|
#include <filesystem>
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
namespace dropshell {
|
|
|
|
std::vector<LocalServiceInfo> get_server_services_info(const std::string& server_name) {
|
|
std::vector<LocalServiceInfo> services;
|
|
|
|
if (server_name.empty())
|
|
return services;
|
|
|
|
std::vector<std::string> local_config_directories = gConfig().get_local_config_directories();
|
|
if (local_config_directories.empty()) {
|
|
std::cerr << "Error: No local config directories found" << std::endl;
|
|
std::cerr << "Run 'dropshell init' to initialise DropShell" << std::endl;
|
|
return services;
|
|
}
|
|
|
|
for (int i = 0; i < localpath::num_config_directories(); i++) {
|
|
std::string serverpath = localpath::config_servers(i);
|
|
if (serverpath.empty()) {
|
|
std::cerr << "Error: Server directory not found: " << serverpath << std::endl;
|
|
return services;
|
|
}
|
|
fs::path server_dir = fs::path(serverpath) / server_name;
|
|
if (fs::exists(server_dir)) {
|
|
for (const auto& entry : fs::directory_iterator(server_dir)) {
|
|
if (fs::is_directory(entry)) {
|
|
auto service = get_service_info(server_name, entry.path().filename().string());
|
|
if (!service.template_name.empty()) {
|
|
services.push_back(service);
|
|
}
|
|
}
|
|
}
|
|
} // end of for (int i = 0; i < getNumConfigDirectories(); i++)
|
|
}
|
|
|
|
|
|
return services;
|
|
}
|
|
|
|
|
|
LocalServiceInfo get_service_info(const std::string &server_name, const std::string &service_name)
|
|
{
|
|
LocalServiceInfo service;
|
|
|
|
if (server_name.empty() || service_name.empty())
|
|
return LocalServiceInfo();
|
|
|
|
service.service_name = service_name;
|
|
|
|
service.local_service_path = localpath::service(server_name, service_name);
|
|
if (service.local_service_path.empty())
|
|
return LocalServiceInfo();
|
|
|
|
|
|
// now set the template name and path.
|
|
std::map<std::string, std::string> variables;
|
|
get_all_service_env_vars(server_name, service_name, variables);
|
|
|
|
// load the service.env file
|
|
auto it = variables.find("TEMPLATE");
|
|
if (it == variables.end()) {
|
|
std::cerr << "Error: TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
|
return LocalServiceInfo();
|
|
}
|
|
service.template_name = it->second;
|
|
|
|
template_info tinfo;
|
|
if (!get_template_info(service.template_name, tinfo)) {
|
|
std::cerr << "Error: Template '" << service.template_name << "' not found" << std::endl;
|
|
return LocalServiceInfo();
|
|
}
|
|
|
|
// find the template path
|
|
service.local_template_path = tinfo.local_template_path;
|
|
|
|
return service;
|
|
}
|
|
|
|
std::set<std::string> get_used_commands(const std::string &server_name, const std::string &service_name)
|
|
{
|
|
std::set<std::string> commands;
|
|
|
|
if (server_name.empty() || service_name.empty())
|
|
return commands;
|
|
|
|
auto service_info = get_service_info(server_name, service_name);
|
|
if (service_info.local_template_path.empty()) {
|
|
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
|
return commands;
|
|
}
|
|
|
|
// 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 _
|
|
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))
|
|
commands.insert(entry.path().stem().string());
|
|
}
|
|
return commands;
|
|
}
|
|
|
|
std::set<std::string> list_backups(const std::string &server_name, const std::string &service_name)
|
|
{
|
|
std::set<std::string> backups;
|
|
|
|
if (server_name.empty() || service_name.empty())
|
|
return backups;
|
|
|
|
// need to find the template for the service.
|
|
auto service_info = get_service_info(server_name, service_name);
|
|
if (service_info.local_template_path.empty()) {
|
|
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
|
return backups;
|
|
}
|
|
|
|
std::string backups_dir = localpath::backups_path();
|
|
if (backups_dir.empty())
|
|
return backups;
|
|
|
|
if (fs::exists(backups_dir)) {
|
|
for (const auto& entry : fs::directory_iterator(backups_dir)) {
|
|
if (fs::is_regular_file(entry) && entry.path().extension() == ".tgz")
|
|
if (entry.path().filename().string().find(service_info.template_name) != std::string::npos)
|
|
{
|
|
backups.insert(entry.path().filename().string());
|
|
}
|
|
}
|
|
}
|
|
return backups;
|
|
}
|
|
|
|
bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, bool silent)
|
|
{
|
|
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())
|
|
{
|
|
if (!silent)
|
|
{
|
|
std::cerr << "Error: Couldn't locate server " << server_name << " in any config directory" << std::endl;
|
|
std::cerr << "Please check the server name is correct and try again" << std::endl;
|
|
std::cerr << "You can list all servers with 'dropshell servers'" << std::endl;
|
|
std::cerr << "You can create a new server with 'dropshell create-server " << server_name << "'" << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (fs::exists(service_dir))
|
|
{
|
|
if (!silent)
|
|
{
|
|
std::cerr << "Error: Service already exists: " << service_name << std::endl;
|
|
std::cerr << "Current service path: " << service_dir << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template_info tinfo;
|
|
if (!get_template_info(template_name, tinfo))
|
|
{
|
|
if (!silent)
|
|
{
|
|
std::cerr << "Error: Template '" << template_name << "' not found" << std::endl;
|
|
std::cerr << "Please check the template name is correct and try again" << std::endl;
|
|
std::cerr << "You can list all templates with 'dropshell templates'" << std::endl;
|
|
std::cerr << "You can create a new template with 'dropshell create-template " << template_name << "'" << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// create the service directory
|
|
fs::create_directory(service_dir);
|
|
|
|
// copy the template example files to the service directory
|
|
recursive_copy(tinfo.local_template_path+"/example", service_dir);
|
|
|
|
if (!silent)
|
|
{
|
|
std::cout << "Service " << service_name <<" created successfully"<<std::endl;
|
|
std::cout << std::endl;
|
|
std::cout << "To complete the installation, please:" << std::endl;
|
|
std::cout << "1. edit the service.env file: dropshell edit " << server_name << " " << service_name << std::endl;
|
|
std::cout << "2. install the remote service: dropshell install " << server_name << " " << service_name << std::endl;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void 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();
|
|
|
|
// add in some handy variables.
|
|
all_env_vars["CONFIG_PATH"] = remotepath::service_config(server_name,service_name);
|
|
all_env_vars["SERVER"] = server_name;
|
|
all_env_vars["SERVICE"] = service_name;
|
|
|
|
|
|
{ // load service.env from the service on this machine.
|
|
std::map<std::string, std::string> env_vars;
|
|
envmanager env_manager(localfile::service_env(server_name,service_name));
|
|
env_manager.load();
|
|
env_manager.get_all_variables(env_vars);
|
|
all_env_vars.merge(env_vars);
|
|
}
|
|
|
|
{ // load .template_info.env from the service on this machine.
|
|
std::map<std::string, std::string> env_vars;
|
|
envmanager env_manager(localfile::template_info_env(server_name,service_name));
|
|
env_manager.load();
|
|
env_manager.get_all_variables(env_vars);
|
|
all_env_vars.merge(env_vars);
|
|
}
|
|
|
|
{ // load _default.env from the template on this machine - gets overridden by service.env
|
|
std::map<std::string, std::string> env_vars;
|
|
auto service_info = get_service_info(server_name, service_name);
|
|
std::string defaultenvpath = service_info.local_template_path + "/_default.env";
|
|
if (std::filesystem::exists(defaultenvpath)) {
|
|
envmanager env_manager(defaultenvpath);
|
|
env_manager.load();
|
|
env_manager.get_all_variables(env_vars);
|
|
all_env_vars.merge(env_vars);
|
|
}
|
|
else
|
|
std::cerr << "Warning: _default.env not found in template: " << defaultenvpath << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
} // namespace dropshell
|