Browse code

api/types/container: make HealthStatus a concrete type

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/11/08 02:36:12
Showing 8 changed files
... ...
@@ -7,9 +7,7 @@ import (
7 7
 )
8 8
 
9 9
 // HealthStatus is a string representation of the container's health.
10
-//
11
-// It currently is an alias for string, but may become a distinct type in future.
12
-type HealthStatus = string
10
+type HealthStatus string
13 11
 
14 12
 // Health states
15 13
 const (
... ...
@@ -41,7 +39,10 @@ type HealthcheckResult struct {
41 41
 }
42 42
 
43 43
 var validHealths = []string{
44
-	NoHealthcheck, Starting, Healthy, Unhealthy,
44
+	string(NoHealthcheck),
45
+	string(Starting),
46
+	string(Healthy),
47
+	string(Unhealthy),
45 48
 }
46 49
 
47 50
 // ValidateHealthStatus checks if the provided string is a valid
... ...
@@ -19,7 +19,7 @@ func TestValidateHealthStatus(t *testing.T) {
19 19
 	}
20 20
 
21 21
 	for _, tc := range tests {
22
-		t.Run(tc.health, func(t *testing.T) {
22
+		t.Run(string(tc.health), func(t *testing.T) {
23 23
 			err := ValidateHealthStatus(tc.health)
24 24
 			if tc.expectedErr == "" {
25 25
 				assert.NilError(t, err)
... ...
@@ -23,7 +23,7 @@ func (s *Health) String() string {
23 23
 	case container.Starting:
24 24
 		return "health: starting"
25 25
 	default: // Healthy and Unhealthy are clear on their own
26
-		return status
26
+		return string(status)
27 27
 	}
28 28
 }
29 29
 
... ...
@@ -244,7 +244,7 @@ func handleProbeResult(d *Daemon, c *container.Container, result *containertypes
244 244
 
245 245
 	current := h.Status()
246 246
 	if oldStatus != current {
247
-		d.LogContainerEvent(c, events.Action(string(events.ActionHealthStatus)+": "+current))
247
+		d.LogContainerEvent(c, events.Action(string(events.ActionHealthStatus)+": "+string(current)))
248 248
 	}
249 249
 }
250 250
 
... ...
@@ -298,7 +298,7 @@ func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, conf
298 298
 	}
299 299
 
300 300
 	err = psFilters.WalkValues("health", func(value string) error {
301
-		if err := containertypes.ValidateHealthStatus(value); err != nil {
301
+		if err := containertypes.ValidateHealthStatus(containertypes.HealthStatus(value)); err != nil {
302 302
 			return errdefs.InvalidParameter(fmt.Errorf("invalid filter 'health=%s': %w", value, err))
303 303
 		}
304 304
 		return nil
... ...
@@ -491,7 +491,7 @@ func includeContainerInList(container *container.Snapshot, filter *listContext)
491 491
 	}
492 492
 
493 493
 	// Do not include container if its health doesn't match the filter
494
-	if !filter.filters.ExactMatch("health", container.Health) {
494
+	if !filter.filters.ExactMatch("health", string(container.Health)) {
495 495
 		return excludeContainer
496 496
 	}
497 497
 
... ...
@@ -26,16 +26,17 @@ func (s *DockerCLIHealthSuite) OnTimeout(t *testing.T) {
26 26
 	s.ds.OnTimeout(t)
27 27
 }
28 28
 
29
-func waitForHealthStatus(t *testing.T, name string, prev string, expected string) {
30
-	prev = prev + "\n"
31
-	expected = expected + "\n"
29
+func waitForHealthStatus(t *testing.T, name string, prev container.HealthStatus, expected container.HealthStatus) {
32 30
 	for {
33 31
 		out := cli.DockerCmd(t, "inspect", "--format={{.State.Health.Status}}", name).Stdout()
34
-		if out == expected {
32
+		actual := container.HealthStatus(strings.TrimSpace(out))
33
+		if actual == expected {
35 34
 			return
36 35
 		}
37
-		assert.Equal(t, out, prev)
38
-		if out != prev {
36
+
37
+		// TODO(thaJeztah): this logic seems broken? assert.Assert would make it fail, so why the "actual != prev"?
38
+		assert.Equal(t, actual, prev)
39
+		if actual != prev {
39 40
 			return
40 41
 		}
41 42
 		time.Sleep(100 * time.Millisecond)
... ...
@@ -84,7 +85,7 @@ func (s *DockerCLIHealthSuite) TestHealth(c *testing.T) {
84 84
 
85 85
 	// Inspect the status
86 86
 	out = cli.DockerCmd(c, "inspect", "--format={{.State.Health.Status}}", name).Stdout()
87
-	assert.Equal(c, strings.TrimSpace(out), container.Unhealthy)
87
+	assert.Equal(c, container.HealthStatus(strings.TrimSpace(out)), container.Unhealthy)
88 88
 
89 89
 	// Make it healthy again
90 90
 	cli.DockerCmd(c, "exec", name, "touch", "/status")
... ...
@@ -140,10 +140,11 @@ func TestHealthStartInterval(t *testing.T) {
140 140
 			return poll.Error(err)
141 141
 		}
142 142
 		if inspect.Container.State.Health.Status != containertypes.Healthy {
143
+			var out string
143 144
 			if len(inspect.Container.State.Health.Log) > 0 {
144
-				t.Log(inspect.Container.State.Health.Log[len(inspect.Container.State.Health.Log)-1])
145
+				out = inspect.Container.State.Health.Log[len(inspect.Container.State.Health.Log)-1].Output
145 146
 			}
146
-			return poll.Continue("waiting on container to be ready")
147
+			return poll.Continue("waiting on container to be ready (%s): %s", inspect.Container.ID, out)
147 148
 		}
148 149
 		return poll.Success()
149 150
 	}, poll.WithTimeout(time.Until(dl)))
... ...
@@ -169,8 +170,7 @@ func TestHealthStartInterval(t *testing.T) {
169 169
 		if h1.Start.Sub(h2.Start) >= inspect.Container.Config.Healthcheck.Interval {
170 170
 			return poll.Success()
171 171
 		}
172
-		t.Log(h1.Start.Sub(h2.Start))
173
-		return poll.Continue("waiting for health check interval to switch from the start interval")
172
+		return poll.Continue("waiting for health check interval to switch from the start interval: %s", h1.Start.Sub(h2.Start))
174 173
 	}, poll.WithDelay(time.Second), poll.WithTimeout(time.Until(dl)))
175 174
 }
176 175
 
... ...
@@ -7,9 +7,7 @@ import (
7 7
 )
8 8
 
9 9
 // HealthStatus is a string representation of the container's health.
10
-//
11
-// It currently is an alias for string, but may become a distinct type in future.
12
-type HealthStatus = string
10
+type HealthStatus string
13 11
 
14 12
 // Health states
15 13
 const (
... ...
@@ -41,7 +39,10 @@ type HealthcheckResult struct {
41 41
 }
42 42
 
43 43
 var validHealths = []string{
44
-	NoHealthcheck, Starting, Healthy, Unhealthy,
44
+	string(NoHealthcheck),
45
+	string(Starting),
46
+	string(Healthy),
47
+	string(Unhealthy),
45 48
 }
46 49
 
47 50
 // ValidateHealthStatus checks if the provided string is a valid