all status!
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 27s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m6s

This commit is contained in:
j
2025-12-30 10:35:34 +13:00
parent ca94eae6d2
commit a0794f5bfb
2 changed files with 452 additions and 283 deletions

View File

@@ -3,12 +3,14 @@
#include <algorithm>
#include <sstream>
#include <mutex>
#include <nlohmann/json.hpp>
#include "utils/utils.hpp"
#include "servers.hpp"
#include "directories.hpp"
#include "services.hpp"
#include "servers.hpp"
#include "utils/output.hpp"
#include "utils/execute.hpp"
#include "transwarp.hpp"
namespace dropshell
@@ -150,6 +152,7 @@ namespace dropshell
// ------------------------------------------------------------------------------------------------
// get_all_services_status : SHARED COMMAND
// Uses all_status.sh on the remote server to get status for all services in one SSH call
// ------------------------------------------------------------------------------------------------
std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env)
{
@@ -165,41 +168,75 @@ namespace dropshell
std::map<std::string, ServiceStatus> status;
std::string server_name = server_env.get_server_name();
// Get all services for this user on this server
std::vector<LocalServiceInfo> services = get_server_services_info(server_name);
// Filter services for this specific user
std::vector<LocalServiceInfo> user_services;
for (const auto& service : services) {
if (service.user == user) {
user_services.push_back(service);
}
// Run all_status.sh on the remote server to get all service statuses in one call
std::string agent_path = remotepath(server_name, user).agent();
std::string output;
sCommand cmd(agent_path, "all_status.sh", {});
bool success = execute_ssh_command(server_env.get_SSH_INFO(user), cmd, cMode::Silent, &output);
if (!success || output.empty()) {
debug << "Failed to run all_status.sh on " << server_name << " for user " << user << std::endl;
return status;
}
// Use parallel execution to check all services simultaneously
// This matches how the list command already works for multiple servers
if (user_services.size() > 0) {
std::mutex status_mutex;
// transwarp requires at least 1 thread
size_t num_threads = std::max(size_t(1), user_services.size());
transwarp::parallel exec{num_threads};
auto task = transwarp::for_each(exec, user_services.begin(), user_services.end(),
[&status, &status_mutex, &server_name](const LocalServiceInfo& service) {
ServiceStatus service_status;
// Get health status using the existing is_healthy function
service_status.health = is_healthy(server_name, service.service_name);
// Get ports using the new get_ports function
service_status.ports = get_ports(server_name, service.service_name);
// Thread-safe update of the status map
std::lock_guard<std::mutex> lock(status_mutex);
status[service.service_name] = service_status;
});
task->wait();
// Parse JSON response
try {
nlohmann::json json_response = nlohmann::json::parse(output);
if (!json_response.contains("services") || !json_response["services"].is_array()) {
debug << "Invalid JSON response from all_status.sh" << std::endl;
return status;
}
for (const auto& service_json : json_response["services"]) {
if (!service_json.contains("name") || !service_json["name"].is_string()) {
continue;
}
std::string service_name = service_json["name"].get<std::string>();
ServiceStatus service_status;
// Parse status
if (service_json.contains("status") && service_json["status"].is_string()) {
std::string status_str = service_json["status"].get<std::string>();
if (status_str == "Running") {
service_status.health = HealthStatus::HEALTHY;
} else if (status_str == "Stopped") {
service_status.health = HealthStatus::UNHEALTHY;
} else if (status_str == "Error") {
service_status.health = HealthStatus::ERROR;
} else {
service_status.health = HealthStatus::UNKNOWN;
}
} else {
service_status.health = HealthStatus::UNKNOWN;
}
// Parse ports
if (service_json.contains("ports") && service_json["ports"].is_string()) {
std::string ports_str = service_json["ports"].get<std::string>();
std::stringstream ss(ports_str);
std::string port_token;
while (ss >> port_token) {
// Remove any commas
port_token.erase(std::remove(port_token.begin(), port_token.end(), ','), port_token.end());
try {
int port = std::stoi(port_token);
if (port > 0 && port <= 65535) {
service_status.ports.push_back(port);
}
} catch (...) {
// Ignore non-numeric entries
}
}
}
status[service_name] = service_status;
}
} catch (const nlohmann::json::parse_error& e) {
debug << "Failed to parse JSON from all_status.sh: " << e.what() << std::endl;
debug << "Output was: " << output << std::endl;
}
return status;