diff --git a/docs/resources/container.md b/docs/resources/container.md index 109c560e..ed5aa476 100644 --- a/docs/resources/container.md +++ b/docs/resources/container.md @@ -127,7 +127,7 @@ Required: Optional: -- `container_path` (String) The path in the container where the device will be bound. +- `container_path` (String) The path in the container where the device will be bound. If not set, it defaults to the value of `host_path`. - `permissions` (String) The cgroup permissions given to the container to access the device. Defaults to `rwm`. diff --git a/docs/v3_v4_migration.md b/docs/v3_v4_migration.md index 4c4a254f..24a87b0c 100644 --- a/docs/v3_v4_migration.md +++ b/docs/v3_v4_migration.md @@ -7,10 +7,12 @@ Bump of minimum terraform version to `1.1.5` or newer. This is done as part of i ## `docker_container` -Reworked handling of stopped containers: If a container is stopped (or exists for some other reason), Terraform now correctly shows a change on `plan` and restarts the container on `apply`. To trigger the change, the `must_run` attribute is exploited. `must_run` defaults to `true` and when a container is in a not running state, the provider sets `must_run` to `false` to trigger a state change. -This fixes the cases where a stopped container gets deleted during a `plan` +**Reworked handling of stopped containers:** If a container is stopped (or exists for some other reason), Terraform now correctly shows a change on `plan` and restarts the container on `apply`. To trigger the change, the `must_run` attribute is exploited. `must_run` defaults to `true` and when a container is in a not running state, the provider sets `must_run` to `false` to trigger a state change. This fixes the cases where a stopped container gets deleted during a `plan`. No migration needed. + +`ports` - **Ports on stopped container force replacement:** This is now fixed through https://github.com/kreuzwerker/terraform-provider-docker/pull/842, no migration needed. + +`devices` - **Fix the replacement of devices** Using `devices` blocks with not all 3 attributes now does not trigger resource replacements anymore. This fixes https://github.com/kreuzwerker/terraform-provider-docker/issues/603. -* Fixes Ports on stopped container force replacement bug (https://github.com/kreuzwerker/terraform-provider-docker/issues/77) ## `docker_network` diff --git a/internal/provider/resource_docker_container.go b/internal/provider/resource_docker_container.go index fe773f11..bd764f00 100644 --- a/internal/provider/resource_docker_container.go +++ b/internal/provider/resource_docker_container.go @@ -649,7 +649,7 @@ func resourceDockerContainer() *schema.Resource { }, "container_path": { Type: schema.TypeString, - Description: "The path in the container where the device will be bound.", + Description: "The path in the container where the device will be bound. If not set, it defaults to the value of `host_path`.", Optional: true, ForceNew: true, }, @@ -658,6 +658,7 @@ func resourceDockerContainer() *schema.Resource { Description: "The cgroup permissions given to the container to access the device. Defaults to `rwm`.", Optional: true, ForceNew: true, + Default: "rwm", }, }, }, diff --git a/internal/provider/resource_docker_container_funcs.go b/internal/provider/resource_docker_container_funcs.go index 7a9e4ee8..f269c38a 100644 --- a/internal/provider/resource_docker_container_funcs.go +++ b/internal/provider/resource_docker_container_funcs.go @@ -797,7 +797,7 @@ func resourceDockerContainerRead(ctx context.Context, d *schema.ResourceData, me // https://github.com/terraform-providers/terraform-provider-docker/pull/269 d.Set("privileged", container.HostConfig.Privileged) - if err = d.Set("devices", flattenDevices(container.HostConfig.Devices)); err != nil { + if err = d.Set("devices", flattenDevices(container.HostConfig.Devices, d.Get("devices").(*schema.Set))); err != nil { log.Printf("[WARN] failed to set container hostconfig devices from API: %s", err) } // "destroy_grace_seconds" can't be imported diff --git a/internal/provider/resource_docker_container_structures.go b/internal/provider/resource_docker_container_structures.go index 6aee1f73..0883cd9b 100644 --- a/internal/provider/resource_docker_container_structures.go +++ b/internal/provider/resource_docker_container_structures.go @@ -241,12 +241,9 @@ func deviceSetToDockerDevices(devices *schema.Set) []container.DeviceMapping { containerPath := deviceMap["container_path"].(string) permissions := deviceMap["permissions"].(string) - switch { - case len(containerPath) == 0: + // Default container_path to host_path if not specified + if len(containerPath) == 0 { containerPath = hostPath - fallthrough - case len(permissions) == 0: - permissions = "rwm" } device := container.DeviceMapping{ @@ -338,14 +335,23 @@ func flattenUlimits(in []*units.Ulimit) []interface{} { return ulimits } -func flattenDevices(in []container.DeviceMapping) []interface{} { +func flattenDevices(in []container.DeviceMapping, configuredDevices *schema.Set) []interface{} { devices := make([]interface{}, len(in)) + list := configuredDevices.List() for i, device := range in { - devices[i] = map[string]interface{}{ - "host_path": device.PathOnHost, - "container_path": device.PathInContainer, - "permissions": device.CgroupPermissions, + configuredDevice := list[i].(map[string]interface{}) + + deviceMap := map[string]interface{}{ + "host_path": device.PathOnHost, + "permissions": device.CgroupPermissions, } + + // Only set container_path if it was explicitly configured by the user + if value, ok := configuredDevice["container_path"].(string); ok && value != "" { + deviceMap["container_path"] = device.PathInContainer + } + + devices[i] = deviceMap } return devices diff --git a/testdata/resources/docker_container/testAccDockerContainerDeviceConfig.tf b/testdata/resources/docker_container/testAccDockerContainerDeviceConfig.tf index c7599854..b438cea4 100644 --- a/testdata/resources/docker_container/testAccDockerContainerDeviceConfig.tf +++ b/testdata/resources/docker_container/testAccDockerContainerDeviceConfig.tf @@ -11,4 +11,8 @@ resource "docker_container" "foo" { container_path = "/dev/zero_test" permissions = "rwm" } + + devices { + host_path = "/dev/null" + } }