From 92518ce1768cf604722e04ef8104723f900e27a3 Mon Sep 17 00:00:00 2001 From: Steph Date: Mon, 15 Apr 2024 13:28:48 +0200 Subject: [PATCH] add state migration for app insights component id --- .../application_insights_resource.go | 3 +- .../{component.go => component_v0_to_v1.go} | 0 ...ent_test.go => component_v0_to_v1_test.go} | 0 .../migration/component_v1_to_v2.go | 129 ++++++++++++++++++ .../migration/component_v1_to_v2_test.go | 59 ++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) rename internal/services/applicationinsights/migration/{component.go => component_v0_to_v1.go} (100%) rename internal/services/applicationinsights/migration/{component_test.go => component_v0_to_v1_test.go} (100%) create mode 100644 internal/services/applicationinsights/migration/component_v1_to_v2.go create mode 100644 internal/services/applicationinsights/migration/component_v1_to_v2_test.go diff --git a/internal/services/applicationinsights/application_insights_resource.go b/internal/services/applicationinsights/application_insights_resource.go index ca1aa1d7da5d..8a9385b83401 100644 --- a/internal/services/applicationinsights/application_insights_resource.go +++ b/internal/services/applicationinsights/application_insights_resource.go @@ -38,9 +38,10 @@ func resourceApplicationInsights() *pluginsdk.Resource { return err }), - SchemaVersion: 1, + SchemaVersion: 2, StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{ 0: migration.ComponentUpgradeV0ToV1{}, + 1: migration.ComponentUpgradeV1ToV2{}, }), Timeouts: &pluginsdk.ResourceTimeout{ diff --git a/internal/services/applicationinsights/migration/component.go b/internal/services/applicationinsights/migration/component_v0_to_v1.go similarity index 100% rename from internal/services/applicationinsights/migration/component.go rename to internal/services/applicationinsights/migration/component_v0_to_v1.go diff --git a/internal/services/applicationinsights/migration/component_test.go b/internal/services/applicationinsights/migration/component_v0_to_v1_test.go similarity index 100% rename from internal/services/applicationinsights/migration/component_test.go rename to internal/services/applicationinsights/migration/component_v0_to_v1_test.go diff --git a/internal/services/applicationinsights/migration/component_v1_to_v2.go b/internal/services/applicationinsights/migration/component_v1_to_v2.go new file mode 100644 index 000000000000..c0fab49e1f58 --- /dev/null +++ b/internal/services/applicationinsights/migration/component_v1_to_v2.go @@ -0,0 +1,129 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package migration + +import ( + "context" + "log" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + components "github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2020-02-02/componentsapis" + "github.com/hashicorp/terraform-provider-azurerm/internal/tags" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +var _ pluginsdk.StateUpgrade = ComponentUpgradeV1ToV2{} + +type ComponentUpgradeV1ToV2 struct{} + +func (ComponentUpgradeV1ToV2) Schema() map[string]*pluginsdk.Schema { + return componentSchemaForV1AndV2() +} + +func (ComponentUpgradeV1ToV2) UpgradeFunc() pluginsdk.StateUpgraderFunc { + return func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + // This state migration is identical to v0 -> v1, however we need to apply it again because application insights + // resources with the incorrect casing could still be imported and exist within some user's state + oldIdRaw := rawState["id"].(string) + id, err := components.ParseComponentIDInsensitively(oldIdRaw) + if err != nil { + return rawState, err + } + + newId := id.ID() + + log.Printf("[DEBUG] Updating ID from %q to %q", oldIdRaw, newId) + rawState["id"] = newId + + return rawState, nil + } +} + +func componentSchemaForV1AndV2() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "location": commonschema.Location(), + + "application_type": { + Type: pluginsdk.TypeString, + Required: true, + }, + + "workspace_id": { + Type: pluginsdk.TypeString, + Optional: true, + }, + + "retention_in_days": { + Type: pluginsdk.TypeInt, + Optional: true, + }, + + "sampling_percentage": { + Type: pluginsdk.TypeFloat, + Optional: true, + }, + + "disable_ip_masking": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + + "tags": tags.Schema(), + + "daily_data_cap_in_gb": { + Type: pluginsdk.TypeFloat, + Optional: true, + Computed: true, + }, + + "daily_data_cap_notifications_disabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "app_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "instrumentation_key": { + Type: pluginsdk.TypeString, + Computed: true, + Sensitive: true, + }, + + "connection_string": { + Type: pluginsdk.TypeString, + Computed: true, + Sensitive: true, + }, + + "local_authentication_disabled": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + + "internet_ingestion_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + + "internet_query_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + "force_customer_storage_for_profiler": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + } +} diff --git a/internal/services/applicationinsights/migration/component_v1_to_v2_test.go b/internal/services/applicationinsights/migration/component_v1_to_v2_test.go new file mode 100644 index 000000000000..30b2a075a636 --- /dev/null +++ b/internal/services/applicationinsights/migration/component_v1_to_v2_test.go @@ -0,0 +1,59 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package migration + +import ( + "context" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func TestComponentV1ToV2(t *testing.T) { + testData := []struct { + name string + input map[string]interface{} + expected *string + }{ + { + name: "old id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourcegroups/group1/providers/microsoft.insights/components/component1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Insights/components/component1"), + }, + { + name: "old id - mixed case", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourcegroups/group1/providers/microsoft.insights/Components/component1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Insights/components/component1"), + }, + { + name: "new id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Insights/components/component1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Insights/components/component1"), + }, + } + for _, test := range testData { + t.Logf("Testing %q...", test.name) + result, err := ComponentUpgradeV1ToV2{}.UpgradeFunc()(context.TODO(), test.input, nil) + if err != nil && test.expected == nil { + continue + } else { + if err == nil && test.expected == nil { + t.Fatalf("Expected an error but didn't get one") + } else if err != nil && test.expected != nil { + t.Fatalf("Expected no error but got: %+v", err) + } + } + + actualId := result["id"].(string) + if *test.expected != actualId { + t.Fatalf("expected %q but got %q!", *test.expected, actualId) + } + } +}