provider/docker: Mount named volumes in containers
This adds support for specifying named volumes for mounting in a `docker_container` resource.
This commit is contained in:
parent
52d1e214fb
commit
4b7a98584a
|
@ -137,6 +137,20 @@ func resourceDockerContainer() *schema.Resource {
|
|||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
||||
value := v.(string)
|
||||
if !regexp.MustCompile(`^/`).MatchString(value) {
|
||||
es = append(es, fmt.Errorf(
|
||||
"%q must be an absolute path", k))
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
|
||||
"volume_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"read_only": &schema.Schema{
|
||||
|
@ -383,6 +397,10 @@ func resourceDockerVolumesHash(v interface{}) int {
|
|||
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
||||
}
|
||||
|
||||
if v, ok := m["volume_name"]; ok {
|
||||
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
||||
}
|
||||
|
||||
if v, ok := m["read_only"]; ok {
|
||||
buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
|
||||
}
|
||||
|
|
|
@ -353,7 +353,10 @@ func volumeSetToDockerVolumes(volumes *schema.Set) (map[string]struct{}, []strin
|
|||
volume := volumeInt.(map[string]interface{})
|
||||
fromContainer := volume["from_container"].(string)
|
||||
containerPath := volume["container_path"].(string)
|
||||
hostPath := volume["host_path"].(string)
|
||||
volumeName := volume["volume_name"].(string)
|
||||
if len(volumeName) == 0 {
|
||||
volumeName = volume["host_path"].(string)
|
||||
}
|
||||
readOnly := volume["read_only"].(bool)
|
||||
|
||||
switch {
|
||||
|
@ -363,13 +366,13 @@ func volumeSetToDockerVolumes(volumes *schema.Set) (map[string]struct{}, []strin
|
|||
return retVolumeMap, retHostConfigBinds, retVolumeFromContainers, errors.New("Both a container and a path specified in a volume entry")
|
||||
case len(fromContainer) != 0:
|
||||
retVolumeFromContainers = append(retVolumeFromContainers, fromContainer)
|
||||
case len(hostPath) != 0:
|
||||
case len(volumeName) != 0:
|
||||
readWrite := "rw"
|
||||
if readOnly {
|
||||
readWrite = "ro"
|
||||
}
|
||||
retVolumeMap[containerPath] = struct{}{}
|
||||
retHostConfigBinds = append(retHostConfigBinds, hostPath+":"+containerPath+":"+readWrite)
|
||||
retHostConfigBinds = append(retHostConfigBinds, volumeName+":"+containerPath+":"+readWrite)
|
||||
default:
|
||||
retVolumeMap[containerPath] = struct{}{}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,48 @@ func TestAccDockerContainer_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccDockerContainer_volume(t *testing.T) {
|
||||
var c dc.Container
|
||||
|
||||
testCheck := func(*terraform.State) error {
|
||||
if len(c.Mounts) != 2 {
|
||||
return fmt.Errorf("Incorrect number of mounts: expected 2, got %d", len(c.Mounts))
|
||||
}
|
||||
|
||||
for _, v := range c.Mounts {
|
||||
if v.Name != "testAccDockerContainerVolume_volume" {
|
||||
continue
|
||||
}
|
||||
|
||||
if v.Destination != "/tmp/volume" {
|
||||
return fmt.Errorf("Bad destination on mount: expected /tmp/volume, got %q", v.Destination)
|
||||
}
|
||||
|
||||
if v.Mode != "rw" {
|
||||
return fmt.Errorf("Bad mode on mount: expected rw, got %q", v.Mode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("Mount for testAccDockerContainerVolume_volume not found")
|
||||
}
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDockerContainerVolumeConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccContainerRunning("docker_container.foo", &c),
|
||||
testCheck,
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDockerContainer_customized(t *testing.T) {
|
||||
var c dc.Container
|
||||
|
||||
|
@ -145,6 +187,27 @@ resource "docker_container" "foo" {
|
|||
}
|
||||
`
|
||||
|
||||
const testAccDockerContainerVolumeConfig = `
|
||||
resource "docker_image" "foo" {
|
||||
name = "nginx:latest"
|
||||
}
|
||||
|
||||
resource "docker_volume" "foo" {
|
||||
name = "testAccDockerContainerVolume_volume"
|
||||
}
|
||||
|
||||
resource "docker_container" "foo" {
|
||||
name = "tf-test"
|
||||
image = "${docker_image.foo.latest}"
|
||||
|
||||
volumes {
|
||||
volume_name = "${docker_volume.foo.name}"
|
||||
container_path = "/tmp/volume"
|
||||
read_only = false
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDockerContainerCustomizedConfig = `
|
||||
resource "docker_image" "foo" {
|
||||
name = "nginx:latest"
|
||||
|
|
|
@ -107,13 +107,17 @@ the following:
|
|||
|
||||
* `from_container` - (Optional, string) The container where the volume is
|
||||
coming from.
|
||||
* `container_path` - (Optional, string) The path in the container where the
|
||||
volume will be mounted.
|
||||
* `host_path` - (Optional, string) The path on the host where the volume
|
||||
is coming from.
|
||||
* `volume_name` - (Optional, string) The name of the docker volume which
|
||||
should be mounted.
|
||||
* `container_path` - (Optional, string) The path in the container where the
|
||||
volume will be mounted.
|
||||
* `read_only` - (Optional, bool) If true, this volume will be readonly.
|
||||
Defaults to false.
|
||||
|
||||
One of `from_container`, `host_path` or `volume_name` must be set.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
|
Loading…
Reference in New Issue