From cab2d49547926488d6c9f249ec5389010c3bee2b Mon Sep 17 00:00:00 2001 From: Heng Lu <79895375+ms-henglu@users.noreply.github.com> Date: Fri, 28 Oct 2022 06:46:39 +0800 Subject: [PATCH] new resource: `azurerm_private_dns_resolver_dns_forwarding_ruleset` (#19012) --- ...esolver_dns_forwarding_ruleset_resource.go | 262 ++++++++++++++++++ ...er_dns_forwarding_ruleset_resource_test.go | 208 ++++++++++++++ .../privatednsresolver/registration.go | 1 + ...olver_dns_forwarding_ruleset.html.markdown | 106 +++++++ 4 files changed, 577 insertions(+) create mode 100644 internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource.go create mode 100644 internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource_test.go create mode 100644 website/docs/r/private_dns_resolver_dns_forwarding_ruleset.html.markdown diff --git a/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource.go b/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource.go new file mode 100644 index 000000000000..938e7db70f94 --- /dev/null +++ b/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource.go @@ -0,0 +1,262 @@ +package privatednsresolver + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-sdk/resource-manager/dnsresolver/2022-07-01/dnsforwardingrulesets" + "github.com/hashicorp/go-azure-sdk/resource-manager/dnsresolver/2022-07-01/outboundendpoints" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type PrivateDNSResolverDnsForwardingRulesetModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + DnsResolverOutboundEndpoints []string `tfschema:"private_dns_resolver_outbound_endpoint_ids"` + Location string `tfschema:"location"` + Tags map[string]string `tfschema:"tags"` +} + +type PrivateDNSResolverDnsForwardingRulesetResource struct{} + +var _ sdk.ResourceWithUpdate = PrivateDNSResolverDnsForwardingRulesetResource{} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) ResourceType() string { + return "azurerm_private_dns_resolver_dns_forwarding_ruleset" +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) ModelObject() interface{} { + return &PrivateDNSResolverDnsForwardingRulesetModel{} +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return dnsforwardingrulesets.ValidateDnsForwardingRulesetID +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "private_dns_resolver_outbound_endpoint_ids": { + Type: pluginsdk.TypeList, + Required: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: outboundendpoints.ValidateOutboundEndpointID, + }, + }, + + "location": commonschema.Location(), + + "tags": commonschema.Tags(), + } +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model PrivateDNSResolverDnsForwardingRulesetModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + client := metadata.Client.PrivateDnsResolver.DnsForwardingRulesetsClient + subscriptionId := metadata.Client.Account.SubscriptionId + id := dnsforwardingrulesets.NewDnsForwardingRulesetID(subscriptionId, model.ResourceGroupName, model.Name) + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for existing %s: %+v", id, err) + } + + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + properties := &dnsforwardingrulesets.DnsForwardingRuleset{ + Location: location.Normalize(model.Location), + Properties: dnsforwardingrulesets.DnsForwardingRulesetProperties{}, + Tags: &model.Tags, + } + + dnsResolverOutboundEndpointsValue, err := expandDnsResolverOutboundEndpoints(model.DnsResolverOutboundEndpoints) + if err != nil { + return err + } + + if dnsResolverOutboundEndpointsValue != nil { + properties.Properties.DnsResolverOutboundEndpoints = *dnsResolverOutboundEndpointsValue + } + + if err := client.CreateOrUpdateThenPoll(ctx, id, *properties, dnsforwardingrulesets.CreateOrUpdateOperationOptions{}); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.PrivateDnsResolver.DnsForwardingRulesetsClient + + id, err := dnsforwardingrulesets.ParseDnsForwardingRulesetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var model PrivateDNSResolverDnsForwardingRulesetModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + resp, err := client.Get(ctx, *id) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + properties := resp.Model + if properties == nil { + return fmt.Errorf("retrieving %s: properties was nil", id) + } + + if metadata.ResourceData.HasChange("dns_resolver_outbound_endpoints") { + dnsResolverOutboundEndpointsValue, err := expandDnsResolverOutboundEndpoints(model.DnsResolverOutboundEndpoints) + if err != nil { + return err + } + + if dnsResolverOutboundEndpointsValue != nil { + properties.Properties.DnsResolverOutboundEndpoints = *dnsResolverOutboundEndpointsValue + } + } + + properties.SystemData = nil + + if metadata.ResourceData.HasChange("tags") { + properties.Tags = &model.Tags + } + + if err := client.CreateOrUpdateThenPoll(ctx, *id, *properties, dnsforwardingrulesets.CreateOrUpdateOperationOptions{}); err != nil { + return fmt.Errorf("updating %s: %+v", *id, err) + } + + return nil + }, + } +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.PrivateDnsResolver.DnsForwardingRulesetsClient + + id, err := dnsforwardingrulesets.ParseDnsForwardingRulesetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + model := resp.Model + if model == nil { + return fmt.Errorf("retrieving %s: model was nil", id) + } + + state := PrivateDNSResolverDnsForwardingRulesetModel{ + Name: id.DnsForwardingRulesetName, + ResourceGroupName: id.ResourceGroupName, + Location: location.Normalize(model.Location), + } + + properties := &model.Properties + dnsResolverOutboundEndpointsValue, err := flattenDnsResolverOutboundEndpoints(&properties.DnsResolverOutboundEndpoints) + if err != nil { + return err + } + + state.DnsResolverOutboundEndpoints = dnsResolverOutboundEndpointsValue + + if model.Tags != nil { + state.Tags = *model.Tags + } + + return metadata.Encode(&state) + }, + } +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.PrivateDnsResolver.DnsForwardingRulesetsClient + + id, err := dnsforwardingrulesets.ParseDnsForwardingRulesetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err := client.DeleteThenPoll(ctx, *id, dnsforwardingrulesets.DeleteOperationOptions{}); err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) + } + + return nil + }, + } +} + +func expandDnsResolverOutboundEndpoints(inputList []string) (*[]dnsforwardingrulesets.SubResource, error) { + var outputList []dnsforwardingrulesets.SubResource + for _, v := range inputList { + output := dnsforwardingrulesets.SubResource{ + Id: v, + } + outputList = append(outputList, output) + } + + return &outputList, nil +} + +func flattenDnsResolverOutboundEndpoints(inputList *[]dnsforwardingrulesets.SubResource) ([]string, error) { + var outputList []string + if inputList == nil { + return outputList, nil + } + + for _, input := range *inputList { + output := input.Id + outputList = append(outputList, output) + } + + return outputList, nil +} diff --git a/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource_test.go b/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource_test.go new file mode 100644 index 000000000000..2ba57d686a1a --- /dev/null +++ b/internal/services/privatednsresolver/private_dns_resolver_dns_forwarding_ruleset_resource_test.go @@ -0,0 +1,208 @@ +package privatednsresolver_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/dnsresolver/2022-07-01/dnsforwardingrulesets" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type PrivateDNSResolverDnsForwardingRulesetResource struct{} + +func TestAccPrivateDNSResolverDnsForwardingRuleset_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_resolver_dns_forwarding_ruleset", "test") + r := PrivateDNSResolverDnsForwardingRulesetResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccPrivateDNSResolverDnsForwardingRuleset_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_resolver_dns_forwarding_ruleset", "test") + r := PrivateDNSResolverDnsForwardingRulesetResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccPrivateDNSResolverDnsForwardingRuleset_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_resolver_dns_forwarding_ruleset", "test") + r := PrivateDNSResolverDnsForwardingRulesetResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccPrivateDNSResolverDnsForwardingRuleset_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_resolver_dns_forwarding_ruleset", "test") + r := PrivateDNSResolverDnsForwardingRulesetResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := dnsforwardingrulesets.ParseDnsForwardingRulesetID(state.ID) + if err != nil { + return nil, err + } + + client := clients.PrivateDnsResolver.DnsForwardingRulesetsClient + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", id, err) + } + return utils.Bool(resp.Model != nil), nil +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctest-rg-%[2]d" + location = "%[1]s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-rg-%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + address_space = ["10.0.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "outbounddns" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.0.64/28"] + + delegation { + name = "Microsoft.Network.dnsResolvers" + service_delegation { + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + name = "Microsoft.Network/dnsResolvers" + } + } +} + +resource "azurerm_private_dns_resolver" "test" { + name = "acctest-dr-%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + virtual_network_id = azurerm_virtual_network.test.id +} + +resource "azurerm_private_dns_resolver_outbound_endpoint" "test" { + name = "acctest-droe-%[2]d" + private_dns_resolver_id = azurerm_private_dns_resolver.test.id + location = azurerm_private_dns_resolver.test.location + subnet_id = azurerm_subnet.test.id +} +`, data.Locations.Primary, data.RandomInteger) +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) basic(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` + %s + +resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "test" { + name = "acctest-drdfr-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + private_dns_resolver_outbound_endpoint_ids = [azurerm_private_dns_resolver_outbound_endpoint.test.id] +} +`, template, data.RandomInteger) +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) requiresImport(data acceptance.TestData) string { + config := r.basic(data) + return fmt.Sprintf(` + %s + +resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "import" { + name = azurerm_private_dns_resolver_dns_forwarding_ruleset.test.name + resource_group_name = azurerm_private_dns_resolver_dns_forwarding_ruleset.test.resource_group_name + location = azurerm_private_dns_resolver_dns_forwarding_ruleset.test.location + private_dns_resolver_outbound_endpoint_ids = azurerm_private_dns_resolver_dns_forwarding_ruleset.test.private_dns_resolver_outbound_endpoint_ids +} +`, config) +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) complete(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` + %s + +resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "test" { + name = "acctest-drdfr-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + private_dns_resolver_outbound_endpoint_ids = [azurerm_private_dns_resolver_outbound_endpoint.test.id] + tags = { + key = "value" + } +} +`, template, data.RandomInteger) +} + +func (r PrivateDNSResolverDnsForwardingRulesetResource) update(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` + %s + +resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "test" { + name = "acctest-drdfr-%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + private_dns_resolver_outbound_endpoint_ids = [azurerm_private_dns_resolver_outbound_endpoint.test.id] + tags = { + key = "updated value" + } +} +`, template, data.RandomInteger) +} diff --git a/internal/services/privatednsresolver/registration.go b/internal/services/privatednsresolver/registration.go index 0f00da9556fb..45cc70884c0d 100644 --- a/internal/services/privatednsresolver/registration.go +++ b/internal/services/privatednsresolver/registration.go @@ -46,6 +46,7 @@ func (r Registration) DataSources() []sdk.DataSource { // Resources returns a list of Resources supported by this Service func (r Registration) Resources() []sdk.Resource { return []sdk.Resource{ + PrivateDNSResolverDnsForwardingRulesetResource{}, PrivateDNSResolverDnsResolverResource{}, PrivateDNSResolverInboundEndpointResource{}, PrivateDNSResolverOutboundEndpointResource{}, diff --git a/website/docs/r/private_dns_resolver_dns_forwarding_ruleset.html.markdown b/website/docs/r/private_dns_resolver_dns_forwarding_ruleset.html.markdown new file mode 100644 index 000000000000..250d5668927b --- /dev/null +++ b/website/docs/r/private_dns_resolver_dns_forwarding_ruleset.html.markdown @@ -0,0 +1,106 @@ +--- +subcategory: "Private DNS Resolver" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_private_dns_resolver_dns_forwarding_ruleset" +description: |- + Manages a Private DNS Resolver Dns Forwarding Ruleset. +--- + +# azurerm_private_dns_resolver_dns_forwarding_ruleset + +Manages a Private DNS Resolver Dns Forwarding Ruleset. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "west europe" +} + +resource "azurerm_virtual_network" "example" { + name = "example-vnet" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + address_space = ["10.0.0.0/16"] +} + +resource "azurerm_subnet" "example" { + name = "outbounddns" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefixes = ["10.0.0.64/28"] + + delegation { + name = "Microsoft.Network.dnsResolvers" + service_delegation { + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + name = "Microsoft.Network/dnsResolvers" + } + } +} + +resource "azurerm_private_dns_resolver" "example" { + name = "example-resolver" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + virtual_network_id = azurerm_virtual_network.example.id +} + +resource "azurerm_private_dns_resolver_outbound_endpoint" "example" { + name = "example-endpoint" + private_dns_resolver_id = azurerm_private_dns_resolver.example.id + location = azurerm_private_dns_resolver.example.location + subnet_id = azurerm_subnet.example.id + tags = { + key = "value" + } +} + +resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "example" { + name = "example-ruleset" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + private_dns_resolver_outbound_endpoint_ids = [azurerm_private_dns_resolver_outbound_endpoint.example.id] + tags = { + key = "value" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name which should be used for this Private DNS Resolver Dns Forwarding Ruleset. Changing this forces a new Private DNS Resolver Dns Forwarding Ruleset to be created. + +* `resource_group_name` - (Required) Specifies the name of the Resource Group where the Private DNS Resolver Dns Forwarding Ruleset should exist. Changing this forces a new Private DNS Resolver Dns Forwarding Ruleset to be created. + +* `dns_resolver_outbound_endpoints` - (Required) The list of IDs of the Private DNS Resolver Outbound Endpoint that is linked to the Private DNS Resolver Dns Forwarding Ruleset . + +* `location` - (Required) Specifies the Azure Region where the Private DNS Resolver Dns Forwarding Ruleset should exist. Changing this forces a new Private DNS Resolver Dns Forwarding Ruleset to be created. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Private DNS Resolver Dns Forwarding Ruleset. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Private DNS Resolver Dns Forwarding Ruleset. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Private DNS Resolver Dns Forwarding Ruleset. +* `read` - (Defaults to 5 minutes) Used when retrieving the Private DNS Resolver Dns Forwarding Ruleset. +* `update` - (Defaults to 30 minutes) Used when updating the Private DNS Resolver Dns Forwarding Ruleset. +* `delete` - (Defaults to 30 minutes) Used when deleting the Private DNS Resolver Dns Forwarding Ruleset. + +## Import + +Private DNS Resolver Dns Forwarding Ruleset can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_private_dns_resolver_dns_forwarding_ruleset.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Network/dnsForwardingRulesets/dnsForwardingRuleset1 +```