From 43ac4fd0ea8acf794ac5c88c11281cf9c86c0d71 Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 16 Jan 2020 22:24:38 -0800 Subject: [PATCH] appconfiguration: add parse ID and function (#5409) --- .../parse/app_configuration.go | 33 +++++++ .../parse/app_configuration_test.go | 73 +++++++++++++++ .../resource_arm_app_configuration.go | 89 +++++++++---------- .../resource_arm_app_configuration_test.go | 20 +++-- 4 files changed, 157 insertions(+), 58 deletions(-) create mode 100644 azurerm/internal/services/appconfiguration/parse/app_configuration.go create mode 100644 azurerm/internal/services/appconfiguration/parse/app_configuration_test.go diff --git a/azurerm/internal/services/appconfiguration/parse/app_configuration.go b/azurerm/internal/services/appconfiguration/parse/app_configuration.go new file mode 100644 index 000000000000..06f9ec4a0631 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/parse/app_configuration.go @@ -0,0 +1,33 @@ +package parse + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type AppConfigurationId struct { + ResourceGroup string + Name string +} + +func AppConfigurationID(input string) (*AppConfigurationId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("[ERROR] Unable to parse Analysis Services Server ID %q: %+v", input, err) + } + + server := AppConfigurationId{ + ResourceGroup: id.ResourceGroup, + } + + if server.Name, err = id.PopSegment("configurationStores"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &server, nil +} diff --git a/azurerm/internal/services/appconfiguration/parse/app_configuration_test.go b/azurerm/internal/services/appconfiguration/parse/app_configuration_test.go new file mode 100644 index 000000000000..911e91ad25c2 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/parse/app_configuration_test.go @@ -0,0 +1,73 @@ +package parse + +import ( + "testing" +) + +func TestAppConfigurationID(t *testing.T) { + testData := []struct { + Name string + Input string + Expected *AppConfigurationId + }{ + { + Name: "Empty", + Input: "", + Expected: nil, + }, + { + Name: "No Resource Groups Segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000", + Expected: nil, + }, + { + Name: "No Resource Groups Value", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/", + Expected: nil, + }, + { + Name: "Resource Group ID", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo/", + Expected: nil, + }, + { + Name: "Missing Stores Value", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.AppConfiguration/configurationStores/", + Expected: nil, + }, + { + Name: "App Configuration ID", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.AppConfiguration/configurationStores/Store1", + Expected: &AppConfigurationId{ + Name: "Store1", + ResourceGroup: "resGroup1", + }, + }, + { + Name: "Wrong Casing", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.AppConfiguration/ConfigurationStores/Store1", + Expected: nil, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := AppConfigurationID(v.Input) + if err != nil { + if v.Expected == nil { + continue + } + + t.Fatalf("Expected a value but got an error: %s", err) + } + + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for Resource Group", v.Expected.ResourceGroup, actual.ResourceGroup) + } + } +} diff --git a/azurerm/internal/services/appconfiguration/resource_arm_app_configuration.go b/azurerm/internal/services/appconfiguration/resource_arm_app_configuration.go index 5b0838e3391e..02ca55004547 100644 --- a/azurerm/internal/services/appconfiguration/resource_arm_app_configuration.go +++ b/azurerm/internal/services/appconfiguration/resource_arm_app_configuration.go @@ -15,7 +15,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -27,10 +29,6 @@ func resourceArmAppConfiguration() *schema.Resource { Update: resourceArmAppConfigurationUpdate, Delete: resourceArmAppConfigurationDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), Read: schema.DefaultTimeout(5 * time.Minute), @@ -38,6 +36,11 @@ func resourceArmAppConfiguration() *schema.Resource { Delete: schema.DefaultTimeout(30 * time.Minute), }, + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.AppConfigurationID(id) + return err + }), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -191,17 +194,12 @@ func resourceArmAppConfigurationCreate(d *schema.ResourceData, meta interface{}) } } - location := azure.NormalizeLocation(d.Get("location").(string)) - t := d.Get("tags").(map[string]interface{}) - skuName := d.Get("sku").(string) - sku := appconf.Sku{ - Name: &skuName, - } - parameters := appconf.ConfigurationStore{ - Location: &location, - Sku: &sku, - Tags: tags.Expand(t), + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + Sku: &appconf.Sku{ + Name: utils.String(d.Get("sku").(string)), + }, + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } future, err := client.Create(ctx, resourceGroup, name, parameters) @@ -232,36 +230,33 @@ func resourceArmAppConfigurationUpdate(d *schema.ResourceData, meta interface{}) defer cancel() log.Printf("[INFO] preparing arguments for Azure ARM App Configuration update.") - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - t := d.Get("tags").(map[string]interface{}) - skuName := d.Get("sku").(string) - sku := appconf.Sku{ - Name: &skuName, + id, err := parse.AppConfigurationID(d.Id()) + if err != nil { + return err } parameters := appconf.ConfigurationStoreUpdateParameters{ - Sku: &sku, - Tags: tags.Expand(t), + Sku: &appconf.Sku{ + Name: utils.String(d.Get("sku").(string)), + }, + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } - future, err := client.Update(ctx, resourceGroup, name, parameters) + future, err := client.Update(ctx, id.ResourceGroup, id.Name, parameters) if err != nil { - return fmt.Errorf("Error updating App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error updating App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for update of App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error waiting for update of App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } - read, err := client.Get(ctx, resourceGroup, name) + read, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { - return fmt.Errorf("Error retrieving App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error retrieving App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if read.ID == nil { - return fmt.Errorf("Cannot read App Configuration %s (resource Group %q) ID", name, resourceGroup) + return fmt.Errorf("Cannot read App Configuration %s (resource Group %q) ID", id.Name, id.ResourceGroup) } d.SetId(*read.ID) @@ -274,25 +269,23 @@ func resourceArmAppConfigurationRead(d *schema.ResourceData, meta interface{}) e ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + id, err := parse.AppConfigurationID(d.Id()) if err != nil { return err } - resourceGroup := id.ResourceGroup - name := id.Path["configurationStores"] - resp, err := client.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] App Configuration %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + log.Printf("[DEBUG] App Configuration %q was not found in Resource Group %q - removing from state!", id.Name, id.ResourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error making Read request on App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error making Read request on App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } d.Set("name", resp.Name) - d.Set("resource_group_name", resourceGroup) + d.Set("resource_group_name", id.ResourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } @@ -305,9 +298,9 @@ func resourceArmAppConfigurationRead(d *schema.ResourceData, meta interface{}) e d.Set("endpoint", resp.Endpoint) } - resultPage, err := client.ListKeys(ctx, resourceGroup, name, "") + resultPage, err := client.ListKeys(ctx, id.ResourceGroup, id.Name, "") if err != nil { - return fmt.Errorf("Failed to receive access keys for App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Failed to receive access keys for App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } values := resultPage.Values() @@ -324,8 +317,8 @@ func resourceArmAppConfigurationRead(d *schema.ResourceData, meta interface{}) e } accessKey := []interface{}{accessKeyParams} - if name := value.Name; name != nil { - if strings.HasPrefix(*name, "Primary") { + if n := value.Name; n != nil { + if strings.HasPrefix(*n, "Primary") { if readOnly := value.ReadOnly; readOnly != nil { if *readOnly { d.Set("primary_read_key", accessKey) @@ -333,7 +326,7 @@ func resourceArmAppConfigurationRead(d *schema.ResourceData, meta interface{}) e d.Set("primary_write_key", accessKey) } } - } else if strings.HasPrefix(*name, "Secondary") { + } else if strings.HasPrefix(*n, "Secondary") { if readOnly := value.ReadOnly; readOnly != nil { if *readOnly { d.Set("secondary_read_key", accessKey) @@ -342,7 +335,7 @@ func resourceArmAppConfigurationRead(d *schema.ResourceData, meta interface{}) e } } } else { - log.Printf("[WARN] Received unknown App Configuration access key '%s', ignoring...", *name) + log.Printf("[WARN] Received unknown App Configuration access key '%s', ignoring...", *n) } } } @@ -355,26 +348,24 @@ func resourceArmAppConfigurationDelete(d *schema.ResourceData, meta interface{}) ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + id, err := parse.AppConfigurationID(d.Id()) if err != nil { return err } - resourceGroup := id.ResourceGroup - name := id.Path["configurationStores"] - fut, err := client.Delete(ctx, resourceGroup, name) + fut, err := client.Delete(ctx, id.ResourceGroup, id.Name) if err != nil { if response.WasNotFound(fut.Response()) { return nil } - return fmt.Errorf("Error deleting App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if err = fut.WaitForCompletionRef(ctx, client.Client); err != nil { if response.WasNotFound(fut.Response()) { return nil } - return fmt.Errorf("Error deleting App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } return nil diff --git a/azurerm/internal/services/appconfiguration/tests/resource_arm_app_configuration_test.go b/azurerm/internal/services/appconfiguration/tests/resource_arm_app_configuration_test.go index 4cc48effe142..443fc88059f0 100644 --- a/azurerm/internal/services/appconfiguration/tests/resource_arm_app_configuration_test.go +++ b/azurerm/internal/services/appconfiguration/tests/resource_arm_app_configuration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" @@ -184,10 +185,12 @@ func testCheckAzureAppConfigurationDestroy(s *terraform.State) error { continue } - name := rs.Primary.Attributes["name"] - resourceGroup := rs.Primary.Attributes["resource_group_name"] + id, err := parse.AppConfigurationID(rs.Primary.ID) + if err != nil { + return err + } - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := conn.Get(ctx, id.ResourceGroup, id.Name) if err != nil { if !utils.ResponseWasNotFound(resp.Response) { return err @@ -211,19 +214,18 @@ func testCheckAzureAppConfigurationExists(resourceName string) resource.TestChec return fmt.Errorf("Not found: %s", resourceName) } - name := rs.Primary.Attributes["name"] - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for App Configuration: %s", name) + id, err := parse.AppConfigurationID(rs.Primary.ID) + if err != nil { + return err } - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := conn.Get(ctx, id.ResourceGroup, id.Name) if err != nil { return fmt.Errorf("Bad: Get on appConfigurationsClient: %+v", err) } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: App Configuration %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: App Configuration %q (resource group: %q) does not exist", id.Name, id.ResourceGroup) } return nil