Browse code

Add output logging to docker build and correctly pull

Pulling was broken because the upstream URL was wrong.

Clayton Coleman authored on 2016/05/04 02:55:35
Showing 2 changed files
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	docker "github.com/fsouza/go-dockerclient"
11
+	"github.com/golang/glog"
11 12
 	"github.com/spf13/cobra"
12 13
 
13 14
 	"k8s.io/kubernetes/pkg/credentialprovider"
... ...
@@ -111,5 +112,22 @@ func (o *DockerbuildOptions) Run() error {
111 111
 	e.Directory = o.Directory
112 112
 	e.Tag = o.Tag
113 113
 	e.AuthFn = o.Keyring.Lookup
114
-	return e.Build(f, o.Arguments)
114
+	e.LogFn = func(format string, args ...interface{}) {
115
+		if glog.V(2) {
116
+			glog.Infof("Builder: "+format, args...)
117
+		} else {
118
+			fmt.Fprintf(e.ErrOut, "# %s\n", fmt.Sprintf(format, args...))
119
+		}
120
+	}
121
+	return stripLeadingError(e.Build(f, o.Arguments))
122
+}
123
+
124
+func stripLeadingError(err error) error {
125
+	if err == nil {
126
+		return err
127
+	}
128
+	if strings.HasPrefix(err.Error(), "Error: ") {
129
+		return fmt.Errorf(strings.TrimPrefix(err.Error(), "Error: "))
130
+	}
131
+	return err
115 132
 }
... ...
@@ -32,6 +32,9 @@ type ClientExecutor struct {
32 32
 	Excludes []string
33 33
 	// Tag is an optional value to tag the resulting built image.
34 34
 	Tag string
35
+	// AllowPull when set will pull images that are not present on
36
+	// the daemon.
37
+	AllowPull bool
35 38
 
36 39
 	Out, ErrOut io.Writer
37 40
 
... ...
@@ -51,6 +54,8 @@ type ClientExecutor struct {
51 51
 	AuthFn func(name string) ([]docker.AuthConfiguration, bool)
52 52
 	// HostConfig is used to start the container (if necessary).
53 53
 	HostConfig *docker.HostConfig
54
+	// LogFn is an optional command to log information to the end user
55
+	LogFn func(format string, args ...interface{})
54 56
 }
55 57
 
56 58
 // NewClientExecutor creates a client executor.
... ...
@@ -162,6 +167,9 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
162 162
 			return err
163 163
 		}
164 164
 		glog.V(4).Infof("step: %s", step.Original)
165
+		if e.LogFn != nil {
166
+			e.LogFn(step.Original)
167
+		}
165 168
 		if err := b.Run(step, e); err != nil {
166 169
 			return err
167 170
 		}
... ...
@@ -172,8 +180,14 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
172 172
 	if len(e.Tag) > 0 {
173 173
 		repository, tag = docker.ParseRepositoryTag(e.Tag)
174 174
 		glog.V(4).Infof("Committing built container %s as image %q: %#v", e.Container.ID, e.Tag, config)
175
+		if e.LogFn != nil {
176
+			e.LogFn("Committing changes to %s ...", e.Tag)
177
+		}
175 178
 	} else {
176 179
 		glog.V(4).Infof("Committing built container %s: %#v", e.Container.ID, config)
180
+		if e.LogFn != nil {
181
+			e.LogFn("Committing changes ...")
182
+		}
177 183
 	}
178 184
 
179 185
 	image, err := e.Client.CommitContainer(docker.CommitContainerOptions{
... ...
@@ -187,6 +201,9 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
187 187
 	}
188 188
 	e.Image = image
189 189
 	glog.V(4).Infof("Committed %s to %s", e.Container.ID, e.Image.ID)
190
+	if e.LogFn != nil {
191
+		e.LogFn("Done")
192
+	}
190 193
 	return nil
191 194
 }
192 195
 
... ...
@@ -214,7 +231,7 @@ func (e *ClientExecutor) CreateScratchImage() (string, error) {
214 214
 	if _, err := io.ReadFull(rand.Reader, random); err != nil {
215 215
 		return "", err
216 216
 	}
217
-	name := fmt.Sprintf("scratch-%s", base64.URLEncoding.EncodeToString(random))
217
+	name := fmt.Sprintf("scratch-%s", strings.TrimRight(base64.URLEncoding.EncodeToString(random), "="))
218 218
 
219 219
 	buf := &bytes.Buffer{}
220 220
 	w := tar.NewWriter(buf)
... ...
@@ -243,27 +260,29 @@ func (e *ClientExecutor) LoadImage(from string) (*docker.Image, error) {
243 243
 		return nil, err
244 244
 	}
245 245
 
246
-	var registry string
247
-	repository, tag := docker.ParseRepositoryTag(from)
248
-	if parts := strings.SplitN(repository, "/", 2); len(parts) > 1 {
249
-		registry, repository = parts[0], parts[1]
246
+	if !e.AllowPull {
247
+		glog.V(4).Info("image %s did not exist", from)
248
+		return nil, docker.ErrNoSuchImage
250 249
 	}
251 250
 
251
+	repository, _ := docker.ParseRepositoryTag(from)
252
+
253
+	glog.V(4).Infof("attempting to pull %s with auth from repository %s", from, repository)
254
+
252 255
 	// TODO: we may want to abstract looping over multiple credentials
253 256
 	auth, _ := e.AuthFn(repository)
254 257
 	if len(auth) == 0 {
255 258
 		auth = append(auth, docker.AuthConfiguration{})
256 259
 	}
257 260
 
261
+	if e.LogFn != nil {
262
+		e.LogFn("Image %s was not found, pulling ...", from)
263
+	}
264
+
258 265
 	var lastErr error
259 266
 	for _, config := range auth {
260 267
 		// TODO: handle IDs?
261
-		err = e.Client.PullImage(docker.PullImageOptions{
262
-			Registry:   registry,
263
-			Repository: repository,
264
-			Tag:        tag,
265
-		}, config)
266
-		if err == nil {
268
+		if err = e.Client.PullImage(docker.PullImageOptions{Repository: from}, config); err == nil {
267 269
 			break
268 270
 		}
269 271
 		lastErr = err