refactor migration code and fix a couple tests

This commit is contained in:
Xander Flood 2019-11-14 17:44:58 -05:00
parent b9d61dc535
commit d878091f95
9 changed files with 70 additions and 48 deletions

View file

@ -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.

40
docker/label_migration.go Normal file
View file

@ -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
}

View file

@ -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
},
},
},

View file

@ -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
},
},
},

View file

@ -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
},
},
},

View file

@ -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
},
},
},
}
}

View file

@ -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"),

View file

@ -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
},
},
},

View file

@ -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"
}