container wait: support health states

Support two new wait conditions, "healthy" and "unhealthy".  This
further paves the way for integrating sdnotify with health checks which
is currently being tracked in #6160.

Fixes: #13627
Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2023-06-22 10:47:24 +02:00
parent 811867249b
commit 1398cbce8a
10 changed files with 137 additions and 47 deletions

View File

@ -698,17 +698,26 @@ func (c *Container) WaitForConditionWithInterval(ctx context.Context, waitTimeou
resultChan := make(chan waitResult)
waitForExit := false
wantedStates := make(map[define.ContainerStatus]bool, len(conditions))
wantedHealthStates := make(map[string]bool)
for _, rawCondition := range conditions {
condition, err := define.StringToContainerStatus(rawCondition)
if err != nil {
return -1, err
}
switch condition {
case define.ContainerStateExited, define.ContainerStateStopped:
waitForExit = true
switch rawCondition {
case define.HealthCheckHealthy, define.HealthCheckUnhealthy:
if !c.HasHealthCheck() {
return -1, fmt.Errorf("cannot use condition %q: container %s has no healthcheck", rawCondition, c.ID())
}
wantedHealthStates[rawCondition] = true
default:
wantedStates[condition] = true
condition, err := define.StringToContainerStatus(rawCondition)
if err != nil {
return -1, err
}
switch condition {
case define.ContainerStateExited, define.ContainerStateStopped:
waitForExit = true
default:
wantedStates[condition] = true
}
}
}
@ -731,20 +740,33 @@ func (c *Container) WaitForConditionWithInterval(ctx context.Context, waitTimeou
}()
}
if len(wantedStates) > 0 {
if len(wantedStates) > 0 || len(wantedHealthStates) > 0 {
wg.Add(1)
go func() {
defer wg.Done()
for {
state, err := c.State()
if err != nil {
trySend(-1, err)
return
if len(wantedStates) > 0 {
state, err := c.State()
if err != nil {
trySend(-1, err)
return
}
if _, found := wantedStates[state]; found {
trySend(-1, nil)
return
}
}
if _, found := wantedStates[state]; found {
trySend(-1, nil)
return
if len(wantedHealthStates) > 0 {
status, err := c.HealthCheckStatus()
if err != nil {
trySend(-1, err)
return
}
if _, found := wantedHealthStates[status]; found {
trySend(-1, nil)
return
}
}
select {
case <-ctx.Done():