check agent on ds list
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Successful in 34s
Build-Test-Publish / build (linux/arm64) (push) Has been cancelled

This commit is contained in:
j
2026-01-02 22:36:02 +13:00
parent ae5a6fabe9
commit 226707539b
3 changed files with 30 additions and 17 deletions

View File

@@ -83,7 +83,7 @@ void list_servers() {
} }
tableprint tp("All DropShell Servers"); tableprint tp("All DropShell Servers");
tp.add_row({"Name", "Address", "User", "Health", "Ports"}); tp.add_row({"Name", "Address", "User", "Agent", "Health", "Ports"});
typedef std::map<std::string, shared_commands::ServiceStatus> tServiceStatusMap; typedef std::map<std::string, shared_commands::ServiceStatus> tServiceStatusMap;
@@ -166,8 +166,9 @@ void list_servers() {
} }
// Only check service status if server is online and not disabled // Only check service status if server is online and not disabled
bool agent_match = true;
if (is_online && !is_disabled) { if (is_online && !is_disabled) {
std::map<std::string, shared_commands::ServiceStatus> status = shared_commands::get_all_services_status(sup.server.get_server_name(),sup.user.user); std::map<std::string, shared_commands::ServiceStatus> status = shared_commands::get_all_services_status(sup.server.get_server_name(),sup.user.user, &agent_match);
for (const auto& [service_name, service_status] : status) { for (const auto& [service_name, service_status] : status) {
ports_used.insert(service_status.ports.begin(), service_status.ports.end()); ports_used.insert(service_status.ports.begin(), service_status.ports.end());
@@ -178,6 +179,12 @@ void list_servers() {
ports_used_str += std::to_string(port) + " "; ports_used_str += std::to_string(port) + " ";
} }
// Agent status column
std::string agent_status = "";
if (is_online && !is_disabled) {
agent_status = agent_match ? ":tick:" : ":cross:";
}
// Add red cross to address if server is offline // Add red cross to address if server is offline
std::string address_display = sup.server.get_SSH_HOST(); std::string address_display = sup.server.get_SSH_HOST();
if (!is_online && !is_disabled) { if (!is_online && !is_disabled) {
@@ -193,7 +200,7 @@ void list_servers() {
// critical section // critical section
{ {
std::lock_guard<std::mutex> lock(tp_mutex); std::lock_guard<std::mutex> lock(tp_mutex);
tp.add_row({server_name_display, address_display, sup.user.user, serviceticks, ports_used_str}); tp.add_row({server_name_display, address_display, sup.user.user, agent_status, serviceticks, ports_used_str});
++checked; ++checked;
} }
// print out a tick character for each server checked. // print out a tick character for each server checked.

View File

@@ -154,20 +154,30 @@ namespace dropshell
// get_all_services_status : SHARED COMMAND // get_all_services_status : SHARED COMMAND
// Uses all_status.sh on the remote server to get status for all services in one SSH call // 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) std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, bool* agent_match)
{ {
std::map<std::string, ServiceStatus> status; std::map<std::string, ServiceStatus> status;
bool all_match = true;
bool any_checked = false;
for (const auto& user : server_env.get_users()) { for (const auto& user : server_env.get_users()) {
status.merge(get_all_services_status(server_env, user.user)); bool user_match = false;
status.merge(get_all_services_status(server_env, user.user, &user_match));
if (!user_match) all_match = false;
any_checked = true;
} }
// Only report match if we actually checked something and all matched
if (agent_match) *agent_match = (any_checked && all_match);
return status; return status;
} }
std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, std::string user) std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, std::string user, bool* agent_match)
{ {
std::map<std::string, ServiceStatus> status; std::map<std::string, ServiceStatus> status;
std::string server_name = server_env.get_server_name(); std::string server_name = server_env.get_server_name();
// Default to false (mismatch/unknown) - only set to true if we get explicit confirmation
if (agent_match) *agent_match = false;
// Run all_status.sh on the remote server to get all service statuses in one call // 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 agent_path = remotepath(server_name, user).agent();
std::string script_path = agent_path + "/all_status.sh"; std::string script_path = agent_path + "/all_status.sh";
@@ -192,16 +202,12 @@ namespace dropshell
try { try {
nlohmann::json json_response = nlohmann::json::parse(output); nlohmann::json json_response = nlohmann::json::parse(output);
// Check agent hash match // Check agent hash match - if field is missing, agent is too old (mismatch)
if (json_response.contains("agent_match") && json_response["agent_match"].is_boolean()) { if (json_response.contains("agent_match") && json_response["agent_match"].is_boolean()) {
if (!json_response["agent_match"].get<bool>()) { bool match = json_response["agent_match"].get<bool>();
std::string remote_hash = json_response.contains("agent_hash") ? if (agent_match) *agent_match = match;
json_response["agent_hash"].get<std::string>() : "unknown";
warning << "Agent mismatch on " << server_name << " (remote: " << remote_hash.substr(0, 8)
<< "..., expected: " << expected_hash.substr(0, 8) << "...)" << std::endl;
warning << "Run 'ds install " << server_name << "' to update the agent" << std::endl;
}
} }
// If agent_match field is missing, leave as false (old agent = needs update)
if (!json_response.contains("services") || !json_response["services"].is_array()) { if (!json_response.contains("services") || !json_response["services"].is_array()) {
debug << "Invalid JSON response from all_status.sh" << std::endl; debug << "Invalid JSON response from all_status.sh" << std::endl;

View File

@@ -68,8 +68,8 @@ namespace dropshell
std::string get_arch(); std::string get_arch();
std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env); std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, bool* agent_match = nullptr);
std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, std::string user); std::map<std::string, ServiceStatus> get_all_services_status(const ServerConfig & server_env, std::string user, bool* agent_match = nullptr);
std::string healthtick(const std::string &server, const std::string &service); std::string healthtick(const std::string &server, const std::string &service);
std::string HealthStatus2String(HealthStatus status); std::string HealthStatus2String(HealthStatus status);