Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/opts" |
| 12 | 12 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
| 13 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 13 | 14 |
"github.com/docker/engine-api/types/swarm" |
| 14 | 15 |
"github.com/docker/go-connections/nat" |
| 15 | 16 |
units "github.com/docker/go-units" |
| ... | ... |
@@ -130,7 +131,7 @@ func (i *Uint64Opt) Value() *uint64 {
|
| 130 | 130 |
|
| 131 | 131 |
// MountOpt is a Value type for parsing mounts |
| 132 | 132 |
type MountOpt struct {
|
| 133 |
- values []swarm.Mount |
|
| 133 |
+ values []mounttypes.Mount |
|
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
// Set a new mount value |
| ... | ... |
@@ -141,23 +142,23 @@ func (m *MountOpt) Set(value string) error {
|
| 141 | 141 |
return err |
| 142 | 142 |
} |
| 143 | 143 |
|
| 144 |
- mount := swarm.Mount{}
|
|
| 144 |
+ mount := mounttypes.Mount{}
|
|
| 145 | 145 |
|
| 146 |
- volumeOptions := func() *swarm.VolumeOptions {
|
|
| 146 |
+ volumeOptions := func() *mounttypes.VolumeOptions {
|
|
| 147 | 147 |
if mount.VolumeOptions == nil {
|
| 148 |
- mount.VolumeOptions = &swarm.VolumeOptions{
|
|
| 148 |
+ mount.VolumeOptions = &mounttypes.VolumeOptions{
|
|
| 149 | 149 |
Labels: make(map[string]string), |
| 150 | 150 |
} |
| 151 | 151 |
} |
| 152 | 152 |
if mount.VolumeOptions.DriverConfig == nil {
|
| 153 |
- mount.VolumeOptions.DriverConfig = &swarm.Driver{}
|
|
| 153 |
+ mount.VolumeOptions.DriverConfig = &mounttypes.Driver{}
|
|
| 154 | 154 |
} |
| 155 | 155 |
return mount.VolumeOptions |
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 |
- bindOptions := func() *swarm.BindOptions {
|
|
| 158 |
+ bindOptions := func() *mounttypes.BindOptions {
|
|
| 159 | 159 |
if mount.BindOptions == nil {
|
| 160 |
- mount.BindOptions = new(swarm.BindOptions) |
|
| 160 |
+ mount.BindOptions = new(mounttypes.BindOptions) |
|
| 161 | 161 |
} |
| 162 | 162 |
return mount.BindOptions |
| 163 | 163 |
} |
| ... | ... |
@@ -171,7 +172,7 @@ func (m *MountOpt) Set(value string) error {
|
| 171 | 171 |
} |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 |
- mount.Type = swarm.MountTypeVolume // default to volume mounts |
|
| 174 |
+ mount.Type = mounttypes.TypeVolume // default to volume mounts |
|
| 175 | 175 |
// Set writable as the default |
| 176 | 176 |
for _, field := range fields {
|
| 177 | 177 |
parts := strings.SplitN(field, "=", 2) |
| ... | ... |
@@ -195,7 +196,7 @@ func (m *MountOpt) Set(value string) error {
|
| 195 | 195 |
value := parts[1] |
| 196 | 196 |
switch key {
|
| 197 | 197 |
case "type": |
| 198 |
- mount.Type = swarm.MountType(strings.ToLower(value)) |
|
| 198 |
+ mount.Type = mounttypes.Type(strings.ToLower(value)) |
|
| 199 | 199 |
case "source", "src": |
| 200 | 200 |
mount.Source = value |
| 201 | 201 |
case "target", "dst", "destination": |
| ... | ... |
@@ -206,7 +207,7 @@ func (m *MountOpt) Set(value string) error {
|
| 206 | 206 |
return fmt.Errorf("invalid value for %s: %s", key, value)
|
| 207 | 207 |
} |
| 208 | 208 |
case "bind-propagation": |
| 209 |
- bindOptions().Propagation = swarm.MountPropagation(strings.ToLower(value)) |
|
| 209 |
+ bindOptions().Propagation = mounttypes.Propagation(strings.ToLower(value)) |
|
| 210 | 210 |
case "volume-nocopy": |
| 211 | 211 |
volumeOptions().NoCopy, err = strconv.ParseBool(value) |
| 212 | 212 |
if err != nil {
|
| ... | ... |
@@ -238,11 +239,11 @@ func (m *MountOpt) Set(value string) error {
|
| 238 | 238 |
return fmt.Errorf("source is required when specifying volume-* options")
|
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 |
- if mount.Type == swarm.MountTypeBind && mount.VolumeOptions != nil {
|
|
| 242 |
- return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", swarm.MountTypeBind)
|
|
| 241 |
+ if mount.Type == mounttypes.TypeBind && mount.VolumeOptions != nil {
|
|
| 242 |
+ return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", mounttypes.TypeBind)
|
|
| 243 | 243 |
} |
| 244 |
- if mount.Type == swarm.MountTypeVolume && mount.BindOptions != nil {
|
|
| 245 |
- return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", swarm.MountTypeVolume)
|
|
| 244 |
+ if mount.Type == mounttypes.TypeVolume && mount.BindOptions != nil {
|
|
| 245 |
+ return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", mounttypes.TypeVolume)
|
|
| 246 | 246 |
} |
| 247 | 247 |
|
| 248 | 248 |
m.values = append(m.values, mount) |
| ... | ... |
@@ -265,7 +266,7 @@ func (m *MountOpt) String() string {
|
| 265 | 265 |
} |
| 266 | 266 |
|
| 267 | 267 |
// Value returns the mounts |
| 268 |
-func (m *MountOpt) Value() []swarm.Mount {
|
|
| 268 |
+func (m *MountOpt) Value() []mounttypes.Mount {
|
|
| 269 | 269 |
return m.values |
| 270 | 270 |
} |
| 271 | 271 |
|
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"time" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/pkg/testutil/assert" |
| 8 |
- "github.com/docker/engine-api/types/swarm" |
|
| 8 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
func TestMemBytesString(t *testing.T) {
|
| ... | ... |
@@ -59,14 +59,14 @@ func TestUint64OptSetAndValue(t *testing.T) {
|
| 59 | 59 |
|
| 60 | 60 |
func TestMountOptString(t *testing.T) {
|
| 61 | 61 |
mount := MountOpt{
|
| 62 |
- values: []swarm.Mount{
|
|
| 62 |
+ values: []mounttypes.Mount{
|
|
| 63 | 63 |
{
|
| 64 |
- Type: swarm.MountTypeBind, |
|
| 64 |
+ Type: mounttypes.TypeBind, |
|
| 65 | 65 |
Source: "/home/path", |
| 66 | 66 |
Target: "/target", |
| 67 | 67 |
}, |
| 68 | 68 |
{
|
| 69 |
- Type: swarm.MountTypeVolume, |
|
| 69 |
+ Type: mounttypes.TypeVolume, |
|
| 70 | 70 |
Source: "foo", |
| 71 | 71 |
Target: "/target/foo", |
| 72 | 72 |
}, |
| ... | ... |
@@ -90,8 +90,8 @@ func TestMountOptSetNoError(t *testing.T) {
|
| 90 | 90 |
|
| 91 | 91 |
mounts := mount.Value() |
| 92 | 92 |
assert.Equal(t, len(mounts), 1) |
| 93 |
- assert.Equal(t, mounts[0], swarm.Mount{
|
|
| 94 |
- Type: swarm.MountTypeBind, |
|
| 93 |
+ assert.Equal(t, mounts[0], mounttypes.Mount{
|
|
| 94 |
+ Type: mounttypes.TypeBind, |
|
| 95 | 95 |
Source: "/source", |
| 96 | 96 |
Target: "/target", |
| 97 | 97 |
}) |
| ... | ... |
@@ -103,7 +103,7 @@ func TestMountOptSetNoError(t *testing.T) {
|
| 103 | 103 |
func TestMountOptDefaultType(t *testing.T) {
|
| 104 | 104 |
var mount MountOpt |
| 105 | 105 |
assert.NilError(t, mount.Set("target=/target,source=/foo"))
|
| 106 |
- assert.Equal(t, mount.values[0].Type, swarm.MountTypeVolume) |
|
| 106 |
+ assert.Equal(t, mount.values[0].Type, mounttypes.TypeVolume) |
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
func TestMountOptSetErrorNoTarget(t *testing.T) {
|
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/opts" |
| 13 | 13 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
| 14 | 14 |
"github.com/docker/engine-api/types" |
| 15 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 15 | 16 |
"github.com/docker/engine-api/types/swarm" |
| 16 | 17 |
"github.com/docker/go-connections/nat" |
| 17 | 18 |
shlex "github.com/flynn-archive/go-shlex" |
| ... | ... |
@@ -353,14 +354,14 @@ func removeItems( |
| 353 | 353 |
return newSeq |
| 354 | 354 |
} |
| 355 | 355 |
|
| 356 |
-func updateMounts(flags *pflag.FlagSet, mounts *[]swarm.Mount) {
|
|
| 356 |
+func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) {
|
|
| 357 | 357 |
if flags.Changed(flagMountAdd) {
|
| 358 | 358 |
values := flags.Lookup(flagMountAdd).Value.(*MountOpt).Value() |
| 359 | 359 |
*mounts = append(*mounts, values...) |
| 360 | 360 |
} |
| 361 | 361 |
toRemove := buildToRemoveSet(flags, flagMountRemove) |
| 362 | 362 |
|
| 363 |
- newMounts := []swarm.Mount{}
|
|
| 363 |
+ newMounts := []mounttypes.Mount{}
|
|
| 364 | 364 |
for _, mount := range *mounts {
|
| 365 | 365 |
if _, exists := toRemove[mount.Target]; !exists {
|
| 366 | 366 |
newMounts = append(newMounts, mount) |
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"testing" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/pkg/testutil/assert" |
| 8 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 8 | 9 |
"github.com/docker/engine-api/types/swarm" |
| 9 | 10 |
) |
| 10 | 11 |
|
| ... | ... |
@@ -104,9 +105,9 @@ func TestUpdateMounts(t *testing.T) {
|
| 104 | 104 |
flags.Set("mount-add", "type=volume,target=/toadd")
|
| 105 | 105 |
flags.Set("mount-rm", "/toremove")
|
| 106 | 106 |
|
| 107 |
- mounts := []swarm.Mount{
|
|
| 108 |
- {Target: "/toremove", Type: swarm.MountTypeBind},
|
|
| 109 |
- {Target: "/tokeep", Type: swarm.MountTypeBind},
|
|
| 107 |
+ mounts := []mounttypes.Mount{
|
|
| 108 |
+ {Target: "/toremove", Type: mounttypes.TypeBind},
|
|
| 109 |
+ {Target: "/tokeep", Type: mounttypes.TypeBind},
|
|
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 | 112 |
updateMounts(flags, &mounts) |
| ... | ... |
@@ -54,7 +54,7 @@ func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
|
| 54 | 54 |
} |
| 55 | 55 |
case "image": |
| 56 | 56 |
getRefFunc = func(ref string) (interface{}, []byte, error) {
|
| 57 |
- return client.ImageInspectWithRaw(ctx, ref, opts.size) |
|
| 57 |
+ return client.ImageInspectWithRaw(ctx, ref) |
|
| 58 | 58 |
} |
| 59 | 59 |
case "task": |
| 60 | 60 |
if opts.size {
|
| ... | ... |
@@ -81,7 +81,7 @@ func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool) |
| 81 | 81 |
return c, rawContainer, err |
| 82 | 82 |
} |
| 83 | 83 |
// Search for image with that id if a container doesn't exist. |
| 84 |
- i, rawImage, err := client.ImageInspectWithRaw(ctx, ref, getSize) |
|
| 84 |
+ i, rawImage, err := client.ImageInspectWithRaw(ctx, ref) |
|
| 85 | 85 |
if err == nil || !apiclient.IsErrNotFound(err) {
|
| 86 | 86 |
return i, rawImage, err |
| 87 | 87 |
} |
| ... | ... |
@@ -30,7 +30,7 @@ func runRemove(dockerCli *client.DockerCli, volumes []string) error {
|
| 30 | 30 |
status := 0 |
| 31 | 31 |
|
| 32 | 32 |
for _, name := range volumes {
|
| 33 |
- if err := client.VolumeRemove(ctx, name); err != nil {
|
|
| 33 |
+ if err := client.VolumeRemove(ctx, name, false); err != nil {
|
|
| 34 | 34 |
fmt.Fprintf(dockerCli.Err(), "%s\n", err) |
| 35 | 35 |
status = 1 |
| 36 | 36 |
continue |
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
"github.com/docker/engine-api/types/events" |
| 16 | 16 |
"github.com/docker/engine-api/types/filters" |
| 17 | 17 |
timetypes "github.com/docker/engine-api/types/time" |
| 18 |
+ "github.com/docker/engine-api/types/versions" |
|
| 18 | 19 |
"golang.org/x/net/context" |
| 19 | 20 |
) |
| 20 | 21 |
|
| ... | ... |
@@ -37,6 +38,14 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht |
| 37 | 37 |
info.Swarm = s.clusterProvider.Info() |
| 38 | 38 |
} |
| 39 | 39 |
|
| 40 |
+ if versions.LessThan("1.25", httputils.VersionFromContext(ctx)) {
|
|
| 41 |
+ // TODO: handle this conversion in engine-api |
|
| 42 |
+ type oldInfo struct {
|
|
| 43 |
+ *types.Info |
|
| 44 |
+ ExecutionDriver string |
|
| 45 |
+ } |
|
| 46 |
+ return httputils.WriteJSON(w, http.StatusOK, &oldInfo{Info: info, ExecutionDriver: "<not supported>"})
|
|
| 47 |
+ } |
|
| 40 | 48 |
return httputils.WriteJSON(w, http.StatusOK, info) |
| 41 | 49 |
} |
| 42 | 50 |
|
| ... | ... |
@@ -129,7 +129,7 @@ func (container *Container) NetworkMounts() []Mount {
|
| 129 | 129 |
Source: container.ResolvConfPath, |
| 130 | 130 |
Destination: "/etc/resolv.conf", |
| 131 | 131 |
Writable: writable, |
| 132 |
- Propagation: volume.DefaultPropagationMode, |
|
| 132 |
+ Propagation: string(volume.DefaultPropagationMode), |
|
| 133 | 133 |
}) |
| 134 | 134 |
} |
| 135 | 135 |
} |
| ... | ... |
@@ -148,7 +148,7 @@ func (container *Container) NetworkMounts() []Mount {
|
| 148 | 148 |
Source: container.HostnamePath, |
| 149 | 149 |
Destination: "/etc/hostname", |
| 150 | 150 |
Writable: writable, |
| 151 |
- Propagation: volume.DefaultPropagationMode, |
|
| 151 |
+ Propagation: string(volume.DefaultPropagationMode), |
|
| 152 | 152 |
}) |
| 153 | 153 |
} |
| 154 | 154 |
} |
| ... | ... |
@@ -167,7 +167,7 @@ func (container *Container) NetworkMounts() []Mount {
|
| 167 | 167 |
Source: container.HostsPath, |
| 168 | 168 |
Destination: "/etc/hosts", |
| 169 | 169 |
Writable: writable, |
| 170 |
- Propagation: volume.DefaultPropagationMode, |
|
| 170 |
+ Propagation: string(volume.DefaultPropagationMode), |
|
| 171 | 171 |
}) |
| 172 | 172 |
} |
| 173 | 173 |
} |
| ... | ... |
@@ -249,7 +249,7 @@ func (container *Container) IpcMounts() []Mount {
|
| 249 | 249 |
Source: container.ShmPath, |
| 250 | 250 |
Destination: "/dev/shm", |
| 251 | 251 |
Writable: true, |
| 252 |
- Propagation: volume.DefaultPropagationMode, |
|
| 252 |
+ Propagation: string(volume.DefaultPropagationMode), |
|
| 253 | 253 |
}) |
| 254 | 254 |
} |
| 255 | 255 |
|
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"strings" |
| 6 | 6 |
|
| 7 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 7 | 8 |
types "github.com/docker/engine-api/types/swarm" |
| 8 | 9 |
swarmapi "github.com/docker/swarmkit/api" |
| 9 | 10 |
"github.com/docker/swarmkit/protobuf/ptypes" |
| ... | ... |
@@ -22,26 +23,26 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
|
| 22 | 22 |
|
| 23 | 23 |
// Mounts |
| 24 | 24 |
for _, m := range c.Mounts {
|
| 25 |
- mount := types.Mount{
|
|
| 25 |
+ mount := mounttypes.Mount{
|
|
| 26 | 26 |
Target: m.Target, |
| 27 | 27 |
Source: m.Source, |
| 28 |
- Type: types.MountType(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])), |
|
| 28 |
+ Type: mounttypes.Type(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])), |
|
| 29 | 29 |
ReadOnly: m.ReadOnly, |
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 | 32 |
if m.BindOptions != nil {
|
| 33 |
- mount.BindOptions = &types.BindOptions{
|
|
| 34 |
- Propagation: types.MountPropagation(strings.ToLower(swarmapi.Mount_BindOptions_MountPropagation_name[int32(m.BindOptions.Propagation)])), |
|
| 33 |
+ mount.BindOptions = &mounttypes.BindOptions{
|
|
| 34 |
+ Propagation: mounttypes.Propagation(strings.ToLower(swarmapi.Mount_BindOptions_MountPropagation_name[int32(m.BindOptions.Propagation)])), |
|
| 35 | 35 |
} |
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 | 38 |
if m.VolumeOptions != nil {
|
| 39 |
- mount.VolumeOptions = &types.VolumeOptions{
|
|
| 39 |
+ mount.VolumeOptions = &mounttypes.VolumeOptions{
|
|
| 40 | 40 |
NoCopy: m.VolumeOptions.NoCopy, |
| 41 | 41 |
Labels: m.VolumeOptions.Labels, |
| 42 | 42 |
} |
| 43 | 43 |
if m.VolumeOptions.DriverConfig != nil {
|
| 44 |
- mount.VolumeOptions.DriverConfig = &types.Driver{
|
|
| 44 |
+ mount.VolumeOptions.DriverConfig = &mounttypes.Driver{
|
|
| 45 | 45 |
Name: m.VolumeOptions.DriverConfig.Name, |
| 46 | 46 |
Options: m.VolumeOptions.DriverConfig.Options, |
| 47 | 47 |
} |
| ... | ... |
@@ -481,7 +481,7 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c |
| 481 | 481 |
|
| 482 | 482 |
if m.Source == "tmpfs" {
|
| 483 | 483 |
data := c.HostConfig.Tmpfs[m.Destination] |
| 484 |
- options := []string{"noexec", "nosuid", "nodev", volume.DefaultPropagationMode}
|
|
| 484 |
+ options := []string{"noexec", "nosuid", "nodev", string(volume.DefaultPropagationMode)}
|
|
| 485 | 485 |
if data != "" {
|
| 486 | 486 |
options = append(options, strings.Split(data, ",")...) |
| 487 | 487 |
} |
| ... | ... |
@@ -37,7 +37,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er |
| 37 | 37 |
Source: path, |
| 38 | 38 |
Destination: m.Destination, |
| 39 | 39 |
Writable: m.RW, |
| 40 |
- Propagation: m.Propagation, |
|
| 40 |
+ Propagation: string(m.Propagation), |
|
| 41 | 41 |
} |
| 42 | 42 |
if m.Volume != nil {
|
| 43 | 43 |
attributes := map[string]string{
|
| ... | ... |
@@ -45,7 +45,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er |
| 45 | 45 |
"container": c.ID, |
| 46 | 46 |
"destination": m.Destination, |
| 47 | 47 |
"read/write": strconv.FormatBool(m.RW), |
| 48 |
- "propagation": m.Propagation, |
|
| 48 |
+ "propagation": string(m.Propagation), |
|
| 49 | 49 |
} |
| 50 | 50 |
daemon.LogVolumeEvent(m.Volume.Name(), "mount", attributes) |
| 51 | 51 |
} |
| ... | ... |
@@ -61,7 +61,7 @@ clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://gith |
| 61 | 61 |
clone git github.com/docker/go-units eb879ae3e2b84e2a142af415b679ddeda47ec71c |
| 62 | 62 |
clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d |
| 63 | 63 |
|
| 64 |
-clone git github.com/docker/engine-api 603ec41824c63d1e6498a22271987fa1f268c0c0 |
|
| 64 |
+clone git github.com/docker/engine-api ebc51d1954fc8934307dd15841b8d64f7cd505df |
|
| 65 | 65 |
clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 |
| 66 | 66 |
clone git github.com/imdario/mergo 0.2.1 |
| 67 | 67 |
|
| ... | ... |
@@ -34,7 +34,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config |
| 34 | 34 |
|
| 35 | 35 |
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) |
| 36 | 36 |
if err != nil {
|
| 37 |
- if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
|
|
| 37 |
+ if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
|
|
| 38 | 38 |
return response, imageNotFoundError{config.Image}
|
| 39 | 39 |
} |
| 40 | 40 |
return response, err |
| ... | ... |
@@ -74,6 +74,10 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro |
| 74 | 74 |
query.Set("pull", "1")
|
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 |
+ if options.Squash {
|
|
| 78 |
+ query.Set("squash", "1")
|
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 77 | 81 |
if !container.Isolation.IsDefault(options.Isolation) {
|
| 78 | 82 |
query.Set("isolation", string(options.Isolation))
|
| 79 | 83 |
} |
| ... | ... |
@@ -28,7 +28,7 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti |
| 28 | 28 |
return resp.body, nil |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
-func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
|
| 31 |
+func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
|
| 32 | 32 |
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
| 33 | 33 |
return cli.post(ctx, "/images/create", query, nil, headers) |
| 34 | 34 |
} |
| ... | ... |
@@ -5,19 +5,14 @@ import ( |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 | 7 |
"net/http" |
| 8 |
- "net/url" |
|
| 9 | 8 |
|
| 10 | 9 |
"github.com/docker/engine-api/types" |
| 11 | 10 |
"golang.org/x/net/context" |
| 12 | 11 |
) |
| 13 | 12 |
|
| 14 | 13 |
// ImageInspectWithRaw returns the image information and its raw representation. |
| 15 |
-func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) {
|
|
| 16 |
- query := url.Values{}
|
|
| 17 |
- if getSize {
|
|
| 18 |
- query.Set("size", "1")
|
|
| 19 |
- } |
|
| 20 |
- serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil) |
|
| 14 |
+func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
|
|
| 15 |
+ serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) |
|
| 21 | 16 |
if err != nil {
|
| 22 | 17 |
if serverResp.statusCode == http.StatusNotFound {
|
| 23 | 18 |
return types.ImageInspect{}, nil, imageNotFoundError{imageID}
|
| ... | ... |
@@ -48,7 +48,7 @@ func (cli *Client) ImagePush(ctx context.Context, ref string, options types.Imag |
| 48 | 48 |
return resp.body, nil |
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
-func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
|
|
| 51 |
+func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) {
|
|
| 52 | 52 |
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
| 53 | 53 |
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) |
| 54 | 54 |
} |
| ... | ... |
@@ -45,7 +45,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I |
| 45 | 45 |
return results, err |
| 46 | 46 |
} |
| 47 | 47 |
|
| 48 |
-func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
|
| 48 |
+func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
|
| 49 | 49 |
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
| 50 | 50 |
return cli.get(ctx, "/images/search", query, headers) |
| 51 | 51 |
} |
| ... | ... |
@@ -68,7 +68,7 @@ type ImageAPIClient interface {
|
| 68 | 68 |
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) |
| 69 | 69 |
ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error) |
| 70 | 70 |
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) |
| 71 |
- ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error) |
|
| 71 |
+ ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) |
|
| 72 | 72 |
ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) |
| 73 | 73 |
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) |
| 74 | 74 |
ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) |
| ... | ... |
@@ -131,5 +131,5 @@ type VolumeAPIClient interface {
|
| 131 | 131 |
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) |
| 132 | 132 |
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) |
| 133 | 133 |
VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error) |
| 134 |
- VolumeRemove(ctx context.Context, volumeID string) error |
|
| 134 |
+ VolumeRemove(ctx context.Context, volumeID string, force bool) error |
|
| 135 | 135 |
} |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) {
|
| 15 | 15 |
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
| 16 | 16 |
|
| 17 |
- if resp != nil && resp.statusCode == http.StatusUnauthorized {
|
|
| 17 |
+ if resp.statusCode == http.StatusUnauthorized {
|
|
| 18 | 18 |
return types.AuthResponse{}, unauthorizedError{err}
|
| 19 | 19 |
} |
| 20 | 20 |
if err != nil {
|
| ... | ... |
@@ -53,7 +53,7 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types |
| 53 | 53 |
return cli.PluginEnable(ctx, name) |
| 54 | 54 |
} |
| 55 | 55 |
|
| 56 |
-func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
|
| 56 |
+func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
|
| 57 | 57 |
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
| 58 | 58 |
return cli.post(ctx, "/plugins/pull", query, nil, headers) |
| 59 | 59 |
} |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"io" |
| 8 | 8 |
"io/ioutil" |
| 9 |
+ "net" |
|
| 9 | 10 |
"net/http" |
| 10 | 11 |
"net/url" |
| 11 | 12 |
"strings" |
| ... | ... |
@@ -24,47 +25,47 @@ type serverResponse struct {
|
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
// head sends an http request to the docker API using the method HEAD. |
| 27 |
-func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
| 27 |
+func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
|
| 28 | 28 |
return cli.sendRequest(ctx, "HEAD", path, query, nil, headers) |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 | 31 |
// getWithContext sends an http request to the docker API using the method GET with a specific go context. |
| 32 |
-func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
| 32 |
+func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
|
| 33 | 33 |
return cli.sendRequest(ctx, "GET", path, query, nil, headers) |
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 | 36 |
// postWithContext sends an http request to the docker API using the method POST with a specific go context. |
| 37 |
-func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
| 37 |
+func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
|
| 38 | 38 |
return cli.sendRequest(ctx, "POST", path, query, obj, headers) |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
-func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
| 41 |
+func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
|
| 42 | 42 |
return cli.sendClientRequest(ctx, "POST", path, query, body, headers) |
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 | 45 |
// put sends an http request to the docker API using the method PUT. |
| 46 |
-func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
| 46 |
+func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
|
| 47 | 47 |
return cli.sendRequest(ctx, "PUT", path, query, obj, headers) |
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 | 50 |
// put sends an http request to the docker API using the method PUT. |
| 51 |
-func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
| 51 |
+func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
|
| 52 | 52 |
return cli.sendClientRequest(ctx, "PUT", path, query, body, headers) |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 | 55 |
// delete sends an http request to the docker API using the method DELETE. |
| 56 |
-func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
| 56 |
+func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
|
| 57 | 57 |
return cli.sendRequest(ctx, "DELETE", path, query, nil, headers) |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
-func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
| 60 |
+func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
|
| 61 | 61 |
var body io.Reader |
| 62 | 62 |
|
| 63 | 63 |
if obj != nil {
|
| 64 | 64 |
var err error |
| 65 | 65 |
body, err = encodeData(obj) |
| 66 | 66 |
if err != nil {
|
| 67 |
- return nil, err |
|
| 67 |
+ return serverResponse{}, err
|
|
| 68 | 68 |
} |
| 69 | 69 |
if headers == nil {
|
| 70 | 70 |
headers = make(map[string][]string) |
| ... | ... |
@@ -75,8 +76,8 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u |
| 75 | 75 |
return cli.sendClientRequest(ctx, method, path, query, body, headers) |
| 76 | 76 |
} |
| 77 | 77 |
|
| 78 |
-func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
| 79 |
- serverResp := &serverResponse{
|
|
| 78 |
+func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
|
| 79 |
+ serverResp := serverResponse{
|
|
| 80 | 80 |
body: nil, |
| 81 | 81 |
statusCode: -1, |
| 82 | 82 |
} |
| ... | ... |
@@ -105,10 +106,6 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q |
| 105 | 105 |
|
| 106 | 106 |
resp, err := cancellable.Do(ctx, cli.transport, req) |
| 107 | 107 |
if err != nil {
|
| 108 |
- if isTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
|
|
| 109 |
- return serverResp, ErrConnectionFailed |
|
| 110 |
- } |
|
| 111 |
- |
|
| 112 | 108 |
if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") {
|
| 113 | 109 |
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
|
| 114 | 110 |
} |
| ... | ... |
@@ -117,6 +114,23 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q |
| 117 | 117 |
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
|
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 |
+ // Don't decorate context sentinel errors; users may be comparing to |
|
| 121 |
+ // them directly. |
|
| 122 |
+ switch err {
|
|
| 123 |
+ case context.Canceled, context.DeadlineExceeded: |
|
| 124 |
+ return serverResp, err |
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ if err, ok := err.(net.Error); ok {
|
|
| 128 |
+ if err.Timeout() {
|
|
| 129 |
+ return serverResp, ErrConnectionFailed |
|
| 130 |
+ } |
|
| 131 |
+ if !err.Temporary() {
|
|
| 132 |
+ if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
|
|
| 133 |
+ return serverResp, ErrConnectionFailed |
|
| 134 |
+ } |
|
| 135 |
+ } |
|
| 136 |
+ } |
|
| 120 | 137 |
return serverResp, fmt.Errorf("An error occurred trying to connect: %v", err)
|
| 121 | 138 |
} |
| 122 | 139 |
|
| ... | ... |
@@ -185,23 +199,10 @@ func encodeData(data interface{}) (*bytes.Buffer, error) {
|
| 185 | 185 |
return params, nil |
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 |
-func ensureReaderClosed(response *serverResponse) {
|
|
| 189 |
- if response != nil && response.body != nil {
|
|
| 188 |
+func ensureReaderClosed(response serverResponse) {
|
|
| 189 |
+ if body := response.body; body != nil {
|
|
| 190 | 190 |
// Drain up to 512 bytes and close the body to let the Transport reuse the connection |
| 191 |
- io.CopyN(ioutil.Discard, response.body, 512) |
|
| 191 |
+ io.CopyN(ioutil.Discard, body, 512) |
|
| 192 | 192 |
response.body.Close() |
| 193 | 193 |
} |
| 194 | 194 |
} |
| 195 |
- |
|
| 196 |
-func isTimeout(err error) bool {
|
|
| 197 |
- type timeout interface {
|
|
| 198 |
- Timeout() bool |
|
| 199 |
- } |
|
| 200 |
- e := err |
|
| 201 |
- switch urlErr := err.(type) {
|
|
| 202 |
- case *url.Error: |
|
| 203 |
- e = urlErr.Err |
|
| 204 |
- } |
|
| 205 |
- t, ok := e.(timeout) |
|
| 206 |
- return ok && t.Timeout() |
|
| 207 |
-} |
| ... | ... |
@@ -8,6 +8,7 @@ package cancellable |
| 8 | 8 |
import ( |
| 9 | 9 |
"io" |
| 10 | 10 |
"net/http" |
| 11 |
+ "sync" |
|
| 11 | 12 |
|
| 12 | 13 |
"github.com/docker/engine-api/client/transport" |
| 13 | 14 |
|
| ... | ... |
@@ -82,7 +83,7 @@ func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http. |
| 82 | 82 |
// The response's Body is closed. |
| 83 | 83 |
} |
| 84 | 84 |
}() |
| 85 |
- resp.Body = ¬ifyingReader{resp.Body, c}
|
|
| 85 |
+ resp.Body = ¬ifyingReader{ReadCloser: resp.Body, notify: c}
|
|
| 86 | 86 |
|
| 87 | 87 |
return resp, nil |
| 88 | 88 |
} |
| ... | ... |
@@ -91,23 +92,24 @@ func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http. |
| 91 | 91 |
// Close is called or a Read fails on the underlying ReadCloser. |
| 92 | 92 |
type notifyingReader struct {
|
| 93 | 93 |
io.ReadCloser |
| 94 |
- notify chan<- struct{}
|
|
| 94 |
+ notify chan<- struct{}
|
|
| 95 |
+ notifyOnce sync.Once |
|
| 95 | 96 |
} |
| 96 | 97 |
|
| 97 | 98 |
func (r *notifyingReader) Read(p []byte) (int, error) {
|
| 98 | 99 |
n, err := r.ReadCloser.Read(p) |
| 99 |
- if err != nil && r.notify != nil {
|
|
| 100 |
- close(r.notify) |
|
| 101 |
- r.notify = nil |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ r.notifyOnce.Do(func() {
|
|
| 102 |
+ close(r.notify) |
|
| 103 |
+ }) |
|
| 102 | 104 |
} |
| 103 | 105 |
return n, err |
| 104 | 106 |
} |
| 105 | 107 |
|
| 106 | 108 |
func (r *notifyingReader) Close() error {
|
| 107 | 109 |
err := r.ReadCloser.Close() |
| 108 |
- if r.notify != nil {
|
|
| 110 |
+ r.notifyOnce.Do(func() {
|
|
| 109 | 111 |
close(r.notify) |
| 110 |
- r.notify = nil |
|
| 111 |
- } |
|
| 112 |
+ }) |
|
| 112 | 113 |
return err |
| 113 | 114 |
} |
| ... | ... |
@@ -1,10 +1,18 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 |
-import "golang.org/x/net/context" |
|
| 3 |
+import ( |
|
| 4 |
+ "net/url" |
|
| 5 |
+ |
|
| 6 |
+ "golang.org/x/net/context" |
|
| 7 |
+) |
|
| 4 | 8 |
|
| 5 | 9 |
// VolumeRemove removes a volume from the docker host. |
| 6 |
-func (cli *Client) VolumeRemove(ctx context.Context, volumeID string) error {
|
|
| 7 |
- resp, err := cli.delete(ctx, "/volumes/"+volumeID, nil, nil) |
|
| 10 |
+func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
|
|
| 11 |
+ query := url.Values{}
|
|
| 12 |
+ if force {
|
|
| 13 |
+ query.Set("force", "1")
|
|
| 14 |
+ } |
|
| 15 |
+ resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) |
|
| 8 | 16 |
ensureReaderClosed(resp) |
| 9 | 17 |
return err |
| 10 | 18 |
} |
| ... | ... |
@@ -147,6 +147,10 @@ type ImageBuildOptions struct {
|
| 147 | 147 |
AuthConfigs map[string]AuthConfig |
| 148 | 148 |
Context io.Reader |
| 149 | 149 |
Labels map[string]string |
| 150 |
+ // squash the resulting image's layers to the parent |
|
| 151 |
+ // preserves the original image and creates a new one from the parent with all |
|
| 152 |
+ // the changes applied to a single layer |
|
| 153 |
+ Squash bool |
|
| 150 | 154 |
} |
| 151 | 155 |
|
| 152 | 156 |
// ImageBuildResponse holds information |
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"strings" |
| 5 | 5 |
|
| 6 | 6 |
"github.com/docker/engine-api/types/blkiodev" |
| 7 |
+ "github.com/docker/engine-api/types/mount" |
|
| 7 | 8 |
"github.com/docker/engine-api/types/strslice" |
| 8 | 9 |
"github.com/docker/go-connections/nat" |
| 9 | 10 |
"github.com/docker/go-units" |
| ... | ... |
@@ -317,4 +318,7 @@ type HostConfig struct {
|
| 317 | 317 |
|
| 318 | 318 |
// Contains container's resources (cgroups, ulimits) |
| 319 | 319 |
Resources |
| 320 |
+ |
|
| 321 |
+ // Mounts specs used by the container |
|
| 322 |
+ Mounts []mount.Mount `json:",omitempty"` |
|
| 320 | 323 |
} |
| 321 | 324 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,58 @@ |
| 0 |
+package mount |
|
| 1 |
+ |
|
| 2 |
+// Type represents the type of a mount. |
|
| 3 |
+type Type string |
|
| 4 |
+ |
|
| 5 |
+const ( |
|
| 6 |
+ // TypeBind BIND |
|
| 7 |
+ TypeBind Type = "bind" |
|
| 8 |
+ // TypeVolume VOLUME |
|
| 9 |
+ TypeVolume Type = "volume" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// Mount represents a mount (volume). |
|
| 13 |
+type Mount struct {
|
|
| 14 |
+ Type Type `json:",omitempty"` |
|
| 15 |
+ Source string `json:",omitempty"` |
|
| 16 |
+ Target string `json:",omitempty"` |
|
| 17 |
+ ReadOnly bool `json:",omitempty"` |
|
| 18 |
+ |
|
| 19 |
+ BindOptions *BindOptions `json:",omitempty"` |
|
| 20 |
+ VolumeOptions *VolumeOptions `json:",omitempty"` |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+// Propagation represents the propagation of a mount. |
|
| 24 |
+type Propagation string |
|
| 25 |
+ |
|
| 26 |
+const ( |
|
| 27 |
+ // PropagationRPrivate RPRIVATE |
|
| 28 |
+ PropagationRPrivate Propagation = "rprivate" |
|
| 29 |
+ // PropagationPrivate PRIVATE |
|
| 30 |
+ PropagationPrivate Propagation = "private" |
|
| 31 |
+ // PropagationRShared RSHARED |
|
| 32 |
+ PropagationRShared Propagation = "rshared" |
|
| 33 |
+ // PropagationShared SHARED |
|
| 34 |
+ PropagationShared Propagation = "shared" |
|
| 35 |
+ // PropagationRSlave RSLAVE |
|
| 36 |
+ PropagationRSlave Propagation = "rslave" |
|
| 37 |
+ // PropagationSlave SLAVE |
|
| 38 |
+ PropagationSlave Propagation = "slave" |
|
| 39 |
+) |
|
| 40 |
+ |
|
| 41 |
+// BindOptions defines options specific to mounts of type "bind". |
|
| 42 |
+type BindOptions struct {
|
|
| 43 |
+ Propagation Propagation `json:",omitempty"` |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+// VolumeOptions represents the options for a mount of type volume. |
|
| 47 |
+type VolumeOptions struct {
|
|
| 48 |
+ NoCopy bool `json:",omitempty"` |
|
| 49 |
+ Labels map[string]string `json:",omitempty"` |
|
| 50 |
+ DriverConfig *Driver `json:",omitempty"` |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+// Driver represents a volume driver. |
|
| 54 |
+type Driver struct {
|
|
| 55 |
+ Name string `json:",omitempty"` |
|
| 56 |
+ Options map[string]string `json:",omitempty"` |
|
| 57 |
+} |
| ... | ... |
@@ -16,6 +16,11 @@ type ServiceConfig struct {
|
| 16 | 16 |
// unmarshalled to JSON |
| 17 | 17 |
type NetIPNet net.IPNet |
| 18 | 18 |
|
| 19 |
+// String returns the CIDR notation of ipnet |
|
| 20 |
+func (ipnet *NetIPNet) String() string {
|
|
| 21 |
+ return (*net.IPNet)(ipnet).String() |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 19 | 24 |
// MarshalJSON returns the JSON representation of the IPNet |
| 20 | 25 |
func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
|
| 21 | 26 |
return json.Marshal((*net.IPNet)(ipnet).String()) |
| ... | ... |
@@ -1,6 +1,10 @@ |
| 1 | 1 |
package swarm |
| 2 | 2 |
|
| 3 |
-import "time" |
|
| 3 |
+import ( |
|
| 4 |
+ "time" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/engine-api/types/mount" |
|
| 7 |
+) |
|
| 4 | 8 |
|
| 5 | 9 |
// ContainerSpec represents the spec of a container. |
| 6 | 10 |
type ContainerSpec struct {
|
| ... | ... |
@@ -11,57 +15,8 @@ type ContainerSpec struct {
|
| 11 | 11 |
Env []string `json:",omitempty"` |
| 12 | 12 |
Dir string `json:",omitempty"` |
| 13 | 13 |
User string `json:",omitempty"` |
| 14 |
- Mounts []Mount `json:",omitempty"` |
|
| 14 |
+ Groups []string `json:",omitempty"` |
|
| 15 |
+ TTY bool `json:",omitempty"` |
|
| 16 |
+ Mounts []mount.Mount `json:",omitempty"` |
|
| 15 | 17 |
StopGracePeriod *time.Duration `json:",omitempty"` |
| 16 | 18 |
} |
| 17 |
- |
|
| 18 |
-// MountType represents the type of a mount. |
|
| 19 |
-type MountType string |
|
| 20 |
- |
|
| 21 |
-const ( |
|
| 22 |
- // MountTypeBind BIND |
|
| 23 |
- MountTypeBind MountType = "bind" |
|
| 24 |
- // MountTypeVolume VOLUME |
|
| 25 |
- MountTypeVolume MountType = "volume" |
|
| 26 |
-) |
|
| 27 |
- |
|
| 28 |
-// Mount represents a mount (volume). |
|
| 29 |
-type Mount struct {
|
|
| 30 |
- Type MountType `json:",omitempty"` |
|
| 31 |
- Source string `json:",omitempty"` |
|
| 32 |
- Target string `json:",omitempty"` |
|
| 33 |
- ReadOnly bool `json:",omitempty"` |
|
| 34 |
- |
|
| 35 |
- BindOptions *BindOptions `json:",omitempty"` |
|
| 36 |
- VolumeOptions *VolumeOptions `json:",omitempty"` |
|
| 37 |
-} |
|
| 38 |
- |
|
| 39 |
-// MountPropagation represents the propagation of a mount. |
|
| 40 |
-type MountPropagation string |
|
| 41 |
- |
|
| 42 |
-const ( |
|
| 43 |
- // MountPropagationRPrivate RPRIVATE |
|
| 44 |
- MountPropagationRPrivate MountPropagation = "rprivate" |
|
| 45 |
- // MountPropagationPrivate PRIVATE |
|
| 46 |
- MountPropagationPrivate MountPropagation = "private" |
|
| 47 |
- // MountPropagationRShared RSHARED |
|
| 48 |
- MountPropagationRShared MountPropagation = "rshared" |
|
| 49 |
- // MountPropagationShared SHARED |
|
| 50 |
- MountPropagationShared MountPropagation = "shared" |
|
| 51 |
- // MountPropagationRSlave RSLAVE |
|
| 52 |
- MountPropagationRSlave MountPropagation = "rslave" |
|
| 53 |
- // MountPropagationSlave SLAVE |
|
| 54 |
- MountPropagationSlave MountPropagation = "slave" |
|
| 55 |
-) |
|
| 56 |
- |
|
| 57 |
-// BindOptions defines options specific to mounts of type "bind". |
|
| 58 |
-type BindOptions struct {
|
|
| 59 |
- Propagation MountPropagation `json:",omitempty"` |
|
| 60 |
-} |
|
| 61 |
- |
|
| 62 |
-// VolumeOptions represents the options for a mount of type volume. |
|
| 63 |
-type VolumeOptions struct {
|
|
| 64 |
- NoCopy bool `json:",omitempty"` |
|
| 65 |
- Labels map[string]string `json:",omitempty"` |
|
| 66 |
- DriverConfig *Driver `json:",omitempty"` |
|
| 67 |
-} |
| ... | ... |
@@ -92,7 +92,7 @@ type IPAMConfig struct {
|
| 92 | 92 |
Gateway string `json:",omitempty"` |
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 |
-// Driver represents a driver (network/volume). |
|
| 95 |
+// Driver represents a network driver. |
|
| 96 | 96 |
type Driver struct {
|
| 97 | 97 |
Name string `json:",omitempty"` |
| 98 | 98 |
Options map[string]string `json:",omitempty"` |
| ... | ... |
@@ -2,7 +2,7 @@ package swarm |
| 2 | 2 |
|
| 3 | 3 |
import "time" |
| 4 | 4 |
|
| 5 |
-// ClusterInfo represents info about a the cluster for outputing in "info" |
|
| 5 |
+// ClusterInfo represents info about the cluster for outputing in "info" |
|
| 6 | 6 |
// it contains the same information as "Swarm", but without the JoinTokens |
| 7 | 7 |
type ClusterInfo struct {
|
| 8 | 8 |
ID string |
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"time" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/engine-api/types/container" |
| 8 |
+ "github.com/docker/engine-api/types/mount" |
|
| 8 | 9 |
"github.com/docker/engine-api/types/network" |
| 9 | 10 |
"github.com/docker/engine-api/types/registry" |
| 10 | 11 |
"github.com/docker/engine-api/types/swarm" |
| ... | ... |
@@ -230,7 +231,6 @@ type Info struct {
|
| 230 | 230 |
OomKillDisable bool |
| 231 | 231 |
NGoroutines int |
| 232 | 232 |
SystemTime string |
| 233 |
- ExecutionDriver string |
|
| 234 | 233 |
LoggingDriver string |
| 235 | 234 |
CgroupDriver string |
| 236 | 235 |
NEventsListener int |
| ... | ... |
@@ -409,14 +409,16 @@ type DefaultNetworkSettings struct {
|
| 409 | 409 |
} |
| 410 | 410 |
|
| 411 | 411 |
// MountPoint represents a mount point configuration inside the container. |
| 412 |
+// This is used for reporting the mountpoints in use by a container. |
|
| 412 | 413 |
type MountPoint struct {
|
| 413 |
- Name string `json:",omitempty"` |
|
| 414 |
+ Type mount.Type `json:",omitempty"` |
|
| 415 |
+ Name string `json:",omitempty"` |
|
| 414 | 416 |
Source string |
| 415 | 417 |
Destination string |
| 416 | 418 |
Driver string `json:",omitempty"` |
| 417 | 419 |
Mode string |
| 418 | 420 |
RW bool |
| 419 |
- Propagation string |
|
| 421 |
+ Propagation mount.Propagation |
|
| 420 | 422 |
} |
| 421 | 423 |
|
| 422 | 424 |
// Volume represents the configuration of a volume for the remote API |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/docker/pkg/stringid" |
| 10 | 10 |
"github.com/docker/docker/pkg/system" |
| 11 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 11 | 12 |
"github.com/opencontainers/runc/libcontainer/label" |
| 12 | 13 |
) |
| 13 | 14 |
|
| ... | ... |
@@ -92,8 +93,8 @@ type MountPoint struct {
|
| 92 | 92 |
Mode string `json:"Relabel"` // Originally field was `Relabel`" |
| 93 | 93 |
|
| 94 | 94 |
// Note Propagation is not used on Windows |
| 95 |
- Propagation string // Mount propagation string |
|
| 96 |
- Named bool // specifies if the mountpoint was specified by name |
|
| 95 |
+ Propagation mounttypes.Propagation // Mount propagation string |
|
| 96 |
+ Named bool // specifies if the mountpoint was specified by name |
|
| 97 | 97 |
|
| 98 | 98 |
// Specifies if data should be copied from the container before the first mount |
| 99 | 99 |
// Use a pointer here so we can tell if the user set this value explicitly |
| ... | ... |
@@ -4,28 +4,31 @@ package volume |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"strings" |
| 7 |
+ |
|
| 8 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 7 | 9 |
) |
| 8 | 10 |
|
| 9 | 11 |
// DefaultPropagationMode defines what propagation mode should be used by |
| 10 | 12 |
// default if user has not specified one explicitly. |
| 11 |
-const DefaultPropagationMode string = "rprivate" |
|
| 13 |
+const DefaultPropagationMode mounttypes.Propagation = "rprivate" |
|
| 12 | 14 |
|
| 13 | 15 |
// propagation modes |
| 14 |
-var propagationModes = map[string]bool{
|
|
| 15 |
- "private": true, |
|
| 16 |
- "rprivate": true, |
|
| 17 |
- "slave": true, |
|
| 18 |
- "rslave": true, |
|
| 19 |
- "shared": true, |
|
| 20 |
- "rshared": true, |
|
| 16 |
+var propagationModes = map[mounttypes.Propagation]bool{
|
|
| 17 |
+ mounttypes.PropagationPrivate: true, |
|
| 18 |
+ mounttypes.PropagationRPrivate: true, |
|
| 19 |
+ mounttypes.PropagationSlave: true, |
|
| 20 |
+ mounttypes.PropagationRSlave: true, |
|
| 21 |
+ mounttypes.PropagationShared: true, |
|
| 22 |
+ mounttypes.PropagationRShared: true, |
|
| 21 | 23 |
} |
| 22 | 24 |
|
| 23 | 25 |
// GetPropagation extracts and returns the mount propagation mode. If there |
| 24 | 26 |
// are no specifications, then by default it is "private". |
| 25 |
-func GetPropagation(mode string) string {
|
|
| 27 |
+func GetPropagation(mode string) mounttypes.Propagation {
|
|
| 26 | 28 |
for _, o := range strings.Split(mode, ",") {
|
| 27 |
- if propagationModes[o] {
|
|
| 28 |
- return o |
|
| 29 |
+ prop := mounttypes.Propagation(o) |
|
| 30 |
+ if propagationModes[prop] {
|
|
| 31 |
+ return prop |
|
| 29 | 32 |
} |
| 30 | 33 |
} |
| 31 | 34 |
return DefaultPropagationMode |
| ... | ... |
@@ -36,7 +39,7 @@ func GetPropagation(mode string) string {
|
| 36 | 36 |
// present, false otherwise. |
| 37 | 37 |
func HasPropagation(mode string) bool {
|
| 38 | 38 |
for _, o := range strings.Split(mode, ",") {
|
| 39 |
- if propagationModes[o] {
|
|
| 39 |
+ if propagationModes[mounttypes.Propagation(o)] {
|
|
| 40 | 40 |
return true |
| 41 | 41 |
} |
| 42 | 42 |
} |
| ... | ... |
@@ -2,15 +2,17 @@ |
| 2 | 2 |
|
| 3 | 3 |
package volume |
| 4 | 4 |
|
| 5 |
+import mounttypes "github.com/docker/engine-api/types/mount" |
|
| 6 |
+ |
|
| 5 | 7 |
// DefaultPropagationMode is used only in linux. In other cases it returns |
| 6 | 8 |
// empty string. |
| 7 |
-const DefaultPropagationMode string = "" |
|
| 9 |
+const DefaultPropagationMode mounttypes.Propagation = "" |
|
| 8 | 10 |
|
| 9 | 11 |
// propagation modes not supported on this platform. |
| 10 | 12 |
var propagationModes = map[string]bool{}
|
| 11 | 13 |
|
| 12 | 14 |
// GetPropagation is not supported. Return empty string. |
| 13 |
-func GetPropagation(mode string) string {
|
|
| 15 |
+func GetPropagation(mode string) mounttypes.Propagation {
|
|
| 14 | 16 |
return DefaultPropagationMode |
| 15 | 17 |
} |
| 16 | 18 |
|
| ... | ... |
@@ -6,6 +6,8 @@ import ( |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"path/filepath" |
| 8 | 8 |
"strings" |
| 9 |
+ |
|
| 10 |
+ mounttypes "github.com/docker/engine-api/types/mount" |
|
| 9 | 11 |
) |
| 10 | 12 |
|
| 11 | 13 |
// read-write modes |
| ... | ... |
@@ -152,7 +154,7 @@ func ValidMountMode(mode string) bool {
|
| 152 | 152 |
rwModeCount++ |
| 153 | 153 |
case labelModes[o]: |
| 154 | 154 |
labelModeCount++ |
| 155 |
- case propagationModes[o]: |
|
| 155 |
+ case propagationModes[mounttypes.Propagation(o)]: |
|
| 156 | 156 |
propagationModeCount++ |
| 157 | 157 |
case copyModeExists(o): |
| 158 | 158 |
copyModeCount++ |