github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/client/image_push.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "net/url" 8 9 "github.com/docker/distribution/reference" 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/errdefs" 12 ) 13 14 // ImagePush requests the docker host to push an image to 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 func (cli *Client) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) { 19 ref, err := reference.ParseNormalizedNamed(image) 20 if err != nil { 21 return nil, err 22 } 23 24 if _, isCanonical := ref.(reference.Canonical); isCanonical { 25 return nil, errors.New("cannot push a digest reference") 26 } 27 28 name := reference.FamiliarName(ref) 29 query := url.Values{} 30 if !options.All { 31 ref = reference.TagNameOnly(ref) 32 if tagged, ok := ref.(reference.Tagged); ok { 33 query.Set("tag", tagged.Tag()) 34 } 35 } 36 37 resp, err := cli.tryImagePush(ctx, name, 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.tryImagePush(ctx, name, query, newAuthHeader) 44 } 45 if err != nil { 46 return nil, err 47 } 48 return resp.body, nil 49 } 50 51 func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { 52 headers := map[string][]string{"X-Registry-Auth": {registryAuth}} 53 return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) 54 }