mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Handle run --rm
against older daemons on the cli
For previous versions of Docker, `--rm` was handled client side, as such
there was no support in the daemon for it.
Now it is handled daemon side, but we still need to handle the case of a
newer client talking to an older daemon.
Falls back to client-side removal when the daemon does not support it.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit f4bb8c51de
)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
This commit is contained in:
parent
2d5f5287c3
commit
b4c0b07d89
1 changed files with 33 additions and 22 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"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/cli/command"
|
"github.com/docker/docker/cli/command"
|
||||||
clientapi "github.com/docker/docker/client"
|
clientapi "github.com/docker/docker/client"
|
||||||
)
|
)
|
||||||
|
@ -19,11 +20,21 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
|
||||||
panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
|
panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var removeErr error
|
||||||
statusChan := make(chan int)
|
statusChan := make(chan int)
|
||||||
exitCode := 125
|
exitCode := 125
|
||||||
|
|
||||||
eventProcessor := func(e events.Message) bool {
|
// Get events via Events API
|
||||||
|
f := filters.NewArgs()
|
||||||
|
f.Add("type", "container")
|
||||||
|
f.Add("container", containerID)
|
||||||
|
options := types.EventsOptions{
|
||||||
|
Filters: f,
|
||||||
|
}
|
||||||
|
eventCtx, cancel := context.WithCancel(ctx)
|
||||||
|
eventq, errq := dockerCli.Client().Events(eventCtx, options)
|
||||||
|
|
||||||
|
eventProcessor := func(e events.Message) bool {
|
||||||
stopProcessing := false
|
stopProcessing := false
|
||||||
switch e.Status {
|
switch e.Status {
|
||||||
case "die":
|
case "die":
|
||||||
|
@ -37,6 +48,18 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
|
||||||
}
|
}
|
||||||
if !waitRemove {
|
if !waitRemove {
|
||||||
stopProcessing = true
|
stopProcessing = true
|
||||||
|
} else {
|
||||||
|
// 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
|
||||||
|
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.25") {
|
||||||
|
go func() {
|
||||||
|
removeErr = dockerCli.Client().ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{RemoveVolumes: true})
|
||||||
|
if removeErr != nil {
|
||||||
|
logrus.Errorf("error removing container: %v", removeErr)
|
||||||
|
cancel() // cancel the event Q
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case "detach":
|
case "detach":
|
||||||
exitCode = 0
|
exitCode = 0
|
||||||
|
@ -44,39 +67,27 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
|
||||||
case "destroy":
|
case "destroy":
|
||||||
stopProcessing = true
|
stopProcessing = true
|
||||||
}
|
}
|
||||||
|
return stopProcessing
|
||||||
if stopProcessing {
|
|
||||||
statusChan <- exitCode
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get events via Events API
|
|
||||||
f := filters.NewArgs()
|
|
||||||
f.Add("type", "container")
|
|
||||||
f.Add("container", containerID)
|
|
||||||
options := types.EventsOptions{
|
|
||||||
Filters: f,
|
|
||||||
}
|
|
||||||
|
|
||||||
eventCtx, cancel := context.WithCancel(ctx)
|
|
||||||
eventq, errq := dockerCli.Client().Events(eventCtx, options)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer cancel()
|
defer func() {
|
||||||
|
statusChan <- exitCode // must always send an exit code or the caller will block
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
case <-eventCtx.Done():
|
||||||
|
if removeErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
case evt := <-eventq:
|
case evt := <-eventq:
|
||||||
if eventProcessor(evt) {
|
if eventProcessor(evt) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
case err := <-errq:
|
case err := <-errq:
|
||||||
logrus.Errorf("error getting events from daemon: %v", err)
|
logrus.Errorf("error getting events from daemon: %v", err)
|
||||||
statusChan <- exitCode
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue