From d878091f95a384f80b40ca4ef4b7ae4d3e7c4095 Mon Sep 17 00:00:00 2001 From: Xander Flood Date: Thu, 14 Nov 2019 17:44:58 -0500 Subject: [PATCH] refactor migration code and fix a couple tests --- docker/label.go | 27 +++++++---------- docker/label_migration.go | 40 ++++++++++++++++++++++++++ docker/resource_docker_container.go | 21 +++----------- docker/resource_docker_network.go | 5 +--- docker/resource_docker_secret.go | 5 +--- docker/resource_docker_service.go | 10 +++++++ docker/resource_docker_service_test.go | 1 - docker/resource_docker_volume.go | 5 +--- docker/resource_docker_volume_test.go | 4 +-- 9 files changed, 70 insertions(+), 48 deletions(-) create mode 100644 docker/label_migration.go diff --git a/docker/label.go b/docker/label.go index b7213ba9..dc49ac5c 100644 --- a/docker/label.go +++ b/docker/label.go @@ -33,6 +33,17 @@ func hashStringLabel(str string) int { return schema.HashString(str) } +func mapStringInterfaceToLabelSet(labels map[string]interface{}) *schema.Set { + var mapped []interface{} + for k, v := range labels { + mapped = append(mapped, map[string]interface{}{ + "label": k, + "value": fmt.Sprintf("%v", v), + }) + } + return schema.NewSet(hashLabel, mapped) +} + func mapToLabelSet(labels map[string]string) *schema.Set { var mapped []interface{} for k, v := range labels { @@ -59,22 +70,6 @@ var labelSchema = &schema.Resource{ }, } -//unfortunately, _one_ of the several place that the old label schema was -//used specified that the keys had to be strings, while the others allowed -//any type of key and coerced them into strings. -func upgradeLabelMapFromV0ToV1(labelMap map[string]interface{}) []map[string]string { - var migratedState []map[string]string - - for l, v := range labelMap { - migratedState = append(migratedState, map[string]string{ - "label": l, - "value": fmt.Sprintf("%v", v), - }) - } - - return migratedState -} - //gatherImmediateSubkeys given an incomplete attribute identifier, find all //the strings (if any) that appear after this one in the various dot-separated //identifiers. diff --git a/docker/label_migration.go b/docker/label_migration.go new file mode 100644 index 00000000..280d4459 --- /dev/null +++ b/docker/label_migration.go @@ -0,0 +1,40 @@ +package docker + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func replaceLabelsMapFieldWithSetField(rawState map[string]interface{}) map[string]interface{} { + labelMap := rawState["labels"].(map[string]interface{}) + rawState["labels"] = mapStringInterfaceToLabelSet(labelMap) + + return rawState +} + +func migrateContainerLabels(rawState map[string]interface{}) map[string]interface{} { + rawState = replaceLabelsMapFieldWithSetField(rawState) + + mounts := rawState["mounts"].(*schema.Set).List() + newMounts := make([]interface{}, len(mounts)) + for i, mountI := range newMounts { + mount := mountI.(map[string]interface{}) + volumeOptions := mount["volume_options"].([]interface{})[0].(map[string]interface{}) + + mount["volume_options"] = replaceLabelsMapFieldWithSetField(volumeOptions) + newMounts[i] = mount + } + rawState["mounts"] = newMounts + + return rawState +} + +func migrateServiceLabels(rawState map[string]interface{}) map[string]interface{} { + rawState = replaceLabelsMapFieldWithSetField(rawState) + + taskSpec := rawState["task_spec"].([]interface{})[0].(map[string]interface{}) + containerSpec := taskSpec["container_spec"].([]interface{})[0].(map[string]interface{}) + taskSpec["container_spec"] = migrateContainerLabels(containerSpec) + + rawState["task_spec"] = taskSpec + return rawState +} diff --git a/docker/resource_docker_container.go b/docker/resource_docker_container.go index a42d6c93..089fbf24 100644 --- a/docker/resource_docker_container.go +++ b/docker/resource_docker_container.go @@ -19,24 +19,11 @@ func resourceDockerContainer() *schema.Resource { Version: 1, Type: resourceDockerContainerV1().CoreConfigSchema().ImpliedType(), Upgrade: func(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { - labelMap := rawState["labels"].(map[string]interface{}) - rawState["labels"] = upgradeLabelMapFromV0ToV1(labelMap) + //TODO do the ohter V0-to-V1 migration, unless we're okay + //with breaking for users who straggled on their docker + //provider version - mounts := rawState["mounts"].(*schema.Set).List() - newMounts := make([]interface{}, len(mounts)) - for i, mountI := range newMounts { - mount := mountI.(map[string]interface{}) - vo := mount["volume_options"].([]interface{})[0].(map[string]interface{}) - - labelMap = vo["labels"].(map[string]interface{}) - vo["labels"] = upgradeLabelMapFromV0ToV1(labelMap) - - mount["volume_options"] = vo - newMounts[i] = mount - } - rawState["mounts"] = newMounts - - return rawState, nil + return migrateContainerLabels(rawState), nil }, }, }, diff --git a/docker/resource_docker_network.go b/docker/resource_docker_network.go index 9d4ebba3..b028ec7f 100644 --- a/docker/resource_docker_network.go +++ b/docker/resource_docker_network.go @@ -125,10 +125,7 @@ func resourceDockerNetwork() *schema.Resource { Version: 0, Type: resourceDockerNetworkV0().CoreConfigSchema().ImpliedType(), Upgrade: func(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { - labelMap := rawState["labels"].(map[string]interface{}) - rawState["labels"] = upgradeLabelMapFromV0ToV1(labelMap) - - return rawState, nil + return replaceLabelsMapFieldWithSetField(rawState), nil }, }, }, diff --git a/docker/resource_docker_secret.go b/docker/resource_docker_secret.go index 35c8f6bb..f3bfca69 100644 --- a/docker/resource_docker_secret.go +++ b/docker/resource_docker_secret.go @@ -46,10 +46,7 @@ func resourceDockerSecret() *schema.Resource { Version: 0, Type: resourceDockerSecretV0().CoreConfigSchema().ImpliedType(), Upgrade: func(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { - labelMap := rawState["labels"].(map[string]interface{}) - rawState["labels"] = upgradeLabelMapFromV0ToV1(labelMap) - - return rawState, nil + return replaceLabelsMapFieldWithSetField(rawState), nil }, }, }, diff --git a/docker/resource_docker_service.go b/docker/resource_docker_service.go index 2373864c..c3578e08 100644 --- a/docker/resource_docker_service.go +++ b/docker/resource_docker_service.go @@ -901,6 +901,16 @@ func resourceDockerService() *schema.Resource { }, }, }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Version: 0, + Type: resourceDockerServiceV0().CoreConfigSchema().ImpliedType(), + Upgrade: func(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return migrateServiceLabels(rawState), nil + }, + }, + }, } } diff --git a/docker/resource_docker_service_test.go b/docker/resource_docker_service_test.go index 8311c49d..3ea3f583 100644 --- a/docker/resource_docker_service_test.go +++ b/docker/resource_docker_service_test.go @@ -402,7 +402,6 @@ func TestAccDockerService_fullSpec(t *testing.T) { resource.TestCheckResourceAttr("docker_service.foo", "name", "tftest-service-basic"), testCheckLabelMap("docker_service.foo", "labels", map[string]string{"servicelabel": "true"}), resource.TestMatchResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:v1.*`)), - resource.TestCheckResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.labels.foo", "bar"), testCheckLabelMap("docker_service.foo", "task_spec.0.container_spec.0.labels", map[string]string{"foo": "bar"}), resource.TestCheckResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.command.0", "ls"), resource.TestCheckResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.args.0", "-las"), diff --git a/docker/resource_docker_volume.go b/docker/resource_docker_volume.go index a4006edc..15719e03 100644 --- a/docker/resource_docker_volume.go +++ b/docker/resource_docker_volume.go @@ -54,10 +54,7 @@ func resourceDockerVolume() *schema.Resource { Version: 0, Type: resourceDockerVolumeV0().CoreConfigSchema().ImpliedType(), Upgrade: func(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { - labelMap := rawState["labels"].(map[string]interface{}) - rawState["labels"] = upgradeLabelMapFromV0ToV1(labelMap) - - return rawState, nil + return replaceLabelsMapFieldWithSetField(rawState), nil }, }, }, diff --git a/docker/resource_docker_volume_test.go b/docker/resource_docker_volume_test.go index 5898332c..fd3256f8 100644 --- a/docker/resource_docker_volume_test.go +++ b/docker/resource_docker_volume_test.go @@ -94,11 +94,11 @@ func testAccVolumeLabel(volume *types.Volume, name string, value string) resourc const testAccDockerVolumeLabelsConfig = ` resource "docker_volume" "foo" { name = "test_foo" - labels = { + labels { label = "com.docker.compose.project" value = "test" } - labels = { + labels { label = "com.docker.compose.volume" value = "foo" }