Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| ... | ... |
@@ -25,7 +25,7 @@ clone git golang.org/x/net 78cb2c067747f08b343f20614155233ab4ea2ad3 https://gith |
| 25 | 25 |
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git |
| 26 | 26 |
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3 |
| 27 | 27 |
clone git github.com/docker/go-connections v0.2.0 |
| 28 |
-clone git github.com/docker/engine-api 8924d6900370b4c7e7984be5adc61f50a80d7537 |
|
| 28 |
+clone git github.com/docker/engine-api a6dca654f28f26b648115649f6382252ada81119 |
|
| 29 | 29 |
clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 |
| 30 | 30 |
clone git github.com/imdario/mergo 0.2.1 |
| 31 | 31 |
|
| ... | ... |
@@ -114,6 +114,12 @@ func (cli *Client) ClientVersion() string {
|
| 114 | 114 |
return cli.version |
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 |
+// UpdateClientVersion updates the version string associated with this |
|
| 118 |
+// instance of the Client. |
|
| 119 |
+func (cli *Client) UpdateClientVersion(v string) {
|
|
| 120 |
+ cli.version = v |
|
| 121 |
+} |
|
| 122 |
+ |
|
| 117 | 123 |
// ParseHost verifies that the given host strings is valid. |
| 118 | 124 |
func ParseHost(host string) (string, string, string, error) {
|
| 119 | 125 |
protoAddrParts := strings.SplitN(host, "://", 2) |
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
// It returns a types.HijackedConnection with the hijacked connection |
| 12 | 12 |
// and the a reader to get output. It's up to the called to close |
| 13 | 13 |
// the hijacked connection by calling types.HijackedResponse.Close. |
| 14 |
-func (cli *Client) ContainerAttach(ctx context.Context, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
|
|
| 14 |
+func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
|
|
| 15 | 15 |
query := url.Values{}
|
| 16 | 16 |
if options.Stream {
|
| 17 | 17 |
query.Set("stream", "1")
|
| ... | ... |
@@ -30,5 +30,5 @@ func (cli *Client) ContainerAttach(ctx context.Context, options types.ContainerA |
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 | 32 |
headers := map[string][]string{"Content-Type": {"text/plain"}}
|
| 33 |
- return cli.postHijacked(ctx, "/containers/"+options.ContainerID+"/attach", query, nil, headers) |
|
| 33 |
+ return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers) |
|
| 34 | 34 |
} |
| ... | ... |
@@ -2,18 +2,36 @@ package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 |
+ "errors" |
|
| 5 | 6 |
"net/url" |
| 6 | 7 |
|
| 8 |
+ distreference "github.com/docker/distribution/reference" |
|
| 7 | 9 |
"github.com/docker/engine-api/types" |
| 10 |
+ "github.com/docker/engine-api/types/reference" |
|
| 8 | 11 |
"golang.org/x/net/context" |
| 9 | 12 |
) |
| 10 | 13 |
|
| 11 | 14 |
// ContainerCommit applies changes into a container and creates a new tagged image. |
| 12 |
-func (cli *Client) ContainerCommit(ctx context.Context, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) {
|
|
| 15 |
+func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) {
|
|
| 16 |
+ var repository, tag string |
|
| 17 |
+ if options.Reference != "" {
|
|
| 18 |
+ distributionRef, err := distreference.ParseNamed(options.Reference) |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return types.ContainerCommitResponse{}, err
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
|
| 24 |
+ return types.ContainerCommitResponse{}, errors.New("refusing to create a tag with a digest reference")
|
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ tag = reference.GetTagFromNamedRef(distributionRef) |
|
| 28 |
+ repository = distributionRef.Name() |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 13 | 31 |
query := url.Values{}
|
| 14 |
- query.Set("container", options.ContainerID)
|
|
| 15 |
- query.Set("repo", options.RepositoryName)
|
|
| 16 |
- query.Set("tag", options.Tag)
|
|
| 32 |
+ query.Set("container", container)
|
|
| 33 |
+ query.Set("repo", repository)
|
|
| 34 |
+ query.Set("tag", tag)
|
|
| 17 | 35 |
query.Set("comment", options.Comment)
|
| 18 | 36 |
query.Set("author", options.Author)
|
| 19 | 37 |
for _, change := range options.Changes {
|
| ... | ... |
@@ -8,9 +8,9 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// ContainerExecCreate creates a new exec configuration to run an exec process. |
| 11 |
-func (cli *Client) ContainerExecCreate(ctx context.Context, config types.ExecConfig) (types.ContainerExecCreateResponse, error) {
|
|
| 11 |
+func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error) {
|
|
| 12 | 12 |
var response types.ContainerExecCreateResponse |
| 13 |
- resp, err := cli.post(ctx, "/containers/"+config.Container+"/exec", nil, config, nil) |
|
| 13 |
+ resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) |
|
| 14 | 14 |
if err != nil {
|
| 15 | 15 |
return response, err |
| 16 | 16 |
} |
| ... | ... |
@@ -35,7 +35,8 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis |
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
if options.Filter.Len() > 0 {
|
| 38 |
- filterJSON, err := filters.ToParam(options.Filter) |
|
| 38 |
+ filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filter) |
|
| 39 |
+ |
|
| 39 | 40 |
if err != nil {
|
| 40 | 41 |
return nil, err |
| 41 | 42 |
} |
| ... | ... |
@@ -13,7 +13,7 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
// ContainerLogs returns the logs generated by a container in an io.ReadCloser. |
| 15 | 15 |
// It's up to the caller to close the stream. |
| 16 |
-func (cli *Client) ContainerLogs(ctx context.Context, options types.ContainerLogsOptions) (io.ReadCloser, error) {
|
|
| 16 |
+func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
|
|
| 17 | 17 |
query := url.Values{}
|
| 18 | 18 |
if options.ShowStdout {
|
| 19 | 19 |
query.Set("stdout", "1")
|
| ... | ... |
@@ -40,7 +40,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, options types.ContainerLog |
| 40 | 40 |
} |
| 41 | 41 |
query.Set("tail", options.Tail)
|
| 42 | 42 |
|
| 43 |
- resp, err := cli.get(ctx, "/containers/"+options.ContainerID+"/logs", query, nil) |
|
| 43 |
+ resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) |
|
| 44 | 44 |
if err != nil {
|
| 45 | 45 |
return nil, err |
| 46 | 46 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// ContainerRemove kills and removes a container from the docker host. |
| 11 |
-func (cli *Client) ContainerRemove(ctx context.Context, options types.ContainerRemoveOptions) error {
|
|
| 11 |
+func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error {
|
|
| 12 | 12 |
query := url.Values{}
|
| 13 | 13 |
if options.RemoveVolumes {
|
| 14 | 14 |
query.Set("v", "1")
|
| ... | ... |
@@ -21,7 +21,7 @@ func (cli *Client) ContainerRemove(ctx context.Context, options types.ContainerR |
| 21 | 21 |
query.Set("force", "1")
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
- resp, err := cli.delete(ctx, "/containers/"+options.ContainerID, query, nil) |
|
| 24 |
+ resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) |
|
| 25 | 25 |
ensureReaderClosed(resp) |
| 26 | 26 |
return err |
| 27 | 27 |
} |
| ... | ... |
@@ -9,13 +9,13 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// ContainerResize changes the size of the tty for a container. |
| 12 |
-func (cli *Client) ContainerResize(ctx context.Context, options types.ResizeOptions) error {
|
|
| 13 |
- return cli.resize(ctx, "/containers/"+options.ID, options.Height, options.Width) |
|
| 12 |
+func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error {
|
|
| 13 |
+ return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width) |
|
| 14 | 14 |
} |
| 15 | 15 |
|
| 16 | 16 |
// ContainerExecResize changes the size of the tty for an exec process running inside a container. |
| 17 |
-func (cli *Client) ContainerExecResize(ctx context.Context, options types.ResizeOptions) error {
|
|
| 18 |
- return cli.resize(ctx, "/exec/"+options.ID, options.Height, options.Width) |
|
| 17 |
+func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error {
|
|
| 18 |
+ return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width) |
|
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 | 21 |
func (cli *Client) resize(ctx context.Context, basePath string, height, width int) error {
|
| ... | ... |
@@ -3,6 +3,7 @@ package client |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/base64" |
| 5 | 5 |
"encoding/json" |
| 6 |
+ "io" |
|
| 6 | 7 |
"net/http" |
| 7 | 8 |
"net/url" |
| 8 | 9 |
"regexp" |
| ... | ... |
@@ -20,7 +21,7 @@ var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`) |
| 20 | 20 |
// ImageBuild sends request to the daemon to build images. |
| 21 | 21 |
// The Body in the response implement an io.ReadCloser and it's up to the caller to |
| 22 | 22 |
// close it. |
| 23 |
-func (cli *Client) ImageBuild(ctx context.Context, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
|
| 23 |
+func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
|
| 24 | 24 |
query, err := imageBuildOptionsToQuery(options) |
| 25 | 25 |
if err != nil {
|
| 26 | 26 |
return types.ImageBuildResponse{}, err
|
| ... | ... |
@@ -34,7 +35,7 @@ func (cli *Client) ImageBuild(ctx context.Context, options types.ImageBuildOptio |
| 34 | 34 |
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
| 35 | 35 |
headers.Set("Content-Type", "application/tar")
|
| 36 | 36 |
|
| 37 |
- serverResp, err := cli.postRaw(ctx, "/build", query, options.Context, headers) |
|
| 37 |
+ serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) |
|
| 38 | 38 |
if err != nil {
|
| 39 | 39 |
return types.ImageBuildResponse{}, err
|
| 40 | 40 |
} |
| ... | ... |
@@ -7,14 +7,20 @@ import ( |
| 7 | 7 |
"golang.org/x/net/context" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/engine-api/types" |
| 10 |
+ "github.com/docker/engine-api/types/reference" |
|
| 10 | 11 |
) |
| 11 | 12 |
|
| 12 | 13 |
// ImageCreate creates a new image based in the parent options. |
| 13 | 14 |
// It returns the JSON content in the response body. |
| 14 |
-func (cli *Client) ImageCreate(ctx context.Context, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
|
| 15 |
+func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
|
| 16 |
+ repository, tag, err := reference.Parse(parentReference) |
|
| 17 |
+ if err != nil {
|
|
| 18 |
+ return nil, err |
|
| 19 |
+ } |
|
| 20 |
+ |
|
| 15 | 21 |
query := url.Values{}
|
| 16 |
- query.Set("fromImage", options.Parent)
|
|
| 17 |
- query.Set("tag", options.Tag)
|
|
| 22 |
+ query.Set("fromImage", repository)
|
|
| 23 |
+ query.Set("tag", tag)
|
|
| 18 | 24 |
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) |
| 19 | 25 |
if err != nil {
|
| 20 | 26 |
return nil, err |
| ... | ... |
@@ -6,22 +6,30 @@ import ( |
| 6 | 6 |
|
| 7 | 7 |
"golang.org/x/net/context" |
| 8 | 8 |
|
| 9 |
+ "github.com/docker/distribution/reference" |
|
| 9 | 10 |
"github.com/docker/engine-api/types" |
| 10 | 11 |
) |
| 11 | 12 |
|
| 12 | 13 |
// ImageImport creates a new image based in the source options. |
| 13 | 14 |
// It returns the JSON content in the response body. |
| 14 |
-func (cli *Client) ImageImport(ctx context.Context, options types.ImageImportOptions) (io.ReadCloser, error) {
|
|
| 15 |
+func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
|
|
| 16 |
+ if ref != "" {
|
|
| 17 |
+ //Check if the given image name can be resolved |
|
| 18 |
+ if _, err := reference.ParseNamed(ref); err != nil {
|
|
| 19 |
+ return nil, err |
|
| 20 |
+ } |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 15 | 23 |
query := url.Values{}
|
| 16 |
- query.Set("fromSrc", options.SourceName)
|
|
| 17 |
- query.Set("repo", options.RepositoryName)
|
|
| 24 |
+ query.Set("fromSrc", source.SourceName)
|
|
| 25 |
+ query.Set("repo", ref)
|
|
| 18 | 26 |
query.Set("tag", options.Tag)
|
| 19 | 27 |
query.Set("message", options.Message)
|
| 20 | 28 |
for _, change := range options.Changes {
|
| 21 | 29 |
query.Add("changes", change)
|
| 22 | 30 |
} |
| 23 | 31 |
|
| 24 |
- resp, err := cli.postRaw(ctx, "/images/create", query, options.Source, nil) |
|
| 32 |
+ resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil) |
|
| 25 | 33 |
if err != nil {
|
| 26 | 34 |
return nil, err |
| 27 | 35 |
} |
| ... | ... |
@@ -8,22 +8,32 @@ import ( |
| 8 | 8 |
"golang.org/x/net/context" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/engine-api/types" |
| 11 |
+ "github.com/docker/engine-api/types/reference" |
|
| 11 | 12 |
) |
| 12 | 13 |
|
| 13 | 14 |
// ImagePull requests the docker host to pull an image from a remote registry. |
| 14 | 15 |
// It executes the privileged function if the operation is unauthorized |
| 15 | 16 |
// and it tries one more time. |
| 16 | 17 |
// It's up to the caller to handle the io.ReadCloser and close it properly. |
| 17 |
-func (cli *Client) ImagePull(ctx context.Context, options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
|
| 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, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
|
|
| 23 |
+ repository, tag, err := reference.Parse(ref) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return nil, err |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 18 | 28 |
query := url.Values{}
|
| 19 |
- query.Set("fromImage", options.ImageID)
|
|
| 20 |
- if options.Tag != "" {
|
|
| 21 |
- query.Set("tag", options.Tag)
|
|
| 29 |
+ query.Set("fromImage", repository)
|
|
| 30 |
+ if tag != "" {
|
|
| 31 |
+ query.Set("tag", tag)
|
|
| 22 | 32 |
} |
| 23 | 33 |
|
| 24 | 34 |
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) |
| 25 | 35 |
if resp.statusCode == http.StatusUnauthorized {
|
| 26 |
- newAuthHeader, privilegeErr := privilegeFunc() |
|
| 36 |
+ newAuthHeader, privilegeErr := options.PrivilegeFunc() |
|
| 27 | 37 |
if privilegeErr != nil {
|
| 28 | 38 |
return nil, privilegeErr |
| 29 | 39 |
} |
| ... | ... |
@@ -1,30 +1,44 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "errors" |
|
| 4 | 5 |
"io" |
| 5 | 6 |
"net/http" |
| 6 | 7 |
"net/url" |
| 7 | 8 |
|
| 8 | 9 |
"golang.org/x/net/context" |
| 9 | 10 |
|
| 11 |
+ distreference "github.com/docker/distribution/reference" |
|
| 10 | 12 |
"github.com/docker/engine-api/types" |
| 13 |
+ "github.com/docker/engine-api/types/reference" |
|
| 11 | 14 |
) |
| 12 | 15 |
|
| 13 | 16 |
// ImagePush requests the docker host to push an image to a remote registry. |
| 14 | 17 |
// It executes the privileged function if the operation is unauthorized |
| 15 | 18 |
// and it tries one more time. |
| 16 | 19 |
// It's up to the caller to handle the io.ReadCloser and close it properly. |
| 17 |
-func (cli *Client) ImagePush(ctx context.Context, options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
|
| 20 |
+func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
|
|
| 21 |
+ distributionRef, err := distreference.ParseNamed(ref) |
|
| 22 |
+ if err != nil {
|
|
| 23 |
+ return nil, err |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
|
| 27 |
+ return nil, errors.New("cannot push a digest reference")
|
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ tag := reference.GetTagFromNamedRef(distributionRef) |
|
| 31 |
+ |
|
| 18 | 32 |
query := url.Values{}
|
| 19 |
- query.Set("tag", options.Tag)
|
|
| 33 |
+ query.Set("tag", tag)
|
|
| 20 | 34 |
|
| 21 |
- resp, err := cli.tryImagePush(ctx, options.ImageID, query, options.RegistryAuth) |
|
| 35 |
+ resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth) |
|
| 22 | 36 |
if resp.statusCode == http.StatusUnauthorized {
|
| 23 |
- newAuthHeader, privilegeErr := privilegeFunc() |
|
| 37 |
+ newAuthHeader, privilegeErr := options.PrivilegeFunc() |
|
| 24 | 38 |
if privilegeErr != nil {
|
| 25 | 39 |
return nil, privilegeErr |
| 26 | 40 |
} |
| 27 |
- resp, err = cli.tryImagePush(ctx, options.ImageID, query, newAuthHeader) |
|
| 41 |
+ resp, err = cli.tryImagePush(ctx, distributionRef.Name(), query, newAuthHeader) |
|
| 28 | 42 |
} |
| 29 | 43 |
if err != nil {
|
| 30 | 44 |
return nil, err |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// ImageRemove removes an image from the docker host. |
| 12 |
-func (cli *Client) ImageRemove(ctx context.Context, options types.ImageRemoveOptions) ([]types.ImageDelete, error) {
|
|
| 12 |
+func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDelete, error) {
|
|
| 13 | 13 |
query := url.Values{}
|
| 14 | 14 |
|
| 15 | 15 |
if options.Force {
|
| ... | ... |
@@ -19,7 +19,7 @@ func (cli *Client) ImageRemove(ctx context.Context, options types.ImageRemoveOpt |
| 19 | 19 |
query.Set("noprune", "1")
|
| 20 | 20 |
} |
| 21 | 21 |
|
| 22 |
- resp, err := cli.delete(ctx, "/images/"+options.ImageID, query, nil) |
|
| 22 |
+ resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) |
|
| 23 | 23 |
if err != nil {
|
| 24 | 24 |
return nil, err |
| 25 | 25 |
} |
| ... | ... |
@@ -12,14 +12,14 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// ImageSearch makes the docker host to search by a term in a remote registry. |
| 14 | 14 |
// The list of results is not sorted in any fashion. |
| 15 |
-func (cli *Client) ImageSearch(ctx context.Context, options types.ImageSearchOptions, privilegeFunc RequestPrivilegeFunc) ([]registry.SearchResult, error) {
|
|
| 15 |
+func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) {
|
|
| 16 | 16 |
var results []registry.SearchResult |
| 17 | 17 |
query := url.Values{}
|
| 18 |
- query.Set("term", options.Term)
|
|
| 18 |
+ query.Set("term", term)
|
|
| 19 | 19 |
|
| 20 | 20 |
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) |
| 21 | 21 |
if resp.statusCode == http.StatusUnauthorized {
|
| 22 |
- newAuthHeader, privilegeErr := privilegeFunc() |
|
| 22 |
+ newAuthHeader, privilegeErr := options.PrivilegeFunc() |
|
| 23 | 23 |
if privilegeErr != nil {
|
| 24 | 24 |
return results, privilegeErr |
| 25 | 25 |
} |
| ... | ... |
@@ -1,22 +1,38 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "errors" |
|
| 5 |
+ "fmt" |
|
| 4 | 6 |
"net/url" |
| 5 | 7 |
|
| 6 |
- "github.com/docker/engine-api/types" |
|
| 7 | 8 |
"golang.org/x/net/context" |
| 9 |
+ |
|
| 10 |
+ distreference "github.com/docker/distribution/reference" |
|
| 11 |
+ "github.com/docker/engine-api/types" |
|
| 12 |
+ "github.com/docker/engine-api/types/reference" |
|
| 8 | 13 |
) |
| 9 | 14 |
|
| 10 | 15 |
// ImageTag tags an image in the docker host |
| 11 |
-func (cli *Client) ImageTag(ctx context.Context, options types.ImageTagOptions) error {
|
|
| 16 |
+func (cli *Client) ImageTag(ctx context.Context, imageID, ref string, options types.ImageTagOptions) error {
|
|
| 17 |
+ distributionRef, err := distreference.ParseNamed(ref) |
|
| 18 |
+ if err != nil {
|
|
| 19 |
+ return fmt.Errorf("Error parsing reference: %q is not a valid repository/tag", ref)
|
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
|
| 23 |
+ return errors.New("refusing to create a tag with a digest reference")
|
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ tag := reference.GetTagFromNamedRef(distributionRef) |
|
| 27 |
+ |
|
| 12 | 28 |
query := url.Values{}
|
| 13 |
- query.Set("repo", options.RepositoryName)
|
|
| 14 |
- query.Set("tag", options.Tag)
|
|
| 29 |
+ query.Set("repo", distributionRef.Name())
|
|
| 30 |
+ query.Set("tag", tag)
|
|
| 15 | 31 |
if options.Force {
|
| 16 | 32 |
query.Set("force", "1")
|
| 17 | 33 |
} |
| 18 | 34 |
|
| 19 |
- resp, err := cli.post(ctx, "/images/"+options.ImageID+"/tag", query, nil, nil) |
|
| 35 |
+ resp, err := cli.post(ctx, "/images/"+imageID+"/tag", query, nil, nil) |
|
| 20 | 36 |
ensureReaderClosed(resp) |
| 21 | 37 |
return err |
| 22 | 38 |
} |
| ... | ... |
@@ -15,59 +15,60 @@ import ( |
| 15 | 15 |
// APIClient is an interface that clients that talk with a docker server must implement. |
| 16 | 16 |
type APIClient interface {
|
| 17 | 17 |
ClientVersion() string |
| 18 |
- ContainerAttach(ctx context.Context, options types.ContainerAttachOptions) (types.HijackedResponse, error) |
|
| 19 |
- ContainerCommit(ctx context.Context, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) |
|
| 18 |
+ ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) |
|
| 19 |
+ ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) |
|
| 20 | 20 |
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) |
| 21 |
- ContainerDiff(ctx context.Context, ontainerID string) ([]types.ContainerChange, error) |
|
| 21 |
+ ContainerDiff(ctx context.Context, container string) ([]types.ContainerChange, error) |
|
| 22 | 22 |
ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) |
| 23 |
- ContainerExecCreate(ctx context.Context, config types.ExecConfig) (types.ContainerExecCreateResponse, error) |
|
| 23 |
+ ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error) |
|
| 24 | 24 |
ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) |
| 25 |
- ContainerExecResize(ctx context.Context, options types.ResizeOptions) error |
|
| 25 |
+ ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error |
|
| 26 | 26 |
ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error |
| 27 |
- ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) |
|
| 28 |
- ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) |
|
| 29 |
- ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) |
|
| 30 |
- ContainerKill(ctx context.Context, containerID, signal string) error |
|
| 27 |
+ ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) |
|
| 28 |
+ ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) |
|
| 29 |
+ ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error) |
|
| 30 |
+ ContainerKill(ctx context.Context, container, signal string) error |
|
| 31 | 31 |
ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) |
| 32 |
- ContainerLogs(ctx context.Context, options types.ContainerLogsOptions) (io.ReadCloser, error) |
|
| 33 |
- ContainerPause(ctx context.Context, containerID string) error |
|
| 34 |
- ContainerRemove(ctx context.Context, options types.ContainerRemoveOptions) error |
|
| 35 |
- ContainerRename(ctx context.Context, containerID, newContainerName string) error |
|
| 36 |
- ContainerResize(ctx context.Context, options types.ResizeOptions) error |
|
| 37 |
- ContainerRestart(ctx context.Context, containerID string, timeout int) error |
|
| 38 |
- ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) |
|
| 39 |
- ContainerStats(ctx context.Context, containerID string, stream bool) (io.ReadCloser, error) |
|
| 40 |
- ContainerStart(ctx context.Context, containerID string) error |
|
| 41 |
- ContainerStop(ctx context.Context, containerID string, timeout int) error |
|
| 42 |
- ContainerTop(ctx context.Context, containerID string, arguments []string) (types.ContainerProcessList, error) |
|
| 43 |
- ContainerUnpause(ctx context.Context, containerID string) error |
|
| 44 |
- ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) error |
|
| 45 |
- ContainerWait(ctx context.Context, containerID string) (int, error) |
|
| 46 |
- CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) |
|
| 32 |
+ ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) |
|
| 33 |
+ ContainerPause(ctx context.Context, container string) error |
|
| 34 |
+ ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error |
|
| 35 |
+ ContainerRename(ctx context.Context, container, newContainerName string) error |
|
| 36 |
+ ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error |
|
| 37 |
+ ContainerRestart(ctx context.Context, container string, timeout int) error |
|
| 38 |
+ ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error) |
|
| 39 |
+ ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error) |
|
| 40 |
+ ContainerStart(ctx context.Context, container string) error |
|
| 41 |
+ ContainerStop(ctx context.Context, container string, timeout int) error |
|
| 42 |
+ ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error) |
|
| 43 |
+ ContainerUnpause(ctx context.Context, container string) error |
|
| 44 |
+ ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error |
|
| 45 |
+ ContainerWait(ctx context.Context, container string) (int, error) |
|
| 46 |
+ CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) |
|
| 47 | 47 |
CopyToContainer(ctx context.Context, options types.CopyToContainerOptions) error |
| 48 | 48 |
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) |
| 49 |
- ImageBuild(ctx context.Context, options types.ImageBuildOptions) (types.ImageBuildResponse, error) |
|
| 50 |
- ImageCreate(ctx context.Context, options types.ImageCreateOptions) (io.ReadCloser, error) |
|
| 51 |
- ImageHistory(ctx context.Context, imageID string) ([]types.ImageHistory, error) |
|
| 52 |
- ImageImport(ctx context.Context, options types.ImageImportOptions) (io.ReadCloser, error) |
|
| 53 |
- ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) |
|
| 49 |
+ ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) |
|
| 50 |
+ ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) |
|
| 51 |
+ ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error) |
|
| 52 |
+ ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) |
|
| 53 |
+ ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error) |
|
| 54 | 54 |
ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) |
| 55 | 55 |
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) |
| 56 |
- ImagePull(ctx context.Context, options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) |
|
| 57 |
- ImagePush(ctx context.Context, options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) |
|
| 58 |
- ImageRemove(ctx context.Context, options types.ImageRemoveOptions) ([]types.ImageDelete, error) |
|
| 59 |
- ImageSearch(ctx context.Context, options types.ImageSearchOptions, privilegeFunc RequestPrivilegeFunc) ([]registry.SearchResult, error) |
|
| 60 |
- ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) |
|
| 61 |
- ImageTag(ctx context.Context, options types.ImageTagOptions) error |
|
| 56 |
+ ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) |
|
| 57 |
+ ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) |
|
| 58 |
+ ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDelete, error) |
|
| 59 |
+ ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) |
|
| 60 |
+ ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) |
|
| 61 |
+ ImageTag(ctx context.Context, image, ref string, options types.ImageTagOptions) error |
|
| 62 | 62 |
Info(ctx context.Context) (types.Info, error) |
| 63 |
- NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error |
|
| 64 |
- NetworkCreate(ctx context.Context, options types.NetworkCreate) (types.NetworkCreateResponse, error) |
|
| 65 |
- NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error |
|
| 63 |
+ NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error |
|
| 64 |
+ NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) |
|
| 65 |
+ NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error |
|
| 66 | 66 |
NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) |
| 67 | 67 |
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) |
| 68 | 68 |
NetworkRemove(ctx context.Context, networkID string) error |
| 69 | 69 |
RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) |
| 70 | 70 |
ServerVersion(ctx context.Context) (types.Version, error) |
| 71 |
+ UpdateClientVersion(v string) |
|
| 71 | 72 |
VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error) |
| 72 | 73 |
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) |
| 73 | 74 |
VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error) |
| ... | ... |
@@ -8,9 +8,13 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// NetworkCreate creates a new network in the docker host. |
| 11 |
-func (cli *Client) NetworkCreate(ctx context.Context, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
|
| 11 |
+func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
|
| 12 |
+ networkCreateRequest := types.NetworkCreateRequest{
|
|
| 13 |
+ NetworkCreate: options, |
|
| 14 |
+ Name: name, |
|
| 15 |
+ } |
|
| 12 | 16 |
var response types.NetworkCreateResponse |
| 13 |
- serverResp, err := cli.post(ctx, "/networks/create", nil, options, nil) |
|
| 17 |
+ serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) |
|
| 14 | 18 |
if err != nil {
|
| 15 | 19 |
return response, err |
| 16 | 20 |
} |
| ... | ... |
@@ -1,9 +1 @@ |
| 1 | 1 |
package client |
| 2 |
- |
|
| 3 |
-// RequestPrivilegeFunc is a function interface that |
|
| 4 |
-// clients can supply to retry operations after |
|
| 5 |
-// getting an authorization error. |
|
| 6 |
-// This function returns the registry authentication |
|
| 7 |
-// header value in base 64 format, or an error |
|
| 8 |
-// if the privilege request fails. |
|
| 9 |
-type RequestPrivilegeFunc func() (string, error) |
| ... | ... |
@@ -56,12 +56,14 @@ func (cli *Client) delete(ctx context.Context, path string, query url.Values, he |
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 | 58 |
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
|
| 59 |
- body, err := encodeData(obj) |
|
| 60 |
- if err != nil {
|
|
| 61 |
- return nil, err |
|
| 62 |
- } |
|
| 59 |
+ var body io.Reader |
|
| 63 | 60 |
|
| 64 |
- if body != nil {
|
|
| 61 |
+ if obj != nil {
|
|
| 62 |
+ var err error |
|
| 63 |
+ body, err = encodeData(obj) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return nil, err |
|
| 66 |
+ } |
|
| 65 | 67 |
if headers == nil {
|
| 66 | 68 |
headers = make(map[string][]string) |
| 67 | 69 |
} |
| ... | ... |
@@ -12,24 +12,21 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// ContainerAttachOptions holds parameters to attach to a container. |
| 14 | 14 |
type ContainerAttachOptions struct {
|
| 15 |
- ContainerID string |
|
| 16 |
- Stream bool |
|
| 17 |
- Stdin bool |
|
| 18 |
- Stdout bool |
|
| 19 |
- Stderr bool |
|
| 20 |
- DetachKeys string |
|
| 15 |
+ Stream bool |
|
| 16 |
+ Stdin bool |
|
| 17 |
+ Stdout bool |
|
| 18 |
+ Stderr bool |
|
| 19 |
+ DetachKeys string |
|
| 21 | 20 |
} |
| 22 | 21 |
|
| 23 | 22 |
// ContainerCommitOptions holds parameters to commit changes into a container. |
| 24 | 23 |
type ContainerCommitOptions struct {
|
| 25 |
- ContainerID string |
|
| 26 |
- RepositoryName string |
|
| 27 |
- Tag string |
|
| 28 |
- Comment string |
|
| 29 |
- Author string |
|
| 30 |
- Changes []string |
|
| 31 |
- Pause bool |
|
| 32 |
- Config *container.Config |
|
| 24 |
+ Reference string |
|
| 25 |
+ Comment string |
|
| 26 |
+ Author string |
|
| 27 |
+ Changes []string |
|
| 28 |
+ Pause bool |
|
| 29 |
+ Config *container.Config |
|
| 33 | 30 |
} |
| 34 | 31 |
|
| 35 | 32 |
// ContainerExecInspect holds information returned by exec inspect. |
| ... | ... |
@@ -54,18 +51,16 @@ type ContainerListOptions struct {
|
| 54 | 54 |
|
| 55 | 55 |
// ContainerLogsOptions holds parameters to filter logs with. |
| 56 | 56 |
type ContainerLogsOptions struct {
|
| 57 |
- ContainerID string |
|
| 58 |
- ShowStdout bool |
|
| 59 |
- ShowStderr bool |
|
| 60 |
- Since string |
|
| 61 |
- Timestamps bool |
|
| 62 |
- Follow bool |
|
| 63 |
- Tail string |
|
| 57 |
+ ShowStdout bool |
|
| 58 |
+ ShowStderr bool |
|
| 59 |
+ Since string |
|
| 60 |
+ Timestamps bool |
|
| 61 |
+ Follow bool |
|
| 62 |
+ Tail string |
|
| 64 | 63 |
} |
| 65 | 64 |
|
| 66 | 65 |
// ContainerRemoveOptions holds parameters to remove containers. |
| 67 | 66 |
type ContainerRemoveOptions struct {
|
| 68 |
- ContainerID string |
|
| 69 | 67 |
RemoveVolumes bool |
| 70 | 68 |
RemoveLinks bool |
| 71 | 69 |
Force bool |
| ... | ... |
@@ -155,19 +150,20 @@ type ImageBuildResponse struct {
|
| 155 | 155 |
|
| 156 | 156 |
// ImageCreateOptions holds information to create images. |
| 157 | 157 |
type ImageCreateOptions struct {
|
| 158 |
- Parent string // Parent is the name of the image to pull |
|
| 159 |
- Tag string // Tag is the name to tag this image with |
|
| 160 | 158 |
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry |
| 161 | 159 |
} |
| 162 | 160 |
|
| 161 |
+// ImageImportSource holds source information for ImageImport |
|
| 162 |
+type ImageImportSource struct {
|
|
| 163 |
+ Source io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName) |
|
| 164 |
+ SourceName string // SourceName is the name of the image to pull (mutually exclusive with Source) |
|
| 165 |
+} |
|
| 166 |
+ |
|
| 163 | 167 |
// ImageImportOptions holds information to import images from the client host. |
| 164 | 168 |
type ImageImportOptions struct {
|
| 165 |
- Source io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName) |
|
| 166 |
- SourceName string // SourceName is the name of the image to pull (mutually exclusive with Source) |
|
| 167 |
- RepositoryName string // RepositoryName is the name of the repository to import this image into |
|
| 168 |
- Message string // Message is the message to tag the image with |
|
| 169 |
- Tag string // Tag is the name to tag this image with |
|
| 170 |
- Changes []string // Changes are the raw changes to apply to this image |
|
| 169 |
+ Tag string // Tag is the name to tag this image with. This attribute is deprecated. |
|
| 170 |
+ Message string // Message is the message to tag the image with |
|
| 171 |
+ Changes []string // Changes are the raw changes to apply to this image |
|
| 171 | 172 |
} |
| 172 | 173 |
|
| 173 | 174 |
// ImageListOptions holds parameters to filter the list of images with. |
| ... | ... |
@@ -185,40 +181,42 @@ type ImageLoadResponse struct {
|
| 185 | 185 |
|
| 186 | 186 |
// ImagePullOptions holds information to pull images. |
| 187 | 187 |
type ImagePullOptions struct {
|
| 188 |
- ImageID string // ImageID is the name of the image to pull |
|
| 189 |
- Tag string // Tag is the name of the tag to be pulled |
|
| 190 |
- RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry |
|
| 188 |
+ RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry |
|
| 189 |
+ PrivilegeFunc RequestPrivilegeFunc |
|
| 191 | 190 |
} |
| 192 | 191 |
|
| 192 |
+// RequestPrivilegeFunc is a function interface that |
|
| 193 |
+// clients can supply to retry operations after |
|
| 194 |
+// getting an authorization error. |
|
| 195 |
+// This function returns the registry authentication |
|
| 196 |
+// header value in base 64 format, or an error |
|
| 197 |
+// if the privilege request fails. |
|
| 198 |
+type RequestPrivilegeFunc func() (string, error) |
|
| 199 |
+ |
|
| 193 | 200 |
//ImagePushOptions holds information to push images. |
| 194 | 201 |
type ImagePushOptions ImagePullOptions |
| 195 | 202 |
|
| 196 | 203 |
// ImageRemoveOptions holds parameters to remove images. |
| 197 | 204 |
type ImageRemoveOptions struct {
|
| 198 |
- ImageID string |
|
| 199 | 205 |
Force bool |
| 200 | 206 |
PruneChildren bool |
| 201 | 207 |
} |
| 202 | 208 |
|
| 203 | 209 |
// ImageSearchOptions holds parameters to search images with. |
| 204 | 210 |
type ImageSearchOptions struct {
|
| 205 |
- Term string |
|
| 206 |
- RegistryAuth string |
|
| 211 |
+ RegistryAuth string |
|
| 212 |
+ PrivilegeFunc RequestPrivilegeFunc |
|
| 207 | 213 |
} |
| 208 | 214 |
|
| 209 | 215 |
// ImageTagOptions holds parameters to tag an image |
| 210 | 216 |
type ImageTagOptions struct {
|
| 211 |
- ImageID string |
|
| 212 |
- RepositoryName string |
|
| 213 |
- Tag string |
|
| 214 |
- Force bool |
|
| 217 |
+ Force bool |
|
| 215 | 218 |
} |
| 216 | 219 |
|
| 217 | 220 |
// ResizeOptions holds parameters to resize a tty. |
| 218 | 221 |
// It can be used to resize container ttys and |
| 219 | 222 |
// exec process ttys too. |
| 220 | 223 |
type ResizeOptions struct {
|
| 221 |
- ID string |
|
| 222 | 224 |
Height int |
| 223 | 225 |
Width int |
| 224 | 226 |
} |
| ... | ... |
@@ -44,7 +44,6 @@ type ExecConfig struct {
|
| 44 | 44 |
User string // User that will run the command |
| 45 | 45 |
Privileged bool // Is the container in privileged mode |
| 46 | 46 |
Tty bool // Attach standard streams to a tty. |
| 47 |
- Container string // Name of the container (to execute in) |
|
| 48 | 47 |
AttachStdin bool // Attach the standard input, makes possible user interaction |
| 49 | 48 |
AttachStderr bool // Attach the standard output |
| 50 | 49 |
AttachStdout bool // Attach the standard error |
| ... | ... |
@@ -19,7 +19,6 @@ type Config struct {
|
| 19 | 19 |
AttachStdout bool // Attach the standard output |
| 20 | 20 |
AttachStderr bool // Attach the standard error |
| 21 | 21 |
ExposedPorts map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports
|
| 22 |
- PublishService string `json:",omitempty"` // Name of the network service exposed by the container |
|
| 23 | 22 |
Tty bool // Attach standard streams to a tty, including stdin if it is not closed. |
| 24 | 23 |
OpenStdin bool // Open stdin |
| 25 | 24 |
StdinOnce bool // If true, close stdin after the 1 attached client disconnects. |
| ... | ... |
@@ -92,11 +92,13 @@ func (n UsernsMode) Valid() bool {
|
| 92 | 92 |
// CgroupSpec represents the cgroup to use for the container. |
| 93 | 93 |
type CgroupSpec string |
| 94 | 94 |
|
| 95 |
+// IsContainer indicates whether the container is using another container cgroup |
|
| 95 | 96 |
func (c CgroupSpec) IsContainer() bool {
|
| 96 | 97 |
parts := strings.SplitN(string(c), ":", 2) |
| 97 | 98 |
return len(parts) > 1 && parts[0] == "container" |
| 98 | 99 |
} |
| 99 | 100 |
|
| 101 |
+// Valid indicates whether the cgroup spec is valid. |
|
| 100 | 102 |
func (c CgroupSpec) Valid() bool {
|
| 101 | 103 |
return c.IsContainer() || c == "" |
| 102 | 104 |
} |
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"errors" |
| 8 | 8 |
"fmt" |
| 9 | 9 |
"regexp" |
| 10 |
+ "strconv" |
|
| 10 | 11 |
"strings" |
| 11 | 12 |
) |
| 12 | 13 |
|
| ... | ... |
@@ -68,6 +69,28 @@ func ToParam(a Args) (string, error) {
|
| 68 | 68 |
return string(buf), nil |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
+// ToParamWithVersion packs the Args into a string for easy transport from client to server. |
|
| 72 |
+// The generated string will depend on the specified version (corresponding to the API version). |
|
| 73 |
+func ToParamWithVersion(version string, a Args) (string, error) {
|
|
| 74 |
+ // this way we don't URL encode {}, just empty space
|
|
| 75 |
+ if a.Len() == 0 {
|
|
| 76 |
+ return "", nil |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ // for daemons older than v1.10, filter must be of the form map[string][]string |
|
| 80 |
+ buf := []byte{}
|
|
| 81 |
+ err := errors.New("")
|
|
| 82 |
+ if version != "" && compareTo(version, "1.22") == -1 {
|
|
| 83 |
+ buf, err = json.Marshal(convertArgsToSlice(a.fields)) |
|
| 84 |
+ } else {
|
|
| 85 |
+ buf, err = json.Marshal(a.fields) |
|
| 86 |
+ } |
|
| 87 |
+ if err != nil {
|
|
| 88 |
+ return "", err |
|
| 89 |
+ } |
|
| 90 |
+ return string(buf), nil |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 71 | 93 |
// FromParam unpacks the filter Args. |
| 72 | 94 |
func FromParam(p string) (Args, error) {
|
| 73 | 95 |
if len(p) == 0 {
|
| ... | ... |
@@ -255,3 +278,48 @@ func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
|
| 255 | 255 |
} |
| 256 | 256 |
return m |
| 257 | 257 |
} |
| 258 |
+ |
|
| 259 |
+func convertArgsToSlice(f map[string]map[string]bool) map[string][]string {
|
|
| 260 |
+ m := map[string][]string{}
|
|
| 261 |
+ for k, v := range f {
|
|
| 262 |
+ values := []string{}
|
|
| 263 |
+ for kk := range v {
|
|
| 264 |
+ if v[kk] {
|
|
| 265 |
+ values = append(values, kk) |
|
| 266 |
+ } |
|
| 267 |
+ } |
|
| 268 |
+ m[k] = values |
|
| 269 |
+ } |
|
| 270 |
+ return m |
|
| 271 |
+} |
|
| 272 |
+ |
|
| 273 |
+// compareTo compares two version strings |
|
| 274 |
+// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise |
|
| 275 |
+func compareTo(v1, v2 string) int {
|
|
| 276 |
+ var ( |
|
| 277 |
+ currTab = strings.Split(v1, ".") |
|
| 278 |
+ otherTab = strings.Split(v2, ".") |
|
| 279 |
+ ) |
|
| 280 |
+ |
|
| 281 |
+ max := len(currTab) |
|
| 282 |
+ if len(otherTab) > max {
|
|
| 283 |
+ max = len(otherTab) |
|
| 284 |
+ } |
|
| 285 |
+ for i := 0; i < max; i++ {
|
|
| 286 |
+ var currInt, otherInt int |
|
| 287 |
+ |
|
| 288 |
+ if len(currTab) > i {
|
|
| 289 |
+ currInt, _ = strconv.Atoi(currTab[i]) |
|
| 290 |
+ } |
|
| 291 |
+ if len(otherTab) > i {
|
|
| 292 |
+ otherInt, _ = strconv.Atoi(otherTab[i]) |
|
| 293 |
+ } |
|
| 294 |
+ if currInt > otherInt {
|
|
| 295 |
+ return 1 |
|
| 296 |
+ } |
|
| 297 |
+ if otherInt > currInt {
|
|
| 298 |
+ return -1 |
|
| 299 |
+ } |
|
| 300 |
+ } |
|
| 301 |
+ return 0 |
|
| 302 |
+} |
| 258 | 303 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,32 @@ |
| 0 |
+package reference |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ distreference "github.com/docker/distribution/reference" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+// Parse parses the given references and return the repository and |
|
| 7 |
+// tag (if present) from it. If there is an error during parsing, it will |
|
| 8 |
+// return an error. |
|
| 9 |
+func Parse(ref string) (string, string, error) {
|
|
| 10 |
+ distributionRef, err := distreference.ParseNamed(ref) |
|
| 11 |
+ if err != nil {
|
|
| 12 |
+ return "", "", err |
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ tag := GetTagFromNamedRef(distributionRef) |
|
| 16 |
+ return distributionRef.Name(), tag, nil |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// GetTagFromNamedRef returns a tag from the specified reference. |
|
| 20 |
+// This function is necessary as long as the docker "server" api make the distinction between repository |
|
| 21 |
+// and tags. |
|
| 22 |
+func GetTagFromNamedRef(ref distreference.Named) string {
|
|
| 23 |
+ var tag string |
|
| 24 |
+ switch x := ref.(type) {
|
|
| 25 |
+ case distreference.Digested: |
|
| 26 |
+ tag = x.Digest().String() |
|
| 27 |
+ case distreference.NamedTagged: |
|
| 28 |
+ tag = x.Tag() |
|
| 29 |
+ } |
|
| 30 |
+ return tag |
|
| 31 |
+} |
| ... | ... |
@@ -91,6 +91,9 @@ type NetworkStats struct {
|
| 91 | 91 |
type PidsStats struct {
|
| 92 | 92 |
// Current is the number of pids in the cgroup |
| 93 | 93 |
Current uint64 `json:"current,omitempty"` |
| 94 |
+ // Limit is the hard limit on the number of pids in the cgroup. |
|
| 95 |
+ // A "Limit" of 0 means that there is no limit. |
|
| 96 |
+ Limit uint64 `json:"limit,omitempty"` |
|
| 94 | 97 |
} |
| 95 | 98 |
|
| 96 | 99 |
// Stats is Ultimate struct aggregating all types of stats of one container |
| ... | ... |
@@ -290,7 +290,7 @@ type ContainerState struct {
|
| 290 | 290 |
FinishedAt string |
| 291 | 291 |
} |
| 292 | 292 |
|
| 293 |
-// NodeData stores information about the node that a container |
|
| 293 |
+// ContainerNode stores information about the node that a container |
|
| 294 | 294 |
// is running on. It's only available in Docker Swarm |
| 295 | 295 |
type ContainerNode struct {
|
| 296 | 296 |
ID string |
| ... | ... |
@@ -438,7 +438,6 @@ type EndpointResource struct {
|
| 438 | 438 |
|
| 439 | 439 |
// NetworkCreate is the expected body of the "create network" http request message |
| 440 | 440 |
type NetworkCreate struct {
|
| 441 |
- Name string |
|
| 442 | 441 |
CheckDuplicate bool |
| 443 | 442 |
Driver string |
| 444 | 443 |
EnableIPv6 bool |
| ... | ... |
@@ -448,6 +447,12 @@ type NetworkCreate struct {
|
| 448 | 448 |
Labels map[string]string |
| 449 | 449 |
} |
| 450 | 450 |
|
| 451 |
+// NetworkCreateRequest is the request message sent to the server for network create call. |
|
| 452 |
+type NetworkCreateRequest struct {
|
|
| 453 |
+ NetworkCreate |
|
| 454 |
+ Name string |
|
| 455 |
+} |
|
| 456 |
+ |
|
| 451 | 457 |
// NetworkCreateResponse is the response message sent by the server for network create call |
| 452 | 458 |
type NetworkCreateResponse struct {
|
| 453 | 459 |
ID string `json:"Id"` |