mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Move VolumeDriver to HostConfig to make containers portable.
Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
		
							parent
							
								
									2434bd8e63
								
							
						
					
					
						commit
						6549d6517b
					
				
					 22 changed files with 181 additions and 78 deletions
				
			
		| 
						 | 
					@ -4,7 +4,6 @@ import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -20,22 +19,6 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/runconfig"
 | 
						"github.com/docker/docker/runconfig"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
					 | 
				
			||||||
	if vars == nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("Missing parameter")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if version.LessThan("1.20") && runtime.GOOS != "windows" {
 | 
					 | 
				
			||||||
		return getContainersByNameDownlevel(w, s, vars["name"])
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	containerJSON, err := s.daemon.ContainerInspect(vars["name"])
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return writeJSON(w, http.StatusOK, containerJSON)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *Server) getContainersJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
					func (s *Server) getContainersJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
				
			||||||
	if err := parseForm(r); err != nil {
 | 
						if err := parseForm(r); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										33
									
								
								api/server/inspect.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								api/server/inspect.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,33 @@
 | 
				
			||||||
 | 
					package server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/version"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getContainersByName inspects containers configuration and serializes it as json.
 | 
				
			||||||
 | 
					func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
				
			||||||
 | 
						if vars == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Missing parameter")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var json interface{}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case version.LessThan("1.20"):
 | 
				
			||||||
 | 
							json, err = s.daemon.ContainerInspectPre120(vars["name"])
 | 
				
			||||||
 | 
						case version.Equal("1.20"):
 | 
				
			||||||
 | 
							json, err = s.daemon.ContainerInspect120(vars["name"])
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							json, err = s.daemon.ContainerInspect(vars["name"])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return writeJSON(w, http.StatusOK, json)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -103,16 +103,6 @@ func allocateDaemonPort(addr string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This
 | 
					 | 
				
			||||||
// is only relevant on non-Windows daemons.
 | 
					 | 
				
			||||||
func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
 | 
					 | 
				
			||||||
	containerJSONRaw, err := s.daemon.ContainerInspectPre120(namevar)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return writeJSON(w, http.StatusOK, containerJSONRaw)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// listenFD returns the specified socket activated files as a slice of
 | 
					// listenFD returns the specified socket activated files as a slice of
 | 
				
			||||||
// net.Listeners or all of the activated files if "*" is given.
 | 
					// net.Listeners or all of the activated files if "*" is given.
 | 
				
			||||||
func listenFD(addr string) ([]net.Listener, error) {
 | 
					func listenFD(addr string) ([]net.Listener, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,9 +56,3 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
 | 
				
			||||||
func allocateDaemonPort(addr string) error {
 | 
					func allocateDaemonPort(addr string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This
 | 
					 | 
				
			||||||
// is only relevant on non-Windows daemons.
 | 
					 | 
				
			||||||
func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -273,24 +273,39 @@ type ContainerJSON struct {
 | 
				
			||||||
	Config *runconfig.Config
 | 
						Config *runconfig.Config
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContainerJSONPre120 is a backcompatibility struct along with ContainerConfig.
 | 
					// ContainerJSON120 is a backcompatibility struct along with ContainerConfig120.
 | 
				
			||||||
 | 
					type ContainerJSON120 struct {
 | 
				
			||||||
 | 
						*ContainerJSONBase
 | 
				
			||||||
 | 
						Mounts []MountPoint
 | 
				
			||||||
 | 
						Config *ContainerConfig120
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContainerJSONPre120 is a backcompatibility struct along with ContainerConfigPre120.
 | 
				
			||||||
// Note this is not used by the Windows daemon.
 | 
					// Note this is not used by the Windows daemon.
 | 
				
			||||||
type ContainerJSONPre120 struct {
 | 
					type ContainerJSONPre120 struct {
 | 
				
			||||||
	*ContainerJSONBase
 | 
						*ContainerJSONBase
 | 
				
			||||||
	Volumes   map[string]string
 | 
						Volumes   map[string]string
 | 
				
			||||||
	VolumesRW map[string]bool
 | 
						VolumesRW map[string]bool
 | 
				
			||||||
	Config    *ContainerConfig
 | 
						Config    *ContainerConfigPre120
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContainerConfig is a backcompatibility struct used in ContainerJSONPre120
 | 
					// ContainerConfigPre120 is a backcompatibility struct used in ContainerJSONPre120
 | 
				
			||||||
type ContainerConfig struct {
 | 
					type ContainerConfigPre120 struct {
 | 
				
			||||||
	*runconfig.Config
 | 
						*runconfig.Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// backward compatibility, they now live in HostConfig
 | 
						// backward compatibility, they now live in HostConfig
 | 
				
			||||||
	Memory     int64
 | 
						VolumeDriver string
 | 
				
			||||||
	MemorySwap int64
 | 
						Memory       int64
 | 
				
			||||||
	CPUShares  int64  `json:"CpuShares"`
 | 
						MemorySwap   int64
 | 
				
			||||||
	CPUSet     string `json:"CpuSet"`
 | 
						CPUShares    int64  `json:"CpuShares"`
 | 
				
			||||||
 | 
						CPUSet       string `json:"CpuSet"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContainerConfig120 is a backcompatibility struct used in ContainerJSON120
 | 
				
			||||||
 | 
					type ContainerConfig120 struct {
 | 
				
			||||||
 | 
						*runconfig.Config
 | 
				
			||||||
 | 
						// backward compatibility, it lives now in HostConfig
 | 
				
			||||||
 | 
						VolumeDriver string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MountPoint represents a mount point configuration inside the container.
 | 
					// MountPoint represents a mount point configuration inside the container.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer container.Unmount()
 | 
						defer container.Unmount()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := createContainerPlatformSpecificSettings(container, config, img); err != nil {
 | 
						if err := createContainerPlatformSpecificSettings(container, config, hostConfig, img); err != nil {
 | 
				
			||||||
		return nil, nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// createContainerPlatformSpecificSettings performs platform specific container create functionality
 | 
					// createContainerPlatformSpecificSettings performs platform specific container create functionality
 | 
				
			||||||
func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error {
 | 
					func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error {
 | 
				
			||||||
	for spec := range config.Volumes {
 | 
						for spec := range config.Volumes {
 | 
				
			||||||
		var (
 | 
							var (
 | 
				
			||||||
			name, destination string
 | 
								name, destination string
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco
 | 
				
			||||||
			return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
 | 
								return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		volumeDriver := config.VolumeDriver
 | 
							volumeDriver := hostConfig.VolumeDriver
 | 
				
			||||||
		if destination != "" && img != nil {
 | 
							if destination != "" && img != nil {
 | 
				
			||||||
			if _, ok := img.ContainerConfig.Volumes[destination]; ok {
 | 
								if _, ok := img.ContainerConfig.Volumes[destination]; ok {
 | 
				
			||||||
				// check for whether bind is not specified and then set to local
 | 
									// check for whether bind is not specified and then set to local
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,6 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// createContainerPlatformSpecificSettings performs platform specific container create functionality
 | 
					// createContainerPlatformSpecificSettings performs platform specific container create functionality
 | 
				
			||||||
func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error {
 | 
					func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,30 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
 | 
				
			||||||
	return &types.ContainerJSON{base, mountPoints, container.Config}, nil
 | 
						return &types.ContainerJSON{base, mountPoints, container.Config}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContainerInspect120 serializes the master version of a container into a json type.
 | 
				
			||||||
 | 
					func (daemon *Daemon) ContainerInspect120(name string) (*types.ContainerJSON120, error) {
 | 
				
			||||||
 | 
						container, err := daemon.Get(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container.Lock()
 | 
				
			||||||
 | 
						defer container.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base, err := daemon.getInspectData(container)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mountPoints := addMountPoints(container)
 | 
				
			||||||
 | 
						config := &types.ContainerConfig120{
 | 
				
			||||||
 | 
							container.Config,
 | 
				
			||||||
 | 
							container.hostConfig.VolumeDriver,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &types.ContainerJSON120{base, mountPoints, config}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
 | 
					func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
 | 
				
			||||||
	// make a copy to play with
 | 
						// make a copy to play with
 | 
				
			||||||
	hostConfig := *container.hostConfig
 | 
						hostConfig := *container.hostConfig
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ func setPlatformSpecificContainerFields(container *Container, contJSONBase *type
 | 
				
			||||||
	return contJSONBase
 | 
						return contJSONBase
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContainerInspectPre120 is for backwards compatibility with pre v1.20 clients.
 | 
					// ContainerInspectPre120 gets containers for pre 1.20 APIs.
 | 
				
			||||||
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONPre120, error) {
 | 
					func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONPre120, error) {
 | 
				
			||||||
	container, err := daemon.Get(name)
 | 
						container, err := daemon.Get(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -36,8 +36,9 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONP
 | 
				
			||||||
		volumesRW[m.Destination] = m.RW
 | 
							volumesRW[m.Destination] = m.RW
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config := &types.ContainerConfig{
 | 
						config := &types.ContainerConfigPre120{
 | 
				
			||||||
		container.Config,
 | 
							container.Config,
 | 
				
			||||||
 | 
							container.hostConfig.VolumeDriver,
 | 
				
			||||||
		container.hostConfig.Memory,
 | 
							container.hostConfig.Memory,
 | 
				
			||||||
		container.hostConfig.MemorySwap,
 | 
							container.hostConfig.MemorySwap,
 | 
				
			||||||
		container.hostConfig.CPUShares,
 | 
							container.hostConfig.CPUShares,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,3 +10,8 @@ func setPlatformSpecificContainerFields(container *Container, contJSONBase *type
 | 
				
			||||||
func addMountPoints(container *Container) []types.MountPoint {
 | 
					func addMountPoints(container *Container) []types.MountPoint {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContainerInspectPre120 get containers for pre 1.20 APIs.
 | 
				
			||||||
 | 
					func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
 | 
				
			||||||
 | 
						return daemon.ContainerInspect(name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,6 @@ package daemon
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/docker/docker/runconfig"
 | 
					 | 
				
			||||||
	"github.com/docker/docker/volume"
 | 
						"github.com/docker/docker/volume"
 | 
				
			||||||
	"github.com/docker/docker/volume/drivers"
 | 
						"github.com/docker/docker/volume/drivers"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -55,8 +54,7 @@ func TestParseBindMount(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		conf := &runconfig.Config{VolumeDriver: c.driver}
 | 
							m, err := parseBindMount(c.bind, c.mountLabel, c.driver)
 | 
				
			||||||
		m, err := parseBindMount(c.bind, c.mountLabel, conf)
 | 
					 | 
				
			||||||
		if c.fail {
 | 
							if c.fail {
 | 
				
			||||||
			if err == nil {
 | 
								if err == nil {
 | 
				
			||||||
				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
 | 
									t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ func (container *Container) setupMounts() ([]execdriver.Mount, error) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseBindMount validates the configuration of mount information in runconfig is valid.
 | 
					// parseBindMount validates the configuration of mount information in runconfig is valid.
 | 
				
			||||||
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
 | 
					func parseBindMount(spec, mountLabel, volumeDriver string) (*mountPoint, error) {
 | 
				
			||||||
	bind := &mountPoint{
 | 
						bind := &mountPoint{
 | 
				
			||||||
		RW: true,
 | 
							RW: true,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(source) == 0 {
 | 
						if len(source) == 0 {
 | 
				
			||||||
		bind.Driver = config.VolumeDriver
 | 
							bind.Driver = volumeDriver
 | 
				
			||||||
		if len(bind.Driver) == 0 {
 | 
							if len(bind.Driver) == 0 {
 | 
				
			||||||
			bind.Driver = volume.DefaultDriverName
 | 
								bind.Driver = volume.DefaultDriverName
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -325,7 +325,7 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
 | 
				
			||||||
	// 3. Read bind mounts
 | 
						// 3. Read bind mounts
 | 
				
			||||||
	for _, b := range hostConfig.Binds {
 | 
						for _, b := range hostConfig.Binds {
 | 
				
			||||||
		// #10618
 | 
							// #10618
 | 
				
			||||||
		bind, err := parseBindMount(b, container.MountLabel, container.Config)
 | 
							bind, err := parseBindMount(b, container.MountLabel, hostConfig.VolumeDriver)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,6 +80,7 @@ This section lists each version from latest to oldest.  Each listing includes a
 | 
				
			||||||
* `POST /volumes` to create a volume.
 | 
					* `POST /volumes` to create a volume.
 | 
				
			||||||
* `GET /volumes/(name)` get low-level information about a volume.
 | 
					* `GET /volumes/(name)` get low-level information about a volume.
 | 
				
			||||||
* `DELETE /volumes/(name)`remove a volume with the specified name.
 | 
					* `DELETE /volumes/(name)`remove a volume with the specified name.
 | 
				
			||||||
 | 
					* `VolumeDriver` has been moved from config to hostConfig to make the configuration portable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### v1.20 API changes
 | 
					### v1.20 API changes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,8 @@ Create a container
 | 
				
			||||||
             "Ulimits": [{}],
 | 
					             "Ulimits": [{}],
 | 
				
			||||||
             "LogConfig": { "Type": "json-file", "Config": {} },
 | 
					             "LogConfig": { "Type": "json-file", "Config": {} },
 | 
				
			||||||
             "SecurityOpt": [""],
 | 
					             "SecurityOpt": [""],
 | 
				
			||||||
             "CgroupParent": ""
 | 
					             "CgroupParent": "",
 | 
				
			||||||
 | 
						      "VolumeDriver": ""
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -300,6 +301,7 @@ Json Parameters:
 | 
				
			||||||
          Available types: `json-file`, `syslog`, `journald`, `gelf`, `none`.
 | 
					          Available types: `json-file`, `syslog`, `journald`, `gelf`, `none`.
 | 
				
			||||||
          `json-file` logging driver.
 | 
					          `json-file` logging driver.
 | 
				
			||||||
    -   **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.
 | 
					    -   **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.
 | 
				
			||||||
 | 
					    -   **VolumeDriver** - Driver that this container users to mount volumes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Query Parameters:
 | 
					Query Parameters:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,7 +409,8 @@ Return low-level information on the container `id`
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			"SecurityOpt": null,
 | 
								"SecurityOpt": null,
 | 
				
			||||||
			"VolumesFrom": null,
 | 
								"VolumesFrom": null,
 | 
				
			||||||
			"Ulimits": [{}]
 | 
								"Ulimits": [{}],
 | 
				
			||||||
 | 
								"VolumeDriver": ""
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"HostnamePath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname",
 | 
							"HostnamePath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname",
 | 
				
			||||||
		"HostsPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts",
 | 
							"HostsPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,3 +48,65 @@ func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *DockerSuite) TestInspectApiContainerVolumeDriverLegacy(c *check.C) {
 | 
				
			||||||
 | 
						out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cleanedContainerID := strings.TrimSpace(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cases := []string{"1.19", "1.20"}
 | 
				
			||||||
 | 
						for _, version := range cases {
 | 
				
			||||||
 | 
							endpoint := fmt.Sprintf("/v%s/containers/%s/json", version, cleanedContainerID)
 | 
				
			||||||
 | 
							status, body, err := sockRequest("GET", endpoint, nil)
 | 
				
			||||||
 | 
							c.Assert(status, check.Equals, http.StatusOK)
 | 
				
			||||||
 | 
							c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var inspectJSON map[string]interface{}
 | 
				
			||||||
 | 
							if err = json.Unmarshal(body, &inspectJSON); err != nil {
 | 
				
			||||||
 | 
								c.Fatalf("unable to unmarshal body for version %s: %v", version, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							config, ok := inspectJSON["Config"]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								c.Fatal("Unable to find 'Config'")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cfg := config.(map[string]interface{})
 | 
				
			||||||
 | 
							if _, ok := cfg["VolumeDriver"]; !ok {
 | 
				
			||||||
 | 
								c.Fatalf("Api version %s expected to include VolumeDriver in 'Config'", version)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *DockerSuite) TestInspectApiContainerVolumeDriver(c *check.C) {
 | 
				
			||||||
 | 
						out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cleanedContainerID := strings.TrimSpace(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endpoint := fmt.Sprintf("/v1.21/containers/%s/json", cleanedContainerID)
 | 
				
			||||||
 | 
						status, body, err := sockRequest("GET", endpoint, nil)
 | 
				
			||||||
 | 
						c.Assert(status, check.Equals, http.StatusOK)
 | 
				
			||||||
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var inspectJSON map[string]interface{}
 | 
				
			||||||
 | 
						if err = json.Unmarshal(body, &inspectJSON); err != nil {
 | 
				
			||||||
 | 
							c.Fatalf("unable to unmarshal body for version 1.21: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config, ok := inspectJSON["Config"]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							c.Fatal("Unable to find 'Config'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cfg := config.(map[string]interface{})
 | 
				
			||||||
 | 
						if _, ok := cfg["VolumeDriver"]; ok {
 | 
				
			||||||
 | 
							c.Fatal("Api version 1.21 expected to not include VolumeDriver in 'Config'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config, ok = inspectJSON["HostConfig"]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							c.Fatal("Unable to find 'HostConfig'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cfg = config.(map[string]interface{})
 | 
				
			||||||
 | 
						if _, ok := cfg["VolumeDriver"]; !ok {
 | 
				
			||||||
 | 
							c.Fatal("Api version 1.21 expected to include VolumeDriver in 'HostConfig'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,15 +253,11 @@ func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	img := "test-checkbindlocalvolume"
 | 
						img := "test-checkbindlocalvolume"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	args := []string{"--host", s.d.sock()}
 | 
						_, err := buildImageWithOutInDamon(s.d.sock(), img, dockerfile, true)
 | 
				
			||||||
	buildOut, err := buildImageArgs(args, img, dockerfile, true)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	fmt.Println(buildOut)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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")
 | 
						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")
 | 
				
			||||||
	if err != nil {
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
		fmt.Println(out)
 | 
					 | 
				
			||||||
		c.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !strings.Contains(out, expected) {
 | 
						if !strings.Contains(out, expected) {
 | 
				
			||||||
		c.Fatalf("External volume mount failed. Output: %s\n", out)
 | 
							c.Fatalf("External volume mount failed. Output: %s\n", out)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1392,22 +1392,14 @@ func createTmpFile(c *check.C, content string) string {
 | 
				
			||||||
	return filename
 | 
						return filename
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func buildImageArgs(args []string, name, dockerfile string, useCache bool) (string, error) {
 | 
					func buildImageWithOutInDamon(socket string, name, dockerfile string, useCache bool) (string, error) {
 | 
				
			||||||
	id, _, err := buildImageWithOutArgs(args, name, dockerfile, useCache)
 | 
						args := []string{"--host", socket}
 | 
				
			||||||
	return id, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func buildImageWithOutArgs(args []string, name, dockerfile string, useCache bool) (string, string, error) {
 | 
					 | 
				
			||||||
	buildCmd := buildImageCmdArgs(args, name, dockerfile, useCache)
 | 
						buildCmd := buildImageCmdArgs(args, name, dockerfile, useCache)
 | 
				
			||||||
	out, exitCode, err := runCommandWithOutput(buildCmd)
 | 
						out, exitCode, err := runCommandWithOutput(buildCmd)
 | 
				
			||||||
	if err != nil || exitCode != 0 {
 | 
						if err != nil || exitCode != 0 {
 | 
				
			||||||
		return "", out, fmt.Errorf("failed to build the image: %s", out)
 | 
							return out, fmt.Errorf("failed to build the image: %s, error: %v", out, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	id, err := getIDByName(name)
 | 
						return out, nil
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", out, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return id, out, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func buildImageCmdArgs(args []string, name, dockerfile string, useCache bool) *exec.Cmd {
 | 
					func buildImageCmdArgs(args []string, name, dockerfile string, useCache bool) *exec.Cmd {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,6 @@ type Config struct {
 | 
				
			||||||
	Cmd             *stringutils.StrSlice // Command to run when starting the container
 | 
						Cmd             *stringutils.StrSlice // Command to run when starting the container
 | 
				
			||||||
	Image           string                // Name of the image as it was passed by the operator (eg. could be symbolic)
 | 
						Image           string                // Name of the image as it was passed by the operator (eg. could be symbolic)
 | 
				
			||||||
	Volumes         map[string]struct{}   // List of volumes (mounts) used for the container
 | 
						Volumes         map[string]struct{}   // List of volumes (mounts) used for the container
 | 
				
			||||||
	VolumeDriver    string                // Name of the volume driver used to mount volumes
 | 
					 | 
				
			||||||
	WorkingDir      string                // Current directory (PWD) in the command will be launched
 | 
						WorkingDir      string                // Current directory (PWD) in the command will be launched
 | 
				
			||||||
	Entrypoint      *stringutils.StrSlice // Entrypoint to run when starting the container
 | 
						Entrypoint      *stringutils.StrSlice // Entrypoint to run when starting the container
 | 
				
			||||||
	NetworkDisabled bool                  // Is network disabled
 | 
						NetworkDisabled bool                  // Is network disabled
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,11 +32,17 @@ func (w *ContainerConfigWrapper) getHostConfig() *HostConfig {
 | 
				
			||||||
			w.InnerHostConfig.CpusetCpus = hc.CpusetCpus
 | 
								w.InnerHostConfig.CpusetCpus = hc.CpusetCpus
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if hc.VolumeDriver != "" && w.InnerHostConfig.VolumeDriver == "" {
 | 
				
			||||||
 | 
								w.InnerHostConfig.VolumeDriver = hc.VolumeDriver
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hc = w.InnerHostConfig
 | 
							hc = w.InnerHostConfig
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if hc != nil && w.Cpuset != "" && hc.CpusetCpus == "" {
 | 
						if hc != nil {
 | 
				
			||||||
		hc.CpusetCpus = w.Cpuset
 | 
							if w.Cpuset != "" && hc.CpusetCpus == "" {
 | 
				
			||||||
 | 
								hc.CpusetCpus = w.Cpuset
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure NetworkMode has an acceptable value. We do this to ensure
 | 
						// Make sure NetworkMode has an acceptable value. We do this to ensure
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,6 +251,7 @@ type HostConfig struct {
 | 
				
			||||||
	LogConfig        LogConfig             // Configuration of the logs for this container
 | 
						LogConfig        LogConfig             // Configuration of the logs for this container
 | 
				
			||||||
	CgroupParent     string                // Parent cgroup.
 | 
						CgroupParent     string                // Parent cgroup.
 | 
				
			||||||
	ConsoleSize      [2]int                // Initial console size on Windows
 | 
						ConsoleSize      [2]int                // Initial console size on Windows
 | 
				
			||||||
 | 
						VolumeDriver     string                // Name of the volume driver used to mount volumes
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DecodeHostConfig creates a HostConfig based on the specified Reader.
 | 
					// DecodeHostConfig creates a HostConfig based on the specified Reader.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -322,7 +322,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 | 
				
			||||||
		Entrypoint:      entrypoint,
 | 
							Entrypoint:      entrypoint,
 | 
				
			||||||
		WorkingDir:      *flWorkingDir,
 | 
							WorkingDir:      *flWorkingDir,
 | 
				
			||||||
		Labels:          convertKVStringsToMap(labels),
 | 
							Labels:          convertKVStringsToMap(labels),
 | 
				
			||||||
		VolumeDriver:    *flVolumeDriver,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hostConfig := &HostConfig{
 | 
						hostConfig := &HostConfig{
 | 
				
			||||||
| 
						 | 
					@ -362,6 +361,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 | 
				
			||||||
		Ulimits:          flUlimits.GetList(),
 | 
							Ulimits:          flUlimits.GetList(),
 | 
				
			||||||
		LogConfig:        LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
 | 
							LogConfig:        LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
 | 
				
			||||||
		CgroupParent:     *flCgroupParent,
 | 
							CgroupParent:     *flCgroupParent,
 | 
				
			||||||
 | 
							VolumeDriver:     *flVolumeDriver,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	applyExperimentalFlags(expFlags, config, hostConfig)
 | 
						applyExperimentalFlags(expFlags, config, hostConfig)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue