Merge pull request #4453 from thaJeztah/small_interface_waitExitOrRemoved

cli/command/container: waitExitOrRemoved: take APIClient as argument
This commit is contained in:
Sebastiaan van Stijn 2023-07-24 14:03:10 +02:00 committed by GitHub
commit e0e2772439
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 20 deletions

View File

@ -187,7 +187,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
defer closeFn() defer closeFn()
} }
statusChan := waitExitOrRemoved(ctx, dockerCli, containerID, copts.autoRemove) statusChan := waitExitOrRemoved(ctx, dockerCli.Client(), containerID, copts.autoRemove)
// start the container // start the container
if err := client.ContainerStart(ctx, containerID, types.ContainerStartOptions{}); err != nil { if err := client.ContainerStart(ctx, containerID, types.ContainerStartOptions{}); err != nil {

View File

@ -145,14 +145,14 @@ func RunStart(dockerCli command.Cli, opts *StartOptions) error {
// 3. We should open a channel for receiving status code of the container // 3. We should open a channel for receiving status code of the container
// no matter it's detached, removed on daemon side(--rm) or exit normally. // no matter it's detached, removed on daemon side(--rm) or exit normally.
statusChan := waitExitOrRemoved(ctx, dockerCli, c.ID, c.HostConfig.AutoRemove) statusChan := waitExitOrRemoved(ctx, dockerCli.Client(), c.ID, c.HostConfig.AutoRemove)
startOptions := types.ContainerStartOptions{
CheckpointID: opts.Checkpoint,
CheckpointDir: opts.CheckpointDir,
}
// 4. Start the container. // 4. Start the container.
if err := dockerCli.Client().ContainerStart(ctx, c.ID, startOptions); err != nil { err = dockerCli.Client().ContainerStart(ctx, c.ID, types.ContainerStartOptions{
CheckpointID: opts.Checkpoint,
CheckpointDir: opts.CheckpointDir,
})
if err != nil {
cancelFun() cancelFun()
<-cErr <-cErr
if c.HostConfig.AutoRemove { if c.HostConfig.AutoRemove {

View File

@ -4,16 +4,16 @@ import (
"context" "context"
"strconv" "strconv"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
func waitExitOrRemoved(ctx context.Context, dockerCli command.Cli, containerID string, waitRemove bool) <-chan int { func waitExitOrRemoved(ctx context.Context, apiClient client.APIClient, containerID string, waitRemove bool) <-chan int {
if len(containerID) == 0 { if len(containerID) == 0 {
// containerID can never be empty // containerID can never be empty
panic("Internal Error: waitExitOrRemoved needs a containerID as parameter") panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
@ -22,8 +22,8 @@ func waitExitOrRemoved(ctx context.Context, dockerCli command.Cli, containerID s
// Older versions used the Events API, and even older versions did not // Older versions used the Events API, and even older versions did not
// support server-side removal. This legacyWaitExitOrRemoved method // support server-side removal. This legacyWaitExitOrRemoved method
// preserves that old behavior and any issues it may have. // preserves that old behavior and any issues it may have.
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") { if versions.LessThan(apiClient.ClientVersion(), "1.30") {
return legacyWaitExitOrRemoved(ctx, dockerCli, containerID, waitRemove) return legacyWaitExitOrRemoved(ctx, apiClient, containerID, waitRemove)
} }
condition := container.WaitConditionNextExit condition := container.WaitConditionNextExit
@ -31,7 +31,7 @@ func waitExitOrRemoved(ctx context.Context, dockerCli command.Cli, containerID s
condition = container.WaitConditionRemoved condition = container.WaitConditionRemoved
} }
resultC, errC := dockerCli.Client().ContainerWait(ctx, containerID, condition) resultC, errC := apiClient.ContainerWait(ctx, containerID, condition)
statusC := make(chan int) statusC := make(chan int)
go func() { go func() {
@ -52,7 +52,7 @@ func waitExitOrRemoved(ctx context.Context, dockerCli command.Cli, containerID s
return statusC return statusC
} }
func legacyWaitExitOrRemoved(ctx context.Context, dockerCli command.Cli, containerID string, waitRemove bool) <-chan int { func legacyWaitExitOrRemoved(ctx context.Context, apiClient client.APIClient, containerID string, waitRemove bool) <-chan int {
var removeErr error var removeErr error
statusChan := make(chan int) statusChan := make(chan int)
exitCode := 125 exitCode := 125
@ -65,7 +65,7 @@ func legacyWaitExitOrRemoved(ctx context.Context, dockerCli command.Cli, contain
Filters: f, Filters: f,
} }
eventCtx, cancel := context.WithCancel(ctx) eventCtx, cancel := context.WithCancel(ctx)
eventq, errq := dockerCli.Client().Events(eventCtx, options) eventq, errq := apiClient.Events(eventCtx, options)
eventProcessor := func(e events.Message) bool { eventProcessor := func(e events.Message) bool {
stopProcessing := false stopProcessing := false
@ -84,9 +84,9 @@ func legacyWaitExitOrRemoved(ctx context.Context, dockerCli command.Cli, contain
} else { } else {
// If we are talking to an older daemon, `AutoRemove` is not supported. // If we are talking to an older daemon, `AutoRemove` is not supported.
// We need to fall back to the old behavior, which is client-side removal // We need to fall back to the old behavior, which is client-side removal
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.25") { if versions.LessThan(apiClient.ClientVersion(), "1.25") {
go func() { go func() {
removeErr = dockerCli.Client().ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{RemoveVolumes: true}) removeErr = apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{RemoveVolumes: true})
if removeErr != nil { if removeErr != nil {
logrus.Errorf("error removing container: %v", removeErr) logrus.Errorf("error removing container: %v", removeErr)
cancel() // cancel the event Q cancel() // cancel the event Q

View File

@ -2,13 +2,12 @@ package container
import ( import (
"context" "context"
"fmt"
"strings" "strings"
"testing" "testing"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api" "github.com/docker/docker/api"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/pkg/errors"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
) )
@ -24,7 +23,7 @@ func waitFn(cid string) (<-chan container.WaitResponse, <-chan error) {
res.StatusCode = 42 res.StatusCode = 42
resC <- res resC <- res
case strings.Contains(cid, "non-existent"): case strings.Contains(cid, "non-existent"):
err := errors.Errorf("no such container: %v", cid) err := fmt.Errorf("no such container: %v", cid)
errC <- err errC <- err
case strings.Contains(cid, "wait-error"): case strings.Contains(cid, "wait-error"):
res.Error = &container.WaitExitError{Message: "removal failed"} res.Error = &container.WaitExitError{Message: "removal failed"}
@ -61,7 +60,7 @@ func TestWaitExitOrRemoved(t *testing.T) {
}, },
} }
client := test.NewFakeCli(&fakeClient{waitFunc: waitFn, Version: api.DefaultVersion}) client := &fakeClient{waitFunc: waitFn, Version: api.DefaultVersion}
for _, testcase := range testcases { for _, testcase := range testcases {
statusC := waitExitOrRemoved(context.Background(), client, testcase.cid, true) statusC := waitExitOrRemoved(context.Background(), client, testcase.cid, true)
exitCode := <-statusC exitCode := <-statusC