Skip to content

Commit f4f90be

Browse files
committed
Use context.Context accross the library
Applications that require full plumbing of context, such as those that rely on cancellation for resource cleanup, would be incompatible with inconsistent plumbing. This *connects* the net/context from the user of the libcompose API to the engine-api and below (where request are cancellable for example). This should also allow us to some cool and safe stuff with concurrent goroutines and cancellation O:) Signed-off-by: Vincent Demeester <[email protected]>
1 parent cee052e commit f4f90be

17 files changed

+313
-293
lines changed

Diff for: cli/app/app.go

+22-18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"strings"
99
"syscall"
1010

11+
"golang.org/x/net/context"
12+
1113
"github.com/Sirupsen/logrus"
1214
"github.com/codegangsta/cli"
1315
"github.com/docker/libcompose/project"
@@ -47,7 +49,7 @@ func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli
4749
// ProjectPs lists the containers.
4850
func ProjectPs(p project.APIProject, c *cli.Context) error {
4951
qFlag := c.Bool("q")
50-
allInfo, err := p.Ps(qFlag, c.Args()...)
52+
allInfo, err := p.Ps(context.Background(), qFlag, c.Args()...)
5153
if err != nil {
5254
return cli.NewExitError(err.Error(), 1)
5355
}
@@ -66,7 +68,7 @@ func ProjectPort(p project.APIProject, c *cli.Context) error {
6668
serviceName := c.Args()[0]
6769
privatePort := c.Args()[1]
6870

69-
port, err := p.Port(index, protocol, serviceName, privatePort)
71+
port, err := p.Port(context.Background(), index, protocol, serviceName, privatePort)
7072
if err != nil {
7173
return cli.NewExitError(err.Error(), 1)
7274
}
@@ -76,7 +78,7 @@ func ProjectPort(p project.APIProject, c *cli.Context) error {
7678

7779
// ProjectStop stops all services.
7880
func ProjectStop(p project.APIProject, c *cli.Context) error {
79-
err := p.Stop(c.Int("timeout"), c.Args()...)
81+
err := p.Stop(context.Background(), c.Int("timeout"), c.Args()...)
8082
if err != nil {
8183
return cli.NewExitError(err.Error(), 1)
8284
}
@@ -90,7 +92,7 @@ func ProjectDown(p project.APIProject, c *cli.Context) error {
9092
RemoveImages: options.ImageType(c.String("rmi")),
9193
RemoveOrphans: c.Bool("remove-orphans"),
9294
}
93-
err := p.Down(options, c.Args()...)
95+
err := p.Down(context.Background(), options, c.Args()...)
9496
if err != nil {
9597
return cli.NewExitError(err.Error(), 1)
9698
}
@@ -104,7 +106,7 @@ func ProjectBuild(p project.APIProject, c *cli.Context) error {
104106
ForceRemove: c.Bool("force-rm"),
105107
Pull: c.Bool("pull"),
106108
}
107-
err := p.Build(config, c.Args()...)
109+
err := p.Build(context.Background(), config, c.Args()...)
108110
if err != nil {
109111
return cli.NewExitError(err.Error(), 1)
110112
}
@@ -118,7 +120,7 @@ func ProjectCreate(p project.APIProject, c *cli.Context) error {
118120
ForceRecreate: c.Bool("force-recreate"),
119121
NoBuild: c.Bool("no-build"),
120122
}
121-
err := p.Create(options, c.Args()...)
123+
err := p.Create(context.Background(), options, c.Args()...)
122124
if err != nil {
123125
return cli.NewExitError(err.Error(), 1)
124126
}
@@ -134,7 +136,8 @@ func ProjectUp(p project.APIProject, c *cli.Context) error {
134136
NoBuild: c.Bool("no-build"),
135137
},
136138
}
137-
err := p.Up(options, c.Args()...)
139+
ctx, cancelFun := context.WithCancel(context.Background())
140+
err := p.Up(ctx, options, c.Args()...)
138141
if err != nil {
139142
return cli.NewExitError(err.Error(), 1)
140143
}
@@ -144,12 +147,13 @@ func ProjectUp(p project.APIProject, c *cli.Context) error {
144147
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
145148
errChan := make(chan error)
146149
go func() {
147-
errChan <- p.Log(true, c.Args()...)
150+
errChan <- p.Log(ctx, true, c.Args()...)
148151
}()
149152
go func() {
150153
select {
151154
case <-signalChan:
152155
fmt.Printf("\nGracefully stopping...\n")
156+
cancelFun()
153157
ProjectStop(p, c)
154158
cleanupDone <- true
155159
case err := <-errChan:
@@ -174,7 +178,7 @@ func ProjectRun(p project.APIProject, c *cli.Context) error {
174178
serviceName := c.Args()[0]
175179
commandParts := c.Args()[1:]
176180

177-
exitCode, err := p.Run(serviceName, commandParts)
181+
exitCode, err := p.Run(context.Background(), serviceName, commandParts)
178182
if err != nil {
179183
return cli.NewExitError(err.Error(), 1)
180184
}
@@ -183,7 +187,7 @@ func ProjectRun(p project.APIProject, c *cli.Context) error {
183187

184188
// ProjectStart starts services.
185189
func ProjectStart(p project.APIProject, c *cli.Context) error {
186-
err := p.Start(c.Args()...)
190+
err := p.Start(context.Background(), c.Args()...)
187191
if err != nil {
188192
return cli.NewExitError(err.Error(), 1)
189193
}
@@ -192,7 +196,7 @@ func ProjectStart(p project.APIProject, c *cli.Context) error {
192196

193197
// ProjectRestart restarts services.
194198
func ProjectRestart(p project.APIProject, c *cli.Context) error {
195-
err := p.Restart(c.Int("timeout"), c.Args()...)
199+
err := p.Restart(context.Background(), c.Int("timeout"), c.Args()...)
196200
if err != nil {
197201
return cli.NewExitError(err.Error(), 1)
198202
}
@@ -201,7 +205,7 @@ func ProjectRestart(p project.APIProject, c *cli.Context) error {
201205

202206
// ProjectLog gets services logs.
203207
func ProjectLog(p project.APIProject, c *cli.Context) error {
204-
err := p.Log(c.Bool("follow"), c.Args()...)
208+
err := p.Log(context.Background(), c.Bool("follow"), c.Args()...)
205209
if err != nil {
206210
return cli.NewExitError(err.Error(), 1)
207211
}
@@ -210,7 +214,7 @@ func ProjectLog(p project.APIProject, c *cli.Context) error {
210214

211215
// ProjectPull pulls images for services.
212216
func ProjectPull(p project.APIProject, c *cli.Context) error {
213-
err := p.Pull(c.Args()...)
217+
err := p.Pull(context.Background(), c.Args()...)
214218
if err != nil && !c.Bool("ignore-pull-failures") {
215219
return cli.NewExitError(err.Error(), 1)
216220
}
@@ -237,7 +241,7 @@ func ProjectDelete(p project.APIProject, c *cli.Context) error {
237241
return true
238242
}
239243
}
240-
err := p.Delete(options, c.Args()...)
244+
err := p.Delete(context.Background(), options, c.Args()...)
241245
if err != nil {
242246
return cli.NewExitError(err.Error(), 1)
243247
}
@@ -246,7 +250,7 @@ func ProjectDelete(p project.APIProject, c *cli.Context) error {
246250

247251
// ProjectKill forces stop service containers.
248252
func ProjectKill(p project.APIProject, c *cli.Context) error {
249-
err := p.Kill(c.String("signal"), c.Args()...)
253+
err := p.Kill(context.Background(), c.String("signal"), c.Args()...)
250254
if err != nil {
251255
return cli.NewExitError(err.Error(), 1)
252256
}
@@ -255,7 +259,7 @@ func ProjectKill(p project.APIProject, c *cli.Context) error {
255259

256260
// ProjectPause pauses service containers.
257261
func ProjectPause(p project.APIProject, c *cli.Context) error {
258-
err := p.Pause(c.Args()...)
262+
err := p.Pause(context.Background(), c.Args()...)
259263
if err != nil {
260264
return cli.NewExitError(err.Error(), 1)
261265
}
@@ -264,7 +268,7 @@ func ProjectPause(p project.APIProject, c *cli.Context) error {
264268

265269
// ProjectUnpause unpauses service containers.
266270
func ProjectUnpause(p project.APIProject, c *cli.Context) error {
267-
err := p.Unpause(c.Args()...)
271+
err := p.Unpause(context.Background(), c.Args()...)
268272
if err != nil {
269273
return cli.NewExitError(err.Error(), 1)
270274
}
@@ -290,7 +294,7 @@ func ProjectScale(p project.APIProject, c *cli.Context) error {
290294
servicesScale[name] = count
291295
}
292296

293-
err := p.Scale(c.Int("timeout"), servicesScale)
297+
err := p.Scale(context.Background(), c.Int("timeout"), servicesScale)
294298
if err != nil {
295299
return cli.NewExitError(err.Error(), 1)
296300
}

Diff for: docker/builder/builder.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,26 @@ type DaemonBuilder struct {
4545

4646
// Build implements Builder. It consumes the docker build API endpoint and sends
4747
// a tar of the specified service build context.
48-
func (d *DaemonBuilder) Build(imageName string) error {
49-
ctx, err := createTar(d.ContextDirectory, d.Dockerfile)
48+
func (d *DaemonBuilder) Build(ctx context.Context, imageName string) error {
49+
buildCtx, err := createTar(d.ContextDirectory, d.Dockerfile)
5050
if err != nil {
5151
return err
5252
}
53-
defer ctx.Close()
53+
defer buildCtx.Close()
5454

5555
var progBuff io.Writer = os.Stdout
5656
var buildBuff io.Writer = os.Stdout
5757

5858
// Setup an upload progress bar
5959
progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(progBuff, true)
6060

61-
var body io.Reader = progress.NewProgressReader(ctx, progressOutput, 0, "", "Sending build context to Docker daemon")
61+
var body io.Reader = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
6262

6363
logrus.Infof("Building %s...", imageName)
6464

6565
outFd, isTerminalOut := term.GetFdInfo(os.Stdout)
6666

67-
response, err := d.Client.ImageBuild(context.Background(), body, types.ImageBuildOptions{
67+
response, err := d.Client.ImageBuild(ctx, body, types.ImageBuildOptions{
6868
Tags: []string{imageName},
6969
NoCache: d.NoCache,
7070
Remove: true,

Diff for: docker/builder/builder_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func TestBuildInvalidContextDirectoryOrDockerfile(t *testing.T) {
9999
ContextDirectory: c.contextDirectory,
100100
Dockerfile: c.dockerfile,
101101
}
102-
err := builder.Build("image")
102+
err := builder.Build(context.Background(), "image")
103103
if err == nil || err.Error() != c.expected {
104104
t.Fatalf("expected an error %q, got %s", c.expected, err)
105105
}
@@ -124,7 +124,7 @@ func TestBuildWithClientBuildError(t *testing.T) {
124124
Client: client,
125125
}
126126

127-
err = builder.Build(imageName)
127+
err = builder.Build(context.Background(), imageName)
128128
if err == nil || err.Error() != "Engine no longer exists" {
129129
t.Fatalf("expected an 'Engine no longer exists', got %s", err)
130130
}
@@ -153,7 +153,7 @@ func TestBuildWithDefaultDockerfile(t *testing.T) {
153153
Client: client,
154154
}
155155

156-
err = builder.Build(imageName)
156+
err = builder.Build(context.Background(), imageName)
157157
if err != nil {
158158
t.Fatal(err)
159159
}
@@ -182,7 +182,7 @@ func TestBuildWithDefaultLowercaseDockerfile(t *testing.T) {
182182
Client: client,
183183
}
184184

185-
err = builder.Build(imageName)
185+
err = builder.Build(context.Background(), imageName)
186186
if err != nil {
187187
t.Fatal(err)
188188
}
@@ -212,7 +212,7 @@ func TestBuildWithSpecificDockerfile(t *testing.T) {
212212
Client: client,
213213
}
214214

215-
err = builder.Build(imageName)
215+
err = builder.Build(context.Background(), imageName)
216216
if err != nil {
217217
t.Fatal(err)
218218
}
@@ -245,7 +245,7 @@ func TestBuildWithDockerignoreNothing(t *testing.T) {
245245
Client: client,
246246
}
247247

248-
err = builder.Build(imageName)
248+
err = builder.Build(context.Background(), imageName)
249249
if err != nil {
250250
t.Fatal(err)
251251
}
@@ -278,7 +278,7 @@ func TestBuildWithDockerignoreDockerfileAndItself(t *testing.T) {
278278
Client: client,
279279
}
280280

281-
err = builder.Build(imageName)
281+
err = builder.Build(context.Background(), imageName)
282282
if err != nil {
283283
t.Fatal(err)
284284
}
@@ -312,7 +312,7 @@ func TestBuildWithDockerignoreAfile(t *testing.T) {
312312
Client: client,
313313
}
314314

315-
err = builder.Build(imageName)
315+
err = builder.Build(context.Background(), imageName)
316316
if err != nil {
317317
t.Fatal(err)
318318
}
@@ -347,7 +347,7 @@ func TestBuildWithErrorJSONMessage(t *testing.T) {
347347
Client: client,
348348
}
349349

350-
err = builder.Build(imageName)
350+
err = builder.Build(context.Background(), imageName)
351351
expectedError := "Status: error, Code: 1"
352352
if err == nil || err.Error() != expectedError {
353353
t.Fatalf("expected an error about %q, got %s", expectedError, err)

0 commit comments

Comments
 (0)