dropshell/source/src/commands/uninstall.cpp
Your Name 343e597d84
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
Working on nuke
2025-05-24 17:16:19 +12:00

106 lines
4.7 KiB
C++

#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 uninstall_handler(const CommandContext &ctx);
static std::vector<std::string> uninstall_name_list = {"uninstall", "remove"};
// Static registration
struct UninstallCommandRegister
{
UninstallCommandRegister()
{
CommandRegistry::instance().register_command({uninstall_name_list,
uninstall_handler,
shared_commands::std_autocomplete_allowall,
false, // hidden
true, // requires_config
true, // requires_install
2, // min_args (after command)
2, // max_args (after command)
"uninstall SERVER SERVICE|all",
"Uninstall a service on a server. Does not remove configuration or user data.",
// heredoc
R"(
Uninstall a service, leaving all configuration and data intact.
uninstall SERVER SERVICE Uninstall the given service on the given server.
uninstall SERVER all Uninstall all services on the given server.
Update and reinstall the service with install, or delete all configuration and data with destroy.
)"});
}
} uninstall_command_register;
namespace shared_commands {
bool uninstall_service(const ServerConfig & server_env, const std::string &service)
{
ASSERT(server_env.is_valid(), "Invalid server environment for " + server_env.get_server_name());
std::string server = server_env.get_server_name();
maketitle("Uninstalling " + service + " on " + server);
std::string user = server_env.get_user_for_service(service);
// 2. Check if service directory exists on server
if (!server_env.check_remote_dir_exists(remotepath(server, user).service(service), user))
{
error << "Service is not installed: " << service << std::endl;
return true; // Nothing to uninstall
}
// 3. Run uninstall script if it exists
std::string uninstall_script = remotepath(server, user).service_template(service) + "/uninstall.sh";
if (!server_env.run_remote_template_command(service, "uninstall", {}, false, {}))
warning << "Uninstall script failed, but continuing with directory removal" << std::endl;
// 4. Remove the service directory from the server, running in a docker container as root.
if (server_env.remove_remote_dir(remotepath(server, user).service(service), false, user))
{
ASSERT(!server_env.check_remote_dir_exists(remotepath(server, user).service(service), user), "Service directory still found on server after uninstall");
info << "Removed remote service directory " << remotepath(server, user).service(service) << std::endl;
}
else
warning << "Failed to remove remote service directory" << std::endl;
info << "Completed service " << service << " uninstall on " << server << std::endl;
return true;
}
} // namespace shared_commands
int uninstall_handler(const CommandContext &ctx)
{
if (ctx.args.size() < 1)
{
error << "uninstall requires a server and a service (or all)" << std::endl;
return 1;
}
std::string server = safearg(ctx.args, 0);
if (safearg(ctx.args, 1) == "all")
{
// uninstall all services on the server
bool okay = true;
std::vector<LocalServiceInfo> services = get_server_services_info(server);
for (const auto &service : services)
{
if (!shared_commands::uninstall_service(server, service.service_name))
okay = false;
}
return okay ? 0 : 1;
}
std::string service = safearg(ctx.args, 1);
return shared_commands::uninstall_service(server, service) ? 0 : 1;
}
} // namespace dropshell