#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 #include namespace fs = std::filesystem; namespace dropshell { std::vector get_server_services_info(const std::string& server_name) { std::vector services; if (server_name.empty()) return services; std::vector 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 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 get_used_commands(const std::string &server_name, const std::string &service_name) { std::set 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 list_backups(const std::string &server_name, const std::string &service_name) { std::set 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"< & 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 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 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 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