Skip to content

Commit

Permalink
Merge pull request #24024 from hashicorp/refactor/privatednszone-use-…
Browse files Browse the repository at this point in the history
…listbysubscription

`d/private_dns_zone`: refactoring to use the `ListBySubscription` API rather than the Resources API
  • Loading branch information
tombuildsstuff authored Nov 27, 2023
2 parents 3ffc36f + 96cd2ac commit 174c63c
Show file tree
Hide file tree
Showing 26 changed files with 1,181 additions and 81 deletions.
48 changes: 48 additions & 0 deletions internal/services/privatedns/client/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package client

import (
"context"
"fmt"

"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/privatedns/2020-06-01/privatezones"
"github.com/hashicorp/go-azure-sdk/resource-manager/resources/2023-07-01/resourcegroups"
)

func (c *Client) FindPrivateDnsZoneId(ctx context.Context, resourceGroupsClient *resourcegroups.ResourceGroupsClient, subscriptionId commonids.SubscriptionId, name string) (*privatezones.PrivateDnsZoneId, error) {
opts := privatezones.DefaultListOperationOptions()
results, err := c.PrivateZonesClient.ListComplete(ctx, subscriptionId, opts)
if err != nil {
return nil, fmt.Errorf("listing the Private DNS Zones within %s: %+v", subscriptionId, err)
}

for _, item := range results.Items {
if item.Id == nil {
continue
}

itemId := *item.Id
parsed, err := privatezones.ParsePrivateDnsZoneIDInsensitively(itemId)
if err != nil {
return nil, fmt.Errorf("parsing %q as a Private DNS Zone ID: %+v", itemId, err)
}

if parsed.PrivateDnsZoneName != name {
continue
}

// however the Resource Group name isn't necessarily cased correctly, so now that we've found the Resource
// Group name let's pull the canonical casing from the Resource Groups API
resourceGroupId := commonids.NewResourceGroupID(parsed.SubscriptionId, parsed.ResourceGroupName)
resp, err := resourceGroupsClient.Get(ctx, resourceGroupId)
if err != nil {
return nil, fmt.Errorf("retrieving %s: %+v", resourceGroupId, err)
}
if model := resp.Model; model != nil && model.Name != nil {
parsed.ResourceGroupName = *model.Name
}
return parsed, nil
}

return nil, fmt.Errorf("No Private DNS Zones found with name: %q", name)
}
91 changes: 27 additions & 64 deletions internal/services/privatedns/private_dns_zone_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
package privatedns

import (
"context"
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-06-01/resources" // nolint: staticcheck
"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/tags"
"github.com/hashicorp/go-azure-sdk/resource-manager/privatedns/2020-06-01/privatezones"
Expand Down Expand Up @@ -64,90 +63,54 @@ func dataSourcePrivateDnsZone() *pluginsdk.Resource {
}

func dataSourcePrivateDnsZoneRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).PrivateDns.PrivateZonesClient
client := meta.(*clients.Client).PrivateDns
resourceGroupsClient := meta.(*clients.Client).Resource.ResourceGroupsClient
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id := privatezones.NewPrivateDnsZoneID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string))

var resp *privatezones.PrivateZone
if id.ResourceGroupName != "" {
zone, err := client.Get(ctx, id)
if err != nil || zone.Model == nil {
if response.WasNotFound(zone.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("reading %s: %+v", id, err)
}
resp = zone.Model
} else {
resourcesClient := meta.(*clients.Client).Resource.ResourcesClient

zone, err := findPrivateZone(ctx, client, resourcesClient, id.PrivateDnsZoneName)
if id.ResourceGroupName == "" {
// we need to discover the Private DNS Zone's resource group
subscriptionResourceId := commonids.NewSubscriptionID(subscriptionId)
zoneId, err := client.FindPrivateDnsZoneId(ctx, resourceGroupsClient, subscriptionResourceId, id.PrivateDnsZoneName)
if err != nil {
return err
}

if zone == nil {
if zoneId == nil {
return fmt.Errorf("unable to determine the Resource Group for Private DNS Zone %q in Subscription %q", id.PrivateDnsZoneName, id.SubscriptionId)
}

id.ResourceGroupName = zoneId.ResourceGroupName
}

resp, err := client.PrivateZonesClient.Get(ctx, id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}

resp = &zone.zone
id.ResourceGroupName = zone.resourceGroup
return fmt.Errorf("reading %s: %+v", id, err)
}

d.SetId(id.ID())

d.Set("name", id.PrivateDnsZoneName)
d.Set("resource_group_name", id.ResourceGroupName)

if props := resp.Properties; props != nil {
d.Set("number_of_record_sets", props.NumberOfRecordSets)
d.Set("max_number_of_record_sets", props.MaxNumberOfRecordSets)
d.Set("max_number_of_virtual_network_links", props.MaxNumberOfVirtualNetworkLinks)
d.Set("max_number_of_virtual_network_links_with_registration", props.MaxNumberOfVirtualNetworkLinksWithRegistration)
}

return tags.FlattenAndSet(d, resp.Tags)
}

type privateDnsZone struct {
zone privatezones.PrivateZone
resourceGroup string
}

func findPrivateZone(ctx context.Context, client *privatezones.PrivateZonesClient, resourcesClient *resources.Client, name string) (*privateDnsZone, error) {
filter := fmt.Sprintf("resourceType eq 'Microsoft.Network/privateDnsZones' and name eq '%s'", name)
privateZones, err := resourcesClient.List(ctx, filter, "", nil)
if err != nil {
return nil, fmt.Errorf("listing Private DNS Zones: %+v", err)
}

if len(privateZones.Values()) > 1 {
return nil, fmt.Errorf("More than one Private DNS Zone found with name: %q", name)
}

for _, z := range privateZones.Values() {
if z.ID == nil {
continue
}

id, err := privatezones.ParsePrivateDnsZoneID(*z.ID)
if err != nil {
continue
if model := resp.Model; model != nil {
if props := model.Properties; props != nil {
d.Set("number_of_record_sets", props.NumberOfRecordSets)
d.Set("max_number_of_record_sets", props.MaxNumberOfRecordSets)
d.Set("max_number_of_virtual_network_links", props.MaxNumberOfVirtualNetworkLinks)
d.Set("max_number_of_virtual_network_links_with_registration", props.MaxNumberOfVirtualNetworkLinksWithRegistration)
}

zone, err := client.Get(ctx, *id)
if err != nil || zone.Model == nil {
return nil, fmt.Errorf("retrieving %s: %+v", id, err)
if err := tags.FlattenAndSet(d, model.Tags); err != nil {
return err
}

return &privateDnsZone{
zone: *zone.Model,
resourceGroup: id.ResourceGroupName,
}, nil
}

return nil, fmt.Errorf("No Private DNS Zones found with name: %q", name)
return nil
}
47 changes: 30 additions & 17 deletions internal/services/resource/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,32 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/resources/2021-07-01/features"
"github.com/hashicorp/go-azure-sdk/resource-manager/resources/2022-02-01/templatespecversions"
"github.com/hashicorp/go-azure-sdk/resource-manager/resources/2022-09-01/providers"
"github.com/hashicorp/go-azure-sdk/resource-manager/resources/2023-07-01/resourcegroups"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

type Client struct {
DeploymentsClient *resources.DeploymentsClient
DeploymentScriptsClient *deploymentscripts.DeploymentScriptsClient
FeaturesClient *features.FeaturesClient
GroupsClient *resources.GroupsClient
LocksClient *managementlocks.ManagementLocksClient
PrivateLinkAssociationClient *privatelinkassociation.PrivateLinkAssociationClient
ResourceGroupsClient *resourcegroups.ResourceGroupsClient
ResourceManagementPrivateLinkClient *resourcemanagementprivatelink.ResourceManagementPrivateLinkClient
ResourceProvidersClient *providers.ProvidersClient
ResourcesClient *resources.Client
TagsClient *resources.TagsClient
TemplateSpecsVersionsClient *templatespecversions.TemplateSpecVersionsClient

options *common.ClientOptions
// TODO: these SDK clients use `Azure/azure-sdk-for-go` - we should migrate to `hashicorp/go-azure-sdk`
// (above) as time allows.
DeploymentsClient *resources.DeploymentsClient
ResourcesClient *resources.Client
TagsClient *resources.TagsClient
options *common.ClientOptions

// Note that the Groups Client which requires additional coordination
GroupsClient *resources.GroupsClient
}

func NewClient(o *common.ClientOptions) (*Client, error) {
deploymentsClient := resources.NewDeploymentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&deploymentsClient.Client, o.ResourceManagerAuthorizer)

deploymentScriptsClient, err := deploymentscripts.NewDeploymentScriptsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building DeploymentScripts client: %+v", err)
Expand All @@ -49,8 +52,11 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(featuresClient.Client, o.Authorizers.ResourceManager)

groupsClient := resources.NewGroupsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&groupsClient.Client, o.ResourceManagerAuthorizer)
resourceGroupsClient, err := resourcegroups.NewResourceGroupsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Features client: %+v", err)
}
o.Configure(resourceGroupsClient.Client, o.Authorizers.ResourceManager)

locksClient, err := managementlocks.NewManagementLocksClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
Expand All @@ -76,32 +82,39 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(resourceProvidersClient.Client, o.Authorizers.ResourceManager)

resourcesClient := resources.NewClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&resourcesClient.Client, o.ResourceManagerAuthorizer)

templateSpecsVersionsClient, err := templatespecversions.NewTemplateSpecVersionsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building TemplateSpecVersions client: %+v", err)
}
o.Configure(templateSpecsVersionsClient.Client, o.Authorizers.ResourceManager)

// NOTE: these clients use `Azure/azure-sdk-for-go` and can be removed in time
deploymentsClient := resources.NewDeploymentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&deploymentsClient.Client, o.ResourceManagerAuthorizer)
groupsClient := resources.NewGroupsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&groupsClient.Client, o.ResourceManagerAuthorizer)
resourcesClient := resources.NewClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&resourcesClient.Client, o.ResourceManagerAuthorizer)
tagsClient := resources.NewTagsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&tagsClient.Client, o.ResourceManagerAuthorizer)

return &Client{
GroupsClient: &groupsClient,
// These come from `hashicorp/go-azure-sdk`
DeploymentsClient: &deploymentsClient,
DeploymentScriptsClient: deploymentScriptsClient,
FeaturesClient: featuresClient,
LocksClient: locksClient,
PrivateLinkAssociationClient: privateLinkAssociationClient,
ResourceManagementPrivateLinkClient: resourceManagementPrivateLinkClient,
ResourceGroupsClient: resourceGroupsClient,
ResourceProvidersClient: resourceProvidersClient,
ResourcesClient: &resourcesClient,
TagsClient: &tagsClient,
TemplateSpecsVersionsClient: templateSpecsVersionsClient,

options: o,
// These use `Azure/azure-sdk-for-go`
GroupsClient: &groupsClient,
ResourcesClient: &resourcesClient,
TagsClient: &tagsClient,
options: o,
}, nil
}

Expand Down
Loading

0 comments on commit 174c63c

Please sign in to comment.