// CheckAndPull checks whether a Docker image exists. If not, it pulls it.
CheckAndPull checks whether a Docker image exists. If not, it pulls it.
// 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.ImageInspectWithRaw(image, false)
	if err == nil {
		glog.V(5).Infof("Image %q found: %#v", image, imageMeta)
		return nil
	}
	if !client.IsErrImageNotFound(err) {
		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)
	}
	pw := imageprogress.NewPullWriter(logProgress)
	defer pw.Close()
	outputStream := pw.(io.Writer)
	if glog.V(5) {
		outputStream = out
	}
	normalized, err := reference.ParseNormalizedNamed(image)
	if err != nil {
		return err
	}
	auth := ""
	var cfgPath string
	if os.Getenv("DOCKERCFG_PATH") != "" {
		cfgPath = os.Getenv("DOCKERCFG_PATH")
	} else if currentUser, err := user.Current(); err == nil {
		cfgPath = filepath.Join(currentUser.HomeDir, ".docker", "config.json")
	}
	cfg, err := credentialprovider.ReadSpecificDockerConfigJsonFile(cfgPath)
	if err != nil {
		glog.Errorf("Reading docker config from %v failed: %v, will attempt to pull image %s anonymously", cfgPath, err, normalized.String())
	}
	keyring := credentialprovider.BasicDockerKeyring{}
	keyring.Add(cfg)
	authConfs, found := keyring.Lookup(normalized.String())
	if found && len(authConfs) > 0 {
		glog.V(3).Infof("Using %s user for Docker authentication for image %s", authConfs[0].Username, normalized.String())
		authConfig := types.AuthConfig{
			Username:      authConfs[0].Username,
			Password:      authConfs[0].Password,
			ServerAddress: authConfs[0].ServerAddress,
			IdentityToken: authConfs[0].IdentityToken,
			RegistryToken: authConfs[0].RegistryToken,
		}
		var buf bytes.Buffer
		if err := json.NewEncoder(&buf).Encode(authConfig); err != nil {
			return starterrors.NewError("error encoding docker credentials").WithCause(err)
		}
		auth = base64.URLEncoding.EncodeToString(buf.Bytes())
	}
	err = h.client.ImagePull(normalized.String(), types.ImagePullOptions{RegistryAuth: auth}, outputStream)
	if err != nil {
		return starterrors.NewError("error pulling Docker image %s", image).WithCause(err)
	}
	_, _, err = h.client.ImageInspectWithRaw(image, false)
	if err != nil {
		glog.V(5).Infof("Image %q not found: %v", image, err)
		return starterrors.NewError("error pulling Docker image %s", image).WithCause(err)
	}
	fmt.Fprintln(out, "Image pull complete")
	return nil
}
func ( h * Helper ) CheckAndPull ( image string , out io . Writer ) error { glog . V ( 5 ) . Infof ( " " , image ) imageMeta , _ , err := h . client . ImageInspectWithRaw ( image , false ) if err == nil { glog . V ( 5 ) . Infof ( " " , image , imageMeta ) return nil } if ! client . IsErrImageNotFound ( err ) { return starterrors . NewError ( " " , image ) . WithCause ( err ) } glog . V ( 5 ) . Infof ( " " , image ) fmt . Fprintf ( out , " \n " , image ) logProgress := func ( s string ) { fmt . Fprintf ( out , " \n " , s ) } pw := imageprogress . NewPullWriter ( logProgress ) defer pw . Close ( ) outputStream := pw . ( io . Writer ) if glog . V ( 5 ) { outputStream = out } normalized , err := reference . ParseNormalizedNamed ( image ) if err != nil { return err } auth := " " var cfgPath string if os . Getenv ( " " ) != " " { cfgPath = os . Getenv ( " " ) } else if currentUser , err := user . Current ( ) ; err == nil { cfgPath = filepath . Join ( currentUser . HomeDir , " " , " " ) } cfg , err := credentialprovider . ReadSpecificDockerConfigJsonFile ( cfgPath ) if err != nil { glog . Errorf ( " " , cfgPath , err , normalized . String ( ) ) } keyring := credentialprovider . BasicDockerKeyring { } keyring . Add ( cfg ) authConfs , found := keyring . Lookup ( normalized . String ( ) ) if found && len ( authConfs ) > 0 { glog . V ( 3 ) . Infof ( " " , authConfs [ 0 ] . Username , normalized . String ( ) ) authConfig := types . AuthConfig { Username : authConfs [ 0 ] . Username , Password : authConfs [ 0 ] . Password , ServerAddress : authConfs [ 0 ] . ServerAddress , IdentityToken : authConfs [ 0 ] . IdentityToken , RegistryToken : authConfs [ 0 ] . RegistryToken , } var buf bytes . Buffer if err := json . NewEncoder ( & buf ) . Encode ( authConfig ) ; err != nil { return starterrors . NewError ( " " ) . WithCause ( err ) } auth = base64 . URLEncoding . EncodeToString ( buf . Bytes ( ) ) } err = h . client . ImagePull ( normalized . String ( ) , types . ImagePullOptions { RegistryAuth : auth } , outputStream ) if err != nil { return starterrors . NewError ( " " , image ) . WithCause ( err ) } _ , _ , err = h . client . ImageInspectWithRaw ( image , false ) if err != nil { glog . V ( 5 ) . Infof ( " " , image , err ) return starterrors . NewError ( " " , image ) . WithCause ( err ) } fmt . Fprintln ( out , " " ) return nil }
CheckAndPull checks whether a Docker image exists.
CheckAndPull checks whether a Docker image exists .
// This is to work around issue https://github.com/docker/docker/api/issues/138 // where engine-api/client/ImagePull does not return an error when it should. // which also still seems to exist in https://github.com/moby/moby/blob/master/client/image_pull.go