diff --git a/internal/clients/builder.go b/internal/clients/builder.go index b8b02e95c498..ea3a891e31b6 100644 --- a/internal/clients/builder.go +++ b/internal/clients/builder.go @@ -158,7 +158,10 @@ func Build(ctx context.Context, builder ClientBuilder) (*Client, error) { if features.EnhancedValidationEnabled() { location.CacheSupportedLocations(ctx, *resourceManagerEndpoint) - resourceproviders.CacheSupportedProviders(ctx, client.Resource.ProvidersClient) + _, err := resourceproviders.CachedSupportedProviders(ctx, client.Resource.ProvidersClient) + if err != nil { + log.Printf("[DEBUG] error retrieving providers: %+v. Enhanced validation will be unavailable", err) + } } return &client, nil diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 80503127b8bb..f2d7f3a5e32c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -453,14 +453,14 @@ func buildClient(ctx context.Context, p *schema.Provider, d *schema.ResourceData if !skipProviderRegistration { // List all the available providers and their registration state to avoid unnecessary // requests. This also lets us check if the provider credentials are correct. - providerList, err := client.Resource.ProvidersClient.List(ctx, nil, "") + providerList, err := resourceproviders.CachedSupportedProviders(ctx, client.Resource.ProvidersClient) if err != nil { return nil, diag.Errorf("Unable to list provider registration status, it is possible that this is due to invalid "+ "credentials or the service principal does not have permission to use the Resource Manager API, Azure "+ "error: %s", err) } - availableResourceProviders := providerList.Values() + availableResourceProviders := *providerList requiredResourceProviders := resourceproviders.Required() if err := resourceproviders.EnsureRegistered(ctx, *client.Resource.ProvidersClient, availableResourceProviders, requiredResourceProviders); err != nil { diff --git a/internal/resourceproviders/azure.go b/internal/resourceproviders/azure.go index 9f4584901001..c44548fff8cc 100644 --- a/internal/resourceproviders/azure.go +++ b/internal/resourceproviders/azure.go @@ -7,22 +7,10 @@ import ( "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" ) -func availableResourceProviders(ctx context.Context, client *resources.ProvidersClient) (*[]string, error) { - providerNames := make([]string, 0) - providers, err := client.ListComplete(ctx, nil, "") +func availableResourceProviders(ctx context.Context, client *resources.ProvidersClient) ([]resources.Provider, error) { + providers, err := client.List(ctx, nil, "") if err != nil { return nil, fmt.Errorf("listing Resource Providers: %+v", err) } - for providers.NotDone() { - provider := providers.Value() - if provider.Namespace != nil { - providerNames = append(providerNames, *provider.Namespace) - } - - if err := providers.NextWithContext(ctx); err != nil { - return nil, err - } - } - - return &providerNames, nil + return providers.Values(), nil } diff --git a/internal/resourceproviders/cache.go b/internal/resourceproviders/cache.go index 37088100d1a8..3745cd05c9e0 100644 --- a/internal/resourceproviders/cache.go +++ b/internal/resourceproviders/cache.go @@ -2,22 +2,30 @@ package resourceproviders import ( "context" - "log" "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" ) // cachedResourceProviders can be (validly) nil - as such this shouldn't be relied on -var cachedResourceProviders *[]string +var cachedResourceProviders *[]resources.Provider -// CacheSupportedProviders attempts to retrieve the supported Resource Providers from the Resource Manager API +// CachedSupportedProviders returns cached the supported Resource Providers, if not cached it attempts to retrieve from the Resource Manager API // and caches them, for used in enhanced validation -func CacheSupportedProviders(ctx context.Context, client *resources.ProvidersClient) { +func CachedSupportedProviders(ctx context.Context, client *resources.ProvidersClient) (*[]resources.Provider, error) { + if cachedResourceProviders != nil { + return cachedResourceProviders, nil + } providers, err := availableResourceProviders(ctx, client) if err != nil { - log.Printf("[DEBUG] error retrieving providers: %s. Enhanced validation will be unavailable", err) - return + return nil, err } - - cachedResourceProviders = providers + cached := make([]resources.Provider, 0) + for _, provider := range providers { + cached = append(cached, resources.Provider{ + Namespace: provider.Namespace, + RegistrationState: provider.RegistrationState, + }) + } + cachedResourceProviders = &cached + return cachedResourceProviders, nil } diff --git a/internal/resourceproviders/validation.go b/internal/resourceproviders/validation.go index 78b509efde46..424e06435ab2 100644 --- a/internal/resourceproviders/validation.go +++ b/internal/resourceproviders/validation.go @@ -41,13 +41,19 @@ func enhancedValidation(i interface{}, k string) ([]string, []error) { found := false for _, provider := range *cachedResourceProviders { - if provider == v { + if provider.Namespace != nil && *provider.Namespace == v { found = true } } if !found { - providersJoined := strings.Join(*cachedResourceProviders, ", ") + cachedResourceProvidersNames := make([]string, 0) + for _, provider := range *cachedResourceProviders { + if provider.Namespace != nil { + cachedResourceProvidersNames = append(cachedResourceProvidersNames, *provider.Namespace) + } + } + providersJoined := strings.Join(cachedResourceProvidersNames, ", ") return nil, []error{ fmt.Errorf("%q was not found in the list of supported Resource Providers: %q", v, providersJoined), } diff --git a/internal/resourceproviders/validation_test.go b/internal/resourceproviders/validation_test.go index 1cc359a394d8..c4c562b56040 100644 --- a/internal/resourceproviders/validation_test.go +++ b/internal/resourceproviders/validation_test.go @@ -3,7 +3,9 @@ package resourceproviders import ( "testing" + "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" "github.com/hashicorp/terraform-provider-azurerm/internal/features" + "github.com/hashicorp/terraform-provider-azurerm/utils" ) func TestEnhancedValidationDisabled(t *testing.T) { @@ -68,7 +70,7 @@ func TestEnhancedValidationEnabled(t *testing.T) { }, } enhancedEnabled = true - cachedResourceProviders = &[]string{"Microsoft.Compute"} + cachedResourceProviders = &[]resources.Provider{{Namespace: utils.String("Microsoft.Compute")}} defer func() { enhancedEnabled = features.EnhancedValidationEnabled() cachedResourceProviders = nil