// CheckAndPull checks whether a Docker image exists. If not, it pulls it. func (h *Helper) CheckAndPull(image string, out io.Writer) error { glog.V(5).Infof("Inspecting Docker image %q", image) imageMeta, err := h.client.InspectImage(image) if err == nil { glog.V(5).Infof("Image %q found: %#v", image, imageMeta) return nil } if err != docker.ErrNoSuchImage { return starterrors.NewError("unexpected error inspecting image %s", image).WithCause(err) } glog.V(5).Infof("Image %q not found. Pulling", image) fmt.Fprintf(out, "Pulling image %s\n", image) logProgress := func(s string) { fmt.Fprintf(out, "%s\n", s) } outputStream := imageprogress.NewPullWriter(logProgress) if glog.V(5) { outputStream = out } err = h.client.PullImage(docker.PullImageOptions{ Repository: image, RawJSONStream: bool(!glog.V(5)), OutputStream: outputStream, }, docker.AuthConfiguration{}) if err != nil { return starterrors.NewError("error pulling Docker image %s", image).WithCause(err) } fmt.Fprintf(out, "Image pull complete\n") return nil }
// LoadImage checks the client for an image matching from. If not found, // attempts to pull the image and then tries to inspect again. func (e *ClientExecutor) LoadImage(from string) (*docker.Image, error) { image, err := e.Client.InspectImage(from) if err == nil { return image, nil } if err != docker.ErrNoSuchImage { return nil, err } if !e.AllowPull { glog.V(4).Infof("image %s did not exist", from) return nil, docker.ErrNoSuchImage } repository, tag := docker.ParseRepositoryTag(from) if len(tag) == 0 { tag = "latest" } glog.V(4).Infof("attempting to pull %s with auth from repository %s:%s", from, repository, tag) // TODO: we may want to abstract looping over multiple credentials auth, _ := e.AuthFn(repository) if len(auth) == 0 { auth = append(auth, dockertypes.AuthConfig{}) } if e.LogFn != nil { e.LogFn("Image %s was not found, pulling ...", from) } var lastErr error outputProgress := func(s string) { e.LogFn("%s", s) } for _, config := range auth { // TODO: handle IDs? pullImageOptions := docker.PullImageOptions{ Repository: repository, Tag: tag, OutputStream: imageprogress.NewPullWriter(outputProgress), RawJSONStream: true, } if glog.V(5) { pullImageOptions.OutputStream = os.Stderr pullImageOptions.RawJSONStream = false } authConfig := docker.AuthConfiguration{Username: config.Username, ServerAddress: config.ServerAddress, Password: config.Password} if err = e.Client.PullImage(pullImageOptions, authConfig); err == nil { break } lastErr = err continue } if lastErr != nil { return nil, fmt.Errorf("unable to pull image (from: %s, tag: %s): %v", repository, tag, lastErr) } return e.Client.InspectImage(from) }
func pullImage(client DockerClient, name string, authConfig docker.AuthConfiguration) error { logProgress := func(s string) { glog.V(0).Infof("%s", s) } opts := docker.PullImageOptions{ Repository: name, OutputStream: imageprogress.NewPullWriter(logProgress), RawJSONStream: true, } if glog.Is(5) { opts.OutputStream = os.Stderr opts.RawJSONStream = false } err := client.PullImage(opts, authConfig) if err == nil { return nil } return err }