Browse code

Vendor engine-api with required arguments

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2016/04/13 17:33:35
Showing 29 changed files
... ...
@@ -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"`