#include "command_registry.hpp" #include "directories.hpp" #include "shared_commands.hpp" #include "templates.hpp" #include "utils/assert.hpp" #include "utils/utils.hpp" #include "services.hpp" namespace dropshell { int create_service_handler(const CommandContext &ctx); bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, bool silent); void create_service_autocomplete(const CommandContext &ctx); static std::vector create_service_name_list = {"create-service"}; // Static registration struct CreateServiceCommandRegister { CreateServiceCommandRegister() { CommandRegistry::instance().register_command({create_service_name_list, create_service_handler, create_service_autocomplete, false, // hidden true, // requires_config true, // requires_install 3, // min_args (after command) 3, // max_args (after command) "create-service SERVER SERVICE TEMPLATE", "Create a service on a server.", // heredoc R"( Create a service on a server. create-service SERVER SERVICE TEMPLATE create the given service on the given server. )"}); } } create_service_command_register; int create_service_handler(const CommandContext &ctx) { std::string server = safearg(ctx.args, 0); std::string service = safearg(ctx.args, 1); std::string template_name = safearg(ctx.args, 2); return create_service(server, template_name, service, false) ? 0 : 1; } void create_service_autocomplete(const CommandContext &ctx) { if (ctx.args.size() < 2) shared_commands::std_autocomplete(ctx); else { if (ctx.args.size() == 2) { std::set templates = gTemplateManager().get_template_list(); for (const auto &template_name : templates) std::cout << template_name << std::endl; } } } 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 (std::filesystem::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 = gTemplateManager().get_template_info(template_name); if (!tinfo.is_set()) { 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; } // check template is all good. if (!gTemplateManager().test_template(tinfo.local_template_path())) { if (!silent) std::cerr << "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); 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 config 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; } } // namespace dropshell