184 lines
6.1 KiB
C++
184 lines
6.1 KiB
C++
#include "command_registry.hpp"
|
|
#include "config.hpp"
|
|
#include "utils/utils.hpp"
|
|
#include "utils/directories.hpp"
|
|
#include "shared_commands.hpp"
|
|
#include "servers.hpp"
|
|
#include "tableprint.hpp"
|
|
#include "transwarp.hpp"
|
|
|
|
#include <unistd.h>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <filesystem>
|
|
#include "utils/assert.hpp"
|
|
|
|
namespace dropshell {
|
|
|
|
int list_handler(const CommandContext& ctx);
|
|
void show_server_details(const std::string& server_name);
|
|
void list_servers();
|
|
|
|
static std::vector<std::string> list_name_list={"list","ls","info","-l"};
|
|
|
|
// Static registration
|
|
struct ListCommandRegister {
|
|
ListCommandRegister() {
|
|
CommandRegistry::instance().register_command({
|
|
list_name_list,
|
|
list_handler,
|
|
std_autocomplete,
|
|
false, // hidden
|
|
true, // requires_config
|
|
true, // requires_install
|
|
0, // min_args (after command)
|
|
2, // max_args (after command)
|
|
"list [SERVER] [SERVICE]",
|
|
"List server or service information and status",
|
|
// heredoc
|
|
R"(
|
|
List details for servers and services controller by dropshell.
|
|
list list all servers.
|
|
list server list all services for the given server.
|
|
list server service list the given service details on the given server.
|
|
)"
|
|
});
|
|
}
|
|
} list_command_register;
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// list command handler
|
|
// ------------------------------------------------------------------------------------------------
|
|
int list_handler(const CommandContext& ctx) {
|
|
if (ctx.args.size() == 0) {
|
|
list_servers();
|
|
return 0;
|
|
}
|
|
|
|
if (ctx.args.size() == 1) {
|
|
show_server_details(ctx.args[0]);
|
|
return 0;
|
|
}
|
|
|
|
std::cout << "List handler called with " << ctx.args.size() << " args\n";
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/bloomen/transwarp?tab=readme-ov-file#range-functions
|
|
void list_servers() {
|
|
auto servers = get_configured_servers();
|
|
|
|
if (servers.empty()) {
|
|
std::cout << "No servers found" << std::endl;
|
|
std::cout << "Please run 'dropshell edit' to set up dropshell." << std::endl;
|
|
std::cout << "Then run 'dropshell create-server' to create a server." << std::endl;
|
|
return;
|
|
}
|
|
|
|
tableprint tp("All DropShell Servers");
|
|
tp.add_row({"Name", "User", "Address", "Health", "Ports"});
|
|
|
|
std::cout << "Checking "<<servers.size() << " servers: " << std::flush;
|
|
int checked = 0;
|
|
|
|
transwarp::parallel exec{servers.size()};
|
|
auto task = transwarp::for_each(exec, servers.begin(), servers.end(), [&](const ServerInfo& server) {
|
|
std::map<std::string, ServiceStatus> status = service_runner::get_all_services_status(server.name);
|
|
|
|
std::set<int> ports_used;
|
|
std::string serviceticks = "";
|
|
for (const auto& [service_name, service_status] : status) {
|
|
ports_used.insert(service_status.ports.begin(), service_status.ports.end());
|
|
serviceticks += HealthStatus2String(service_status.health) + " ";
|
|
}
|
|
std::string ports_used_str = "";
|
|
for (const auto& port : ports_used)
|
|
ports_used_str += std::to_string(port) + " ";
|
|
|
|
tp.add_row({server.name, server.ssh_user, server.ssh_host, serviceticks, ports_used_str});
|
|
++checked;
|
|
// print out a tick character for each server checked.
|
|
std::cout << checked << " ✓ " << std::flush;
|
|
});
|
|
task->wait();
|
|
std::cout << std::endl << std::endl;
|
|
tp.print();
|
|
}
|
|
|
|
|
|
|
|
|
|
void show_server_details(const std::string& server_name) {
|
|
server_env_manager env(server_name);
|
|
if (!env.is_valid()) {
|
|
std::cerr << "Error: Invalid server environment file: " << server_name << std::endl;
|
|
return;
|
|
}
|
|
|
|
//---------------------
|
|
// Check if server is reachable via SSH
|
|
std::string ssh_address = env.get_SSH_HOST();
|
|
std::string ssh_user = env.get_SSH_USER();
|
|
std::string ssh_port = env.get_SSH_PORT();
|
|
if (!ssh_address.empty()) {
|
|
std::cout << std::endl << "Server Status:" << std::endl;
|
|
std::cout << std::string(40, '-') << std::endl;
|
|
|
|
// Try to connect to the server
|
|
std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_user + "@" + ssh_address + " -p " + ssh_port + " 'echo connected' 2>/dev/null";
|
|
int result = system(cmd.c_str());
|
|
if (result == 0) {
|
|
std::cout << "Status: Online" << std::endl;
|
|
|
|
// // Get uptime if possible
|
|
// cmd = "ssh " + ssh_address + " 'uptime' 2>/dev/null";
|
|
// int rval = system(cmd.c_str());
|
|
// if (rval != 0) {
|
|
// std::cout << "Error: Failed to get uptime" << std::endl;
|
|
// }
|
|
} else {
|
|
std::cout << "Status: Offline" << std::endl;
|
|
}
|
|
}
|
|
std::cout << std::endl;
|
|
|
|
//---------------------
|
|
{
|
|
std::cout << std::endl;
|
|
tableprint tp("Server Configuration: " + server_name, true);
|
|
tp.add_row({"Key", "Value"});
|
|
for (const auto& [key, value] : env.get_variables()) {
|
|
tp.add_row({key, value});
|
|
}
|
|
tp.print();
|
|
}
|
|
|
|
//---------------------
|
|
// list services, and run healthcheck on each
|
|
{
|
|
tableprint tp("Services: " + server_name, false);
|
|
tp.add_row({"Status", "Service", "Ports"});
|
|
|
|
|
|
std::map<std::string, ServiceStatus> status = service_runner::get_all_services_status(server_name);
|
|
|
|
std::set<int> ports_used;
|
|
std::string serviceticks = "";
|
|
for (const auto& [service_name, service_status] : status) {
|
|
std::string healthy = HealthStatus2String(service_status.health);
|
|
|
|
std::string ports_str = "";
|
|
for (const auto& port : service_status.ports)
|
|
ports_str += std::to_string(port) + " ";
|
|
|
|
tp.add_row({healthy, service_name, ports_str});
|
|
} // end of for (const auto& service : services)
|
|
tp.print();
|
|
} // end of list services
|
|
} // end of show_server_details
|
|
|
|
|
|
} // namespace dropshell
|