Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/storage_share: switching the state migration over to 0.12 format #3882

Merged
merged 1 commit into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion azurerm/resource_arm_storage_share.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,19 @@ func resourceArmStorageShare() *schema.Resource {
State: schema.ImportStatePassthrough,
},
SchemaVersion: 2,
MigrateState: resourceStorageShareMigrateState,
StateUpgraders: []schema.StateUpgrader{
{
// this should have been applied from pre-0.12 migration system; backporting just in-case
Type: resourceStorageShareStateResourceV0V1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceStorageShareStateUpgradeV0ToV1,
Version: 0,
},
{
Type: resourceStorageShareStateResourceV0V1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceStorageShareStateUpgradeV1ToV2,
Version: 1,
},
},

Schema: map[string]*schema.Schema{
"name": {
Expand Down
92 changes: 53 additions & 39 deletions azurerm/resource_arm_storage_share_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,76 @@ package azurerm
import (
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
)

func resourceStorageShareMigrateState(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
switch v {
case 0:
log.Println("[INFO] Found AzureRM Storage Share State v0; migrating to v1")
return migrateStorageShareStateV0toV1(is)
case 1:
log.Println("[INFO] Found AzureRM Storage Share State v1; migrating to v2")
return migrateStorageShareStateV1toV2(is, meta)
default:
return is, fmt.Errorf("Unexpected schema version: %d", v)
// the schema schema was used for both V0 and V1
func resourceStorageShareStateResourceV0V1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateArmStorageShareName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I believe you can remove extraneous elements like ValidateFunc, ForceNew, Required, etc. from these old schema definitions since the state upgraders only need the type information, but either which way though!

},
"resource_group_name": azure.SchemaResourceGroupName(),
"storage_account_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"quota": {
Type: schema.TypeInt,
Optional: true,
Default: 5120,
ValidateFunc: validation.IntBetween(1, 5120),
},
"url": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func migrateStorageShareStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
if is.Empty() {
log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
return is, nil
}

log.Printf("[DEBUG] ARM Storage Share Attributes before Migration: %#v", is.Attributes)
func resourceStorageShareStateUpgradeV0ToV1(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
shareName := rawState["name"].(string)
resourceGroup := rawState["resource_group_name"].(string)
accountName := rawState["storage_account_name"].(string)

name := is.Attributes["name"]
resourceGroupName := is.Attributes["resource_group_name"]
storageAccountName := is.Attributes["storage_account_name"]
newID := fmt.Sprintf("%s/%s/%s", name, resourceGroupName, storageAccountName)
is.Attributes["id"] = newID
is.ID = newID
id := rawState["id"].(string)
newResourceID := fmt.Sprintf("%s/%s/%s", shareName, resourceGroup, accountName)
log.Printf("[DEBUG] Updating ID from %q to %q", id, newResourceID)

log.Printf("[DEBUG] ARM Storage Share Attributes after State Migration: %#v", is.Attributes)

return is, nil
rawState["id"] = newResourceID
return rawState, nil
}

func migrateStorageShareStateV1toV2(is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
if is.Empty() {
log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
return is, nil
func resourceStorageShareStateUpgradeV1ToV2(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
id := rawState["id"].(string)

// name/resourceGroup/accountName
parsedId := strings.Split(id, "/")
if len(parsedId) != 3 {
return rawState, fmt.Errorf("Expected 3 segments in the ID but got %d", len(parsedId))
}

log.Printf("[DEBUG] ARM Storage Share Attributes before Migration: %#v", is.Attributes)
shareName := parsedId[0]
accountName := parsedId[2]

environment := meta.(*ArmClient).environment
client := shares.NewWithEnvironment(environment)

shareName := is.Attributes["name"]
storageAccountName := is.Attributes["storage_account_name"]
newID := client.GetResourceID(storageAccountName, shareName)
is.Attributes["id"] = newID
is.ID = newID
newResourceId := client.GetResourceID(accountName, shareName)
log.Printf("[DEBUG] Updating Resource ID from %q to %q", id, newResourceId)

log.Printf("[DEBUG] ARM Storage Share Attributes after State Migration: %#v", is.Attributes)
rawState["id"] = newResourceId

return is, nil
return rawState, nil
}
137 changes: 75 additions & 62 deletions azurerm/resource_arm_storage_share_migration_test.go
Original file line number Diff line number Diff line change
@@ -1,80 +1,93 @@
package azurerm

import (
"fmt"
"reflect"
"testing"

"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/terraform/terraform"
)

func TestAzureRMStorageShareMigrateState(t *testing.T) {
cases := map[string]struct {
StateVersion int
ID string
InputAttributes map[string]string
ExpectedAttributes map[string]string
Meta interface{}
}{
"v0_1": {
StateVersion: 0,
ID: "some_id",
InputAttributes: map[string]string{
"name": "some_id",
"resource_group_name": "some_rgn",
"storage_account_name": "some_sgn",
},
ExpectedAttributes: map[string]string{
"id": "some_id/some_rgn/some_sgn",
},
},
"v1_2_public": {
StateVersion: 1,
ID: "some_id",
InputAttributes: map[string]string{
"name": "some_id",
"resource_group_name": "some_rgn",
"storage_account_name": "some_sgn",
},
ExpectedAttributes: map[string]string{
"id": "https://some_sgn.file.core.windows.net/some_id",
},
Meta: &ArmClient{
environment: azure.PublicCloud,
},
},
"v1_2_germany": {
StateVersion: 1,
ID: "some_id",
InputAttributes: map[string]string{
"name": "some_id",
"resource_group_name": "some_rgn",
"storage_account_name": "some_sgn",
},
ExpectedAttributes: map[string]string{
"id": "https://some_sgn.file.core.cloudapi.de/some_id",
},
Meta: &ArmClient{
environment: azure.GermanCloud,
},
},
func TestAzureRMStorageShareMigrateStateV0ToV1(t *testing.T) {
clouds := []azure.Environment{
azure.ChinaCloud,
azure.GermanCloud,
azure.PublicCloud,
azure.USGovernmentCloud,
}

for tn, tc := range cases {
is := &terraform.InstanceState{
ID: tc.ID,
Attributes: tc.InputAttributes,
for _, cloud := range clouds {
t.Logf("[DEBUG] Testing with Cloud %q", cloud.Name)

input := map[string]interface{}{
"id": "share1",
"name": "share1",
"resource_group_name": "group1",
"storage_account_name": "account1",
"quota": 5120,
}
meta := &ArmClient{
environment: cloud,
}
expected := map[string]interface{}{
"id": "share1/group1/account1",
"name": "share1",
"resource_group_name": "group1",
"storage_account_name": "account1",
"quota": 5120,
}
is, err := resourceStorageShareMigrateState(tc.StateVersion, is, tc.Meta)

actual, err := resourceStorageShareStateUpgradeV0ToV1(input, meta)
if err != nil {
t.Fatalf("bad: %s, err: %#v", tn, err)
t.Fatalf("Expected no error but got: %s", err)
}

for k, v := range tc.ExpectedAttributes {
actual := is.Attributes[k]
if actual != v {
t.Fatalf("Bad Storage Share Migrate for %q: %q\n\n expected: %q", k, actual, v)
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %+v. Got %+v. But expected them to be the same", expected, actual)
}

t.Logf("[DEBUG] Ok!")
}
}

func TestAzureRMStorageShareMigrateStateV1ToV2(t *testing.T) {
clouds := []azure.Environment{
azure.ChinaCloud,
azure.GermanCloud,
azure.PublicCloud,
azure.USGovernmentCloud,
}

for _, cloud := range clouds {
t.Logf("[DEBUG] Testing with Cloud %q", cloud.Name)

input := map[string]interface{}{
"id": "share1/group1/account1",
"name": "share1",
"resource_group_name": "group1",
"storage_account_name": "account1",
"quota": 5120,
}
meta := &ArmClient{
environment: cloud,
}
expected := map[string]interface{}{
"id": fmt.Sprintf("https://account1.file.%s/share1", cloud.StorageEndpointSuffix),
"name": "share1",
"resource_group_name": "group1",
"storage_account_name": "account1",
"quota": 5120,
}

actual, err := resourceStorageShareStateUpgradeV1ToV2(input, meta)
if err != nil {
t.Fatalf("Expected no error but got: %s", err)
}

if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %+v. Got %+v. But expected them to be the same", expected, actual)
}

t.Logf("[DEBUG] Ok!")
}
}