diff --git a/src/commands/edit.cpp b/src/commands/edit.cpp index 0bf0a52..cb623d4 100644 --- a/src/commands/edit.cpp +++ b/src/commands/edit.cpp @@ -1,9 +1,8 @@ #include "command_registry.hpp" #include "config.hpp" #include "utils/utils.hpp" -#include "service_runner.hpp" #include "utils/directories.hpp" -#include "standard_autocomplete.hpp" +#include "shared_commands.hpp" #include #include @@ -14,7 +13,6 @@ namespace dropshell { -void edit_autocomplete(const CommandContext& ctx); int edit_handler(const CommandContext& ctx); static std::vector edit_name_list={"edit"}; @@ -25,7 +23,7 @@ struct EditCommandRegister { CommandRegistry::instance().register_command({ edit_name_list, edit_handler, - edit_autocomplete, + std_autocomplete, false, // hidden false, // requires_config 0, // min_args (after command) @@ -166,12 +164,6 @@ int edit_handler(const CommandContext& ctx) { return -1; } -// ------------------------------------------------------------------------------------------------ -// edit command autocomplete -// ------------------------------------------------------------------------------------------------ -void edit_autocomplete(const CommandContext& ctx) { - std_autocomplete(edit_name_list, ctx); -} diff --git a/src/commands/health.cpp b/src/commands/health.cpp index 8ff0d6e..47b63f2 100644 --- a/src/commands/health.cpp +++ b/src/commands/health.cpp @@ -1,64 +1,132 @@ #include "command_registry.hpp" #include "config.hpp" #include "utils/utils.hpp" -#include "service_runner.hpp" #include "utils/directories.hpp" -#include "standard_autocomplete.hpp" #include "templates.hpp" #include "shared_commands.hpp" +#include "server_env_manager.hpp" +#include "services.hpp" +#include "servers.hpp" +namespace dropshell +{ -namespace dropshell { + int health_handler(const CommandContext &ctx); - int health_handler(const CommandContext& ctx); - void health_autocomplete(const CommandContext& ctx); - - static std::vector health_name_list={"health","check","healthcheck","status"}; + static std::vector health_name_list = {"health", "check", "healthcheck", "status"}; // Static registration - struct HealthCommandRegister { - HealthCommandRegister() { - CommandRegistry::instance().register_command({ - health_name_list, - health_handler, - health_autocomplete, - false, // hidden - false, // requires_config - 1, // min_args (after command) - 2, // max_args (after command) - "health SERVER", - "Check the health of a server.", - R"( + struct HealthCommandRegister + { + HealthCommandRegister() + { + CommandRegistry::instance().register_command({health_name_list, + health_handler, + std_autocomplete, + false, // hidden + false, // requires_config + 1, // min_args (after command) + 2, // max_args (after command) + "health SERVER", + "Check the health of a server.", + R"( health - )" - }); + )"}); } } health_command_register; - // ------------------------------------------------------------------------------------------------ // health command implementation - std::string healthtick(const std::string& server, const std::string& service) { - return "OK"; + HealthStatus is_healthy(const std::string &server, const std::string &service) + { + server_env_manager env(server); + if (!env.is_valid()) + { + std::cerr << "Error: Server service not initialized" << std::endl; + return HealthStatus::ERROR; + } + + if (!env.check_remote_dir_exists(remotepath::service(server, service))) + { + return HealthStatus::NOTINSTALLED; + } + + std::string script_path = remotepath::service_template(server, service) + "/status.sh"; + if (!env.check_remote_file_exists(script_path)) + { + return HealthStatus::UNKNOWN; + } + + // Run status script, does not display output. + if (!env.run_remote_template_command(service, "status", {}, true, {})) + return HealthStatus::UNHEALTHY; + return HealthStatus::HEALTHY; + } + + std::string healthtick(const std::string &server, const std::string &service) + { + std::string green_tick = "\033[32m✓\033[0m"; + std::string red_cross = "\033[31m✗\033[0m"; + std::string yellow_exclamation = "\033[33m!\033[0m"; + std::string unknown = "\033[37m✓\033[0m"; + + HealthStatus status = is_healthy(server, service); + if (status == HealthStatus::HEALTHY) + return green_tick; + else if (status == HealthStatus::UNHEALTHY) + return red_cross; + else if (status == HealthStatus::UNKNOWN) + return unknown; + else + return yellow_exclamation; + } + + std::string HealthStatus2String(HealthStatus status) + { + if (status == HealthStatus::HEALTHY) + return ":tick:"; + else if (status == HealthStatus::UNHEALTHY) + return ":cross:"; + else if (status == HealthStatus::UNKNOWN) + return ":greytick:"; + else if (status == HealthStatus::NOTINSTALLED) + return ":warning:"; + else + return ":error:"; + } + + std::string healthmark(const std::string &server, const std::string &service) + { + HealthStatus status = is_healthy(server, service); + return HealthStatus2String(status); } // ------------------------------------------------------------------------------------------------ // health command implementation // ------------------------------------------------------------------------------------------------ - int health_handler(const CommandContext& ctx) { - if (ctx.args.size() < 1) { - + int health_handler(const CommandContext &ctx) + { + if (ctx.args.size() < 1) + { + std::cerr << "Error: Server name is required" << std::endl; + return 1; + } + + std::string server = safearg(ctx.args, 0); + + if (ctx.args.size() == 1) { + // get all services on server + std::vector services = get_server_services_info(server); + for (const auto& service : services) { + std::cout << service.service_name << " " << healthtick(server, service.service_name) << std::endl; + } + } else { + // get service status + std::string service = safearg(ctx.args, 1); + std::cout << service << " " << healthtick(server, service) << std::endl; } return 0; } - // ------------------------------------------------------------------------------------------------ - // health autocomplete - // ------------------------------------------------------------------------------------------------ - void health_autocomplete(const CommandContext& ctx) { - if (ctx.args.size() == 1) { - - } - } } // namespace dropshell diff --git a/src/commands/help.cpp b/src/commands/help.cpp index 1bc2437..e2fba72 100644 --- a/src/commands/help.cpp +++ b/src/commands/help.cpp @@ -1,9 +1,8 @@ #include "command_registry.hpp" #include "config.hpp" #include "utils/utils.hpp" -#include "service_runner.hpp" #include "utils/directories.hpp" -#include "standard_autocomplete.hpp" +#include "shared_commands.hpp" #include "version.hpp" #include diff --git a/src/commands/install.cpp b/src/commands/install.cpp index 6c04501..b57a47e 100644 --- a/src/commands/install.cpp +++ b/src/commands/install.cpp @@ -1,9 +1,7 @@ #include "command_registry.hpp" #include "config.hpp" #include "utils/utils.hpp" -#include "service_runner.hpp" #include "utils/directories.hpp" -#include "standard_autocomplete.hpp" #include "templates.hpp" #include "shared_commands.hpp" @@ -16,7 +14,6 @@ namespace dropshell { -void install_autocomplete(const CommandContext& ctx); int install_handler(const CommandContext& ctx); static std::vector install_name_list={"install"}; @@ -27,17 +24,18 @@ struct InstallCommandRegister { CommandRegistry::instance().register_command({ install_name_list, install_handler, - install_autocomplete, + std_autocomplete, false, // hidden false, // requires_config - 2, // min_args (after command) + 1, // min_args (after command) 2, // max_args (after command) - "install SERVER SERVICE", + "install SERVER [SERVICE]", "Install/reinstall/update service(s). Safe/non-destructive.", // heredoc R"( - Install a service on a server. - install install the given service on the given server. + Install a service(s) on a server. + install (re)install the given service on the given server. + install (re)install all configured services on the given server. Note you need to create the service first with: dropshell create-service