github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/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 "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, image string, options types.ImagePushOptions) (io.ReadCloser, error) { 20 ref, err := reference.ParseNormalizedNamed(image) 21 if err != nil { 22 return nil, err 23 } 24 25 if _, isCanonical := ref.(reference.Canonical); isCanonical { 26 return nil, errors.New("cannot push a digest reference") 27 } 28 29 tag := "" 30 name := reference.FamiliarName(ref) 31 32 if nameTaggedRef, isNamedTagged := ref.(reference.NamedTagged); isNamedTagged { 33 tag = nameTaggedRef.Tag() 34 } 35 36 query := url.Values{} 37 query.Set("tag", tag) 38 39 resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth) 40 if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { 41 newAuthHeader, privilegeErr := options.PrivilegeFunc() 42 if privilegeErr != nil { 43 return nil, privilegeErr 44 } 45 resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader) 46 } 47 if err != nil { 48 return nil, err 49 } 50 return resp.body, nil 51 } 52 53 func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { 54 headers := map[string][]string{"X-Registry-Auth": {registryAuth}} 55 return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) 56 }