From 6a1ddee68f7622e690279c550252ac967c6ea55b Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 27 Nov 2017 17:04:25 -0600 Subject: [PATCH] ex: dockergc: fix use of contexts --- pkg/oc/experimental/dockergc/client.go | 82 ++++++++++++++++++++++++ pkg/oc/experimental/dockergc/dockergc.go | 30 ++++----- 2 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 pkg/oc/experimental/dockergc/client.go diff --git a/pkg/oc/experimental/dockergc/client.go b/pkg/oc/experimental/dockergc/client.go new file mode 100644 index 000000000000..e43a4ffc5b57 --- /dev/null +++ b/pkg/oc/experimental/dockergc/client.go @@ -0,0 +1,82 @@ +package dockergc + +import ( + "context" + "time" + + dockerapi "github.com/docker/engine-api/client" + dockertypes "github.com/docker/engine-api/types" +) + +type dockerClient struct { + // timeout is the timeout of short running docker operations. + timeout time.Duration + // docker API client + client *dockerapi.Client +} + +func newDockerClient(timeout time.Duration) (*dockerClient, error) { + client, err := dockerapi.NewEnvClient() + if err != nil { + return nil, err + } + return &dockerClient{ + client: client, + timeout: timeout, + }, nil +} + +func clientErr(ctx context.Context, err error) error { + if ctx.Err() != nil { + return ctx.Err() + } + return err +} + +func (c *dockerClient) getTimeoutContext() (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), c.timeout) +} + +func (c *dockerClient) Info() (*dockertypes.Info, error) { + ctx, cancel := c.getTimeoutContext() + defer cancel() + info, err := c.client.Info(ctx) + if err := clientErr(ctx, err); err != nil { + return nil, err + } + return &info, nil +} + +func (c *dockerClient) ContainerList(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) { + ctx, cancel := c.getTimeoutContext() + defer cancel() + containers, err := c.client.ContainerList(ctx, options) + if err := clientErr(ctx, err); err != nil { + return nil, err + } + return containers, nil +} + +func (c *dockerClient) ContainerRemove(id string, opts dockertypes.ContainerRemoveOptions) error { + ctx, cancel := c.getTimeoutContext() + defer cancel() + err := c.client.ContainerRemove(ctx, id, opts) + return clientErr(ctx, err) +} + +func (c *dockerClient) ImageList(opts dockertypes.ImageListOptions) ([]dockertypes.Image, error) { + ctx, cancel := c.getTimeoutContext() + defer cancel() + images, err := c.client.ImageList(ctx, opts) + if err := clientErr(ctx, err); err != nil { + return nil, err + } + return images, nil +} + +func (c *dockerClient) ImageRemove(image string, opts dockertypes.ImageRemoveOptions) error { + ctx, cancel := c.getTimeoutContext() + defer cancel() + _, err := c.client.ImageRemove(ctx, image, opts) + return clientErr(ctx, err) +} diff --git a/pkg/oc/experimental/dockergc/dockergc.go b/pkg/oc/experimental/dockergc/dockergc.go index 5bacc6116010..3853651b026d 100644 --- a/pkg/oc/experimental/dockergc/dockergc.go +++ b/pkg/oc/experimental/dockergc/dockergc.go @@ -1,7 +1,6 @@ package dockergc import ( - "context" "fmt" "io" "os" @@ -17,7 +16,6 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - dockerapi "github.com/docker/engine-api/client" dockertypes "github.com/docker/engine-api/types" dockerfilters "github.com/docker/engine-api/types/filters" "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" @@ -31,6 +29,8 @@ const ( var ( DefaultMinimumGCAge = metav1.Duration{Duration: time.Hour} + + dockerTimeout = time.Duration(2 * time.Minute) ) // DockerGCConfigCmdOptions are options supported by the dockergc admin command. @@ -146,7 +146,7 @@ func parseDockerTimestamp(s string) (time.Time, error) { return time.Parse(time.RFC3339Nano, s) } -func doGarbageCollection(ctx context.Context, client *dockerapi.Client, options *dockerGCConfigCmdOptions, rootDir string) error { +func doGarbageCollection(client *dockerClient, options *dockerGCConfigCmdOptions, rootDir string) error { glog.Infof("gathering disk usage data") capacityBytes, usageBytes, err := getRootDirInfo(rootDir) if err != nil { @@ -167,10 +167,7 @@ func doGarbageCollection(ctx context.Context, client *dockerapi.Client, options // conatiners exitedFilter := dockerfilters.NewArgs() exitedFilter.Add("status", "exited") - containers, err := client.ContainerList(ctx, dockertypes.ContainerListOptions{All: true, Filter: exitedFilter}) - if ctx.Err() == context.DeadlineExceeded { - return ctx.Err() - } + containers, err := client.ContainerList(dockertypes.ContainerListOptions{All: true, Filter: exitedFilter}) if err != nil { return err } @@ -189,7 +186,7 @@ func doGarbageCollection(ctx context.Context, client *dockerapi.Client, options glog.Infof("removing container %v (size: %v, age: %v)", c.ID, c.SizeRw, age) var err error if !options.DryRun { - err = client.ContainerRemove(ctx, c.ID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true}) + err = client.ContainerRemove(c.ID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true}) } if err != nil { glog.Infof("unable to remove container: %v", err) @@ -199,10 +196,7 @@ func doGarbageCollection(ctx context.Context, client *dockerapi.Client, options } // images - images, err := client.ImageList(ctx, dockertypes.ImageListOptions{}) - if ctx.Err() == context.DeadlineExceeded { - return ctx.Err() - } + images, err := client.ImageList(dockertypes.ImageListOptions{}) if err != nil { return err } @@ -230,7 +224,7 @@ func doGarbageCollection(ctx context.Context, client *dockerapi.Client, options glog.Infof("removing image %v (size: %v, age: %v)", i.ID, i.Size, age) var err error if !options.DryRun { - _, err = client.ImageRemove(ctx, i.ID, dockertypes.ImageRemoveOptions{PruneChildren: true}) + err = client.ImageRemove(i.ID, dockertypes.ImageRemoveOptions{PruneChildren: true}) } if err != nil { glog.Infof("unable to remove image: %v", err) @@ -250,14 +244,12 @@ func Run(f *clientcmd.Factory, options *dockerGCConfigCmdOptions, cmd *cobra.Com glog.Infof("Running in dry-run mode") } glog.Infof("MinimumGCAge: %v, ImageGCHighThresholdPercent: %v, ImageGCLowThresholdPercent: %v", options.MinimumGCAge, options.ImageGCHighThresholdPercent, options.ImageGCLowThresholdPercent) - client, err := dockerapi.NewEnvClient() + client, err := newDockerClient(dockerTimeout) if err != nil { return err } - timeout := time.Duration(2 * time.Minute) - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - info, err := client.Info(ctx) + + info, err := client.Info() if err != nil { return err } @@ -270,7 +262,7 @@ func Run(f *clientcmd.Factory, options *dockerGCConfigCmdOptions, cmd *cobra.Com } for { - err := doGarbageCollection(ctx, client, options, rootDir) + err := doGarbageCollection(client, options, rootDir) if err != nil { return err }