@@ -440,6 +440,93 @@ fn print_command_result(info: &AgentCommandInfo, json: bool) {
440440 }
441441}
442442
443+ fn print_health_result ( info : & AgentCommandInfo ) {
444+ if let Some ( ref result) = info. result {
445+ let result_type = result. get ( "type" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "" ) ;
446+
447+ // "all_health": list of all containers
448+ if result_type == "all_health" {
449+ let overall = result. get ( "status" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
450+ println ! ( "Overall: {} {}" , progress:: status_icon( overall) , overall) ;
451+ println ! ( ) ;
452+ if let Some ( containers) = result. get ( "containers" ) . and_then ( |v| v. as_array ( ) ) {
453+ println ! ( "{:<28} {:<10} {}" , "CONTAINER" , "STATE" , "STATUS" ) ;
454+ for c in containers {
455+ let name = c. get ( "container_name" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
456+ let state = c. get ( "container_state" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
457+ let status = c. get ( "status" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
458+ println ! (
459+ "{:<28} {} {:<8} {}" ,
460+ fmt:: truncate( name, 26 ) ,
461+ progress:: status_icon( state) ,
462+ state,
463+ status,
464+ ) ;
465+ }
466+ }
467+ return ;
468+ }
469+
470+ // Single-container health
471+ if result_type == "health" {
472+ let state = result. get ( "container_state" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
473+ let status = result. get ( "status" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
474+ let app = result. get ( "app_code" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
475+ println ! (
476+ "{}: {} {} ({})" ,
477+ app,
478+ progress:: status_icon( state) ,
479+ state,
480+ status
481+ ) ;
482+ if let Some ( metrics) = result. get ( "metrics" ) {
483+ println ! ( "{}" , fmt:: pretty_json( metrics) ) ;
484+ }
485+ return ;
486+ }
487+
488+ // Fallback
489+ println ! ( "{}" , fmt:: pretty_json( result) ) ;
490+ }
491+
492+ if let Some ( error) = agent_command_error_message ( info) {
493+ eprintln ! ( "Error: {}" , error) ;
494+ }
495+ }
496+
497+ fn print_all_container_health ( containers : & [ serde_json:: Value ] ) {
498+ if containers. is_empty ( ) {
499+ println ! ( "No containers found." ) ;
500+ return ;
501+ }
502+
503+ let all_running = containers. iter ( ) . all ( |c| {
504+ let state = c. get ( "status" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
505+ state == "running"
506+ } ) ;
507+ let overall = if all_running { "running" } else { "degraded" } ;
508+ println ! ( "Overall: {} {}" , progress:: status_icon( overall) , overall) ;
509+ println ! ( ) ;
510+
511+ println ! ( "{:<28} {:<12} {:<8} {:<8} {}" , "CONTAINER" , "STATE" , "CPU%" , "MEM%" , "IMAGE" ) ;
512+ for c in containers {
513+ let name = c. get ( "name" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
514+ let state = c. get ( "status" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
515+ let image = c. get ( "image" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
516+ let cpu = c. get ( "cpu_pct" ) . and_then ( |v| v. as_f64 ( ) ) . unwrap_or ( 0.0 ) ;
517+ let mem = c. get ( "mem_pct" ) . and_then ( |v| v. as_f64 ( ) ) . unwrap_or ( 0.0 ) ;
518+ println ! (
519+ "{:<28} {} {:<10} {:<8.1} {:<8.1} {}" ,
520+ fmt:: truncate( name, 26 ) ,
521+ progress:: status_icon( state) ,
522+ state,
523+ cpu,
524+ mem,
525+ fmt:: truncate( image, 30 ) ,
526+ ) ;
527+ }
528+ }
529+
443530/// Pre-flight connection check for risky agent commands.
444531///
445532/// Enqueues a `check_connections` command to the agent and, if active HTTP
@@ -566,8 +653,21 @@ impl CallableTrait for AgentHealthCommand {
566653 let ctx = CliRuntime :: new ( "agent health" ) ?;
567654 let hash = resolve_deployment_hash ( & self . deployment , & ctx) ?;
568655
656+ // No specific app requested → list all containers with health metrics.
657+ // This avoids sending app_code="all" to older agents that don't handle it.
658+ if self . app_code . is_none ( ) && !self . include_system {
659+ let containers = fetch_live_containers ( & ctx, & hash) ?
660+ . unwrap_or_default ( ) ;
661+ if self . json {
662+ println ! ( "{}" , serde_json:: to_string_pretty( & containers) ?) ;
663+ } else {
664+ print_all_container_health ( & containers) ;
665+ }
666+ return Ok ( ( ) ) ;
667+ }
668+
569669 let params = crate :: forms:: status_panel:: HealthCommandRequest {
570- app_code : self . app_code . clone ( ) . unwrap_or_else ( || "all" . to_string ( ) ) ,
670+ app_code : self . app_code . clone ( ) . unwrap_or_default ( ) ,
571671 container : None ,
572672 include_metrics : true ,
573673 include_system : self . include_system ,
@@ -578,7 +678,11 @@ impl CallableTrait for AgentHealthCommand {
578678 . map_err ( |e| CliError :: ConfigValidation ( format ! ( "Invalid parameters: {}" , e) ) ) ?;
579679
580680 let info = run_agent_command ( & ctx, & request, "Checking health" , DEFAULT_TIMEOUT_SECS ) ?;
581- print_command_result ( & info, self . json ) ;
681+ if self . json {
682+ print_command_result ( & info, true ) ;
683+ } else {
684+ print_health_result ( & info) ;
685+ }
582686 Ok ( ( ) )
583687 }
584688}
@@ -1660,7 +1764,7 @@ fn print_containers_summary(containers: &[serde_json::Value]) {
16601764 return ;
16611765 }
16621766
1663- println ! ( "{:<24} {:<12} {:<30}" , "CONTAINER" , "STATE" , "IMAGE" ) ;
1767+ println ! ( "{:<24} {:<12} {:<22} {:< 30}" , "CONTAINER" , "STATE" , "PORTS ", "IMAGE" ) ;
16641768 for c in containers {
16651769 let name = c. get ( "name" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
16661770 let state = c
@@ -1669,11 +1773,23 @@ fn print_containers_summary(containers: &[serde_json::Value]) {
16691773 . and_then ( |v| v. as_str ( ) )
16701774 . unwrap_or ( "-" ) ;
16711775 let image = c. get ( "image" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "-" ) ;
1776+ let ports = c
1777+ . get ( "ports" )
1778+ . and_then ( |v| v. as_array ( ) )
1779+ . map ( |arr| {
1780+ arr. iter ( )
1781+ . filter_map ( |p| p. as_str ( ) )
1782+ . collect :: < Vec < _ > > ( )
1783+ . join ( ", " )
1784+ } )
1785+ . filter ( |s| !s. is_empty ( ) )
1786+ . unwrap_or_else ( || "-" . to_string ( ) ) ;
16721787 println ! (
1673- "{:<24} {} {:<10} {:<30}" ,
1788+ "{:<24} {} {:<10} {:<22} {:< 30}" ,
16741789 fmt:: truncate( name, 22 ) ,
16751790 progress:: status_icon( state) ,
16761791 state,
1792+ fmt:: truncate( & ports, 20 ) ,
16771793 fmt:: truncate( image, 28 ) ,
16781794 ) ;
16791795 }
0 commit comments