diff --git a/README.md b/README.md
index 6be3b5f2..80a853ab 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,9 @@
The documentation for the provider is available on the [Terraform Registry](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs).
-Do you want to migrate from `v2.x` to `v3.x`? Please read the [migration guide](docs/v2_v3_migration.md)
+Migration guides:
+* Do you want to migrate from `v3.x` to `v4.x`? Please read the [V3 - V4 migration guide](docs/v3_v4_migration.md)
+* Do you want to migrate from `v2.x` to `v3.x`? Please read the [V2 - V3 migration guide](docs/v2_v3_migration.md)
## Example usage
diff --git a/docs/resources/network.md b/docs/resources/network.md
index fe26da50..06d9443c 100644
--- a/docs/resources/network.md
+++ b/docs/resources/network.md
@@ -28,7 +28,6 @@ resource "docker_network" "private_network" {
### Optional
- `attachable` (Boolean) Enable manual container attachment to the network.
-- `check_duplicate` (Boolean, Deprecated) Requests daemon to check for networks with same name.
- `driver` (String) The driver of the Docker network. Possible values are `bridge`, `host`, `overlay`, `macvlan`. See [network docs](https://docs.docker.com/network/#network-drivers) for more details.
- `ingress` (Boolean) Create swarm routing-mesh network. Defaults to `false`.
- `internal` (Boolean) Whether the network is internal.
diff --git a/docs/resources/service.md b/docs/resources/service.md
index 403909fd..bcf30ab0 100644
--- a/docs/resources/service.md
+++ b/docs/resources/service.md
@@ -558,14 +558,12 @@ Optional:
### Nested Schema for `task_spec.networks_advanced`
-Required:
-
-- `name` (String) The name/id of the network.
-
Optional:
- `aliases` (Set of String) The network aliases of the container in the specific network.
- `driver_opts` (Set of String) An array of driver options for the network, e.g. `opts1=value`
+- `id` (String) The id of the docker network to use. Please use `docker_network.id`. Using the name attribute of the docker network will lead to constant replacements.
+- `name` (String, Deprecated) Deprecated attribute. The name/id of the docker network. Conflicts with `id` attribute.
diff --git a/docs/v3_v4_migration.md b/docs/v3_v4_migration.md
new file mode 100644
index 00000000..bb056109
--- /dev/null
+++ b/docs/v3_v4_migration.md
@@ -0,0 +1,18 @@
+# V3 to V4 Migration Guide
+
+
+## `docker_network`
+
+Removed attributes:
+
+* `check_duplicate`
+
+## `docker_service`
+
+New attribute:
+
+* `networks_advanced.id`
+
+Deprecated attribute:
+
+* `networks_advanced.name`: Replaced by `id` attribute to make it clear that the `docker_network.id` needs to be used to prevent constant recreation of the service
\ No newline at end of file
diff --git a/internal/provider/resource_docker_network.go b/internal/provider/resource_docker_network.go
index 29594c5c..0dc88eee 100644
--- a/internal/provider/resource_docker_network.go
+++ b/internal/provider/resource_docker_network.go
@@ -37,14 +37,6 @@ func resourceDockerNetwork() *schema.Resource {
Elem: labelSchema,
},
- "check_duplicate": {
- Type: schema.TypeBool,
- Description: "Requests daemon to check for networks with same name.",
- Optional: true,
- ForceNew: true,
- Deprecated: "This option is deprecated and will be removed in a future version. The Docker daemon will always check for duplicate networks.",
- },
-
"driver": {
Type: schema.TypeString,
Description: "The driver of the Docker network. Possible values are `bridge`, `host`, `overlay`, `macvlan`. See [network docs](https://docs.docker.com/network/#network-drivers) for more details.",
diff --git a/internal/provider/resource_docker_network_funcs.go b/internal/provider/resource_docker_network_funcs.go
index c2bbbc79..494c07c0 100644
--- a/internal/provider/resource_docker_network_funcs.go
+++ b/internal/provider/resource_docker_network_funcs.go
@@ -78,7 +78,6 @@ func resourceDockerNetworkCreate(ctx context.Context, d *schema.ResourceData, me
}
d.SetId(retNetwork.ID)
- // d.Set("check_duplicate") TODO mavogel
return resourceDockerNetworkRead(ctx, d, meta)
}
diff --git a/internal/provider/resource_docker_service.go b/internal/provider/resource_docker_service.go
index 9c0d3f5a..39d0095b 100644
--- a/internal/provider/resource_docker_service.go
+++ b/internal/provider/resource_docker_service.go
@@ -700,9 +700,16 @@ func resourceDockerService() *schema.Resource {
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
- Description: "The name/id of the network.",
- Required: true,
+ Description: "Deprecated attribute. The name/id of the docker network. Conflicts with `id` attribute.",
ForceNew: true,
+ Optional: true,
+ Deprecated: "Use the id attribute.",
+ },
+ "id": {
+ Type: schema.TypeString,
+ Description: "The id of the docker network to use. Please use `docker_network.id`. Using the name attribute of the docker network will lead to constant replacements.",
+ ForceNew: true,
+ Optional: true,
},
"aliases": {
Type: schema.TypeSet,
diff --git a/internal/provider/resource_docker_service_structures.go b/internal/provider/resource_docker_service_structures.go
index f842d4cb..c626a3f2 100644
--- a/internal/provider/resource_docker_service_structures.go
+++ b/internal/provider/resource_docker_service_structures.go
@@ -1,6 +1,7 @@
package provider
import (
+ "fmt"
"log"
"os"
"strconv"
@@ -515,7 +516,7 @@ func flattenTaskNetworksAdvanced(in []swarm.NetworkAttachmentConfig) *schema.Set
out := make([]interface{}, len(in))
for i, v := range in {
m := make(map[string]interface{})
- m["name"] = v.Target
+ m["id"] = v.Target
m["driver_opts"] = stringSliceToSchemaSet(mapTypeMapValsToStringSlice(mapStringStringToMapStringInterface(v.DriverOpts)))
if len(v.Aliases) > 0 {
m["aliases"] = stringSliceToSchemaSet(v.Aliases)
@@ -1112,7 +1113,14 @@ func createServiceAdvancedNetworks(v interface{}) ([]swarm.NetworkAttachmentConf
if len(v.(*schema.Set).List()) > 0 {
for _, rawNetwork := range v.(*schema.Set).List() {
rawNetwork := rawNetwork.(map[string]interface{})
- networkID := rawNetwork["name"].(string)
+ networkID := ""
+ if id, ok := rawNetwork["id"]; ok && id.(string) != "" {
+ networkID = id.(string)
+ } else if name, ok := rawNetwork["name"]; ok && name.(string) != "" {
+ networkID = name.(string)
+ } else {
+ return networks, fmt.Errorf("network 'name' or 'id' must be specified")
+ }
networkAliases := stringSetToStringSlice(rawNetwork["aliases"].(*schema.Set))
network := swarm.NetworkAttachmentConfig{
Target: networkID,
diff --git a/testdata/resources/docker_service/testAccDockerServiceFullSpec.tf b/testdata/resources/docker_service/testAccDockerServiceFullSpec.tf
index 53df8582..809dffec 100644
--- a/testdata/resources/docker_service/testAccDockerServiceFullSpec.tf
+++ b/testdata/resources/docker_service/testAccDockerServiceFullSpec.tf
@@ -177,7 +177,7 @@ resource "docker_service" "foo" {
runtime = "container"
networks_advanced {
- name = docker_network.test_network.id
+ id = docker_network.test_network.id
aliases = ["tftest-foobar"]
driver_opts = [
"foo=bar"