Merge pull request #25721 from cpuguy83/revendor_engine-api

revendor engine-api
This commit is contained in:
Brian Goff 2016-08-16 17:18:43 -04:00 committed by GitHub
commit 37302bbb3f
42 changed files with 241 additions and 182 deletions

View file

@ -182,7 +182,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \

View file

@ -133,7 +133,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \

View file

@ -138,7 +138,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \

View file

@ -60,7 +60,7 @@ RUN set -x \
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT

View file

@ -151,7 +151,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \

View file

@ -155,7 +155,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 7befe694bd21e3c54bb1d7825270ea4bd6864c13
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \

View file

@ -10,6 +10,7 @@ import (
"github.com/docker/docker/opts"
runconfigopts "github.com/docker/docker/runconfig/opts"
mounttypes "github.com/docker/engine-api/types/mount"
"github.com/docker/engine-api/types/swarm"
"github.com/docker/go-connections/nat"
units "github.com/docker/go-units"
@ -130,7 +131,7 @@ func (i *Uint64Opt) Value() *uint64 {
// MountOpt is a Value type for parsing mounts
type MountOpt struct {
values []swarm.Mount
values []mounttypes.Mount
}
// Set a new mount value
@ -141,23 +142,23 @@ func (m *MountOpt) Set(value string) error {
return err
}
mount := swarm.Mount{}
mount := mounttypes.Mount{}
volumeOptions := func() *swarm.VolumeOptions {
volumeOptions := func() *mounttypes.VolumeOptions {
if mount.VolumeOptions == nil {
mount.VolumeOptions = &swarm.VolumeOptions{
mount.VolumeOptions = &mounttypes.VolumeOptions{
Labels: make(map[string]string),
}
}
if mount.VolumeOptions.DriverConfig == nil {
mount.VolumeOptions.DriverConfig = &swarm.Driver{}
mount.VolumeOptions.DriverConfig = &mounttypes.Driver{}
}
return mount.VolumeOptions
}
bindOptions := func() *swarm.BindOptions {
bindOptions := func() *mounttypes.BindOptions {
if mount.BindOptions == nil {
mount.BindOptions = new(swarm.BindOptions)
mount.BindOptions = new(mounttypes.BindOptions)
}
return mount.BindOptions
}
@ -171,7 +172,7 @@ func (m *MountOpt) Set(value string) error {
}
}
mount.Type = swarm.MountTypeVolume // default to volume mounts
mount.Type = mounttypes.TypeVolume // default to volume mounts
// Set writable as the default
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)
@ -195,7 +196,7 @@ func (m *MountOpt) Set(value string) error {
value := parts[1]
switch key {
case "type":
mount.Type = swarm.MountType(strings.ToLower(value))
mount.Type = mounttypes.Type(strings.ToLower(value))
case "source", "src":
mount.Source = value
case "target", "dst", "destination":
@ -206,7 +207,7 @@ func (m *MountOpt) Set(value string) error {
return fmt.Errorf("invalid value for %s: %s", key, value)
}
case "bind-propagation":
bindOptions().Propagation = swarm.MountPropagation(strings.ToLower(value))
bindOptions().Propagation = mounttypes.Propagation(strings.ToLower(value))
case "volume-nocopy":
volumeOptions().NoCopy, err = strconv.ParseBool(value)
if err != nil {
@ -238,11 +239,11 @@ func (m *MountOpt) Set(value string) error {
return fmt.Errorf("source is required when specifying volume-* options")
}
if mount.Type == swarm.MountTypeBind && mount.VolumeOptions != nil {
return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", swarm.MountTypeBind)
if mount.Type == mounttypes.TypeBind && mount.VolumeOptions != nil {
return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", mounttypes.TypeBind)
}
if mount.Type == swarm.MountTypeVolume && mount.BindOptions != nil {
return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", swarm.MountTypeVolume)
if mount.Type == mounttypes.TypeVolume && mount.BindOptions != nil {
return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", mounttypes.TypeVolume)
}
m.values = append(m.values, mount)
@ -265,7 +266,7 @@ func (m *MountOpt) String() string {
}
// Value returns the mounts
func (m *MountOpt) Value() []swarm.Mount {
func (m *MountOpt) Value() []mounttypes.Mount {
return m.values
}

View file

@ -5,7 +5,7 @@ import (
"time"
"github.com/docker/docker/pkg/testutil/assert"
"github.com/docker/engine-api/types/swarm"
mounttypes "github.com/docker/engine-api/types/mount"
)
func TestMemBytesString(t *testing.T) {
@ -59,14 +59,14 @@ func TestUint64OptSetAndValue(t *testing.T) {
func TestMountOptString(t *testing.T) {
mount := MountOpt{
values: []swarm.Mount{
values: []mounttypes.Mount{
{
Type: swarm.MountTypeBind,
Type: mounttypes.TypeBind,
Source: "/home/path",
Target: "/target",
},
{
Type: swarm.MountTypeVolume,
Type: mounttypes.TypeVolume,
Source: "foo",
Target: "/target/foo",
},
@ -90,8 +90,8 @@ func TestMountOptSetNoError(t *testing.T) {
mounts := mount.Value()
assert.Equal(t, len(mounts), 1)
assert.Equal(t, mounts[0], swarm.Mount{
Type: swarm.MountTypeBind,
assert.Equal(t, mounts[0], mounttypes.Mount{
Type: mounttypes.TypeBind,
Source: "/source",
Target: "/target",
})
@ -103,7 +103,7 @@ func TestMountOptSetNoError(t *testing.T) {
func TestMountOptDefaultType(t *testing.T) {
var mount MountOpt
assert.NilError(t, mount.Set("target=/target,source=/foo"))
assert.Equal(t, mount.values[0].Type, swarm.MountTypeVolume)
assert.Equal(t, mount.values[0].Type, mounttypes.TypeVolume)
}
func TestMountOptSetErrorNoTarget(t *testing.T) {

View file

@ -13,6 +13,7 @@ import (
"github.com/docker/docker/opts"
runconfigopts "github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types"
mounttypes "github.com/docker/engine-api/types/mount"
"github.com/docker/engine-api/types/swarm"
"github.com/docker/go-connections/nat"
shlex "github.com/flynn-archive/go-shlex"
@ -353,14 +354,14 @@ func removeItems(
return newSeq
}
func updateMounts(flags *pflag.FlagSet, mounts *[]swarm.Mount) {
func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) {
if flags.Changed(flagMountAdd) {
values := flags.Lookup(flagMountAdd).Value.(*MountOpt).Value()
*mounts = append(*mounts, values...)
}
toRemove := buildToRemoveSet(flags, flagMountRemove)
newMounts := []swarm.Mount{}
newMounts := []mounttypes.Mount{}
for _, mount := range *mounts {
if _, exists := toRemove[mount.Target]; !exists {
newMounts = append(newMounts, mount)

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/docker/docker/pkg/testutil/assert"
mounttypes "github.com/docker/engine-api/types/mount"
"github.com/docker/engine-api/types/swarm"
)
@ -104,9 +105,9 @@ func TestUpdateMounts(t *testing.T) {
flags.Set("mount-add", "type=volume,target=/toadd")
flags.Set("mount-rm", "/toremove")
mounts := []swarm.Mount{
{Target: "/toremove", Type: swarm.MountTypeBind},
{Target: "/tokeep", Type: swarm.MountTypeBind},
mounts := []mounttypes.Mount{
{Target: "/toremove", Type: mounttypes.TypeBind},
{Target: "/tokeep", Type: mounttypes.TypeBind},
}
updateMounts(flags, &mounts)

View file

@ -54,7 +54,7 @@ func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
}
case "image":
getRefFunc = func(ref string) (interface{}, []byte, error) {
return client.ImageInspectWithRaw(ctx, ref, opts.size)
return client.ImageInspectWithRaw(ctx, ref)
}
case "task":
if opts.size {
@ -81,7 +81,7 @@ func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool)
return c, rawContainer, err
}
// Search for image with that id if a container doesn't exist.
i, rawImage, err := client.ImageInspectWithRaw(ctx, ref, getSize)
i, rawImage, err := client.ImageInspectWithRaw(ctx, ref)
if err == nil || !apiclient.IsErrNotFound(err) {
return i, rawImage, err
}

View file

@ -30,7 +30,7 @@ func runRemove(dockerCli *client.DockerCli, volumes []string) error {
status := 0
for _, name := range volumes {
if err := client.VolumeRemove(ctx, name); err != nil {
if err := client.VolumeRemove(ctx, name, false); err != nil {
fmt.Fprintf(dockerCli.Err(), "%s\n", err)
status = 1
continue

View file

@ -15,6 +15,7 @@ import (
"github.com/docker/engine-api/types/events"
"github.com/docker/engine-api/types/filters"
timetypes "github.com/docker/engine-api/types/time"
"github.com/docker/engine-api/types/versions"
"golang.org/x/net/context"
)
@ -37,6 +38,14 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
info.Swarm = s.clusterProvider.Info()
}
if versions.LessThan("1.25", httputils.VersionFromContext(ctx)) {
// TODO: handle this conversion in engine-api
type oldInfo struct {
*types.Info
ExecutionDriver string
}
return httputils.WriteJSON(w, http.StatusOK, &oldInfo{Info: info, ExecutionDriver: "<not supported>"})
}
return httputils.WriteJSON(w, http.StatusOK, info)
}

View file

@ -129,7 +129,7 @@ func (container *Container) NetworkMounts() []Mount {
Source: container.ResolvConfPath,
Destination: "/etc/resolv.conf",
Writable: writable,
Propagation: volume.DefaultPropagationMode,
Propagation: string(volume.DefaultPropagationMode),
})
}
}
@ -148,7 +148,7 @@ func (container *Container) NetworkMounts() []Mount {
Source: container.HostnamePath,
Destination: "/etc/hostname",
Writable: writable,
Propagation: volume.DefaultPropagationMode,
Propagation: string(volume.DefaultPropagationMode),
})
}
}
@ -167,7 +167,7 @@ func (container *Container) NetworkMounts() []Mount {
Source: container.HostsPath,
Destination: "/etc/hosts",
Writable: writable,
Propagation: volume.DefaultPropagationMode,
Propagation: string(volume.DefaultPropagationMode),
})
}
}
@ -249,7 +249,7 @@ func (container *Container) IpcMounts() []Mount {
Source: container.ShmPath,
Destination: "/dev/shm",
Writable: true,
Propagation: volume.DefaultPropagationMode,
Propagation: string(volume.DefaultPropagationMode),
})
}

View file

@ -4,6 +4,7 @@ import (
"fmt"
"strings"
mounttypes "github.com/docker/engine-api/types/mount"
types "github.com/docker/engine-api/types/swarm"
swarmapi "github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/protobuf/ptypes"
@ -22,26 +23,26 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
// Mounts
for _, m := range c.Mounts {
mount := types.Mount{
mount := mounttypes.Mount{
Target: m.Target,
Source: m.Source,
Type: types.MountType(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])),
Type: mounttypes.Type(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])),
ReadOnly: m.ReadOnly,
}
if m.BindOptions != nil {
mount.BindOptions = &types.BindOptions{
Propagation: types.MountPropagation(strings.ToLower(swarmapi.Mount_BindOptions_MountPropagation_name[int32(m.BindOptions.Propagation)])),
mount.BindOptions = &mounttypes.BindOptions{
Propagation: mounttypes.Propagation(strings.ToLower(swarmapi.Mount_BindOptions_MountPropagation_name[int32(m.BindOptions.Propagation)])),
}
}
if m.VolumeOptions != nil {
mount.VolumeOptions = &types.VolumeOptions{
mount.VolumeOptions = &mounttypes.VolumeOptions{
NoCopy: m.VolumeOptions.NoCopy,
Labels: m.VolumeOptions.Labels,
}
if m.VolumeOptions.DriverConfig != nil {
mount.VolumeOptions.DriverConfig = &types.Driver{
mount.VolumeOptions.DriverConfig = &mounttypes.Driver{
Name: m.VolumeOptions.DriverConfig.Name,
Options: m.VolumeOptions.DriverConfig.Options,
}

View file

@ -481,7 +481,7 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
if m.Source == "tmpfs" {
data := c.HostConfig.Tmpfs[m.Destination]
options := []string{"noexec", "nosuid", "nodev", volume.DefaultPropagationMode}
options := []string{"noexec", "nosuid", "nodev", string(volume.DefaultPropagationMode)}
if data != "" {
options = append(options, strings.Split(data, ",")...)
}

View file

@ -37,7 +37,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
Source: path,
Destination: m.Destination,
Writable: m.RW,
Propagation: m.Propagation,
Propagation: string(m.Propagation),
}
if m.Volume != nil {
attributes := map[string]string{
@ -45,7 +45,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
"container": c.ID,
"destination": m.Destination,
"read/write": strconv.FormatBool(m.RW),
"propagation": m.Propagation,
"propagation": string(m.Propagation),
}
daemon.LogVolumeEvent(m.Volume.Name(), "mount", attributes)
}

View file

@ -61,7 +61,7 @@ clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://gith
clone git github.com/docker/go-units eb879ae3e2b84e2a142af415b679ddeda47ec71c
clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
clone git github.com/docker/engine-api 603ec41824c63d1e6498a22271987fa1f268c0c0
clone git github.com/docker/engine-api ebc51d1954fc8934307dd15841b8d64f7cd505df
clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
clone git github.com/imdario/mergo 0.2.1

View file

@ -34,7 +34,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
if err != nil {
if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, imageNotFoundError{config.Image}
}
return response, err

View file

@ -74,6 +74,10 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
query.Set("pull", "1")
}
if options.Squash {
query.Set("squash", "1")
}
if !container.Isolation.IsDefault(options.Isolation) {
query.Set("isolation", string(options.Isolation))
}

View file

@ -28,7 +28,7 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
return resp.body, nil
}
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.post(ctx, "/images/create", query, nil, headers)
}

View file

@ -5,19 +5,14 @@ import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ImageInspectWithRaw returns the image information and its raw representation.
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) {
query := url.Values{}
if getSize {
query.Set("size", "1")
}
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil)
if err != nil {
if serverResp.statusCode == http.StatusNotFound {
return types.ImageInspect{}, nil, imageNotFoundError{imageID}

View file

@ -48,7 +48,7 @@ func (cli *Client) ImagePush(ctx context.Context, ref string, options types.Imag
return resp.body, nil
}
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
}

View file

@ -45,7 +45,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
return results, err
}
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.get(ctx, "/images/search", query, headers)
}

View file

@ -68,7 +68,7 @@ type ImageAPIClient interface {
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error)
ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error)
ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error)
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
@ -131,5 +131,5 @@ type VolumeAPIClient interface {
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error)
VolumeRemove(ctx context.Context, volumeID string) error
VolumeRemove(ctx context.Context, volumeID string, force bool) error
}

View file

@ -14,7 +14,7 @@ import (
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) {
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
if resp != nil && resp.statusCode == http.StatusUnauthorized {
if resp.statusCode == http.StatusUnauthorized {
return types.AuthResponse{}, unauthorizedError{err}
}
if err != nil {

View file

@ -53,7 +53,7 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
return cli.PluginEnable(ctx, name)
}
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.post(ctx, "/plugins/pull", query, nil, headers)
}

View file

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"strings"
@ -24,47 +25,47 @@ type serverResponse struct {
}
// head sends an http request to the docker API using the method HEAD.
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "HEAD", path, query, nil, headers)
}
// getWithContext sends an http request to the docker API using the method GET with a specific go context.
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "GET", path, query, nil, headers)
}
// postWithContext sends an http request to the docker API using the method POST with a specific go context.
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "POST", path, query, obj, headers)
}
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
return cli.sendClientRequest(ctx, "POST", path, query, body, headers)
}
// put sends an http request to the docker API using the method PUT.
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "PUT", path, query, obj, headers)
}
// put sends an http request to the docker API using the method PUT.
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
return cli.sendClientRequest(ctx, "PUT", path, query, body, headers)
}
// delete sends an http request to the docker API using the method DELETE.
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "DELETE", path, query, nil, headers)
}
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
var body io.Reader
if obj != nil {
var err error
body, err = encodeData(obj)
if err != nil {
return nil, err
return serverResponse{}, err
}
if headers == nil {
headers = make(map[string][]string)
@ -75,8 +76,8 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
return cli.sendClientRequest(ctx, method, path, query, body, headers)
}
func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
serverResp := &serverResponse{
func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
serverResp := serverResponse{
body: nil,
statusCode: -1,
}
@ -105,10 +106,6 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q
resp, err := cancellable.Do(ctx, cli.transport, req)
if err != nil {
if isTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
return serverResp, ErrConnectionFailed
}
if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") {
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
}
@ -117,6 +114,23 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
}
// Don't decorate context sentinel errors; users may be comparing to
// them directly.
switch err {
case context.Canceled, context.DeadlineExceeded:
return serverResp, err
}
if err, ok := err.(net.Error); ok {
if err.Timeout() {
return serverResp, ErrConnectionFailed
}
if !err.Temporary() {
if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
return serverResp, ErrConnectionFailed
}
}
}
return serverResp, fmt.Errorf("An error occurred trying to connect: %v", err)
}
@ -185,23 +199,10 @@ func encodeData(data interface{}) (*bytes.Buffer, error) {
return params, nil
}
func ensureReaderClosed(response *serverResponse) {
if response != nil && response.body != nil {
func ensureReaderClosed(response serverResponse) {
if body := response.body; body != nil {
// Drain up to 512 bytes and close the body to let the Transport reuse the connection
io.CopyN(ioutil.Discard, response.body, 512)
io.CopyN(ioutil.Discard, body, 512)
response.body.Close()
}
}
func isTimeout(err error) bool {
type timeout interface {
Timeout() bool
}
e := err
switch urlErr := err.(type) {
case *url.Error:
e = urlErr.Err
}
t, ok := e.(timeout)
return ok && t.Timeout()
}

View file

@ -8,6 +8,7 @@ package cancellable
import (
"io"
"net/http"
"sync"
"github.com/docker/engine-api/client/transport"
@ -82,7 +83,7 @@ func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.
// The response's Body is closed.
}
}()
resp.Body = &notifyingReader{resp.Body, c}
resp.Body = &notifyingReader{ReadCloser: resp.Body, notify: c}
return resp, nil
}
@ -91,23 +92,24 @@ func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.
// Close is called or a Read fails on the underlying ReadCloser.
type notifyingReader struct {
io.ReadCloser
notify chan<- struct{}
notify chan<- struct{}
notifyOnce sync.Once
}
func (r *notifyingReader) Read(p []byte) (int, error) {
n, err := r.ReadCloser.Read(p)
if err != nil && r.notify != nil {
close(r.notify)
r.notify = nil
if err != nil {
r.notifyOnce.Do(func() {
close(r.notify)
})
}
return n, err
}
func (r *notifyingReader) Close() error {
err := r.ReadCloser.Close()
if r.notify != nil {
r.notifyOnce.Do(func() {
close(r.notify)
r.notify = nil
}
})
return err
}

View file

@ -1,10 +1,18 @@
package client
import "golang.org/x/net/context"
import (
"net/url"
"golang.org/x/net/context"
)
// VolumeRemove removes a volume from the docker host.
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string) error {
resp, err := cli.delete(ctx, "/volumes/"+volumeID, nil, nil)
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
query := url.Values{}
if force {
query.Set("force", "1")
}
resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil)
ensureReaderClosed(resp)
return err
}

View file

@ -147,6 +147,10 @@ type ImageBuildOptions struct {
AuthConfigs map[string]AuthConfig
Context io.Reader
Labels map[string]string
// squash the resulting image's layers to the parent
// preserves the original image and creates a new one from the parent with all
// the changes applied to a single layer
Squash bool
}
// ImageBuildResponse holds information

View file

@ -4,6 +4,7 @@ import (
"strings"
"github.com/docker/engine-api/types/blkiodev"
"github.com/docker/engine-api/types/mount"
"github.com/docker/engine-api/types/strslice"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
@ -317,4 +318,7 @@ type HostConfig struct {
// Contains container's resources (cgroups, ulimits)
Resources
// Mounts specs used by the container
Mounts []mount.Mount `json:",omitempty"`
}

View file

@ -0,0 +1,58 @@
package mount
// Type represents the type of a mount.
type Type string
const (
// TypeBind BIND
TypeBind Type = "bind"
// TypeVolume VOLUME
TypeVolume Type = "volume"
)
// Mount represents a mount (volume).
type Mount struct {
Type Type `json:",omitempty"`
Source string `json:",omitempty"`
Target string `json:",omitempty"`
ReadOnly bool `json:",omitempty"`
BindOptions *BindOptions `json:",omitempty"`
VolumeOptions *VolumeOptions `json:",omitempty"`
}
// Propagation represents the propagation of a mount.
type Propagation string
const (
// PropagationRPrivate RPRIVATE
PropagationRPrivate Propagation = "rprivate"
// PropagationPrivate PRIVATE
PropagationPrivate Propagation = "private"
// PropagationRShared RSHARED
PropagationRShared Propagation = "rshared"
// PropagationShared SHARED
PropagationShared Propagation = "shared"
// PropagationRSlave RSLAVE
PropagationRSlave Propagation = "rslave"
// PropagationSlave SLAVE
PropagationSlave Propagation = "slave"
)
// BindOptions defines options specific to mounts of type "bind".
type BindOptions struct {
Propagation Propagation `json:",omitempty"`
}
// VolumeOptions represents the options for a mount of type volume.
type VolumeOptions struct {
NoCopy bool `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
DriverConfig *Driver `json:",omitempty"`
}
// Driver represents a volume driver.
type Driver struct {
Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"`
}

View file

@ -16,6 +16,11 @@ type ServiceConfig struct {
// unmarshalled to JSON
type NetIPNet net.IPNet
// String returns the CIDR notation of ipnet
func (ipnet *NetIPNet) String() string {
return (*net.IPNet)(ipnet).String()
}
// MarshalJSON returns the JSON representation of the IPNet
func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
return json.Marshal((*net.IPNet)(ipnet).String())

View file

@ -1,6 +1,10 @@
package swarm
import "time"
import (
"time"
"github.com/docker/engine-api/types/mount"
)
// ContainerSpec represents the spec of a container.
type ContainerSpec struct {
@ -11,57 +15,8 @@ type ContainerSpec struct {
Env []string `json:",omitempty"`
Dir string `json:",omitempty"`
User string `json:",omitempty"`
Mounts []Mount `json:",omitempty"`
Groups []string `json:",omitempty"`
TTY bool `json:",omitempty"`
Mounts []mount.Mount `json:",omitempty"`
StopGracePeriod *time.Duration `json:",omitempty"`
}
// MountType represents the type of a mount.
type MountType string
const (
// MountTypeBind BIND
MountTypeBind MountType = "bind"
// MountTypeVolume VOLUME
MountTypeVolume MountType = "volume"
)
// Mount represents a mount (volume).
type Mount struct {
Type MountType `json:",omitempty"`
Source string `json:",omitempty"`
Target string `json:",omitempty"`
ReadOnly bool `json:",omitempty"`
BindOptions *BindOptions `json:",omitempty"`
VolumeOptions *VolumeOptions `json:",omitempty"`
}
// MountPropagation represents the propagation of a mount.
type MountPropagation string
const (
// MountPropagationRPrivate RPRIVATE
MountPropagationRPrivate MountPropagation = "rprivate"
// MountPropagationPrivate PRIVATE
MountPropagationPrivate MountPropagation = "private"
// MountPropagationRShared RSHARED
MountPropagationRShared MountPropagation = "rshared"
// MountPropagationShared SHARED
MountPropagationShared MountPropagation = "shared"
// MountPropagationRSlave RSLAVE
MountPropagationRSlave MountPropagation = "rslave"
// MountPropagationSlave SLAVE
MountPropagationSlave MountPropagation = "slave"
)
// BindOptions defines options specific to mounts of type "bind".
type BindOptions struct {
Propagation MountPropagation `json:",omitempty"`
}
// VolumeOptions represents the options for a mount of type volume.
type VolumeOptions struct {
NoCopy bool `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
DriverConfig *Driver `json:",omitempty"`
}

View file

@ -92,7 +92,7 @@ type IPAMConfig struct {
Gateway string `json:",omitempty"`
}
// Driver represents a driver (network/volume).
// Driver represents a network driver.
type Driver struct {
Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"`

View file

@ -2,7 +2,7 @@ package swarm
import "time"
// ClusterInfo represents info about a the cluster for outputing in "info"
// ClusterInfo represents info about the cluster for outputing in "info"
// it contains the same information as "Swarm", but without the JoinTokens
type ClusterInfo struct {
ID string

View file

@ -5,6 +5,7 @@ import (
"time"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/mount"
"github.com/docker/engine-api/types/network"
"github.com/docker/engine-api/types/registry"
"github.com/docker/engine-api/types/swarm"
@ -230,7 +231,6 @@ type Info struct {
OomKillDisable bool
NGoroutines int
SystemTime string
ExecutionDriver string
LoggingDriver string
CgroupDriver string
NEventsListener int
@ -409,14 +409,16 @@ type DefaultNetworkSettings struct {
}
// MountPoint represents a mount point configuration inside the container.
// This is used for reporting the mountpoints in use by a container.
type MountPoint struct {
Name string `json:",omitempty"`
Type mount.Type `json:",omitempty"`
Name string `json:",omitempty"`
Source string
Destination string
Driver string `json:",omitempty"`
Mode string
RW bool
Propagation string
Propagation mount.Propagation
}
// Volume represents the configuration of a volume for the remote API

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/system"
mounttypes "github.com/docker/engine-api/types/mount"
"github.com/opencontainers/runc/libcontainer/label"
)
@ -92,8 +93,8 @@ type MountPoint struct {
Mode string `json:"Relabel"` // Originally field was `Relabel`"
// Note Propagation is not used on Windows
Propagation string // Mount propagation string
Named bool // specifies if the mountpoint was specified by name
Propagation mounttypes.Propagation // Mount propagation string
Named bool // specifies if the mountpoint was specified by name
// Specifies if data should be copied from the container before the first mount
// Use a pointer here so we can tell if the user set this value explicitly

View file

@ -4,28 +4,31 @@ package volume
import (
"strings"
mounttypes "github.com/docker/engine-api/types/mount"
)
// DefaultPropagationMode defines what propagation mode should be used by
// default if user has not specified one explicitly.
const DefaultPropagationMode string = "rprivate"
const DefaultPropagationMode mounttypes.Propagation = "rprivate"
// propagation modes
var propagationModes = map[string]bool{
"private": true,
"rprivate": true,
"slave": true,
"rslave": true,
"shared": true,
"rshared": true,
var propagationModes = map[mounttypes.Propagation]bool{
mounttypes.PropagationPrivate: true,
mounttypes.PropagationRPrivate: true,
mounttypes.PropagationSlave: true,
mounttypes.PropagationRSlave: true,
mounttypes.PropagationShared: true,
mounttypes.PropagationRShared: true,
}
// GetPropagation extracts and returns the mount propagation mode. If there
// are no specifications, then by default it is "private".
func GetPropagation(mode string) string {
func GetPropagation(mode string) mounttypes.Propagation {
for _, o := range strings.Split(mode, ",") {
if propagationModes[o] {
return o
prop := mounttypes.Propagation(o)
if propagationModes[prop] {
return prop
}
}
return DefaultPropagationMode
@ -36,7 +39,7 @@ func GetPropagation(mode string) string {
// present, false otherwise.
func HasPropagation(mode string) bool {
for _, o := range strings.Split(mode, ",") {
if propagationModes[o] {
if propagationModes[mounttypes.Propagation(o)] {
return true
}
}

View file

@ -2,15 +2,17 @@
package volume
import mounttypes "github.com/docker/engine-api/types/mount"
// DefaultPropagationMode is used only in linux. In other cases it returns
// empty string.
const DefaultPropagationMode string = ""
const DefaultPropagationMode mounttypes.Propagation = ""
// propagation modes not supported on this platform.
var propagationModes = map[string]bool{}
// GetPropagation is not supported. Return empty string.
func GetPropagation(mode string) string {
func GetPropagation(mode string) mounttypes.Propagation {
return DefaultPropagationMode
}

View file

@ -6,6 +6,8 @@ import (
"fmt"
"path/filepath"
"strings"
mounttypes "github.com/docker/engine-api/types/mount"
)
// read-write modes
@ -152,7 +154,7 @@ func ValidMountMode(mode string) bool {
rwModeCount++
case labelModes[o]:
labelModeCount++
case propagationModes[o]:
case propagationModes[mounttypes.Propagation(o)]:
propagationModeCount++
case copyModeExists(o):
copyModeCount++