@@ -32,6 +32,7 @@ import (
3232 "github.com/containerd/nerdctl/mod/tigron/tig"
3333
3434 "github.com/containerd/nerdctl/v2/pkg/healthcheck"
35+ "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
3536 "github.com/containerd/nerdctl/v2/pkg/rootlessutil"
3637 "github.com/containerd/nerdctl/v2/pkg/testutil"
3738 "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
@@ -931,6 +932,107 @@ func TestHealthCheck_SystemdIntegration_Basic(t *testing.T) {
931932 testCase .Run (t )
932933}
933934
935+ func TestHealthCheck_GlobalFlags (t * testing.T ) {
936+ testCase := nerdtest .Setup ()
937+ testCase .Require = require .Not (nerdtest .Docker )
938+ // Skip systemd tests in rootless environment to bypass dbus permission issues
939+ if rootlessutil .IsRootless () {
940+ t .Skip ("systemd healthcheck tests are skipped in rootless environment" )
941+ }
942+
943+ testCase .SubTests = []* test.Case {
944+ {
945+ Description : "Healthcheck works with custom namespace flag" ,
946+ Setup : func (data test.Data , helpers test.Helpers ) {
947+ // Create container in custom namespace with healthcheck
948+ helpers .Ensure ("--namespace=healthcheck-test" , "run" , "-d" , "--name" , data .Identifier (),
949+ "--health-cmd" , "echo healthy" ,
950+ "--health-interval" , "2s" ,
951+ testutil .CommonImage , "sleep" , "30" )
952+ // Wait a bit to ensure container is running (can't use EnsureContainerStarted with custom namespace)
953+ time .Sleep (1 * time .Second )
954+ },
955+ Cleanup : func (data test.Data , helpers test.Helpers ) {
956+ helpers .Anyhow ("--namespace=healthcheck-test" , "rm" , "-f" , data .Identifier ())
957+ },
958+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
959+ // Wait a bit for healthcheck to run
960+ time .Sleep (3 * time .Second )
961+ // Verify container is accessible in the custom namespace
962+ return helpers .Command ("--namespace=healthcheck-test" , "inspect" , data .Identifier ())
963+ },
964+ Expected : func (data test.Data , helpers test.Helpers ) * test.Expected {
965+ return & test.Expected {
966+ ExitCode : 0 ,
967+ Output : func (stdout string , t tig.T ) {
968+ var inspectResults []dockercompat.Container
969+ err := json .Unmarshal ([]byte (stdout ), & inspectResults )
970+ assert .NilError (t , err , "failed to parse inspect output" )
971+ assert .Assert (t , len (inspectResults ) > 0 , "expected at least one container in inspect results" )
972+
973+ inspect := inspectResults [0 ]
974+ h := inspect .State .Health
975+ assert .Assert (t , h != nil , "expected health state to be present" )
976+ assert .Assert (t , h .Status == healthcheck .Healthy || h .Status == healthcheck .Starting ,
977+ "expected health status to be healthy or starting, got: %s" , h .Status )
978+ assert .Assert (t , len (h .Log ) > 0 , "expected at least one health check log entry" )
979+ },
980+ }
981+ },
982+ },
983+ {
984+ Description : "Healthcheck works correctly with namespace after container restart" ,
985+ Setup : func (data test.Data , helpers test.Helpers ) {
986+ // Create container in custom namespace
987+ helpers .Ensure ("--namespace=restart-test" , "run" , "-d" , "--name" , data .Identifier (),
988+ "--health-cmd" , "echo healthy" ,
989+ "--health-interval" , "2s" ,
990+ testutil .CommonImage , "sleep" , "60" )
991+ // Wait a bit to ensure container is running (can't use EnsureContainerStarted with custom namespace)
992+ time .Sleep (1 * time .Second )
993+ },
994+ Cleanup : func (data test.Data , helpers test.Helpers ) {
995+ helpers .Anyhow ("--namespace=restart-test" , "rm" , "-f" , data .Identifier ())
996+ },
997+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
998+ // Wait for initial healthcheck
999+ time .Sleep (3 * time .Second )
1000+
1001+ // Stop and restart the container
1002+ helpers .Ensure ("--namespace=restart-test" , "stop" , data .Identifier ())
1003+ helpers .Ensure ("--namespace=restart-test" , "start" , data .Identifier ())
1004+ // Wait a bit to ensure container is running after restart
1005+ time .Sleep (1 * time .Second )
1006+
1007+ // Wait for healthcheck to run after restart
1008+ time .Sleep (3 * time .Second )
1009+
1010+ return helpers .Command ("--namespace=restart-test" , "inspect" , data .Identifier ())
1011+ },
1012+ Expected : func (data test.Data , helpers test.Helpers ) * test.Expected {
1013+ return & test.Expected {
1014+ ExitCode : 0 ,
1015+ Output : func (stdout string , t tig.T ) {
1016+ // Parse the inspect JSON output directly since we're in a custom namespace
1017+ var inspectResults []dockercompat.Container
1018+ err := json .Unmarshal ([]byte (stdout ), & inspectResults )
1019+ assert .NilError (t , err , "failed to parse inspect output" )
1020+ assert .Assert (t , len (inspectResults ) > 0 , "expected at least one container in inspect results" )
1021+
1022+ inspect := inspectResults [0 ]
1023+ h := inspect .State .Health
1024+ assert .Assert (t , h != nil , "expected health state after restart" )
1025+ assert .Assert (t , h .Status == healthcheck .Healthy || h .Status == healthcheck .Starting ,
1026+ "expected health status to be healthy or starting after restart, got: %s" , h .Status )
1027+ assert .Assert (t , len (h .Log ) > 0 , "expected health check logs after restart" )
1028+ },
1029+ }
1030+ },
1031+ },
1032+ }
1033+ testCase .Run (t )
1034+ }
1035+
9341036func TestHealthCheck_SystemdIntegration_Advanced (t * testing.T ) {
9351037 testCase := nerdtest .Setup ()
9361038 testCase .Require = require .Not (nerdtest .Docker )
0 commit comments