mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Implement docker push with standalone client lib.
Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
e78f02c4db
commit
42670e30ee
5 changed files with 72 additions and 13 deletions
|
@ -50,6 +50,7 @@ type apiClient interface {
|
|||
ImageList(options types.ImageListOptions) ([]types.Image, error)
|
||||
ImageLoad(input io.Reader) (io.ReadCloser, error)
|
||||
ImagePull(options types.ImagePullOptions, privilegeFunc lib.RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImagePush(options types.ImagePushOptions, privilegeFunc lib.RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImageRemove(options types.ImageRemoveOptions) ([]types.ImageDelete, error)
|
||||
ImageSave(imageIDs []string) (io.ReadCloser, error)
|
||||
ImageTag(options types.ImageTagOptions) error
|
||||
|
|
36
api/client/lib/image_push.go
Normal file
36
api/client/lib/image_push.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
// ImagePush request the docker host to push an image to a remote registry.
|
||||
// It executes the privileged function if the operation is unauthorized
|
||||
// and it tries one more time.
|
||||
// It's up to the caller to handle the io.ReadCloser and close it properly.
|
||||
func (cli *Client) ImagePush(options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("tag", options.Tag)
|
||||
|
||||
resp, err := cli.tryImagePush(options.ImageID, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized {
|
||||
newAuthHeader, privilegeErr := privilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImagePush(options.ImageID, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryImagePush(imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
return cli.post("/images/"+imageID+"/push", query, nil, headers)
|
||||
}
|
|
@ -3,10 +3,14 @@ package client
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"io"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/client/lib"
|
||||
"github.com/docker/docker/api/types"
|
||||
Cli "github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/registry"
|
||||
)
|
||||
|
@ -53,13 +57,30 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
|||
return fmt.Errorf("You cannot push a \"root\" repository. Please rename your repository to <user>/<repo> (ex: %s/%s)", username, repoInfo.LocalName)
|
||||
}
|
||||
|
||||
requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push")
|
||||
if isTrusted() {
|
||||
return cli.trustedPush(repoInfo, tag, authConfig)
|
||||
return cli.trustedPush(repoInfo, tag, authConfig, requestPrivilege)
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("tag", tag)
|
||||
|
||||
_, _, err = cli.clientRequestAttemptLogin("POST", "/images/"+ref.Name()+"/push?"+v.Encode(), nil, cli.out, repoInfo.Index, "push")
|
||||
return err
|
||||
return cli.imagePushPrivileged(authConfig, ref.Name(), tag, cli.out, requestPrivilege)
|
||||
}
|
||||
|
||||
func (cli *DockerCli) imagePushPrivileged(authConfig cliconfig.AuthConfig, imageID, tag string, outputStream io.Writer, requestPrivilege lib.RequestPrivilegeFunc) error {
|
||||
encodedAuth, err := authConfig.EncodeToBase64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options := types.ImagePushOptions{
|
||||
ImageID: imageID,
|
||||
Tag: tag,
|
||||
RegistryAuth: encodedAuth,
|
||||
}
|
||||
|
||||
responseBody, err := cli.client.ImagePush(options, requestPrivilege)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
|
||||
return jsonmessage.DisplayJSONMessagesStream(responseBody, outputStream, cli.outFd, cli.isTerminalOut)
|
||||
}
|
||||
|
|
|
@ -380,20 +380,18 @@ func targetStream(in io.Writer) (io.WriteCloser, <-chan []target) {
|
|||
return ioutils.NewWriteCloserWrapper(out, w.Close), targetChan
|
||||
}
|
||||
|
||||
func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, authConfig cliconfig.AuthConfig) error {
|
||||
func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, authConfig cliconfig.AuthConfig, requestPrivilege lib.RequestPrivilegeFunc) error {
|
||||
streamOut, targetChan := targetStream(cli.out)
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("tag", tag)
|
||||
reqError := cli.imagePushPrivileged(authConfig, repoInfo.LocalName.Name(), tag, streamOut, requestPrivilege)
|
||||
|
||||
_, _, err := cli.clientRequestAttemptLogin("POST", "/images/"+repoInfo.LocalName.Name()+"/push?"+v.Encode(), nil, streamOut, repoInfo.Index, "push")
|
||||
// Close stream channel to finish target parsing
|
||||
if err := streamOut.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Check error from request
|
||||
if err != nil {
|
||||
return err
|
||||
if reqError != nil {
|
||||
return reqError
|
||||
}
|
||||
|
||||
// Get target results
|
||||
|
|
|
@ -187,6 +187,9 @@ type ImagePullOptions struct {
|
|||
RegistryAuth string
|
||||
}
|
||||
|
||||
//ImagePushOptions holds information to push images.
|
||||
type ImagePushOptions ImagePullOptions
|
||||
|
||||
// ImageRemoveOptions holds parameters to remove images.
|
||||
type ImageRemoveOptions struct {
|
||||
ImageID string
|
||||
|
|
Loading…
Add table
Reference in a new issue