github.com/lacework-dev/go-moby@v20.10.12+incompatible/integration/container/health_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/docker/docker/api/types" 9 containertypes "github.com/docker/docker/api/types/container" 10 "github.com/docker/docker/client" 11 "github.com/docker/docker/integration/internal/container" 12 "gotest.tools/v3/assert" 13 "gotest.tools/v3/poll" 14 "gotest.tools/v3/skip" 15 ) 16 17 // TestHealthCheckWorkdir verifies that health-checks inherit the containers' 18 // working-dir. 19 func TestHealthCheckWorkdir(t *testing.T) { 20 skip.If(t, testEnv.OSType == "windows", "FIXME") 21 defer setupTest(t)() 22 ctx := context.Background() 23 client := testEnv.APIClient() 24 25 cID := container.Run(ctx, t, client, container.WithTty(true), container.WithWorkingDir("/foo"), func(c *container.TestContainerConfig) { 26 c.Config.Healthcheck = &containertypes.HealthConfig{ 27 Test: []string{"CMD-SHELL", "if [ \"$PWD\" = \"/foo\" ]; then exit 0; else exit 1; fi;"}, 28 Interval: 50 * time.Millisecond, 29 Retries: 3, 30 } 31 }) 32 33 poll.WaitOn(t, pollForHealthStatus(ctx, client, cID, types.Healthy), poll.WithDelay(100*time.Millisecond)) 34 } 35 36 // GitHub #37263 37 // Do not stop healthchecks just because we sent a signal to the container 38 func TestHealthKillContainer(t *testing.T) { 39 skip.If(t, testEnv.OSType == "windows", "Windows only supports SIGKILL and SIGTERM? See https://github.com/moby/moby/issues/39574") 40 defer setupTest(t)() 41 42 ctx := context.Background() 43 client := testEnv.APIClient() 44 45 id := container.Run(ctx, t, client, func(c *container.TestContainerConfig) { 46 cmd := ` 47 # Set the initial HEALTH value so the healthcheck passes 48 HEALTH="1" 49 echo $HEALTH > /health 50 51 # Any time doHealth is run we flip the value 52 # This lets us use kill signals to determine when healtchecks have run. 53 doHealth() { 54 case "$HEALTH" in 55 "0") 56 HEALTH="1" 57 ;; 58 "1") 59 HEALTH="0" 60 ;; 61 esac 62 echo $HEALTH > /health 63 } 64 65 trap 'doHealth' USR1 66 67 while true; do sleep 1; done 68 ` 69 c.Config.Cmd = []string{"/bin/sh", "-c", cmd} 70 c.Config.Healthcheck = &containertypes.HealthConfig{ 71 Test: []string{"CMD-SHELL", `[ "$(cat /health)" = "1" ]`}, 72 Interval: time.Second, 73 Retries: 5, 74 } 75 }) 76 77 ctxPoll, cancel := context.WithTimeout(ctx, 30*time.Second) 78 defer cancel() 79 poll.WaitOn(t, pollForHealthStatus(ctxPoll, client, id, "healthy"), poll.WithDelay(100*time.Millisecond)) 80 81 err := client.ContainerKill(ctx, id, "SIGUSR1") 82 assert.NilError(t, err) 83 84 ctxPoll, cancel = context.WithTimeout(ctx, 30*time.Second) 85 defer cancel() 86 poll.WaitOn(t, pollForHealthStatus(ctxPoll, client, id, "unhealthy"), poll.WithDelay(100*time.Millisecond)) 87 88 err = client.ContainerKill(ctx, id, "SIGUSR1") 89 assert.NilError(t, err) 90 91 ctxPoll, cancel = context.WithTimeout(ctx, 30*time.Second) 92 defer cancel() 93 poll.WaitOn(t, pollForHealthStatus(ctxPoll, client, id, "healthy"), poll.WithDelay(100*time.Millisecond)) 94 } 95 96 func pollForHealthStatus(ctx context.Context, client client.APIClient, containerID string, healthStatus string) func(log poll.LogT) poll.Result { 97 return func(log poll.LogT) poll.Result { 98 inspect, err := client.ContainerInspect(ctx, containerID) 99 100 switch { 101 case err != nil: 102 return poll.Error(err) 103 case inspect.State.Health.Status == healthStatus: 104 return poll.Success() 105 default: 106 return poll.Continue("waiting for container to become %s", healthStatus) 107 } 108 } 109 }