diff --git a/internal/services/appconfiguration/app_configuration_feature_resource.go b/internal/services/appconfiguration/app_configuration_feature_resource.go index e9ab5b72bc75..786197e6b615 100644 --- a/internal/services/appconfiguration/app_configuration_feature_resource.go +++ b/internal/services/appconfiguration/app_configuration_feature_resource.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" @@ -333,8 +334,8 @@ 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) + subscriptionId := commonids.NewSubscriptionID(metadata.Client.Account.SubscriptionId) + configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, subscriptionId, nestedItemId.ConfigurationStoreEndpoint) 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 fadae00e2037..a16d702b9367 100644 --- a/internal/services/appconfiguration/app_configuration_key_resource.go +++ b/internal/services/appconfiguration/app_configuration_key_resource.go @@ -11,6 +11,7 @@ import ( "time" "github.com/Azure/go-autorest/autorest" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/configurationstores" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" @@ -241,8 +242,8 @@ 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) + subscriptionId := commonids.NewSubscriptionID(metadata.Client.Account.SubscriptionId) + configurationStoreIdRaw, err := metadata.Client.AppConfiguration.ConfigurationStoreIDFromEndpoint(ctx, subscriptionId, nestedItemId.ConfigurationStoreEndpoint) 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/client.go b/internal/services/appconfiguration/client/client.go index 9cb616eb0438..264a9bda4f58 100644 --- a/internal/services/appconfiguration/client/client.go +++ b/internal/services/appconfiguration/client/client.go @@ -27,7 +27,7 @@ type Client struct { configureClientFunc func(c *autorest.Client, authorizer autorest.Authorizer) } -func (c Client) DataPlaneClientWithEndpoint(configurationStoreEndpoint string) (*appconfiguration.BaseClient, error) { +func (c *Client) DataPlaneClientWithEndpoint(configurationStoreEndpoint string) (*appconfiguration.BaseClient, error) { api := environments.NewApiEndpoint("AppConfiguration", configurationStoreEndpoint, nil) appConfigAuth, err := c.authorizerFunc(api) if err != nil { @@ -40,7 +40,7 @@ func (c Client) DataPlaneClientWithEndpoint(configurationStoreEndpoint string) ( return &client, nil } -func (c Client) LinkWorkaroundDataPlaneClientWithEndpoint(configurationStoreEndpoint string) (*azuresdkhacks.DataPlaneClient, error) { +func (c *Client) LinkWorkaroundDataPlaneClientWithEndpoint(configurationStoreEndpoint string) (*azuresdkhacks.DataPlaneClient, error) { api := environments.NewApiEndpoint("AppConfiguration", configurationStoreEndpoint, nil) appConfigAuth, err := c.authorizerFunc(api) if err != nil { diff --git a/internal/services/appconfiguration/client/helpers.go b/internal/services/appconfiguration/client/helpers.go index ff69d9311e01..0be3ed3a0d7f 100644 --- a/internal/services/appconfiguration/client/helpers.go +++ b/internal/services/appconfiguration/client/helpers.go @@ -11,13 +11,12 @@ 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 ( - ConfigurationStoreCache = map[string]ConfigurationStoreDetails{} + configurationStoreCache = map[string]ConfigurationStoreDetails{} keysmith = &sync.RWMutex{} lock = map[string]*sync.RWMutex{} ) @@ -27,17 +26,17 @@ type ConfigurationStoreDetails struct { dataPlaneEndpoint string } -func (c Client) AddToCache(configurationStoreId configurationstores.ConfigurationStoreId, dataPlaneEndpoint string) { +func (c *Client) AddToCache(configurationStoreId configurationstores.ConfigurationStoreId, dataPlaneEndpoint string) { cacheKey := c.cacheKeyForConfigurationStore(configurationStoreId.ConfigurationStoreName) keysmith.Lock() - ConfigurationStoreCache[cacheKey] = ConfigurationStoreDetails{ + configurationStoreCache[cacheKey] = ConfigurationStoreDetails{ configurationStoreId: configurationStoreId.ID(), dataPlaneEndpoint: dataPlaneEndpoint, } keysmith.Unlock() } -func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, resourcesClient *resourcesClient.Client, configurationStoreEndpoint string) (*string, error) { +func (c *Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, subscriptionId commonids.SubscriptionId, configurationStoreEndpoint string) (*string, error) { configurationStoreName, err := c.parseNameFromEndpoint(configurationStoreEndpoint) if err != nil { return nil, err @@ -52,53 +51,41 @@ func (c Client) ConfigurationStoreIDFromEndpoint(ctx context.Context, resourcesC lock[cacheKey].Lock() defer lock[cacheKey].Unlock() - if v, ok := ConfigurationStoreCache[cacheKey]; ok { + // first check the cache + if v, ok := configurationStoreCache[cacheKey]; ok { 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)) + // If it's not present, populate the entire cache + configurationStores, err := c.ConfigurationStoresClient.ListComplete(ctx, subscriptionId) 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("retrieving the list of Configuration Stores in %s: %+v", subscriptionId, err) + } + for _, item := range configurationStores.Items { + if item.Id == nil || item.Properties == nil || item.Properties.Endpoint == nil { + continue } - if err := result.NextWithContext(ctx); err != nil { - return nil, fmt.Errorf("iterating over results: %+v", err) + itemId := *item.Id + endpointUri := *item.Properties.Endpoint + configurationStoreId, err := configurationstores.ParseConfigurationStoreIDInsensitively(itemId) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", itemId, err) } + + c.AddToCache(*configurationStoreId, endpointUri) + } + + // finally try and pull this from the cache + if v, ok := configurationStoreCache[cacheKey]; ok { + return &v.configurationStoreId, nil } // we haven't found it, but Data Sources and Resources need to handle this error separately return nil, nil } -func (c Client) EndpointForConfigurationStore(ctx context.Context, configurationStoreId configurationstores.ConfigurationStoreId) (*string, error) { +func (c *Client) EndpointForConfigurationStore(ctx context.Context, configurationStoreId configurationstores.ConfigurationStoreId) (*string, error) { cacheKey := c.cacheKeyForConfigurationStore(configurationStoreId.ConfigurationStoreName) keysmith.Lock() if lock[cacheKey] == nil { @@ -108,7 +95,7 @@ func (c Client) EndpointForConfigurationStore(ctx context.Context, configuration lock[cacheKey].Lock() defer lock[cacheKey].Unlock() - if v, ok := ConfigurationStoreCache[cacheKey]; ok { + if v, ok := configurationStoreCache[cacheKey]; ok { return &v.dataPlaneEndpoint, nil } @@ -126,7 +113,7 @@ func (c Client) EndpointForConfigurationStore(ctx context.Context, configuration return resp.Model.Properties.Endpoint, nil } -func (c Client) Exists(ctx context.Context, configurationStoreId configurationstores.ConfigurationStoreId) (bool, error) { +func (c *Client) Exists(ctx context.Context, configurationStoreId configurationstores.ConfigurationStoreId) (bool, error) { cacheKey := c.cacheKeyForConfigurationStore(configurationStoreId.ConfigurationStoreName) keysmith.Lock() if lock[cacheKey] == nil { @@ -136,7 +123,7 @@ func (c Client) Exists(ctx context.Context, configurationStoreId configurationst lock[cacheKey].Lock() defer lock[cacheKey].Unlock() - if _, ok := ConfigurationStoreCache[cacheKey]; ok { + if _, ok := configurationStoreCache[cacheKey]; ok { return true, nil } @@ -157,7 +144,7 @@ func (c Client) Exists(ctx context.Context, configurationStoreId configurationst return true, nil } -func (c Client) RemoveFromCache(configurationStoreId configurationstores.ConfigurationStoreId) { +func (c *Client) RemoveFromCache(configurationStoreId configurationstores.ConfigurationStoreId) { cacheKey := c.cacheKeyForConfigurationStore(configurationStoreId.ConfigurationStoreName) keysmith.Lock() if lock[cacheKey] == nil { @@ -165,15 +152,15 @@ func (c Client) RemoveFromCache(configurationStoreId configurationstores.Configu } keysmith.Unlock() lock[cacheKey].Lock() - delete(ConfigurationStoreCache, cacheKey) + delete(configurationStoreCache, cacheKey) lock[cacheKey].Unlock() } -func (c Client) cacheKeyForConfigurationStore(name string) string { +func (c *Client) cacheKeyForConfigurationStore(name string) string { return strings.ToLower(name) } -func (c Client) parseNameFromEndpoint(input string) (*string, error) { +func (c *Client) parseNameFromEndpoint(input string) (*string, error) { uri, err := url.ParseRequestURI(input) if err != nil { return nil, err