github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/client/image_pull.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "context" 5 "io" 6 "net/url" 7 "strings" 8 9 "github.com/docker/distribution/reference" 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/errdefs" 12 ) 13 14 // ImagePull requests the docker host to pull an image from a remote registry. 15 // It executes the privileged function if the operation is unauthorized 16 // and it tries one more time. 17 // It's up to the caller to handle the io.ReadCloser and close it properly. 18 // 19 // FIXME(vdemeester): there is currently used in a few way in docker/docker 20 // - if not in trusted content, ref is used to pass the whole reference, and tag is empty 21 // - if in trusted content, ref is used to pass the reference name, and tag for the digest 22 func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) { 23 ref, err := reference.ParseNormalizedNamed(refStr) 24 if err != nil { 25 return nil, err 26 } 27 28 query := url.Values{} 29 query.Set("fromImage", reference.FamiliarName(ref)) 30 if !options.All { 31 query.Set("tag", getAPITagFromNamedRef(ref)) 32 } 33 if options.Platform != "" { 34 query.Set("platform", strings.ToLower(options.Platform)) 35 } 36 37 resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) 38 if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { 39 newAuthHeader, privilegeErr := options.PrivilegeFunc() 40 if privilegeErr != nil { 41 return nil, privilegeErr 42 } 43 resp, err = cli.tryImageCreate(ctx, query, newAuthHeader) 44 } 45 if err != nil { 46 return nil, err 47 } 48 return resp.body, nil 49 } 50 51 // getAPITagFromNamedRef returns a tag from the specified reference. 52 // This function is necessary as long as the docker "server" api expects 53 // digests to be sent as tags and makes a distinction between the name 54 // and tag/digest part of a reference. 55 func getAPITagFromNamedRef(ref reference.Named) string { 56 if digested, ok := ref.(reference.Digested); ok { 57 return digested.Digest().String() 58 } 59 ref = reference.TagNameOnly(ref) 60 if tagged, ok := ref.(reference.Tagged); ok { 61 return tagged.Tag() 62 } 63 return "" 64 }