mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #1496 from xdissent/1351-volumes-from-before-volumes
* Runtime: Apply volumes-from before creating volumes
This commit is contained in:
commit
631c449183
2 changed files with 99 additions and 30 deletions
64
container.go
64
container.go
|
@ -577,40 +577,12 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||||
binds[path.Clean(dst)] = bindMap
|
binds[path.Clean(dst)] = bindMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: evaluate volumes-from before individual volumes, so that the latter can override the former.
|
|
||||||
// Create the requested volumes volumes
|
|
||||||
if container.Volumes == nil || len(container.Volumes) == 0 {
|
if container.Volumes == nil || len(container.Volumes) == 0 {
|
||||||
container.Volumes = make(map[string]string)
|
container.Volumes = make(map[string]string)
|
||||||
container.VolumesRW = make(map[string]bool)
|
container.VolumesRW = make(map[string]bool)
|
||||||
|
|
||||||
for volPath := range container.Config.Volumes {
|
|
||||||
volPath = path.Clean(volPath)
|
|
||||||
// If an external bind is defined for this volume, use that as a source
|
|
||||||
if bindMap, exists := binds[volPath]; exists {
|
|
||||||
container.Volumes[volPath] = bindMap.SrcPath
|
|
||||||
if strings.ToLower(bindMap.Mode) == "rw" {
|
|
||||||
container.VolumesRW[volPath] = true
|
|
||||||
}
|
|
||||||
// Otherwise create an directory in $ROOT/volumes/ and use that
|
|
||||||
} else {
|
|
||||||
c, err := container.runtime.volumes.Create(nil, container, "", "", nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
srcPath, err := c.layer()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
container.Volumes[volPath] = srcPath
|
|
||||||
container.VolumesRW[volPath] = true // RW by default
|
|
||||||
}
|
|
||||||
// Create the mountpoint
|
|
||||||
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply volumes from another container if requested
|
||||||
if container.Config.VolumesFrom != "" {
|
if container.Config.VolumesFrom != "" {
|
||||||
c := container.runtime.Get(container.Config.VolumesFrom)
|
c := container.runtime.Get(container.Config.VolumesFrom)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
|
@ -618,7 +590,7 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||||
}
|
}
|
||||||
for volPath, id := range c.Volumes {
|
for volPath, id := range c.Volumes {
|
||||||
if _, exists := container.Volumes[volPath]; exists {
|
if _, exists := container.Volumes[volPath]; exists {
|
||||||
return fmt.Errorf("The requested volume %s overlap one of the volume of the container %s", volPath, c.ID)
|
continue
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -630,6 +602,38 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the requested volumes if they don't exist
|
||||||
|
for volPath := range container.Config.Volumes {
|
||||||
|
volPath = path.Clean(volPath)
|
||||||
|
// Skip existing volumes
|
||||||
|
if _, exists := container.Volumes[volPath]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If an external bind is defined for this volume, use that as a source
|
||||||
|
if bindMap, exists := binds[volPath]; exists {
|
||||||
|
container.Volumes[volPath] = bindMap.SrcPath
|
||||||
|
if strings.ToLower(bindMap.Mode) == "rw" {
|
||||||
|
container.VolumesRW[volPath] = true
|
||||||
|
}
|
||||||
|
// Otherwise create an directory in $ROOT/volumes/ and use that
|
||||||
|
} else {
|
||||||
|
c, err := container.runtime.volumes.Create(nil, container, "", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srcPath, err := c.layer()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
container.Volumes[volPath] = srcPath
|
||||||
|
container.VolumesRW[volPath] = true // RW by default
|
||||||
|
}
|
||||||
|
// Create the mountpoint
|
||||||
|
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := container.generateLXCConfig(); err != nil {
|
if err := container.generateLXCConfig(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1283,6 +1283,71 @@ func TestRestartWithVolumes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for #1351
|
||||||
|
func TestVolumesFromWithVolumes(t *testing.T) {
|
||||||
|
runtime := mkRuntime(t)
|
||||||
|
defer nuke(runtime)
|
||||||
|
|
||||||
|
container, err := NewBuilder(runtime).Create(&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
||||||
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container)
|
||||||
|
|
||||||
|
for key := range container.Config.Volumes {
|
||||||
|
if key != "/test" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = container.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := container.Volumes["/test"]
|
||||||
|
if expected == "" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
container2, err := NewBuilder(runtime).Create(
|
||||||
|
&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"cat", "/test/foo"},
|
||||||
|
VolumesFrom: container.ID,
|
||||||
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container2)
|
||||||
|
|
||||||
|
output, err := container2.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(output) != "bar" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if container.Volumes["/test"] != container2.Volumes["/test"] {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure it restarts successfully
|
||||||
|
_, err = container2.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
|
func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
Loading…
Add table
Reference in a new issue