Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"io" |
| 6 | 6 |
"net/http" |
| 7 |
- "runtime" |
|
| 8 | 7 |
"strconv" |
| 9 | 8 |
"strings" |
| 10 | 9 |
"time" |
| ... | ... |
@@ -20,22 +19,6 @@ import ( |
| 20 | 20 |
"github.com/docker/docker/runconfig" |
| 21 | 21 |
) |
| 22 | 22 |
|
| 23 |
-func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
| 24 |
- if vars == nil {
|
|
| 25 |
- return fmt.Errorf("Missing parameter")
|
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- if version.LessThan("1.20") && runtime.GOOS != "windows" {
|
|
| 29 |
- return getContainersByNameDownlevel(w, s, vars["name"]) |
|
| 30 |
- } |
|
| 31 |
- |
|
| 32 |
- containerJSON, err := s.daemon.ContainerInspect(vars["name"]) |
|
| 33 |
- if err != nil {
|
|
| 34 |
- return err |
|
| 35 |
- } |
|
| 36 |
- return writeJSON(w, http.StatusOK, containerJSON) |
|
| 37 |
-} |
|
| 38 |
- |
|
| 39 | 23 |
func (s *Server) getContainersJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 40 | 24 |
if err := parseForm(r); err != nil {
|
| 41 | 25 |
return err |
| 42 | 26 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,33 @@ |
| 0 |
+package server |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net/http" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/pkg/version" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// getContainersByName inspects containers configuration and serializes it as json. |
|
| 10 |
+func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
| 11 |
+ if vars == nil {
|
|
| 12 |
+ return fmt.Errorf("Missing parameter")
|
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ var json interface{}
|
|
| 16 |
+ var err error |
|
| 17 |
+ |
|
| 18 |
+ switch {
|
|
| 19 |
+ case version.LessThan("1.20"):
|
|
| 20 |
+ json, err = s.daemon.ContainerInspectPre120(vars["name"]) |
|
| 21 |
+ case version.Equal("1.20"):
|
|
| 22 |
+ json, err = s.daemon.ContainerInspect120(vars["name"]) |
|
| 23 |
+ default: |
|
| 24 |
+ json, err = s.daemon.ContainerInspect(vars["name"]) |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ if err != nil {
|
|
| 28 |
+ return err |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ return writeJSON(w, http.StatusOK, json) |
|
| 32 |
+} |
| ... | ... |
@@ -103,16 +103,6 @@ func allocateDaemonPort(addr string) error {
|
| 103 | 103 |
return nil |
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 |
-// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This |
|
| 107 |
-// is only relevant on non-Windows daemons. |
|
| 108 |
-func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
|
|
| 109 |
- containerJSONRaw, err := s.daemon.ContainerInspectPre120(namevar) |
|
| 110 |
- if err != nil {
|
|
| 111 |
- return err |
|
| 112 |
- } |
|
| 113 |
- return writeJSON(w, http.StatusOK, containerJSONRaw) |
|
| 114 |
-} |
|
| 115 |
- |
|
| 116 | 106 |
// listenFD returns the specified socket activated files as a slice of |
| 117 | 107 |
// net.Listeners or all of the activated files if "*" is given. |
| 118 | 108 |
func listenFD(addr string) ([]net.Listener, error) {
|
| ... | ... |
@@ -56,9 +56,3 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
| 56 | 56 |
func allocateDaemonPort(addr string) error {
|
| 57 | 57 |
return nil |
| 58 | 58 |
} |
| 59 |
- |
|
| 60 |
-// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This |
|
| 61 |
-// is only relevant on non-Windows daemons. |
|
| 62 |
-func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
|
|
| 63 |
- return nil |
|
| 64 |
-} |
| ... | ... |
@@ -273,24 +273,39 @@ type ContainerJSON struct {
|
| 273 | 273 |
Config *runconfig.Config |
| 274 | 274 |
} |
| 275 | 275 |
|
| 276 |
-// ContainerJSONPre120 is a backcompatibility struct along with ContainerConfig. |
|
| 276 |
+// ContainerJSON120 is a backcompatibility struct along with ContainerConfig120. |
|
| 277 |
+type ContainerJSON120 struct {
|
|
| 278 |
+ *ContainerJSONBase |
|
| 279 |
+ Mounts []MountPoint |
|
| 280 |
+ Config *ContainerConfig120 |
|
| 281 |
+} |
|
| 282 |
+ |
|
| 283 |
+// ContainerJSONPre120 is a backcompatibility struct along with ContainerConfigPre120. |
|
| 277 | 284 |
// Note this is not used by the Windows daemon. |
| 278 | 285 |
type ContainerJSONPre120 struct {
|
| 279 | 286 |
*ContainerJSONBase |
| 280 | 287 |
Volumes map[string]string |
| 281 | 288 |
VolumesRW map[string]bool |
| 282 |
- Config *ContainerConfig |
|
| 289 |
+ Config *ContainerConfigPre120 |
|
| 283 | 290 |
} |
| 284 | 291 |
|
| 285 |
-// ContainerConfig is a backcompatibility struct used in ContainerJSONPre120 |
|
| 286 |
-type ContainerConfig struct {
|
|
| 292 |
+// ContainerConfigPre120 is a backcompatibility struct used in ContainerJSONPre120 |
|
| 293 |
+type ContainerConfigPre120 struct {
|
|
| 287 | 294 |
*runconfig.Config |
| 288 | 295 |
|
| 289 | 296 |
// backward compatibility, they now live in HostConfig |
| 290 |
- Memory int64 |
|
| 291 |
- MemorySwap int64 |
|
| 292 |
- CPUShares int64 `json:"CpuShares"` |
|
| 293 |
- CPUSet string `json:"CpuSet"` |
|
| 297 |
+ VolumeDriver string |
|
| 298 |
+ Memory int64 |
|
| 299 |
+ MemorySwap int64 |
|
| 300 |
+ CPUShares int64 `json:"CpuShares"` |
|
| 301 |
+ CPUSet string `json:"CpuSet"` |
|
| 302 |
+} |
|
| 303 |
+ |
|
| 304 |
+// ContainerConfig120 is a backcompatibility struct used in ContainerJSON120 |
|
| 305 |
+type ContainerConfig120 struct {
|
|
| 306 |
+ *runconfig.Config |
|
| 307 |
+ // backward compatibility, it lives now in HostConfig |
|
| 308 |
+ VolumeDriver string |
|
| 294 | 309 |
} |
| 295 | 310 |
|
| 296 | 311 |
// MountPoint represents a mount point configuration inside the container. |
| ... | ... |
@@ -105,7 +105,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos |
| 105 | 105 |
} |
| 106 | 106 |
defer container.Unmount() |
| 107 | 107 |
|
| 108 |
- if err := createContainerPlatformSpecificSettings(container, config, img); err != nil {
|
|
| 108 |
+ if err := createContainerPlatformSpecificSettings(container, config, hostConfig, img); err != nil {
|
|
| 109 | 109 |
return nil, nil, err |
| 110 | 110 |
} |
| 111 | 111 |
|
| ... | ... |
@@ -16,7 +16,7 @@ import ( |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 | 18 |
// createContainerPlatformSpecificSettings performs platform specific container create functionality |
| 19 |
-func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error {
|
|
| 19 |
+func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error {
|
|
| 20 | 20 |
for spec := range config.Volumes {
|
| 21 | 21 |
var ( |
| 22 | 22 |
name, destination string |
| ... | ... |
@@ -44,7 +44,7 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco |
| 44 | 44 |
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
|
| 45 | 45 |
} |
| 46 | 46 |
|
| 47 |
- volumeDriver := config.VolumeDriver |
|
| 47 |
+ volumeDriver := hostConfig.VolumeDriver |
|
| 48 | 48 |
if destination != "" && img != nil {
|
| 49 | 49 |
if _, ok := img.ContainerConfig.Volumes[destination]; ok {
|
| 50 | 50 |
// check for whether bind is not specified and then set to local |
| ... | ... |
@@ -6,6 +6,6 @@ import ( |
| 6 | 6 |
) |
| 7 | 7 |
|
| 8 | 8 |
// createContainerPlatformSpecificSettings performs platform specific container create functionality |
| 9 |
-func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error {
|
|
| 9 |
+func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error {
|
|
| 10 | 10 |
return nil |
| 11 | 11 |
} |
| ... | ... |
@@ -29,6 +29,30 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error |
| 29 | 29 |
return &types.ContainerJSON{base, mountPoints, container.Config}, nil
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 |
+// ContainerInspect120 serializes the master version of a container into a json type. |
|
| 33 |
+func (daemon *Daemon) ContainerInspect120(name string) (*types.ContainerJSON120, error) {
|
|
| 34 |
+ container, err := daemon.Get(name) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ return nil, err |
|
| 37 |
+ } |
|
| 38 |
+ |
|
| 39 |
+ container.Lock() |
|
| 40 |
+ defer container.Unlock() |
|
| 41 |
+ |
|
| 42 |
+ base, err := daemon.getInspectData(container) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return nil, err |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ mountPoints := addMountPoints(container) |
|
| 48 |
+ config := &types.ContainerConfig120{
|
|
| 49 |
+ container.Config, |
|
| 50 |
+ container.hostConfig.VolumeDriver, |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ return &types.ContainerJSON120{base, mountPoints, config}, nil
|
|
| 54 |
+} |
|
| 55 |
+ |
|
| 32 | 56 |
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
|
| 33 | 57 |
// make a copy to play with |
| 34 | 58 |
hostConfig := *container.hostConfig |
| ... | ... |
@@ -14,7 +14,7 @@ func setPlatformSpecificContainerFields(container *Container, contJSONBase *type |
| 14 | 14 |
return contJSONBase |
| 15 | 15 |
} |
| 16 | 16 |
|
| 17 |
-// ContainerInspectPre120 is for backwards compatibility with pre v1.20 clients. |
|
| 17 |
+// ContainerInspectPre120 gets containers for pre 1.20 APIs. |
|
| 18 | 18 |
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONPre120, error) {
|
| 19 | 19 |
container, err := daemon.Get(name) |
| 20 | 20 |
if err != nil {
|
| ... | ... |
@@ -36,8 +36,9 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONP |
| 36 | 36 |
volumesRW[m.Destination] = m.RW |
| 37 | 37 |
} |
| 38 | 38 |
|
| 39 |
- config := &types.ContainerConfig{
|
|
| 39 |
+ config := &types.ContainerConfigPre120{
|
|
| 40 | 40 |
container.Config, |
| 41 |
+ container.hostConfig.VolumeDriver, |
|
| 41 | 42 |
container.hostConfig.Memory, |
| 42 | 43 |
container.hostConfig.MemorySwap, |
| 43 | 44 |
container.hostConfig.CPUShares, |
| ... | ... |
@@ -10,3 +10,8 @@ func setPlatformSpecificContainerFields(container *Container, contJSONBase *type |
| 10 | 10 |
func addMountPoints(container *Container) []types.MountPoint {
|
| 11 | 11 |
return nil |
| 12 | 12 |
} |
| 13 |
+ |
|
| 14 |
+// ContainerInspectPre120 get containers for pre 1.20 APIs. |
|
| 15 |
+func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
|
|
| 16 |
+ return daemon.ContainerInspect(name) |
|
| 17 |
+} |
| ... | ... |
@@ -5,7 +5,6 @@ package daemon |
| 5 | 5 |
import ( |
| 6 | 6 |
"testing" |
| 7 | 7 |
|
| 8 |
- "github.com/docker/docker/runconfig" |
|
| 9 | 8 |
"github.com/docker/docker/volume" |
| 10 | 9 |
"github.com/docker/docker/volume/drivers" |
| 11 | 10 |
) |
| ... | ... |
@@ -55,8 +54,7 @@ func TestParseBindMount(t *testing.T) {
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
for _, c := range cases {
|
| 58 |
- conf := &runconfig.Config{VolumeDriver: c.driver}
|
|
| 59 |
- m, err := parseBindMount(c.bind, c.mountLabel, conf) |
|
| 58 |
+ m, err := parseBindMount(c.bind, c.mountLabel, c.driver) |
|
| 60 | 59 |
if c.fail {
|
| 61 | 60 |
if err == nil {
|
| 62 | 61 |
t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
|
| ... | ... |
@@ -59,7 +59,7 @@ func (container *Container) setupMounts() ([]execdriver.Mount, error) {
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
// parseBindMount validates the configuration of mount information in runconfig is valid. |
| 62 |
-func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
|
|
| 62 |
+func parseBindMount(spec, mountLabel, volumeDriver string) (*mountPoint, error) {
|
|
| 63 | 63 |
bind := &mountPoint{
|
| 64 | 64 |
RW: true, |
| 65 | 65 |
} |
| ... | ... |
@@ -87,7 +87,7 @@ func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (* |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 | 89 |
if len(source) == 0 {
|
| 90 |
- bind.Driver = config.VolumeDriver |
|
| 90 |
+ bind.Driver = volumeDriver |
|
| 91 | 91 |
if len(bind.Driver) == 0 {
|
| 92 | 92 |
bind.Driver = volume.DefaultDriverName |
| 93 | 93 |
} |
| ... | ... |
@@ -325,7 +325,7 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc |
| 325 | 325 |
// 3. Read bind mounts |
| 326 | 326 |
for _, b := range hostConfig.Binds {
|
| 327 | 327 |
// #10618 |
| 328 |
- bind, err := parseBindMount(b, container.MountLabel, container.Config) |
|
| 328 |
+ bind, err := parseBindMount(b, container.MountLabel, hostConfig.VolumeDriver) |
|
| 329 | 329 |
if err != nil {
|
| 330 | 330 |
return err |
| 331 | 331 |
} |
| ... | ... |
@@ -80,6 +80,7 @@ This section lists each version from latest to oldest. Each listing includes a |
| 80 | 80 |
* `POST /volumes` to create a volume. |
| 81 | 81 |
* `GET /volumes/(name)` get low-level information about a volume. |
| 82 | 82 |
* `DELETE /volumes/(name)`remove a volume with the specified name. |
| 83 |
+* `VolumeDriver` has been moved from config to hostConfig to make the configuration portable. |
|
| 83 | 84 |
|
| 84 | 85 |
|
| 85 | 86 |
### v1.20 API changes |
| ... | ... |
@@ -196,7 +196,8 @@ Create a container |
| 196 | 196 |
"Ulimits": [{}],
|
| 197 | 197 |
"LogConfig": { "Type": "json-file", "Config": {} },
|
| 198 | 198 |
"SecurityOpt": [""], |
| 199 |
- "CgroupParent": "" |
|
| 199 |
+ "CgroupParent": "", |
|
| 200 |
+ "VolumeDriver": "" |
|
| 200 | 201 |
} |
| 201 | 202 |
} |
| 202 | 203 |
|
| ... | ... |
@@ -300,6 +301,7 @@ Json Parameters: |
| 300 | 300 |
Available types: `json-file`, `syslog`, `journald`, `gelf`, `none`. |
| 301 | 301 |
`json-file` logging driver. |
| 302 | 302 |
- **CgroupParent** - Path to `cgroups` under which the container's `cgroup` is created. If the path is not absolute, the path is considered to be relative to the `cgroups` path of the init process. Cgroups are created if they do not already exist. |
| 303 |
+ - **VolumeDriver** - Driver that this container users to mount volumes. |
|
| 303 | 304 |
|
| 304 | 305 |
Query Parameters: |
| 305 | 306 |
|
| ... | ... |
@@ -407,7 +409,8 @@ Return low-level information on the container `id` |
| 407 | 407 |
}, |
| 408 | 408 |
"SecurityOpt": null, |
| 409 | 409 |
"VolumesFrom": null, |
| 410 |
- "Ulimits": [{}]
|
|
| 410 |
+ "Ulimits": [{}],
|
|
| 411 |
+ "VolumeDriver": "" |
|
| 411 | 412 |
}, |
| 412 | 413 |
"HostnamePath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname", |
| 413 | 414 |
"HostsPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts", |
| ... | ... |
@@ -48,3 +48,65 @@ func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) {
|
| 48 | 48 |
} |
| 49 | 49 |
} |
| 50 | 50 |
} |
| 51 |
+ |
|
| 52 |
+func (s *DockerSuite) TestInspectApiContainerVolumeDriverLegacy(c *check.C) {
|
|
| 53 |
+ out, _ := dockerCmd(c, "run", "-d", "busybox", "true") |
|
| 54 |
+ |
|
| 55 |
+ cleanedContainerID := strings.TrimSpace(out) |
|
| 56 |
+ |
|
| 57 |
+ cases := []string{"1.19", "1.20"}
|
|
| 58 |
+ for _, version := range cases {
|
|
| 59 |
+ endpoint := fmt.Sprintf("/v%s/containers/%s/json", version, cleanedContainerID)
|
|
| 60 |
+ status, body, err := sockRequest("GET", endpoint, nil)
|
|
| 61 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
| 62 |
+ c.Assert(err, check.IsNil) |
|
| 63 |
+ |
|
| 64 |
+ var inspectJSON map[string]interface{}
|
|
| 65 |
+ if err = json.Unmarshal(body, &inspectJSON); err != nil {
|
|
| 66 |
+ c.Fatalf("unable to unmarshal body for version %s: %v", version, err)
|
|
| 67 |
+ } |
|
| 68 |
+ |
|
| 69 |
+ config, ok := inspectJSON["Config"] |
|
| 70 |
+ if !ok {
|
|
| 71 |
+ c.Fatal("Unable to find 'Config'")
|
|
| 72 |
+ } |
|
| 73 |
+ cfg := config.(map[string]interface{})
|
|
| 74 |
+ if _, ok := cfg["VolumeDriver"]; !ok {
|
|
| 75 |
+ c.Fatalf("Api version %s expected to include VolumeDriver in 'Config'", version)
|
|
| 76 |
+ } |
|
| 77 |
+ } |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+func (s *DockerSuite) TestInspectApiContainerVolumeDriver(c *check.C) {
|
|
| 81 |
+ out, _ := dockerCmd(c, "run", "-d", "busybox", "true") |
|
| 82 |
+ |
|
| 83 |
+ cleanedContainerID := strings.TrimSpace(out) |
|
| 84 |
+ |
|
| 85 |
+ endpoint := fmt.Sprintf("/v1.21/containers/%s/json", cleanedContainerID)
|
|
| 86 |
+ status, body, err := sockRequest("GET", endpoint, nil)
|
|
| 87 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
| 88 |
+ c.Assert(err, check.IsNil) |
|
| 89 |
+ |
|
| 90 |
+ var inspectJSON map[string]interface{}
|
|
| 91 |
+ if err = json.Unmarshal(body, &inspectJSON); err != nil {
|
|
| 92 |
+ c.Fatalf("unable to unmarshal body for version 1.21: %v", err)
|
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ config, ok := inspectJSON["Config"] |
|
| 96 |
+ if !ok {
|
|
| 97 |
+ c.Fatal("Unable to find 'Config'")
|
|
| 98 |
+ } |
|
| 99 |
+ cfg := config.(map[string]interface{})
|
|
| 100 |
+ if _, ok := cfg["VolumeDriver"]; ok {
|
|
| 101 |
+ c.Fatal("Api version 1.21 expected to not include VolumeDriver in 'Config'")
|
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ config, ok = inspectJSON["HostConfig"] |
|
| 105 |
+ if !ok {
|
|
| 106 |
+ c.Fatal("Unable to find 'HostConfig'")
|
|
| 107 |
+ } |
|
| 108 |
+ cfg = config.(map[string]interface{})
|
|
| 109 |
+ if _, ok := cfg["VolumeDriver"]; !ok {
|
|
| 110 |
+ c.Fatal("Api version 1.21 expected to include VolumeDriver in 'HostConfig'")
|
|
| 111 |
+ } |
|
| 112 |
+} |
| ... | ... |
@@ -253,15 +253,11 @@ func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindL |
| 253 | 253 |
|
| 254 | 254 |
img := "test-checkbindlocalvolume" |
| 255 | 255 |
|
| 256 |
- args := []string{"--host", s.d.sock()}
|
|
| 257 |
- buildOut, err := buildImageArgs(args, img, dockerfile, true) |
|
| 258 |
- fmt.Println(buildOut) |
|
| 256 |
+ _, err := buildImageWithOutInDamon(s.d.sock(), img, dockerfile, true) |
|
| 257 |
+ c.Assert(err, check.IsNil) |
|
| 259 | 258 |
|
| 260 | 259 |
out, err := s.d.Cmd("run", "--rm", "--name", "test-data-nobind", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", img, "cat", "/nobindthenlocalvol/test")
|
| 261 |
- if err != nil {
|
|
| 262 |
- fmt.Println(out) |
|
| 263 |
- c.Fatal(err) |
|
| 264 |
- } |
|
| 260 |
+ c.Assert(err, check.IsNil) |
|
| 265 | 261 |
|
| 266 | 262 |
if !strings.Contains(out, expected) {
|
| 267 | 263 |
c.Fatalf("External volume mount failed. Output: %s\n", out)
|
| ... | ... |
@@ -1392,22 +1392,14 @@ func createTmpFile(c *check.C, content string) string {
|
| 1392 | 1392 |
return filename |
| 1393 | 1393 |
} |
| 1394 | 1394 |
|
| 1395 |
-func buildImageArgs(args []string, name, dockerfile string, useCache bool) (string, error) {
|
|
| 1396 |
- id, _, err := buildImageWithOutArgs(args, name, dockerfile, useCache) |
|
| 1397 |
- return id, err |
|
| 1398 |
-} |
|
| 1399 |
- |
|
| 1400 |
-func buildImageWithOutArgs(args []string, name, dockerfile string, useCache bool) (string, string, error) {
|
|
| 1395 |
+func buildImageWithOutInDamon(socket string, name, dockerfile string, useCache bool) (string, error) {
|
|
| 1396 |
+ args := []string{"--host", socket}
|
|
| 1401 | 1397 |
buildCmd := buildImageCmdArgs(args, name, dockerfile, useCache) |
| 1402 | 1398 |
out, exitCode, err := runCommandWithOutput(buildCmd) |
| 1403 | 1399 |
if err != nil || exitCode != 0 {
|
| 1404 |
- return "", out, fmt.Errorf("failed to build the image: %s", out)
|
|
| 1400 |
+ return out, fmt.Errorf("failed to build the image: %s, error: %v", out, err)
|
|
| 1405 | 1401 |
} |
| 1406 |
- id, err := getIDByName(name) |
|
| 1407 |
- if err != nil {
|
|
| 1408 |
- return "", out, err |
|
| 1409 |
- } |
|
| 1410 |
- return id, out, nil |
|
| 1402 |
+ return out, nil |
|
| 1411 | 1403 |
} |
| 1412 | 1404 |
|
| 1413 | 1405 |
func buildImageCmdArgs(args []string, name, dockerfile string, useCache bool) *exec.Cmd {
|
| ... | ... |
@@ -28,7 +28,6 @@ type Config struct {
|
| 28 | 28 |
Cmd *stringutils.StrSlice // Command to run when starting the container |
| 29 | 29 |
Image string // Name of the image as it was passed by the operator (eg. could be symbolic) |
| 30 | 30 |
Volumes map[string]struct{} // List of volumes (mounts) used for the container
|
| 31 |
- VolumeDriver string // Name of the volume driver used to mount volumes |
|
| 32 | 31 |
WorkingDir string // Current directory (PWD) in the command will be launched |
| 33 | 32 |
Entrypoint *stringutils.StrSlice // Entrypoint to run when starting the container |
| 34 | 33 |
NetworkDisabled bool // Is network disabled |
| ... | ... |
@@ -32,11 +32,17 @@ func (w *ContainerConfigWrapper) getHostConfig() *HostConfig {
|
| 32 | 32 |
w.InnerHostConfig.CpusetCpus = hc.CpusetCpus |
| 33 | 33 |
} |
| 34 | 34 |
|
| 35 |
+ if hc.VolumeDriver != "" && w.InnerHostConfig.VolumeDriver == "" {
|
|
| 36 |
+ w.InnerHostConfig.VolumeDriver = hc.VolumeDriver |
|
| 37 |
+ } |
|
| 38 |
+ |
|
| 35 | 39 |
hc = w.InnerHostConfig |
| 36 | 40 |
} |
| 37 | 41 |
|
| 38 |
- if hc != nil && w.Cpuset != "" && hc.CpusetCpus == "" {
|
|
| 39 |
- hc.CpusetCpus = w.Cpuset |
|
| 42 |
+ if hc != nil {
|
|
| 43 |
+ if w.Cpuset != "" && hc.CpusetCpus == "" {
|
|
| 44 |
+ hc.CpusetCpus = w.Cpuset |
|
| 45 |
+ } |
|
| 40 | 46 |
} |
| 41 | 47 |
|
| 42 | 48 |
// Make sure NetworkMode has an acceptable value. We do this to ensure |
| ... | ... |
@@ -251,6 +251,7 @@ type HostConfig struct {
|
| 251 | 251 |
LogConfig LogConfig // Configuration of the logs for this container |
| 252 | 252 |
CgroupParent string // Parent cgroup. |
| 253 | 253 |
ConsoleSize [2]int // Initial console size on Windows |
| 254 |
+ VolumeDriver string // Name of the volume driver used to mount volumes |
|
| 254 | 255 |
} |
| 255 | 256 |
|
| 256 | 257 |
// DecodeHostConfig creates a HostConfig based on the specified Reader. |
| ... | ... |
@@ -322,7 +322,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 322 | 322 |
Entrypoint: entrypoint, |
| 323 | 323 |
WorkingDir: *flWorkingDir, |
| 324 | 324 |
Labels: convertKVStringsToMap(labels), |
| 325 |
- VolumeDriver: *flVolumeDriver, |
|
| 326 | 325 |
} |
| 327 | 326 |
|
| 328 | 327 |
hostConfig := &HostConfig{
|
| ... | ... |
@@ -362,6 +361,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 362 | 362 |
Ulimits: flUlimits.GetList(), |
| 363 | 363 |
LogConfig: LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
|
| 364 | 364 |
CgroupParent: *flCgroupParent, |
| 365 |
+ VolumeDriver: *flVolumeDriver, |
|
| 365 | 366 |
} |
| 366 | 367 |
|
| 367 | 368 |
applyExperimentalFlags(expFlags, config, hostConfig) |