diff --git a/.golangci.yml b/.golangci.yml index e0f08aad21dc..368f8cfba267 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -41,3 +41,5 @@ linters-settings: ignore-words: - hdinsight - exportfs + nakedret: + max-func-lines: 40 diff --git a/azurerm/internal/services/appconfiguration/app_configuration_data_source.go b/azurerm/internal/services/appconfiguration/app_configuration_data_source.go index bbb397c293ff..27bd3530b307 100644 --- a/azurerm/internal/services/appconfiguration/app_configuration_data_source.go +++ b/azurerm/internal/services/appconfiguration/app_configuration_data_source.go @@ -4,14 +4,17 @@ import ( "fmt" "time" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/sdk/configurationstores" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceAppConfiguration() *pluginsdk.Resource { @@ -145,7 +148,7 @@ func dataSourceAppConfiguration() *pluginsdk.Resource { } func dataSourceAppConfigurationRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).AppConfiguration.AppConfigurationsClient + client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -153,41 +156,39 @@ func dataSourceAppConfigurationRead(d *pluginsdk.ResourceData, meta interface{}) name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - resp, err := client.Get(ctx, resourceGroup, name) + id := configurationstores.NewConfigurationStoreID(subscriptionId, resourceGroup, name) + resp, err := client.Get(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("App Configuration %q was not found in Resource Group %q", name, resourceGroup) + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("%s was not found", id) } - return fmt.Errorf("Error retrieving App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } - resultPage, err := client.ListKeys(ctx, resourceGroup, name, "") + resultPage, err := client.ListKeysComplete(ctx, id) 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("retrieving access keys for %s: %+v", id, err) } - d.SetId(parse.NewConfigurationStoreID(subscriptionId, resourceGroup, name).ID()) + d.SetId(id.ID()) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } + if model := resp.Model; model != nil { + d.Set("location", location.Normalize(model.Location)) + d.Set("sku", model.Sku.Name) - skuName := "" - if resp.Sku != nil && resp.Sku.Name != nil { - skuName = *resp.Sku.Name - } - d.Set("sku", skuName) + if props := model.Properties; props != nil { + d.Set("endpoint", props.Endpoint) + } - if props := resp.ConfigurationStoreProperties; props != nil { - d.Set("endpoint", props.Endpoint) - } + accessKeys := flattenAppConfigurationAccessKeys(resultPage.Items) + d.Set("primary_read_key", accessKeys.primaryReadKey) + d.Set("primary_write_key", accessKeys.primaryWriteKey) + d.Set("secondary_read_key", accessKeys.secondaryReadKey) + d.Set("secondary_write_key", accessKeys.secondaryWriteKey) - accessKeys := flattenAppConfigurationAccessKeys(resultPage.Values()) - d.Set("primary_read_key", accessKeys.primaryReadKey) - d.Set("primary_write_key", accessKeys.primaryWriteKey) - d.Set("secondary_read_key", accessKeys.secondaryReadKey) - d.Set("secondary_write_key", accessKeys.secondaryWriteKey) + return tags.FlattenAndSet(d, flattenTags(model.Tags)) + } - return tags.FlattenAndSet(d, resp.Tags) + return nil } diff --git a/azurerm/internal/services/appconfiguration/app_configuration_resource.go b/azurerm/internal/services/appconfiguration/app_configuration_resource.go index b9c04c4c398d..a4158bd456fc 100644 --- a/azurerm/internal/services/appconfiguration/app_configuration_resource.go +++ b/azurerm/internal/services/appconfiguration/app_configuration_resource.go @@ -6,18 +6,19 @@ import ( "strings" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" + "github.com/Azure/azure-sdk-for-go/services/appconfiguration/mgmt/2020-06-01/appconfiguration" "github.com/hashicorp/go-azure-helpers/response" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "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/services/appconfiguration/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/sdk/configurationstores" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceAppConfiguration() *pluginsdk.Resource { @@ -35,7 +36,7 @@ func resourceAppConfiguration() *pluginsdk.Resource { }, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.ConfigurationStoreID(id) + _, err := configurationstores.ConfigurationStoreID(id) return err }), @@ -195,7 +196,7 @@ func resourceAppConfiguration() *pluginsdk.Resource { } func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).AppConfiguration.AppConfigurationsClient + client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -204,161 +205,128 @@ func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - resourceId := parse.NewConfigurationStoreID(subscriptionId, resourceGroup, name).ID() - existing, err := client.Get(ctx, resourceGroup, name) + resourceId := configurationstores.NewConfigurationStoreID(subscriptionId, resourceGroup, name) + existing, err := client.Get(ctx, resourceId) if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing App Configuration %q (Resource Group %q): %s", name, resourceGroup, err) + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", resourceId, err) } } - if !utils.ResponseWasNotFound(existing.Response) { - return tf.ImportAsExistsError("azurerm_app_configuration", resourceId) + if !response.WasNotFound(existing.HttpResponse) { + return tf.ImportAsExistsError("azurerm_app_configuration", resourceId.ID()) } - parameters := appconfiguration.ConfigurationStore{ - Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), - Sku: &appconfiguration.Sku{ - Name: utils.String(d.Get("sku").(string)), + parameters := configurationstores.ConfigurationStore{ + Location: azure.NormalizeLocation(d.Get("location").(string)), + Sku: configurationstores.Sku{ + Name: d.Get("sku").(string), }, - Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + Tags: expandTags(d.Get("tags").(map[string]interface{})), } parameters.Identity = expandAppConfigurationIdentity(d.Get("identity").([]interface{})) - future, err := client.Create(ctx, resourceGroup, name, parameters) - if err != nil { - return fmt.Errorf("Error creating App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) + if err := client.CreateThenPoll(ctx, resourceId, parameters); err != nil { + return fmt.Errorf("creating %s: %+v", resourceId, err) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for creation of App Configuration %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - d.SetId(resourceId) + d.SetId(resourceId.ID()) return resourceAppConfigurationRead(d, meta) } func resourceAppConfigurationUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).AppConfiguration.AppConfigurationsClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() log.Printf("[INFO] preparing arguments for Azure ARM App Configuration update.") - id, err := parse.ConfigurationStoreID(d.Id()) + id, err := configurationstores.ConfigurationStoreID(d.Id()) if err != nil { return err } - parameters := appconfiguration.ConfigurationStoreUpdateParameters{ - Sku: &appconfiguration.Sku{ - Name: utils.String(d.Get("sku").(string)), + parameters := configurationstores.ConfigurationStoreUpdateParameters{ + Sku: &configurationstores.Sku{ + Name: d.Get("sku").(string), }, - Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + Tags: expandTags(d.Get("tags").(map[string]interface{})), } if d.HasChange("identity") { parameters.Identity = expandAppConfigurationIdentity(d.Get("identity").([]interface{})) } - 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", id.Name, id.ResourceGroup, err) + if err := client.UpdateThenPoll(ctx, *id, parameters); err != nil { + return fmt.Errorf("updating %s: %+v", *id, 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", id.Name, id.ResourceGroup, err) - } - - read, err := client.Get(ctx, id.ResourceGroup, id.Name) - if err != nil { - 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", id.Name, id.ResourceGroup) - } - - d.SetId(*read.ID) - return resourceAppConfigurationRead(d, meta) } func resourceAppConfigurationRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).AppConfiguration.AppConfigurationsClient + client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.ConfigurationStoreID(d.Id()) + id, err := configurationstores.ConfigurationStoreID(d.Id()) if err != nil { return err } - resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + resp, err := client.Get(ctx, *id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] App Configuration %q was not found in Resource Group %q - removing from state!", id.Name, id.ResourceGroup) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s was not found - removing from state!", *id) d.SetId("") return nil } - return fmt.Errorf("Error making Read request on App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", *id, err) } - resultPage, err := client.ListKeys(ctx, id.ResourceGroup, id.Name, "") + resultPage, err := client.ListKeysComplete(ctx, *id) if err != nil { - return fmt.Errorf("Failed to receive access keys for App Configuration %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("retrieving access keys for %s: %+v", *id, err) } d.Set("name", id.Name) d.Set("resource_group_name", id.ResourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - skuName := "" - if resp.Sku != nil && resp.Sku.Name != nil { - skuName = *resp.Sku.Name - } - d.Set("sku", skuName) + if model := resp.Model; model != nil { + d.Set("location", location.Normalize(model.Location)) + d.Set("sku", model.Sku.Name) - if props := resp.ConfigurationStoreProperties; props != nil { - d.Set("endpoint", props.Endpoint) - } + if props := model.Properties; props != nil { + d.Set("endpoint", props.Endpoint) + } - accessKeys := flattenAppConfigurationAccessKeys(resultPage.Values()) - d.Set("primary_read_key", accessKeys.primaryReadKey) - d.Set("primary_write_key", accessKeys.primaryWriteKey) - d.Set("secondary_read_key", accessKeys.secondaryReadKey) - d.Set("secondary_write_key", accessKeys.secondaryWriteKey) + accessKeys := flattenAppConfigurationAccessKeys(resultPage.Items) + d.Set("primary_read_key", accessKeys.primaryReadKey) + d.Set("primary_write_key", accessKeys.primaryWriteKey) + d.Set("secondary_read_key", accessKeys.secondaryReadKey) + d.Set("secondary_write_key", accessKeys.secondaryWriteKey) - if err := d.Set("identity", flattenAppConfigurationIdentity(resp.Identity)); err != nil { - return fmt.Errorf("Error setting `identity`: %+v", err) + if err := d.Set("identity", flattenAppConfigurationIdentity(model.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + + return tags.FlattenAndSet(d, flattenTags(model.Tags)) } - return tags.FlattenAndSet(d, resp.Tags) + return nil } func resourceAppConfigurationDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).AppConfiguration.AppConfigurationsClient + client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.ConfigurationStoreID(d.Id()) + id, err := configurationstores.ConfigurationStoreID(d.Id()) if err != nil { return err } - 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", 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", id.Name, id.ResourceGroup, err) + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) } return nil @@ -371,7 +339,7 @@ type flattenedAccessKeys struct { secondaryWriteKey []interface{} } -func flattenAppConfigurationAccessKeys(values []appconfiguration.APIKey) flattenedAccessKeys { +func flattenAppConfigurationAccessKeys(values []configurationstores.AccessKey) flattenedAccessKeys { result := flattenedAccessKeys{ primaryReadKey: make([]interface{}, 0), primaryWriteKey: make([]interface{}, 0), @@ -408,7 +376,7 @@ func flattenAppConfigurationAccessKeys(values []appconfiguration.APIKey) flatten return result } -func flattenAppConfigurationAccessKey(input appconfiguration.APIKey) []interface{} { +func flattenAppConfigurationAccessKey(input configurationstores.AccessKey) []interface{} { connectionString := "" if input.ConnectionString != nil { @@ -434,37 +402,44 @@ func flattenAppConfigurationAccessKey(input appconfiguration.APIKey) []interface } } -func expandAppConfigurationIdentity(identities []interface{}) *appconfiguration.ResourceIdentity { - if len(identities) == 0 { - return &appconfiguration.ResourceIdentity{ - Type: appconfiguration.IdentityTypeNone, +func expandAppConfigurationIdentity(identities []interface{}) *configurationstores.ResourceIdentity { + var out = func(in configurationstores.IdentityType) *configurationstores.ResourceIdentity { + return &configurationstores.ResourceIdentity{ + Type: &in, } } - identity := identities[0].(map[string]interface{}) - identityType := appconfiguration.IdentityType(identity["type"].(string)) - return &appconfiguration.ResourceIdentity{ - Type: identityType, + + if len(identities) == 0 { + return out(configurationstores.IdentityTypeNone) } + identity := identities[0].(map[string]interface{}) + identityType := configurationstores.IdentityType(identity["type"].(string)) + return out(identityType) } -func flattenAppConfigurationIdentity(identity *appconfiguration.ResourceIdentity) []interface{} { - if identity == nil || identity.Type == appconfiguration.IdentityTypeNone { +func flattenAppConfigurationIdentity(identity *configurationstores.ResourceIdentity) []interface{} { + if identity == nil || identity.Type == nil || *identity.Type == configurationstores.IdentityTypeNone { return []interface{}{} } + identityType := "" + if identity.Type != nil { + identityType = string(*identity.Type) + } + principalId := "" - if identity.PrincipalID != nil { - principalId = *identity.PrincipalID + if identity.PrincipalId != nil { + principalId = *identity.PrincipalId } tenantId := "" - if identity.TenantID != nil { - tenantId = *identity.TenantID + if identity.TenantId != nil { + tenantId = *identity.TenantId } return []interface{}{ map[string]interface{}{ - "type": string(identity.Type), + "type": identityType, "principal_id": principalId, "tenant_id": tenantId, }, diff --git a/azurerm/internal/services/appconfiguration/app_configuration_resource_test.go b/azurerm/internal/services/appconfiguration/app_configuration_resource_test.go index bbe7831ee033..fd813bf782ec 100644 --- a/azurerm/internal/services/appconfiguration/app_configuration_resource_test.go +++ b/azurerm/internal/services/appconfiguration/app_configuration_resource_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/sdk/configurationstores" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" @@ -145,17 +145,17 @@ func TestAccAppConfiguration_update(t *testing.T) { } func (t AppConfigurationResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.ConfigurationStoreID(state.ID) + id, err := configurationstores.ConfigurationStoreID(state.ID) if err != nil { return nil, err } - resp, err := clients.AppConfiguration.AppConfigurationsClient.Get(ctx, id.ResourceGroup, id.Name) + resp, err := clients.AppConfiguration.ConfigurationStoresClient.Get(ctx, *id) if err != nil { return nil, fmt.Errorf("retrieving App Configuration %q (resource group: %q): %+v", id.Name, id.ResourceGroup, err) } - return utils.Bool(resp.ConfigurationStoreProperties != nil), nil + return utils.Bool(resp.Model != nil), nil } func (AppConfigurationResource) free(data acceptance.TestData) string { diff --git a/azurerm/internal/services/appconfiguration/client/client.go b/azurerm/internal/services/appconfiguration/client/client.go index 4f1f9c4cfdce..45f1d21d6347 100644 --- a/azurerm/internal/services/appconfiguration/client/client.go +++ b/azurerm/internal/services/appconfiguration/client/client.go @@ -1,19 +1,19 @@ package client import ( - appconf "github.com/Azure/azure-sdk-for-go/services/appconfiguration/mgmt/2020-06-01/appconfiguration" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/sdk/configurationstores" ) type Client struct { - AppConfigurationsClient *appconf.ConfigurationStoresClient + ConfigurationStoresClient *configurationstores.ConfigurationStoresClient } func NewClient(o *common.ClientOptions) *Client { - AppConfigurationsClient := appconf.NewConfigurationStoresClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&AppConfigurationsClient.Client, o.ResourceManagerAuthorizer) + configurationStores := configurationstores.NewConfigurationStoresClientWithBaseURI(o.ResourceManagerEndpoint) + o.ConfigureClient(&configurationStores.Client, o.ResourceManagerAuthorizer) return &Client{ - AppConfigurationsClient: &AppConfigurationsClient, + ConfigurationStoresClient: &configurationStores, } } diff --git a/azurerm/internal/services/appconfiguration/parse/configuration_store_test.go b/azurerm/internal/services/appconfiguration/parse/configuration_store_test.go deleted file mode 100644 index e889ea1c25d7..000000000000 --- a/azurerm/internal/services/appconfiguration/parse/configuration_store_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package parse_test - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" -) - -var _ resourceid.Formatter = parse.ConfigurationStoreId{} - -func TestConfigurationStoreIDFormatter(t *testing.T) { - actual := parse.NewConfigurationStoreID("12345678-1234-9876-4563-123456789012", "group1", "store1").ID() - expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/store1" - if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) - } -} - -func TestConfigurationStoreID(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *parse.ConfigurationStoreId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/", - Error: true, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/store1", - Expected: &parse.ConfigurationStoreId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "group1", - Name: "store1", - }, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/GROUP1/PROVIDERS/MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES/STORE1", - Error: true, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := parse.ConfigurationStoreID(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) - } - } -} diff --git a/azurerm/internal/services/appconfiguration/resourceids.go b/azurerm/internal/services/appconfiguration/resourceids.go deleted file mode 100644 index b49b87985aba..000000000000 --- a/azurerm/internal/services/appconfiguration/resourceids.go +++ /dev/null @@ -1,3 +0,0 @@ -package appconfiguration - -//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ConfigurationStore -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/store1 diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/client.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/client.go new file mode 100644 index 000000000000..ac4377b23a6d --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/client.go @@ -0,0 +1,15 @@ +package configurationstores + +import "github.com/Azure/go-autorest/autorest" + +type ConfigurationStoresClient struct { + Client autorest.Client + baseUri string +} + +func NewConfigurationStoresClientWithBaseURI(endpoint string) ConfigurationStoresClient { + return ConfigurationStoresClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/constants.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/constants.go new file mode 100644 index 000000000000..0503eacb9e91 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/constants.go @@ -0,0 +1,44 @@ +package configurationstores + +type ActionsRequired string + +const ( + ActionsRequiredNone ActionsRequired = "None" + ActionsRequiredRecreate ActionsRequired = "Recreate" +) + +type ConnectionStatus string + +const ( + ConnectionStatusApproved ConnectionStatus = "Approved" + ConnectionStatusDisconnected ConnectionStatus = "Disconnected" + ConnectionStatusPending ConnectionStatus = "Pending" + ConnectionStatusRejected ConnectionStatus = "Rejected" +) + +type IdentityType string + +const ( + IdentityTypeNone IdentityType = "None" + IdentityTypeSystemAssigned IdentityType = "SystemAssigned" + IdentityTypeSystemAssignedUserAssigned IdentityType = "SystemAssigned, UserAssigned" + IdentityTypeUserAssigned IdentityType = "UserAssigned" +) + +type ProvisioningState string + +const ( + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateCreating ProvisioningState = "Creating" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" + ProvisioningStateUpdating ProvisioningState = "Updating" +) + +type PublicNetworkAccess string + +const ( + PublicNetworkAccessDisabled PublicNetworkAccess = "Disabled" + PublicNetworkAccessEnabled PublicNetworkAccess = "Enabled" +) diff --git a/azurerm/internal/services/appconfiguration/parse/configuration_store.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore.go similarity index 53% rename from azurerm/internal/services/appconfiguration/parse/configuration_store.go rename to azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore.go index bb7e30ae6738..8f4a4d81efa9 100644 --- a/azurerm/internal/services/appconfiguration/parse/configuration_store.go +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore.go @@ -1,12 +1,10 @@ -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten +package configurationstores import ( "fmt" "strings" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) type ConfigurationStoreId struct { @@ -39,7 +37,7 @@ func (id ConfigurationStoreId) ID() string { // ConfigurationStoreID parses a ConfigurationStore ID into an ConfigurationStoreId struct func ConfigurationStoreID(input string) (*ConfigurationStoreId, error) { - id, err := azure.ParseAzureResourceID(input) + id, err := resourceids.ParseAzureResourceID(input) if err != nil { return nil, err } @@ -67,3 +65,44 @@ func ConfigurationStoreID(input string) (*ConfigurationStoreId, error) { return &resourceId, nil } + +// ConfigurationStoreIDInsensitively parses an ConfigurationStore ID into an ConfigurationStoreId struct, insensitively +// This should only be used to parse an ID for rewriting to a consistent casing, +// the ConfigurationStoreID method should be used instead for validation etc. +func ConfigurationStoreIDInsensitively(input string) (*ConfigurationStoreId, error) { + id, err := resourceids.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := ConfigurationStoreId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + // find the correct casing for the 'configurationStores' segment + configurationStoresKey := "configurationStores" + for key := range id.Path { + if strings.EqualFold(key, configurationStoresKey) { + configurationStoresKey = key + break + } + } + if resourceId.Name, err = id.PopSegment(configurationStoresKey); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore_test.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore_test.go new file mode 100644 index 000000000000..b666b3ca1147 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/id_configurationstore_test.go @@ -0,0 +1,227 @@ +package configurationstores + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.Id = ConfigurationStoreId{} + +func TestConfigurationStoreIDFormatter(t *testing.T) { + actual := NewConfigurationStoreID("{subscriptionId}", "{resourceGroupName}", "{configStoreName}").ID() + expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationStores/{configStoreName}" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestConfigurationStoreID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ConfigurationStoreId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/{subscriptionId}/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/{subscriptionId}/resourceGroups/", + Error: true, + }, + + { + // missing Name + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/", + Error: true, + }, + + { + // missing value for Name + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationStores/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationStores/{configStoreName}", + Expected: &ConfigurationStoreId{ + SubscriptionId: "{subscriptionId}", + ResourceGroup: "{resourceGroupName}", + Name: "{configStoreName}", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/PROVIDERS/MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES/{CONFIGSTORENAME}", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ConfigurationStoreID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + } +} + +func TestConfigurationStoreIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ConfigurationStoreId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/{subscriptionId}/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/{subscriptionId}/resourceGroups/", + Error: true, + }, + + { + // missing Name + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/", + Error: true, + }, + + { + // missing value for Name + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationStores/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationStores/{configStoreName}", + Expected: &ConfigurationStoreId{ + SubscriptionId: "{subscriptionId}", + ResourceGroup: "{resourceGroupName}", + Name: "{configStoreName}", + }, + }, + + { + // lower-cased segment names + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/configurationstores/{configStoreName}", + Expected: &ConfigurationStoreId{ + SubscriptionId: "{subscriptionId}", + ResourceGroup: "{resourceGroupName}", + Name: "{configStoreName}", + }, + }, + + { + // upper-cased segment names + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/CONFIGURATIONSTORES/{configStoreName}", + Expected: &ConfigurationStoreId{ + SubscriptionId: "{subscriptionId}", + ResourceGroup: "{resourceGroupName}", + Name: "{configStoreName}", + }, + }, + + { + // mixed-cased segment names + Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AppConfiguration/CoNfIgUrAtIoNsToReS/{configStoreName}", + Expected: &ConfigurationStoreId{ + SubscriptionId: "{subscriptionId}", + ResourceGroup: "{resourceGroupName}", + Name: "{configStoreName}", + }, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ConfigurationStoreIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + } +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_create_autorest.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_create_autorest.go new file mode 100644 index 000000000000..78b3ada60b0b --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_create_autorest.go @@ -0,0 +1,75 @@ +package configurationstores + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type CreateResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Create ... +func (c ConfigurationStoresClient) Create(ctx context.Context, id ConfigurationStoreId, input ConfigurationStore) (result CreateResponse, err error) { + req, err := c.preparerForCreate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Create", nil, "Failure preparing request") + return + } + + result, err = c.senderForCreate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Create", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// CreateThenPoll performs Create then polls until it's completed +func (c ConfigurationStoresClient) CreateThenPoll(ctx context.Context, id ConfigurationStoreId, input ConfigurationStore) error { + result, err := c.Create(ctx, id, input) + if err != nil { + return fmt.Errorf("performing Create: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Create: %+v", err) + } + + return nil +} + +// preparerForCreate prepares the Create request. +func (c ConfigurationStoresClient) preparerForCreate(ctx context.Context, id ConfigurationStoreId, input ConfigurationStore) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForCreate sends the Create request. The method will close the +// http.Response Body if it receives an error. +func (c ConfigurationStoresClient) senderForCreate(ctx context.Context, req *http.Request) (future CreateResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_delete_autorest.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_delete_autorest.go new file mode 100644 index 000000000000..91970e504773 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_delete_autorest.go @@ -0,0 +1,73 @@ +package configurationstores + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type DeleteResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Delete ... +func (c ConfigurationStoresClient) Delete(ctx context.Context, id ConfigurationStoreId) (result DeleteResponse, err error) { + req, err := c.preparerForDelete(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Delete", nil, "Failure preparing request") + return + } + + result, err = c.senderForDelete(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Delete", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// DeleteThenPoll performs Delete then polls until it's completed +func (c ConfigurationStoresClient) DeleteThenPoll(ctx context.Context, id ConfigurationStoreId) error { + result, err := c.Delete(ctx, id) + if err != nil { + return fmt.Errorf("performing Delete: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Delete: %+v", err) + } + + return nil +} + +// preparerForDelete prepares the Delete request. +func (c ConfigurationStoresClient) preparerForDelete(ctx context.Context, id ConfigurationStoreId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsDelete(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForDelete sends the Delete request. The method will close the +// http.Response Body if it receives an error. +func (c ConfigurationStoresClient) senderForDelete(ctx context.Context, req *http.Request) (future DeleteResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_get_autorest.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_get_autorest.go new file mode 100644 index 000000000000..ea7ed1dddfbb --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_get_autorest.go @@ -0,0 +1,64 @@ +package configurationstores + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type GetResponse struct { + HttpResponse *http.Response + Model *ConfigurationStore +} + +// Get ... +func (c ConfigurationStoresClient) Get(ctx context.Context, id ConfigurationStoreId) (result GetResponse, err error) { + req, err := c.preparerForGet(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Get", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Get", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForGet(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Get", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForGet prepares the Get request. +func (c ConfigurationStoresClient) preparerForGet(ctx context.Context, id ConfigurationStoreId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForGet handles the response to the Get request. The method always +// closes the http.Response Body. +func (c ConfigurationStoresClient) responderForGet(resp *http.Response) (result GetResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_listkeys_autorest.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_listkeys_autorest.go new file mode 100644 index 000000000000..d312a3437be5 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_listkeys_autorest.go @@ -0,0 +1,196 @@ +package configurationstores + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type ListKeysResponse struct { + HttpResponse *http.Response + Model *[]AccessKey + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (ListKeysResponse, error) +} + +type ListKeysCompleteResult struct { + Items []AccessKey +} + +func (r ListKeysResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r ListKeysResponse) LoadMore(ctx context.Context) (resp ListKeysResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +type AccessKeyPredicate struct { + // TODO: implement me +} + +func (p AccessKeyPredicate) Matches(input AccessKey) bool { + // TODO: implement me + // if p.Name != nil && input.Name != *p.Name { + // return false + // } + + return true +} + +// ListKeys ... +func (c ConfigurationStoresClient) ListKeys(ctx context.Context, id ConfigurationStoreId) (resp ListKeysResponse, err error) { + req, err := c.preparerForListKeys(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForListKeys(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// ListKeysCompleteMatchingPredicate retrieves all of the results into a single object +func (c ConfigurationStoresClient) ListKeysComplete(ctx context.Context, id ConfigurationStoreId) (ListKeysCompleteResult, error) { + return c.ListKeysCompleteMatchingPredicate(ctx, id, AccessKeyPredicate{}) +} + +// ListKeysCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c ConfigurationStoresClient) ListKeysCompleteMatchingPredicate(ctx context.Context, id ConfigurationStoreId, predicate AccessKeyPredicate) (resp ListKeysCompleteResult, err error) { + items := make([]AccessKey, 0) + + page, err := c.ListKeys(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := ListKeysCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForListKeys prepares the ListKeys request. +func (c ConfigurationStoresClient) preparerForListKeys(ctx context.Context, id ConfigurationStoreId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/listKeys", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForListKeysWithNextLink prepares the ListKeys request with the given nextLink token. +func (c ConfigurationStoresClient) preparerForListKeysWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForListKeys handles the response to the ListKeys request. The method always +// closes the http.Response Body. +func (c ConfigurationStoresClient) responderForListKeys(resp *http.Response) (result ListKeysResponse, err error) { + type page struct { + Values []AccessKey `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result ListKeysResponse, err error) { + req, err := c.preparerForListKeysWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForListKeys(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "ListKeys", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_update_autorest.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_update_autorest.go new file mode 100644 index 000000000000..810ebbff1b64 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/method_update_autorest.go @@ -0,0 +1,75 @@ +package configurationstores + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type UpdateResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Update ... +func (c ConfigurationStoresClient) Update(ctx context.Context, id ConfigurationStoreId, input ConfigurationStoreUpdateParameters) (result UpdateResponse, err error) { + req, err := c.preparerForUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Update", nil, "Failure preparing request") + return + } + + result, err = c.senderForUpdate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "configurationstores.ConfigurationStoresClient", "Update", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// UpdateThenPoll performs Update then polls until it's completed +func (c ConfigurationStoresClient) UpdateThenPoll(ctx context.Context, id ConfigurationStoreId, input ConfigurationStoreUpdateParameters) error { + result, err := c.Update(ctx, id, input) + if err != nil { + return fmt.Errorf("performing Update: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Update: %+v", err) + } + + return nil +} + +// preparerForUpdate prepares the Update request. +func (c ConfigurationStoresClient) preparerForUpdate(ctx context.Context, id ConfigurationStoreId, input ConfigurationStoreUpdateParameters) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPatch(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForUpdate sends the Update request. The method will close the +// http.Response Body if it receives an error. +func (c ConfigurationStoresClient) senderForUpdate(ctx context.Context, req *http.Request) (future UpdateResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_accesskey.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_accesskey.go new file mode 100644 index 000000000000..4a9dc9adb1f3 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_accesskey.go @@ -0,0 +1,25 @@ +package configurationstores + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/formatting" +) + +type AccessKey struct { + ConnectionString *string `json:"connectionString,omitempty"` + ID *string `json:"id,omitempty"` + LastModified *string `json:"lastModified,omitempty"` + Name *string `json:"name,omitempty"` + ReadOnly *bool `json:"readOnly,omitempty"` + Value *string `json:"value,omitempty"` +} + +func (o AccessKey) ListLastModifiedAsTime() (*time.Time, error) { + return formatting.ParseAsDateFormat(o.LastModified, "2006-01-02T15:04:05Z07:00") +} + +func (o AccessKey) SetLastModifiedAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.LastModified = &formatted +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstore.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstore.go new file mode 100644 index 000000000000..ed42f14301e6 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstore.go @@ -0,0 +1,12 @@ +package configurationstores + +type ConfigurationStore struct { + Id *string `json:"id,omitempty"` + Identity *ResourceIdentity `json:"identity,omitempty"` + Location string `json:"location"` + Name *string `json:"name,omitempty"` + Properties *ConfigurationStoreProperties `json:"properties,omitempty"` + Sku Sku `json:"sku"` + Tags *map[string]string `json:"tags,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreproperties.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreproperties.go new file mode 100644 index 000000000000..5beb569402f8 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreproperties.go @@ -0,0 +1,25 @@ +package configurationstores + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/formatting" +) + +type ConfigurationStoreProperties struct { + CreationDate *string `json:"creationDate,omitempty"` + Encryption *EncryptionProperties `json:"encryption,omitempty"` + Endpoint *string `json:"endpoint,omitempty"` + PrivateEndpointConnections *[]PrivateEndpointConnection `json:"privateEndpointConnections,omitempty"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` + PublicNetworkAccess *PublicNetworkAccess `json:"publicNetworkAccess,omitempty"` +} + +func (o ConfigurationStoreProperties) ListCreationDateAsTime() (*time.Time, error) { + return formatting.ParseAsDateFormat(o.CreationDate, "2006-01-02T15:04:05Z07:00") +} + +func (o ConfigurationStoreProperties) SetCreationDateAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.CreationDate = &formatted +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstorepropertiesupdateparameters.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstorepropertiesupdateparameters.go new file mode 100644 index 000000000000..96ada82f5c6d --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstorepropertiesupdateparameters.go @@ -0,0 +1,6 @@ +package configurationstores + +type ConfigurationStorePropertiesUpdateParameters struct { + Encryption *EncryptionProperties `json:"encryption,omitempty"` + PublicNetworkAccess *PublicNetworkAccess `json:"publicNetworkAccess,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreupdateparameters.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreupdateparameters.go new file mode 100644 index 000000000000..86f2dcff447e --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_configurationstoreupdateparameters.go @@ -0,0 +1,8 @@ +package configurationstores + +type ConfigurationStoreUpdateParameters struct { + Identity *ResourceIdentity `json:"identity,omitempty"` + Properties *ConfigurationStorePropertiesUpdateParameters `json:"properties,omitempty"` + Sku *Sku `json:"sku,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_encryptionproperties.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_encryptionproperties.go new file mode 100644 index 000000000000..e53ec95700fc --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_encryptionproperties.go @@ -0,0 +1,5 @@ +package configurationstores + +type EncryptionProperties struct { + KeyVaultProperties *KeyVaultProperties `json:"keyVaultProperties,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_keyvaultproperties.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_keyvaultproperties.go new file mode 100644 index 000000000000..d013eaf7a730 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_keyvaultproperties.go @@ -0,0 +1,6 @@ +package configurationstores + +type KeyVaultProperties struct { + IdentityClientId *string `json:"identityClientId,omitempty"` + KeyIdentifier *string `json:"keyIdentifier,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpoint.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpoint.go new file mode 100644 index 000000000000..91860fa0d079 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpoint.go @@ -0,0 +1,5 @@ +package configurationstores + +type PrivateEndpoint struct { + Id *string `json:"id,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnection.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnection.go new file mode 100644 index 000000000000..4f64ddb79d0d --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnection.go @@ -0,0 +1,8 @@ +package configurationstores + +type PrivateEndpointConnection struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *PrivateEndpointConnectionProperties `json:"properties,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnectionproperties.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnectionproperties.go new file mode 100644 index 000000000000..85fa5c76899e --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privateendpointconnectionproperties.go @@ -0,0 +1,7 @@ +package configurationstores + +type PrivateEndpointConnectionProperties struct { + PrivateEndpoint *PrivateEndpoint `json:"privateEndpoint,omitempty"` + PrivateLinkServiceConnectionState PrivateLinkServiceConnectionState `json:"privateLinkServiceConnectionState"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privatelinkserviceconnectionstate.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privatelinkserviceconnectionstate.go new file mode 100644 index 000000000000..e42c185e0842 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_privatelinkserviceconnectionstate.go @@ -0,0 +1,7 @@ +package configurationstores + +type PrivateLinkServiceConnectionState struct { + ActionsRequired *ActionsRequired `json:"actionsRequired,omitempty"` + Description *string `json:"description,omitempty"` + Status *ConnectionStatus `json:"status,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_resourceidentity.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_resourceidentity.go new file mode 100644 index 000000000000..59b9a84556d6 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_resourceidentity.go @@ -0,0 +1,7 @@ +package configurationstores + +type ResourceIdentity struct { + PrincipalId *string `json:"principalId,omitempty"` + TenantId *string `json:"tenantId,omitempty"` + Type *IdentityType `json:"type,omitempty"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_sku.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_sku.go new file mode 100644 index 000000000000..6a4664e6af21 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/model_sku.go @@ -0,0 +1,5 @@ +package configurationstores + +type Sku struct { + Name string `json:"name"` +} diff --git a/azurerm/internal/services/appconfiguration/sdk/configurationstores/version.go b/azurerm/internal/services/appconfiguration/sdk/configurationstores/version.go new file mode 100644 index 000000000000..e5aea194ad34 --- /dev/null +++ b/azurerm/internal/services/appconfiguration/sdk/configurationstores/version.go @@ -0,0 +1,9 @@ +package configurationstores + +import "fmt" + +const defaultApiVersion = "2020-06-01" + +func userAgent() string { + return fmt.Sprintf("pandora/configurationstores/%s", defaultApiVersion) +} diff --git a/azurerm/internal/services/appconfiguration/transform.go b/azurerm/internal/services/appconfiguration/transform.go new file mode 100644 index 000000000000..e722d3a3c5eb --- /dev/null +++ b/azurerm/internal/services/appconfiguration/transform.go @@ -0,0 +1,24 @@ +package appconfiguration + +func flattenTags(input *map[string]string) map[string]*string { + output := make(map[string]*string) + if input == nil { + return output + } + + for k, v := range *input { + output[k] = &v + } + + return output +} + +func expandTags(input map[string]interface{}) *map[string]string { + output := make(map[string]string) + + for k, v := range input { + output[k] = v.(string) + } + + return &output +} diff --git a/azurerm/internal/services/appconfiguration/validate/configuration_store_id.go b/azurerm/internal/services/appconfiguration/validate/configuration_store_id.go deleted file mode 100644 index 9ae4995e247e..000000000000 --- a/azurerm/internal/services/appconfiguration/validate/configuration_store_id.go +++ /dev/null @@ -1,23 +0,0 @@ -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/parse" -) - -func ConfigurationStoreID(input interface{}, key string) (warnings []string, errors []error) { - v, ok := input.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected %q to be a string", key)) - return - } - - if _, err := parse.ConfigurationStoreID(v); err != nil { - errors = append(errors, err) - } - - return -} diff --git a/azurerm/internal/services/appconfiguration/validate/configuration_store_id_test.go b/azurerm/internal/services/appconfiguration/validate/configuration_store_id_test.go deleted file mode 100644 index b1a52db37d5d..000000000000 --- a/azurerm/internal/services/appconfiguration/validate/configuration_store_id_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package validate_test - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/appconfiguration/validate" -) - -func TestConfigurationStoreID(t *testing.T) { - cases := []struct { - Input string - Valid bool - }{ - - { - // empty - Input: "", - Valid: false, - }, - - { - // missing SubscriptionId - Input: "/", - Valid: false, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Valid: false, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Valid: false, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Valid: false, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/", - Valid: false, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/", - Valid: false, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.AppConfiguration/configurationStores/store1", - Valid: true, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/GROUP1/PROVIDERS/MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES/STORE1", - Valid: false, - }, - } - for _, tc := range cases { - t.Logf("[DEBUG] Testing Value %s", tc.Input) - _, errors := validate.ConfigurationStoreID(tc.Input, "test") - valid := len(errors) == 0 - - if tc.Valid != valid { - t.Fatalf("Expected %t but got %t", tc.Valid, valid) - } - } -} diff --git a/vendor/github.com/hashicorp/go-azure-helpers/formatting/dates.go b/vendor/github.com/hashicorp/go-azure-helpers/formatting/dates.go new file mode 100644 index 000000000000..b77e08e30638 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-helpers/formatting/dates.go @@ -0,0 +1,21 @@ +package formatting + +import ( + "fmt" + "time" +) + +// ParseAsDateFormat parses the given nilable string as a time.Time using the specified +// format (for example RFC3339) +func ParseAsDateFormat(input *string, format string) (*time.Time, error) { + if input == nil { + return nil, nil + } + + val, err := time.Parse(format, *input) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", *input, err) + } + + return &val, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-helpers/polling/poller.go b/vendor/github.com/hashicorp/go-azure-helpers/polling/poller.go new file mode 100644 index 000000000000..b1501bddb52e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-helpers/polling/poller.go @@ -0,0 +1,34 @@ +package polling + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type LongRunningPoller struct { + future *azure.Future + ctx context.Context + client autorest.Client +} + +// NewLongRunningPollerFromResponse creates a new LongRunningPoller from the HTTP Response +func NewLongRunningPollerFromResponse(ctx context.Context, resp *http.Response, client autorest.Client) (LongRunningPoller, error) { + poller := LongRunningPoller{ + ctx: ctx, + client: client, + } + future, err := azure.NewFutureFromResponse(resp) + if err != nil { + return poller, err + } + poller.future = &future + return poller, nil +} + +// PollUntilDone polls until this Long Running Poller is completed +func (fw *LongRunningPoller) PollUntilDone() error { + return fw.future.WaitForCompletionRef(fw.ctx, fw.client) +} diff --git a/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/ids.go b/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/ids.go new file mode 100644 index 000000000000..a77fde7238d2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/ids.go @@ -0,0 +1,112 @@ +package resourceids + +import ( + "fmt" + "net/url" + "strings" +) + +// ResourceID represents a parsed long-form Azure Resource Manager ID +// with the Subscription ID, Resource Group and the Provider as top- +// level fields, and other key-value pairs available via a map in the +// Path field. +type ResourceID struct { + SubscriptionID string + ResourceGroup string + Provider string + Path map[string]string +} + +// ParseAzureResourceID converts a long-form Azure Resource Manager ID +// into a ResourceID. +func ParseAzureResourceID(id string) (*ResourceID, error) { + idURL, err := url.ParseRequestURI(id) + if err != nil { + return nil, fmt.Errorf("parsing Azure ID: %s", err) + } + + path := idURL.Path + + path = strings.TrimPrefix(path, "/") + path = strings.TrimSuffix(path, "/") + + components := strings.Split(path, "/") + + // We should have an even number of key-value pairs. + if len(components)%2 != 0 { + return nil, fmt.Errorf("the number of path segments is not divisible by 2 in %q", path) + } + + var subscriptionID string + + // Put the constituent key-value pairs into a map + componentMap := make(map[string]string, len(components)/2) + for current := 0; current < len(components); current += 2 { + key := components[current] + value := components[current+1] + + // Check key/value for empty strings. + if key == "" || value == "" { + return nil, fmt.Errorf("Key/Value cannot be empty strings. Key: '%s', Value: '%s'", key, value) + } + + // Catch the subscriptionID before it can be overwritten by another "subscriptions" + // value in the ID which is the case for the Service Bus subscription resource + if key == "subscriptions" && subscriptionID == "" { + subscriptionID = value + } else { + componentMap[key] = value + } + } + + // Build up a TargetResourceID from the map + idObj := &ResourceID{} + idObj.Path = componentMap + + if subscriptionID != "" { + idObj.SubscriptionID = subscriptionID + } else { + return nil, fmt.Errorf("No subscription ID found in: %q", path) + } + + if resourceGroup, ok := componentMap["resourceGroups"]; ok { + idObj.ResourceGroup = resourceGroup + delete(componentMap, "resourceGroups") + } else if resourceGroup, ok := componentMap["resourcegroups"]; ok { + // Some Azure APIs are weird and provide things in lower case... + // However it's not clear whether the casing of other elements in the URI + // matter, so we explicitly look for that case here. + idObj.ResourceGroup = resourceGroup + delete(componentMap, "resourcegroups") + } + + // It is OK not to have a provider in the case of a resource group + if provider, ok := componentMap["providers"]; ok { + idObj.Provider = provider + delete(componentMap, "providers") + } + + return idObj, nil +} + +// PopSegment retrieves a segment from the Path and returns it +// if found it removes it from the Path then return the value +// if not found, this returns nil +func (id *ResourceID) PopSegment(name string) (string, error) { + val, ok := id.Path[name] + if !ok { + return "", fmt.Errorf("ID was missing the `%s` element", name) + } + + delete(id.Path, name) + return val, nil +} + +// ValidateNoEmptySegments validates ... +func (id *ResourceID) ValidateNoEmptySegments(sourceId string) error { + if len(id.Path) == 0 { + return nil + } + + return fmt.Errorf("ID contained more segments than required: %q, %v", sourceId, id.Path) +} diff --git a/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/interface.go b/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/interface.go new file mode 100644 index 000000000000..f3dc7418f42e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids/interface.go @@ -0,0 +1,11 @@ +package resourceids + +// Id defines a type for a ResourceId of some kind +type Id interface { + // ID returns the fully formatted ID for this Resource ID + ID() string + + // String returns a friendly description of the components of this Resource ID + // which is suitable for use in error messages (for example 'MyThing %q / Resource Group %q') + String() string +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f7a2b40336f3..2a9cf0c61b0b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -266,6 +266,9 @@ github.com/hashicorp/errwrap # github.com/hashicorp/go-azure-helpers v0.16.2 ## explicit github.com/hashicorp/go-azure-helpers/authentication +github.com/hashicorp/go-azure-helpers/formatting +github.com/hashicorp/go-azure-helpers/polling +github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids github.com/hashicorp/go-azure-helpers/resourceproviders github.com/hashicorp/go-azure-helpers/response github.com/hashicorp/go-azure-helpers/sender