github.com/getong/docker@v1.13.1/client/image_push.go (about) 1 package client 2 3 import ( 4 "errors" 5 "io" 6 "net/http" 7 "net/url" 8 9 "golang.org/x/net/context" 10 11 distreference "github.com/docker/distribution/reference" 12 "github.com/docker/docker/api/types" 13 ) 14 15 // ImagePush requests the docker host to push an image to a remote registry. 16 // It executes the privileged function if the operation is unauthorized 17 // and it tries one more time. 18 // It's up to the caller to handle the io.ReadCloser and close it properly. 19 func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) { 20 distributionRef, err := distreference.ParseNamed(ref) 21 if err != nil { 22 return nil, err 23 } 24 25 if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical { 26 return nil, errors.New("cannot push a digest reference") 27 } 28 29 var tag = "" 30 if nameTaggedRef, isNamedTagged := distributionRef.(distreference.NamedTagged); isNamedTagged { 31 tag = nameTaggedRef.Tag() 32 } 33 34 query := url.Values{} 35 query.Set("tag", tag) 36 37 resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth) 38 if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { 39 newAuthHeader, privilegeErr := options.PrivilegeFunc() 40 if privilegeErr != nil { 41 return nil, privilegeErr 42 } 43 resp, err = cli.tryImagePush(ctx, distributionRef.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 }