From a7ebe7f6859a85acb27972724db86d69974212ec Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Thu, 11 May 2023 11:53:04 +0800 Subject: [PATCH 01/11] add app configuration checkNameAvailability --- .../app_configuration_resource.go | 71 ++++++++++- .../app_configuration_resource_test.go | 2 - .../appconfiguration/client/client.go | 9 ++ .../2023-03-01/operations/README.md | 62 ++++++++++ .../2023-03-01/operations/client.go | 26 ++++ .../2023-03-01/operations/constants.go | 48 ++++++++ .../2023-03-01/operations/id_location.go | 114 ++++++++++++++++++ .../method_checknameavailability.go | 57 +++++++++ .../method_regionalchecknameavailability.go | 56 +++++++++ .../model_checknameavailabilityparameters.go | 9 ++ .../model_nameavailabilitystatus.go | 10 ++ .../2023-03-01/operations/version.go | 12 ++ vendor/modules.txt | 1 + 13 files changed, 473 insertions(+), 4 deletions(-) create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/README.md create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/client.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/constants.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_checknameavailability.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_regionalchecknameavailability.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_checknameavailabilityparameters.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_nameavailabilitystatus.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/version.go diff --git a/internal/services/appconfiguration/app_configuration_resource.go b/internal/services/appconfiguration/app_configuration_resource.go index 7db443ef6936..ead9b2e9be95 100644 --- a/internal/services/appconfiguration/app_configuration_resource.go +++ b/internal/services/appconfiguration/app_configuration_resource.go @@ -10,12 +10,14 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/deletedconfigurationstores" + "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations" "github.com/hashicorp/go-azure-sdk/sdk/client" "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" @@ -231,6 +233,7 @@ func resourceAppConfiguration() *pluginsdk.Resource { func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).AppConfiguration.ConfigurationStoresClient deletedConfigurationStoresClient := meta.(*clients.Client).AppConfiguration.DeletedConfigurationStoresClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -300,7 +303,13 @@ func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) return fmt.Errorf("expanding `identity`: %+v", err) } parameters.Identity = identity - // TODO: retry checkNameAvailability before creation when SDK is ready, see https://github.com/Azure/AppConfiguration/issues/677 + + // retry checkNameAvailability until the name is released by purged app configuration, see https://github.com/Azure/AppConfiguration/issues/677 + operationsClient := meta.(*clients.Client).AppConfiguration.OperationsClient + if err = resourceConfigurationStoreWaitForNameAvailable(ctx, operationsClient, resourceId); err != nil { + return err + } + if err := client.CreateThenPoll(ctx, resourceId, parameters); err != nil { return fmt.Errorf("creating %s: %+v", resourceId, err) } @@ -571,7 +580,11 @@ func resourceAppConfigurationDelete(d *pluginsdk.ResourceData, meta interface{}) return fmt.Errorf("polling after purging for %s: %+v", *id, err) } - // TODO: retry checkNameAvailability after deletion when SDK is ready, see https://github.com/Azure/AppConfiguration/issues/677 + // retry checkNameAvailability until the name is released by purged app configuration, see https://github.com/Azure/AppConfiguration/issues/677 + operationsClient := meta.(*clients.Client).AppConfiguration.OperationsClient + if err = resourceConfigurationStoreWaitForNameAvailable(ctx, operationsClient, *id); err != nil { + return err + } log.Printf("[DEBUG] Purged AppConfiguration %q.", id.ConfigurationStoreName) } @@ -732,3 +745,57 @@ func parsePublicNetworkAccess(input string) *configurationstores.PublicNetworkAc out := configurationstores.PublicNetworkAccess(input) return &out } + +func resourceConfigurationStoreWaitForNameAvailable(ctx context.Context, client *operations.OperationsClient, configurationStoreId configurationstores.ConfigurationStoreId) error { + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("internal error: context had no deadline") + } + state := &pluginsdk.StateChangeConf{ + MinTimeout: 10 * time.Second, + ContinuousTargetOccurence: 2, + Pending: []string{"Unavailable"}, + Target: []string{"Available"}, + Refresh: resourceConfigurationStoreNameAvailabilityRefreshFunc(ctx, client, configurationStoreId), + Timeout: time.Until(deadline), + } + + _, err := state.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf("waiting for the Configuration Store %s Name Available: %+v", configurationStoreId, err) + } + + return nil + +} + +func resourceConfigurationStoreNameAvailabilityRefreshFunc(ctx context.Context, client *operations.OperationsClient, configurationStoreId configurationstores.ConfigurationStoreId) pluginsdk.StateRefreshFunc { + return func() (interface{}, string, error) { + log.Printf("[DEBUG] Checking to see if Configuration Store %s is name available ..", configurationStoreId) + + subscriptionId := commonids.NewSubscriptionID(configurationStoreId.SubscriptionId) + + parameters := operations.CheckNameAvailabilityParameters{ + Name: configurationStoreId.ConfigurationStoreName, + Type: operations.ConfigurationResourceTypeMicrosoftPointAppConfigurationConfigurationStores, + } + + resp, err := client.CheckNameAvailability(ctx, subscriptionId, parameters) + if err != nil { + return resp, "Error", fmt.Errorf("retrieving Deployment: %+v", err) + } + + if resp.Model == nil { + return resp, "Error", fmt.Errorf("unexpected null model of %s", configurationStoreId) + } + + if resp.Model.NameAvailable == nil { + return resp, "Error", fmt.Errorf("unexpected null NameAvailable property of %s", configurationStoreId) + } + + if !*resp.Model.NameAvailable { + return resp, "Unavailable", nil + } + return resp, "Available", nil + } +} diff --git a/internal/services/appconfiguration/app_configuration_resource_test.go b/internal/services/appconfiguration/app_configuration_resource_test.go index 7532f3f5338d..d1378a258944 100644 --- a/internal/services/appconfiguration/app_configuration_resource_test.go +++ b/internal/services/appconfiguration/app_configuration_resource_test.go @@ -260,8 +260,6 @@ func TestAccAppConfiguration_softDeleteRecoveryDisabled(t *testing.T) { }) } -// This test may fail due to service API behaviour -// TODO: retry checkNameAvailability to fix this test when SDK is ready, see https://github.com/Azure/AppConfiguration/issues/677 func TestAccAppConfiguration_softDeletePurgeThenRecreate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_app_configuration", "test") r := AppConfigurationResource{} diff --git a/internal/services/appconfiguration/client/client.go b/internal/services/appconfiguration/client/client.go index fd2c212e42b2..e7fb06f429de 100644 --- a/internal/services/appconfiguration/client/client.go +++ b/internal/services/appconfiguration/client/client.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/deletedconfigurationstores" + "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations" authWrapper "github.com/hashicorp/go-azure-sdk/sdk/auth/autorest" "github.com/hashicorp/go-azure-sdk/sdk/environments" "github.com/hashicorp/terraform-provider-azurerm/internal/common" @@ -18,6 +19,7 @@ import ( type Client struct { ConfigurationStoresClient *configurationstores.ConfigurationStoresClient DeletedConfigurationStoresClient *deletedconfigurationstores.DeletedConfigurationStoresClient + OperationsClient *operations.OperationsClient authorizerFunc common.ApiAuthorizerFunc configureClientFunc func(c *autorest.Client, authorizer autorest.Authorizer) } @@ -129,9 +131,16 @@ func NewClient(o *common.ClientOptions) (*Client, error) { } o.Configure(deletedConfigurationStores.Client, o.Authorizers.ResourceManager) + operationsClient, err := operations.NewOperationsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("building Operations client: %+v", err) + } + o.Configure(operationsClient.Client, o.Authorizers.ResourceManager) + return &Client{ ConfigurationStoresClient: configurationStores, DeletedConfigurationStoresClient: deletedConfigurationStores, + OperationsClient: operationsClient, authorizerFunc: o.Authorizers.AuthorizerFunc, configureClientFunc: o.ConfigureClient, }, nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/README.md new file mode 100644 index 000000000000..92244b5914e2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/README.md @@ -0,0 +1,62 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations` Documentation + +The `operations` SDK allows for interaction with the Azure Resource Manager Service `appconfiguration` (API Version `2023-03-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations" +``` + + +### Client Initialization + +```go +client := operations.NewOperationsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `OperationsClient.CheckNameAvailability` + +```go +ctx := context.TODO() +id := operations.NewSubscriptionID("12345678-1234-9876-4563-123456789012") + +payload := operations.CheckNameAvailabilityParameters{ + // ... +} + + +read, err := client.CheckNameAvailability(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `OperationsClient.RegionalCheckNameAvailability` + +```go +ctx := context.TODO() +id := operations.NewLocationID("12345678-1234-9876-4563-123456789012", "locationValue") + +payload := operations.CheckNameAvailabilityParameters{ + // ... +} + + +read, err := client.RegionalCheckNameAvailability(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/client.go new file mode 100644 index 000000000000..c3543fd2469e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/client.go @@ -0,0 +1,26 @@ +package operations + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type OperationsClient struct { + Client *resourcemanager.Client +} + +func NewOperationsClientWithBaseURI(api environments.Api) (*OperationsClient, error) { + client, err := resourcemanager.NewResourceManagerClient(api, "operations", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating OperationsClient: %+v", err) + } + + return &OperationsClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/constants.go new file mode 100644 index 000000000000..ba229f1a3fbb --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/constants.go @@ -0,0 +1,48 @@ +package operations + +import ( + "encoding/json" + "fmt" + "strings" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ConfigurationResourceType string + +const ( + ConfigurationResourceTypeMicrosoftPointAppConfigurationConfigurationStores ConfigurationResourceType = "Microsoft.AppConfiguration/configurationStores" +) + +func PossibleValuesForConfigurationResourceType() []string { + return []string{ + string(ConfigurationResourceTypeMicrosoftPointAppConfigurationConfigurationStores), + } +} + +func (s *ConfigurationResourceType) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseConfigurationResourceType(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseConfigurationResourceType(input string) (*ConfigurationResourceType, error) { + vals := map[string]ConfigurationResourceType{ + "microsoft.appconfiguration/configurationstores": ConfigurationResourceTypeMicrosoftPointAppConfigurationConfigurationStores, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ConfigurationResourceType(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go new file mode 100644 index 000000000000..d5e5852f949a --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go @@ -0,0 +1,114 @@ +package operations + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +var _ resourceids.ResourceId = LocationId{} + +// LocationId is a struct representing the Resource ID for a Location +type LocationId struct { + SubscriptionId string + LocationName string +} + +// NewLocationID returns a new LocationId struct +func NewLocationID(subscriptionId string, locationName string) LocationId { + return LocationId{ + SubscriptionId: subscriptionId, + LocationName: locationName, + } +} + +// ParseLocationID parses 'input' into a LocationId +func ParseLocationID(input string) (*LocationId, error) { + parser := resourceids.NewParserFromResourceIdType(LocationId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := LocationId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.LocationName, ok = parsed.Parsed["locationName"]; !ok { + return nil, fmt.Errorf("the segment 'locationName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseLocationIDInsensitively parses 'input' case-insensitively into a LocationId +// note: this method should only be used for API response data and not user input +func ParseLocationIDInsensitively(input string) (*LocationId, error) { + parser := resourceids.NewParserFromResourceIdType(LocationId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := LocationId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.LocationName, ok = parsed.Parsed["locationName"]; !ok { + return nil, fmt.Errorf("the segment 'locationName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateLocationID checks that 'input' can be parsed as a Location ID +func ValidateLocationID(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 := ParseLocationID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Location ID +func (id LocationId) ID() string { + fmtString := "/subscriptions/%s/providers/Microsoft.AppConfiguration/locations/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.LocationName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Location ID +func (id LocationId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftAppConfiguration", "Microsoft.AppConfiguration", "Microsoft.AppConfiguration"), + resourceids.StaticSegment("staticLocations", "locations", "locations"), + resourceids.UserSpecifiedSegment("locationName", "locationValue"), + } +} + +// String returns a human-readable description of this Location ID +func (id LocationId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Location Name: %q", id.LocationName), + } + return fmt.Sprintf("Location (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_checknameavailability.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_checknameavailability.go new file mode 100644 index 000000000000..8d217eda6fec --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_checknameavailability.go @@ -0,0 +1,57 @@ +package operations + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CheckNameAvailabilityOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *NameAvailabilityStatus +} + +// CheckNameAvailability ... +func (c OperationsClient) CheckNameAvailability(ctx context.Context, id commonids.SubscriptionId, input CheckNameAvailabilityParameters) (result CheckNameAvailabilityOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodPost, + Path: fmt.Sprintf("%s/providers/Microsoft.AppConfiguration/checkNameAvailability", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + if err = resp.Unmarshal(&result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_regionalchecknameavailability.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_regionalchecknameavailability.go new file mode 100644 index 000000000000..2f8795c16dd8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/method_regionalchecknameavailability.go @@ -0,0 +1,56 @@ +package operations + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RegionalCheckNameAvailabilityOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *NameAvailabilityStatus +} + +// RegionalCheckNameAvailability ... +func (c OperationsClient) RegionalCheckNameAvailability(ctx context.Context, id LocationId, input CheckNameAvailabilityParameters) (result RegionalCheckNameAvailabilityOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodPost, + Path: fmt.Sprintf("%s/checkNameAvailability", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + if err = resp.Unmarshal(&result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_checknameavailabilityparameters.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_checknameavailabilityparameters.go new file mode 100644 index 000000000000..3aa13268d061 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_checknameavailabilityparameters.go @@ -0,0 +1,9 @@ +package operations + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CheckNameAvailabilityParameters struct { + Name string `json:"name"` + Type ConfigurationResourceType `json:"type"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_nameavailabilitystatus.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_nameavailabilitystatus.go new file mode 100644 index 000000000000..abec08ec6572 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/model_nameavailabilitystatus.go @@ -0,0 +1,10 @@ +package operations + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type NameAvailabilityStatus struct { + Message *string `json:"message,omitempty"` + NameAvailable *bool `json:"nameAvailable,omitempty"` + Reason *string `json:"reason,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/version.go new file mode 100644 index 000000000000..7f02904b82e4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/version.go @@ -0,0 +1,12 @@ +package operations + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2023-03-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/operations/%s", defaultApiVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 61c480affd9e..43dac62db24a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -152,6 +152,7 @@ github.com/hashicorp/go-azure-sdk/resource-manager/analysisservices/2017-08-01/s github.com/hashicorp/go-azure-sdk/resource-manager/apimanagement/2021-08-01/schema github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/deletedconfigurationstores +github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2020-11-20/workbooktemplatesapis github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2022-04-01/workbooksapis github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2022-06-15/webtestsapis From 6470fb836b5a9866f217c6d0a1fa747a31331404 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Thu, 11 May 2023 20:05:48 +0800 Subject: [PATCH 02/11] remove retry logic in create --- .../services/appconfiguration/app_configuration_resource.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration_resource.go b/internal/services/appconfiguration/app_configuration_resource.go index ead9b2e9be95..0c3571f6607b 100644 --- a/internal/services/appconfiguration/app_configuration_resource.go +++ b/internal/services/appconfiguration/app_configuration_resource.go @@ -304,12 +304,6 @@ func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) } parameters.Identity = identity - // retry checkNameAvailability until the name is released by purged app configuration, see https://github.com/Azure/AppConfiguration/issues/677 - operationsClient := meta.(*clients.Client).AppConfiguration.OperationsClient - if err = resourceConfigurationStoreWaitForNameAvailable(ctx, operationsClient, resourceId); err != nil { - return err - } - if err := client.CreateThenPoll(ctx, resourceId, parameters); err != nil { return fmt.Errorf("creating %s: %+v", resourceId, err) } From 3b889e2779472ec7a748549492aeafd68b4d4e9e Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Thu, 11 May 2023 20:34:41 +0800 Subject: [PATCH 03/11] go mod vendor --- .../appconfiguration/2023-03-01/operations/id_location.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go index d5e5852f949a..a8367fe1dc7d 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/operations/id_location.go @@ -38,11 +38,11 @@ func ParseLocationID(input string) (*LocationId, error) { id := LocationId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.LocationName, ok = parsed.Parsed["locationName"]; !ok { - return nil, fmt.Errorf("the segment 'locationName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "locationName", *parsed) } return &id, nil @@ -61,11 +61,11 @@ func ParseLocationIDInsensitively(input string) (*LocationId, error) { id := LocationId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.LocationName, ok = parsed.Parsed["locationName"]; !ok { - return nil, fmt.Errorf("the segment 'locationName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "locationName", *parsed) } return &id, nil From eefb7a26a663ed3ad57a4f5ea41dfb5014edd237 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Thu, 11 May 2023 21:30:32 +0800 Subject: [PATCH 04/11] increace fault tolerance --- .../app_configuration_feature_resource.go | 11 ++++++----- .../app_configuration_key_resource.go | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index f132e7350d2b..1ac8a33fd80b 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -214,11 +214,12 @@ func (k FeatureResource) Create() sdk.ResourceFunc { // allow some time for role permission to be done propagated metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be done propagated", featureKey) stateConf := &pluginsdk.StateChangeConf{ - Pending: []string{"Forbidden"}, - Target: []string{"Error", "Exists"}, - Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, featureKey, model.Label), - PollInterval: 20 * time.Second, - Timeout: time.Until(deadline), + Pending: []string{"Forbidden"}, + Target: []string{"Error", "Exists"}, + Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, featureKey, model.Label), + PollInterval: 20 * time.Second, + ContinuousTargetOccurence: 3, + Timeout: time.Until(deadline), } if _, err = stateConf.WaitForStateContext(ctx); err != nil { diff --git a/internal/services/appconfiguration/app_configuration_key_resource.go b/internal/services/appconfiguration/app_configuration_key_resource.go index c479f3c14b5e..64340a0f50f3 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -153,11 +153,12 @@ func (k KeyResource) Create() sdk.ResourceFunc { // allow some time for role permission to be done propagated metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be done propagated", model.Key) stateConf := &pluginsdk.StateChangeConf{ - Pending: []string{"Forbidden"}, - Target: []string{"Error", "Exists"}, - Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), - PollInterval: 20 * time.Second, - Timeout: time.Until(deadline), + Pending: []string{"Forbidden"}, + Target: []string{"Error", "Exists"}, + Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), + PollInterval: 20 * time.Second, + ContinuousTargetOccurence: 3, + Timeout: time.Until(deadline), } if _, err = stateConf.WaitForStateContext(ctx); err != nil { From 1825a270d8ae531dfcf763221a6854a08720bc04 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Tue, 23 May 2023 13:58:48 +0800 Subject: [PATCH 05/11] switch list method --- .../app_configuration_feature_resource.go | 5 +- .../app_configuration_key_resource.go | 5 +- .../appconfiguration/client/helpers.go | 48 +++++-------------- 3 files changed, 17 insertions(+), 41 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index 1ac8a33fd80b..7d998d85bcd2 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -259,8 +259,9 @@ func (k FeatureResource) Read() sdk.ResourceFunc { return fmt.Errorf("while parsing resource ID: %+v", err) } - resourceClient := metadata.Client.Resource - configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, resourceClient, nestedItemId.ConfigurationStoreEndpoint) + configurationStoresClient := metadata.Client.AppConfiguration.ConfigurationStoresClient + subscriptionId := metadata.Client.Account.SubscriptionId + configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, configurationStoresClient, nestedItemId.ConfigurationStoreEndpoint, subscriptionId) if err != nil { return fmt.Errorf("while retrieving the Resource ID of Configuration Store at Endpoint: %q: %s", nestedItemId.ConfigurationStoreEndpoint, err) } diff --git a/internal/services/appconfiguration/app_configuration_key_resource.go b/internal/services/appconfiguration/app_configuration_key_resource.go index 64340a0f50f3..1c7b6627ae70 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -223,8 +223,9 @@ func (k KeyResource) Read() sdk.ResourceFunc { return fmt.Errorf("while parsing resource ID: %+v", err) } - resourceClient := metadata.Client.Resource - configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, resourceClient, nestedItemId.ConfigurationStoreEndpoint) + configurationStoresClient := metadata.Client.AppConfiguration.ConfigurationStoresClient + subscriptionId := metadata.Client.Account.SubscriptionId + configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, configurationStoresClient, nestedItemId.ConfigurationStoreEndpoint, subscriptionId) if err != nil { return fmt.Errorf("while retrieving the Resource ID of Configuration Store at Endpoint: %q: %s", nestedItemId.ConfigurationStoreEndpoint, err) } diff --git a/internal/services/appconfiguration/client/helpers.go b/internal/services/appconfiguration/client/helpers.go index b9bcc141bf5f..c490c60f4752 100644 --- a/internal/services/appconfiguration/client/helpers.go +++ b/internal/services/appconfiguration/client/helpers.go @@ -8,9 +8,8 @@ import ( "sync" "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" - resourcesClient "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/client" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) var ( @@ -34,7 +33,7 @@ func (c Client) AddToCache(configurationStoreId configurationstores.Configuratio keysmith.Unlock() } -func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, resourcesClient *resourcesClient.Client, configurationStoreEndpoint string) (*string, error) { +func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, configurationStoresClient *configurationstores.ConfigurationStoresClient, configurationStoreEndpoint string, subscriptionId string) (*string, error) { configurationStoreName, err := c.parseNameFromEndpoint(configurationStoreEndpoint) if err != nil { return nil, err @@ -53,42 +52,17 @@ func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, resourcesC return &v.configurationStoreId, nil } - filter := fmt.Sprintf("resourceType eq 'Microsoft.AppConfiguration/configurationStores' and name eq '%s'", *configurationStoreName) - result, err := resourcesClient.ResourcesClient.List(ctx, filter, "", utils.Int32(5)) + subscriptionIdStruct := commonids.NewSubscriptionID(subscriptionId) + predicate := configurationstores.ConfigurationStoreOperationPredicate{ + Name: configurationStoreName, + } + result, err := configurationStoresClient.ListCompleteMatchingPredicate(ctx, subscriptionIdStruct, predicate) if err != nil { - return nil, fmt.Errorf("listing resources matching %q: %+v", filter, err) - } - - for result.NotDone() { - for _, v := range result.Values() { - if v.ID == nil { - continue - } - - id, err := configurationstores.ParseConfigurationStoreIDInsensitively(*v.ID) - if err != nil { - return nil, fmt.Errorf("parsing %q: %+v", *v.ID, err) - } - if !strings.EqualFold(id.ConfigurationStoreName, *configurationStoreName) { - continue - } - - resp, err := c.ConfigurationStoresClient.Get(ctx, *id) - if err != nil { - return nil, fmt.Errorf("retrieving %s: %+v", *id, err) - } - if resp.Model == nil || resp.Model.Properties == nil || resp.Model.Properties.Endpoint == nil { - return nil, fmt.Errorf("retrieving %s: `model.properties.Endpoint` was nil", *id) - } - - c.AddToCache(*id, *resp.Model.Properties.Endpoint) - - return utils.String(id.ID()), nil - } + return nil, fmt.Errorf("listing Configuration Stores: %+v", err) + } - if err := result.NextWithContext(ctx); err != nil { - return nil, fmt.Errorf("iterating over results: %+v", err) - } + if len(result.Items) != 0 { + return result.Items[0].Id, nil } // we haven't found it, but Data Sources and Resources need to handle this error separately From c3994a78d0c9c70521e468e038570822e7dd97c6 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Wed, 24 May 2023 15:18:06 +0800 Subject: [PATCH 06/11] add to cache when retrieve ID from endpoint --- internal/services/appconfiguration/client/helpers.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/services/appconfiguration/client/helpers.go b/internal/services/appconfiguration/client/helpers.go index c490c60f4752..b88d5c85977d 100644 --- a/internal/services/appconfiguration/client/helpers.go +++ b/internal/services/appconfiguration/client/helpers.go @@ -7,6 +7,7 @@ import ( "strings" "sync" + "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" @@ -62,7 +63,13 @@ func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, configurat } if len(result.Items) != 0 { - return result.Items[0].Id, nil + configurationStoreId, err := configurationstores.ParseConfigurationStoreID(*result.Items[0].Id) + if err != nil { + return nil, fmt.Errorf("parsing Configuration Store ID: %+v", err) + } + c.AddToCache(*configurationStoreId, configurationStoreEndpoint) + + return pointer.To(configurationStoreId.ID()), nil } // we haven't found it, but Data Sources and Resources need to handle this error separately From 30cb68e488fa8872b81f7394e035ace6776514f8 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Fri, 26 May 2023 17:01:51 +0800 Subject: [PATCH 07/11] cache app conf in create --- .../appconfiguration/app_configuration_resource.go | 12 ++++++++++++ internal/services/appconfiguration/client/helpers.go | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/services/appconfiguration/app_configuration_resource.go b/internal/services/appconfiguration/app_configuration_resource.go index 0c3571f6607b..2a0ec79df9be 100644 --- a/internal/services/appconfiguration/app_configuration_resource.go +++ b/internal/services/appconfiguration/app_configuration_resource.go @@ -309,6 +309,16 @@ func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) } d.SetId(resourceId.ID()) + + resp, err := client.Get(ctx, resourceId) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", resourceId, err) + } + if resp.Model == nil || resp.Model.Properties == nil || resp.Model.Properties.Endpoint == nil { + return fmt.Errorf("retrieving %s: `model.properties.Endpoint` was nil", resourceId) + } + meta.(*clients.Client).AppConfiguration.AddToCache(resourceId, *resp.Model.Properties.Endpoint) + return resourceAppConfigurationRead(d, meta) } @@ -582,6 +592,8 @@ func resourceAppConfigurationDelete(d *pluginsdk.ResourceData, meta interface{}) log.Printf("[DEBUG] Purged AppConfiguration %q.", id.ConfigurationStoreName) } + meta.(*clients.Client).AppConfiguration.RemoveFromCache(*id) + return nil } diff --git a/internal/services/appconfiguration/client/helpers.go b/internal/services/appconfiguration/client/helpers.go index b88d5c85977d..f25affc21890 100644 --- a/internal/services/appconfiguration/client/helpers.go +++ b/internal/services/appconfiguration/client/helpers.go @@ -135,7 +135,7 @@ func (c Client) Exists(ctx context.Context, configurationStoreId configurationst return true, nil } -func (c Client) Purge(configurationStoreId configurationstores.ConfigurationStoreId) { +func (c Client) RemoveFromCache(configurationStoreId configurationstores.ConfigurationStoreId) { cacheKey := c.cacheKeyForConfigurationStore(configurationStoreId.ConfigurationStoreName) keysmith.Lock() if lock[cacheKey] == nil { From 5ad6c67be00be10d53108a19f6042718029efcbe Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Fri, 26 May 2023 18:29:13 +0800 Subject: [PATCH 08/11] add state wait for key provision --- .../appconfiguration/app_configuration.go | 3 +++ .../app_configuration_feature_resource.go | 22 ++++++++++++++----- .../app_configuration_key_resource.go | 18 +++++++++++++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration.go b/internal/services/appconfiguration/app_configuration.go index f21103cb7bdf..aec69ba6073c 100644 --- a/internal/services/appconfiguration/app_configuration.go +++ b/internal/services/appconfiguration/app_configuration.go @@ -30,6 +30,9 @@ func appConfigurationGetKeyRefreshFunc(ctx context.Context, client *appconfigura if utils.ResponseWasForbidden(autorest.Response{Response: v.Response}) { return "Forbidden", "Forbidden", nil } + if utils.ResponseWasNotFound(autorest.Response{Response: v.Response}) { + return "NotFound", "NotFound", nil + } } return res, "Error", nil } diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index 7d998d85bcd2..47e0165de00a 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -212,12 +212,12 @@ func (k FeatureResource) Create() sdk.ResourceFunc { // from https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-enable-rbac#azure-built-in-roles-for-azure-app-configuration // allow some time for role permission to be done propagated - metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be done propagated", featureKey) + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q read permission to be done propagated", featureKey) stateConf := &pluginsdk.StateChangeConf{ Pending: []string{"Forbidden"}, - Target: []string{"Error", "Exists"}, + Target: []string{"Error", "Exists", "NotFound"}, Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, featureKey, model.Label), - PollInterval: 20 * time.Second, + PollInterval: 10 * time.Second, ContinuousTargetOccurence: 3, Timeout: time.Until(deadline), } @@ -244,6 +244,20 @@ func (k FeatureResource) Create() sdk.ResourceFunc { return fmt.Errorf("while creating feature: %+v", err) } + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q to be done provisioned", model.Key) + stateConf = &pluginsdk.StateChangeConf{ + Pending: []string{"NotFound"}, + Target: []string{"Exists"}, + Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), + PollInterval: 10 * time.Second, + ContinuousTargetOccurence: 2, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for App Configuration Feature %q read permission to be propagated: %+v", model.Key, err) + } + metadata.SetID(nestedItemId) return nil }, @@ -296,8 +310,6 @@ func (k FeatureResource) Read() sdk.ResourceFunc { if utils.ResponseWasNotFound(autorest.Response{Response: v.Response}) { return metadata.MarkAsGone(nestedItemId) } - } else { - return fmt.Errorf("while checking for key %q existence: %+v", *nestedItemId, err) } return fmt.Errorf("while checking for key %q existence: %+v", *nestedItemId, err) } diff --git a/internal/services/appconfiguration/app_configuration_key_resource.go b/internal/services/appconfiguration/app_configuration_key_resource.go index 1c7b6627ae70..b01fb1bb337b 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -154,9 +154,9 @@ func (k KeyResource) Create() sdk.ResourceFunc { metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be done propagated", model.Key) stateConf := &pluginsdk.StateChangeConf{ Pending: []string{"Forbidden"}, - Target: []string{"Error", "Exists"}, + Target: []string{"Error", "Exists", "NotFound"}, Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), - PollInterval: 20 * time.Second, + PollInterval: 10 * time.Second, ContinuousTargetOccurence: 3, Timeout: time.Until(deadline), } @@ -208,6 +208,20 @@ func (k KeyResource) Create() sdk.ResourceFunc { } } + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q to be done provisioned", model.Key) + stateConf = &pluginsdk.StateChangeConf{ + Pending: []string{"NotFound"}, + Target: []string{"Exists"}, + Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), + PollInterval: 10 * time.Second, + ContinuousTargetOccurence: 2, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for App Configuration Key %q read permission to be propagated: %+v", model.Key, err) + } + metadata.SetID(nestedItemId) return nil }, From 50ac61897d8026ad9fe4757a33cc70e1732b99b0 Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Fri, 26 May 2023 22:21:58 +0800 Subject: [PATCH 09/11] fix feature key --- .../appconfiguration/app_configuration_feature_resource.go | 6 +++--- .../appconfiguration/app_configuration_key_resource.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index 47e0165de00a..9bb2f94eb600 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -223,7 +223,7 @@ func (k FeatureResource) Create() sdk.ResourceFunc { } if _, err = stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for App Configuration Key %q read permission to be propagated: %+v", featureKey, err) + return fmt.Errorf("waiting for App Configuration Feature %q read permission to be propagated: %+v", featureKey, err) } kv, err := client.GetKeyValue(ctx, featureKey, model.Label, "", "", "", []appconfiguration.KeyValueFields{}) @@ -248,14 +248,14 @@ func (k FeatureResource) Create() sdk.ResourceFunc { stateConf = &pluginsdk.StateChangeConf{ Pending: []string{"NotFound"}, Target: []string{"Exists"}, - Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, model.Key, model.Label), + Refresh: appConfigurationGetKeyRefreshFunc(ctx, client, featureKey, model.Label), PollInterval: 10 * time.Second, ContinuousTargetOccurence: 2, Timeout: time.Until(deadline), } if _, err = stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for App Configuration Feature %q read permission to be propagated: %+v", model.Key, err) + return fmt.Errorf("waiting for App Configuration Feature %q to be provisioned: %+v", featureKey, err) } metadata.SetID(nestedItemId) diff --git a/internal/services/appconfiguration/app_configuration_key_resource.go b/internal/services/appconfiguration/app_configuration_key_resource.go index b01fb1bb337b..a2e6e390903a 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -219,7 +219,7 @@ func (k KeyResource) Create() sdk.ResourceFunc { } if _, err = stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for App Configuration Key %q read permission to be propagated: %+v", model.Key, err) + return fmt.Errorf("waiting for App Configuration Key %q to be provisioned: %+v", model.Key, err) } metadata.SetID(nestedItemId) From eb897d48071716538ebdf86c838cc507af5ee8ca Mon Sep 17 00:00:00 2001 From: Tao <104055472+teowa@users.noreply.github.com> Date: Wed, 31 May 2023 13:27:47 +0800 Subject: [PATCH 10/11] fix error message and link to https://github.com/Azure/AppConfiguration/issues/763 --- internal/services/appconfiguration/app_configuration.go | 6 +++--- .../appconfiguration/app_configuration_feature_resource.go | 7 ++++--- .../appconfiguration/app_configuration_key_resource.go | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration.go b/internal/services/appconfiguration/app_configuration.go index aec69ba6073c..2886eca39098 100644 --- a/internal/services/appconfiguration/app_configuration.go +++ b/internal/services/appconfiguration/app_configuration.go @@ -4,9 +4,9 @@ import ( "context" "github.com/Azure/go-autorest/autorest" + "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" "github.com/tombuildsstuff/kermit/sdk/appconfiguration/1.0/appconfiguration" ) @@ -27,10 +27,10 @@ func appConfigurationGetKeyRefreshFunc(ctx context.Context, client *appconfigura res, err := client.GetKeyValue(ctx, key, label, "", "", "", []appconfiguration.KeyValueFields{}) if err != nil { if v, ok := err.(autorest.DetailedError); ok { - if utils.ResponseWasForbidden(autorest.Response{Response: v.Response}) { + if response.WasForbidden(v.Response) { return "Forbidden", "Forbidden", nil } - if utils.ResponseWasNotFound(autorest.Response{Response: v.Response}) { + if response.WasNotFound(v.Response) { return "NotFound", "NotFound", nil } } diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index 9bb2f94eb600..e8807e563b9a 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -211,8 +211,8 @@ func (k FeatureResource) Create() sdk.ResourceFunc { } // from https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-enable-rbac#azure-built-in-roles-for-azure-app-configuration - // allow some time for role permission to be done propagated - metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q read permission to be done propagated", featureKey) + // allow some time for role permission to be propagated + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q read permission to be propagated", featureKey) stateConf := &pluginsdk.StateChangeConf{ Pending: []string{"Forbidden"}, Target: []string{"Error", "Exists", "NotFound"}, @@ -244,7 +244,8 @@ func (k FeatureResource) Create() sdk.ResourceFunc { return fmt.Errorf("while creating feature: %+v", err) } - metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q to be done provisioned", model.Key) + // https://github.com/Azure/AppConfiguration/issues/763 + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Feature %q to be provisioned", model.Key) stateConf = &pluginsdk.StateChangeConf{ Pending: []string{"NotFound"}, Target: []string{"Exists"}, diff --git a/internal/services/appconfiguration/app_configuration_key_resource.go b/internal/services/appconfiguration/app_configuration_key_resource.go index a2e6e390903a..f0e5c33ca10b 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -150,8 +150,8 @@ func (k KeyResource) Create() sdk.ResourceFunc { } // from https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-enable-rbac#azure-built-in-roles-for-azure-app-configuration - // allow some time for role permission to be done propagated - metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be done propagated", model.Key) + // allow some time for role permission to be propagated + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q read permission to be propagated", model.Key) stateConf := &pluginsdk.StateChangeConf{ Pending: []string{"Forbidden"}, Target: []string{"Error", "Exists", "NotFound"}, @@ -208,7 +208,8 @@ func (k KeyResource) Create() sdk.ResourceFunc { } } - metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q to be done provisioned", model.Key) + // https://github.com/Azure/AppConfiguration/issues/763 + metadata.Logger.Infof("[DEBUG] Waiting for App Configuration Key %q to be provisioned", model.Key) stateConf = &pluginsdk.StateChangeConf{ Pending: []string{"NotFound"}, Target: []string{"Exists"}, From bba88a1f914a685fc1604bf1bc9461928aeedfff Mon Sep 17 00:00:00 2001 From: stephybun Date: Thu, 1 Jun 2023 10:27:55 +0200 Subject: [PATCH 11/11] rephrase error and log message for grammar --- .../services/appconfiguration/app_configuration_resource.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/services/appconfiguration/app_configuration_resource.go b/internal/services/appconfiguration/app_configuration_resource.go index 2a0ec79df9be..f566f11ae8ac 100644 --- a/internal/services/appconfiguration/app_configuration_resource.go +++ b/internal/services/appconfiguration/app_configuration_resource.go @@ -768,7 +768,7 @@ func resourceConfigurationStoreWaitForNameAvailable(ctx context.Context, client _, err := state.WaitForStateContext(ctx) if err != nil { - return fmt.Errorf("waiting for the Configuration Store %s Name Available: %+v", configurationStoreId, err) + return fmt.Errorf("waiting for the Name from %s to become available: %+v", configurationStoreId, err) } return nil @@ -777,7 +777,7 @@ func resourceConfigurationStoreWaitForNameAvailable(ctx context.Context, client func resourceConfigurationStoreNameAvailabilityRefreshFunc(ctx context.Context, client *operations.OperationsClient, configurationStoreId configurationstores.ConfigurationStoreId) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - log.Printf("[DEBUG] Checking to see if Configuration Store %s is name available ..", configurationStoreId) + log.Printf("[DEBUG] Checking to see if the name for %s is available ..", configurationStoreId) subscriptionId := commonids.NewSubscriptionID(configurationStoreId.SubscriptionId)