Skip to content

Commit

Permalink
appconfiguration: using the ListBySubscription endpoint rather than t…
Browse files Browse the repository at this point in the history
…he Resources API

This removes a dependency on the Resources API - plus also caches the Configuration Stores within the Subscription
when performing the expensive API call
  • Loading branch information
tombuildsstuff committed Nov 24, 2023
1 parent f461325 commit 741f90c
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/services/appconfiguration/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
81 changes: 34 additions & 47 deletions internal/services/appconfiguration/client/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
)
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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
}

Expand All @@ -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 {
Expand All @@ -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
}

Expand All @@ -157,23 +144,23 @@ 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 {
lock[cacheKey] = &sync.RWMutex{}
}
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
Expand Down

0 comments on commit 741f90c

Please sign in to comment.