#include "command_registry.hpp" #include "shared_commands.hpp" #include "config.hpp" #include "services.hpp" #include "server_env_manager.hpp" #include "utils/directories.hpp" #include "servers.hpp" #include "templates.hpp" #include "utils/assert.hpp" #pragma message ("TODO: Fix issues with Nuke below.") namespace dropshell { int nuke_handler(const CommandContext& ctx); static std::vector nuke_name_list={"nuke"}; // Static registration struct NukeCommandRegister { NukeCommandRegister() { CommandRegistry::instance().register_command({ nuke_name_list, nuke_handler, std_autocomplete, false, // hidden true, // requires_config true, // requires_install 2, // min_args (after command) 2, // max_args (after command) "nuke SERVER SERVICE|all", "Nuke a service on a server. Destroys everything, both local and remote!", // heredoc R"( Nuke a service on a server. Destroys everything, both local and remote! nuke SERVER SERVICE nuke the given service on the given server. nuke SERVER all nuke all services on the given server. )" }); } } nuke_command_register; int nuke_one(std::string server, std::string service) { server_env_manager server_env(server); // step 1 - nuke on remote server. if (server_env.is_valid()) { LocalServiceInfo service_info; service_info = get_service_info(server, service); if (!SIvalid(service_info)) std::cerr << "Warning: Invalid service: " << service << std::endl; if (server_env.check_remote_dir_exists(remotepath::service(server, service))) { // run the nuke script on the remote server if it exists. // otherwise just uninstall. if (gTemplateManager().template_command_exists(service_info.template_name, "nuke")) { if (!server_env.run_remote_template_command(service, "nuke", {}, false, {})) std::cerr << "Warning: Failed to run nuke script: " << service << std::endl; } else { if (!server_env.run_remote_template_command(service, "uninstall", {}, false, {})) std::cerr << "Warning: Failed to uninstall service: " << service << std::endl; } // Remove the service directory from the server, running in a docker container as root. if (server_env.remove_remote_dir(remotepath::service(server, service), true)) { ASSERT(!server_env.check_remote_dir_exists(remotepath::service(server, service)), "Service directory still found on server after uninstall"); std::cout << "Remote service directory removed: " << remotepath::service(server, service) << std::endl; } else std::cerr << "Warning: Failed to remove remote service directory" << std::endl; } else std::cerr << "Warning: Service not found on remote server: " << remotepath::service(server, service) << std::endl; } else std::cerr << "Warning: Can't nuke the remote service as the server is invalid: " << server << std::endl; // step 2 - nuke the local service directory. std::string local_service_path = localpath::service(server, service); if (local_service_path.empty() || !std::filesystem::exists(local_service_path)) { std::cerr << "Warning: Local service directory not found: " << local_service_path << std::endl; } else { auto itemsdeleted = std::filesystem::remove_all(local_service_path); if (itemsdeleted == 0) std::cerr << "Error: Failed to remove local service directory" << std::endl; } std::cout << "Nuked service " << service << " on server " << server << std::endl; return 0; } int nuke_handler(const CommandContext &ctx) { ASSERT(ctx.args.size() == 2, "Usage: nuke SERVER SERVICE|all (requires 2 args - you supplied " + std::to_string(ctx.args.size()) + ")"); ASSERT(gConfig().is_config_set(), "No configuration found. Please run 'dropshell config' to set up your configuration."); std::string server = safearg(ctx.args, 0); std::string service = safearg(ctx.args, 1); if (service == "all") { int rval = 0; // iterate through all service folders in the server directory. std::string server_path = localpath::server(server); if (server_path.empty()) { std::cerr << "Error: Server not found: " << server << std::endl; return 1; } for (const auto& entry : std::filesystem::directory_iterator(server_path)) { if (entry.is_directory() && entry.path().filename().string().find(".") != 0) { std::string service_name = entry.path().filename().string(); rval |= nuke_one(server, service_name); } } return rval; } else { return nuke_one(server, service); } } } // namespace dropshell