Skip to content

Commit 09c2838

Browse files
committed
Refactoring Builder by making it less coupled to context
- Add a BuildOptions to the Project.Build to be able to specify options on build. - Refactor DaemonBuilder to not be coupled to project.Context ; makes it easier to test and to use indenpendently. Signed-off-by: Vincent Demeester <[email protected]>
1 parent b57e5c2 commit 09c2838

File tree

13 files changed

+741
-58
lines changed

13 files changed

+741
-58
lines changed

Diff for: cli/app/app.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/Sirupsen/logrus"
1212
"github.com/codegangsta/cli"
1313
"github.com/docker/libcompose/project"
14+
"github.com/docker/libcompose/project/types"
1415
)
1516

1617
// ProjectAction is an adapter to allow the use of ordinary functions as libcompose actions.
@@ -112,7 +113,10 @@ func ProjectDown(p *project.Project, c *cli.Context) {
112113

113114
// ProjectBuild builds or rebuilds services.
114115
func ProjectBuild(p *project.Project, c *cli.Context) {
115-
err := p.Build(c.Args()...)
116+
config := types.BuildOptions{
117+
NoCache: c.Bool("no-cache"),
118+
}
119+
err := p.Build(config, c.Args()...)
116120
if err != nil {
117121
logrus.Fatal(err)
118122
}

Diff for: cli/command/command.go

-2
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,5 @@ func Populate(context *project.Context, c *cli.Context) {
318318
context.Signal = c.String("signal")
319319
} else if c.Command.Name == "rm" {
320320
context.Volume = c.Bool("v")
321-
} else if c.Command.Name == "build" {
322-
context.NoCache = c.Bool("no-cache")
323321
}
324322
}

Diff for: docker/builder.go renamed to docker/builder/builder.go

+27-37
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package docker
1+
package builder
22

33
import (
44
"fmt"
@@ -19,8 +19,8 @@ import (
1919
"github.com/docker/docker/pkg/progress"
2020
"github.com/docker/docker/pkg/streamformatter"
2121
"github.com/docker/docker/pkg/term"
22+
"github.com/docker/engine-api/client"
2223
"github.com/docker/engine-api/types"
23-
"github.com/docker/libcompose/project"
2424
)
2525

2626
// DefaultDockerfileName is the default name of a Dockerfile
@@ -29,29 +29,22 @@ const DefaultDockerfileName = "Dockerfile"
2929
// Builder defines methods to provide a docker builder. This makes libcompose
3030
// not tied up to the docker daemon builder.
3131
type Builder interface {
32-
Build(imageName string, p *project.Project, service project.Service) error
32+
Build(imageName string) error
3333
}
3434

3535
// DaemonBuilder is the daemon "docker build" Builder implementation.
3636
type DaemonBuilder struct {
37-
context *Context
38-
}
39-
40-
// NewDaemonBuilder creates a DaemonBuilder based on the specified context.
41-
func NewDaemonBuilder(ctx *Context) *DaemonBuilder {
42-
return &DaemonBuilder{
43-
context: ctx,
44-
}
37+
Client client.APIClient
38+
ContextDirectory string
39+
Dockerfile string
40+
AuthConfigs map[string]types.AuthConfig
41+
NoCache bool
4542
}
4643

4744
// Build implements Builder. It consumes the docker build API endpoint and sends
4845
// a tar of the specified service build context.
49-
func (d *DaemonBuilder) Build(imageName string, p *project.Project, service project.Service) error {
50-
if service.Config().Build == "" {
51-
return fmt.Errorf("Specified service does not have a build section")
52-
}
53-
54-
ctx, err := CreateTar(p, service.Name())
46+
func (d *DaemonBuilder) Build(imageName string) error {
47+
ctx, err := createTar(d.ContextDirectory, d.Dockerfile)
5548
if err != nil {
5649
return err
5750
}
@@ -65,19 +58,20 @@ func (d *DaemonBuilder) Build(imageName string, p *project.Project, service proj
6558

6659
var body io.Reader = progress.NewProgressReader(ctx, progressOutput, 0, "", "Sending build context to Docker daemon")
6760

68-
client := d.context.ClientFactory.Create(service)
69-
7061
logrus.Infof("Building %s...", imageName)
7162

7263
outFd, isTerminalOut := term.GetFdInfo(os.Stdout)
7364

74-
response, err := client.ImageBuild(context.Background(), body, types.ImageBuildOptions{
65+
response, err := d.Client.ImageBuild(context.Background(), body, types.ImageBuildOptions{
7566
Tags: []string{imageName},
76-
NoCache: d.context.NoCache,
67+
NoCache: d.NoCache,
7768
Remove: true,
78-
Dockerfile: service.Config().Dockerfile,
79-
AuthConfigs: d.context.ConfigFile.AuthConfigs,
69+
Dockerfile: d.Dockerfile,
70+
AuthConfigs: d.AuthConfigs,
8071
})
72+
if err != nil {
73+
return err
74+
}
8175

8276
err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, outFd, isTerminalOut, nil)
8377
if err != nil {
@@ -86,37 +80,33 @@ func (d *DaemonBuilder) Build(imageName string, p *project.Project, service proj
8680
if jerr.Code == 0 {
8781
jerr.Code = 1
8882
}
89-
fmt.Fprintf(os.Stderr, "%s%s", progBuff, buildBuff)
9083
return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code)
9184
}
9285
}
9386
return err
9487
}
9588

9689
// CreateTar create a build context tar for the specified project and service name.
97-
func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
90+
func createTar(contextDirectory, dockerfile string) (io.ReadCloser, error) {
9891
// This code was ripped off from docker/api/client/build.go
99-
serviceConfig, _ := p.Configs.Get(name)
100-
101-
root := serviceConfig.Build
102-
dockerfileName := filepath.Join(root, serviceConfig.Dockerfile)
92+
dockerfileName := filepath.Join(contextDirectory, dockerfile)
10393

104-
absRoot, err := filepath.Abs(root)
94+
absContextDirectory, err := filepath.Abs(contextDirectory)
10595
if err != nil {
10696
return nil, err
10797
}
10898

10999
filename := dockerfileName
110100

111-
if dockerfileName == "" {
101+
if dockerfile == "" {
112102
// No -f/--file was specified so use the default
113103
dockerfileName = DefaultDockerfileName
114-
filename = filepath.Join(absRoot, dockerfileName)
104+
filename = filepath.Join(absContextDirectory, dockerfileName)
115105

116106
// Just to be nice ;-) look for 'dockerfile' too but only
117107
// use it if we found it, otherwise ignore this check
118108
if _, err = os.Lstat(filename); os.IsNotExist(err) {
119-
tmpFN := path.Join(absRoot, strings.ToLower(dockerfileName))
109+
tmpFN := path.Join(absContextDirectory, strings.ToLower(dockerfileName))
120110
if _, err = os.Lstat(tmpFN); err == nil {
121111
dockerfileName = strings.ToLower(dockerfileName)
122112
filename = tmpFN
@@ -130,7 +120,7 @@ func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
130120
}
131121

132122
// Now reset the dockerfileName to be relative to the build context
133-
dockerfileName, err = filepath.Rel(absRoot, filename)
123+
dockerfileName, err = filepath.Rel(absContextDirectory, filename)
134124
if err != nil {
135125
return nil, err
136126
}
@@ -147,7 +137,7 @@ func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
147137
var includes = []string{"."}
148138
var excludes []string
149139

150-
dockerIgnorePath := path.Join(root, ".dockerignore")
140+
dockerIgnorePath := path.Join(contextDirectory, ".dockerignore")
151141
dockerIgnore, err := os.Open(dockerIgnorePath)
152142
if err != nil {
153143
if !os.IsNotExist(err) {
@@ -174,7 +164,7 @@ func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
174164
includes = append(includes, ".dockerignore", dockerfileName)
175165
}
176166

177-
if err := builder.ValidateContextDirectory(root, excludes); err != nil {
167+
if err := builder.ValidateContextDirectory(contextDirectory, excludes); err != nil {
178168
return nil, fmt.Errorf("Error checking context is accessible: '%s'. Please check permissions and try again.", err)
179169
}
180170

@@ -184,5 +174,5 @@ func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
184174
IncludeFiles: includes,
185175
}
186176

187-
return archive.TarWithOptions(root, options)
177+
return archive.TarWithOptions(contextDirectory, options)
188178
}

0 commit comments

Comments
 (0)