Skip to content

Commit ce3eb26

Browse files
WodansSontombuildsstuff
andauthoredJun 18, 2020
* Fixed requiresImport test case * Progress exposing dns zone groups * Work thus far redesign * Progress thus far * Progress * Change data structure * Close mostly working now * Remove old resources * Code complete needs docs and tests * Add docs and example * Added Tests and updated docs * Fix Lint Errors * Update azurerm/internal/services/network/parse/private_endpoint.go Co-authored-by: Tom Harvey <[email protected]> * Update azurerm/internal/services/network/private_endpoint_resource.go Co-authored-by: Tom Harvey <[email protected]> * Update azurerm/internal/services/network/private_endpoint_resource.go Co-authored-by: Tom Harvey <[email protected]> * Changes per PR * Fix lint error * Requested changes per PR comment Co-authored-by: Tom Harvey <[email protected]>
1 parent 1a7f16d commit ce3eb26

File tree

11 files changed

+1131
-18
lines changed

11 files changed

+1131
-18
lines changed
 

‎azurerm/internal/services/network/client/client.go

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Client struct {
4242
VpnServerConfigurationsClient *network.VpnServerConfigurationsClient
4343
WatcherClient *network.WatchersClient
4444
WebApplicationFirewallPoliciesClient *network.WebApplicationFirewallPoliciesClient
45+
PrivateDnsZoneGroupClient *network.PrivateDNSZoneGroupsClient
4546
PrivateLinkServiceClient *network.PrivateLinkServicesClient
4647
}
4748

@@ -112,6 +113,9 @@ func NewClient(o *common.ClientOptions) *Client {
112113
PublicIPPrefixesClient := network.NewPublicIPPrefixesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
113114
o.ConfigureClient(&PublicIPPrefixesClient.Client, o.ResourceManagerAuthorizer)
114115

116+
PrivateDnsZoneGroupClient := network.NewPrivateDNSZoneGroupsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
117+
o.ConfigureClient(&PrivateDnsZoneGroupClient.Client, o.ResourceManagerAuthorizer)
118+
115119
PrivateLinkServiceClient := network.NewPrivateLinkServicesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
116120
o.ConfigureClient(&PrivateLinkServiceClient.Client, o.ResourceManagerAuthorizer)
117121

@@ -194,6 +198,7 @@ func NewClient(o *common.ClientOptions) *Client {
194198
VpnServerConfigurationsClient: &vpnServerConfigurationsClient,
195199
WatcherClient: &WatcherClient,
196200
WebApplicationFirewallPoliciesClient: &WebApplicationFirewallPoliciesClient,
201+
PrivateDnsZoneGroupClient: &PrivateDnsZoneGroupClient,
197202
PrivateLinkServiceClient: &PrivateLinkServiceClient,
198203
}
199204
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package parse
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
8+
)
9+
10+
type NameResourceGroup struct {
11+
ResourceGroup string
12+
Name string
13+
ID string
14+
}
15+
16+
func PrivateDnsZoneGroupResourceID(input string) (*NameResourceGroup, error) {
17+
if len(strings.TrimSpace(input)) == 0 {
18+
return nil, fmt.Errorf("unable to parse Private DNS Zone Group ID %q: input is empty", input)
19+
}
20+
21+
id, err := azure.ParseAzureResourceID(input)
22+
if err != nil {
23+
return nil, fmt.Errorf("unable to parse Private DNS Zone Group ID %q: %+v", input, err)
24+
}
25+
26+
privateDnsZoneGroup := NameResourceGroup{
27+
ResourceGroup: id.ResourceGroup,
28+
}
29+
30+
if privateDnsZoneGroup.Name, err = id.PopSegment("privateDnsZoneGroups"); err != nil {
31+
return nil, err
32+
}
33+
34+
if privateDnsZoneGroup.ID = input; err != nil {
35+
return nil, err
36+
}
37+
38+
return &privateDnsZoneGroup, nil
39+
}
40+
41+
func PrivateDnsZoneResourceIDs(input []interface{}) (*[]NameResourceGroup, error) {
42+
results := make([]NameResourceGroup, 0)
43+
44+
for _, item := range input {
45+
v := item.(string)
46+
47+
if privateDnsZone, err := PrivateDnsZoneResourceID(v); err != nil {
48+
return nil, fmt.Errorf("unable to parse Private DNS Zone ID %q: %+v", v, err)
49+
} else {
50+
results = append(results, *privateDnsZone)
51+
}
52+
}
53+
54+
return &results, nil
55+
}
56+
57+
func PrivateDnsZoneResourceID(input string) (*NameResourceGroup, error) {
58+
if len(strings.TrimSpace(input)) == 0 {
59+
return nil, fmt.Errorf("unable to parse Private DNS Zone ID %q: input is empty", input)
60+
}
61+
62+
id, err := azure.ParseAzureResourceID(input)
63+
if err != nil {
64+
return nil, fmt.Errorf("unable to parse Private DNS Zone ID %q: %+v", input, err)
65+
}
66+
67+
privateDnsZone := NameResourceGroup{
68+
ResourceGroup: id.ResourceGroup,
69+
}
70+
71+
if privateDnsZone.Name, err = id.PopSegment("privateDnsZones"); err != nil {
72+
return nil, err
73+
}
74+
75+
if privateDnsZone.ID = input; err != nil {
76+
return nil, err
77+
}
78+
79+
return &privateDnsZone, nil
80+
}
81+
82+
func PrivateEndpointResourceID(input string) (*NameResourceGroup, error) {
83+
id, err := azure.ParseAzureResourceID(input)
84+
if err != nil {
85+
return nil, fmt.Errorf("unable to parse Private Endpoint ID %q: %+v", input, err)
86+
}
87+
88+
privateEndpoint := NameResourceGroup{
89+
ResourceGroup: id.ResourceGroup,
90+
}
91+
92+
if privateEndpoint.Name, err = id.PopSegment("privateEndpoints"); err != nil {
93+
return nil, err
94+
}
95+
96+
if privateEndpoint.ID = input; err != nil {
97+
return nil, err
98+
}
99+
100+
return &privateEndpoint, nil
101+
}
102+
103+
func ValidatePrivateDnsZoneResourceID(i interface{}, k string) (warnings []string, errors []error) {
104+
v, ok := i.(string)
105+
if !ok {
106+
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
107+
return
108+
}
109+
110+
if id, err := azure.ParseAzureResourceID(v); err != nil {
111+
errors = append(errors, fmt.Errorf("Can not parse %q as a resource id: %v", k, err))
112+
} else if _, err = id.PopSegment("privateDnsZones"); err != nil {
113+
errors = append(errors, fmt.Errorf("Can not parse %q as a private dns zone resource id: %v", k, err))
114+
}
115+
116+
return warnings, errors
117+
}

‎azurerm/internal/services/network/private_endpoint_resource.go

+387-14
Large diffs are not rendered by default.

‎azurerm/internal/services/network/tests/private_endpoint_resource_test.go

+447-2
Large diffs are not rendered by default.

‎azurerm/internal/services/network/tests/private_link_service_resource_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ func testAccAzureRMPrivateLinkService_requiresImport(data acceptance.TestData) s
351351
352352
resource "azurerm_private_link_service" "import" {
353353
name = azurerm_private_link_service.test.name
354-
location = azurerm_private_link_service.test.location
355-
resource_group_name = azurerm_private_link_service.test.name
354+
location = azurerm_resource_group.test.location
355+
resource_group_name = azurerm_resource_group.test.name
356356
357357
nat_ip_configuration {
358358
name = "primaryIpConfiguration-%d"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package privatedns
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
7+
)
8+
9+
func ValidatePrivateDnsZoneGroupName(i interface{}, k string) (_ []string, errors []error) {
10+
v, ok := i.(string)
11+
if !ok {
12+
return nil, append(errors, fmt.Errorf("expected type of %s to be string", k))
13+
}
14+
15+
// The name attribute rules per the Nat Gateway service team are (Friday, October 18, 2019 4:20 PM):
16+
// 1. Must not be empty.
17+
// 2. Must be between 1 and 80 characters.
18+
// 3. The attribute must:
19+
// a) begin with a letter or number
20+
// b) end with a letter, number or underscore
21+
// c) may contain only letters, numbers, underscores, periods, or hyphens.
22+
23+
if len(v) == 1 {
24+
if m, _ := validate.RegExHelper(i, k, `^([a-zA-Z\d])`); !m {
25+
errors = append(errors, fmt.Errorf("%s must begin with a letter or number", k))
26+
}
27+
} else if m, _ := validate.RegExHelper(i, k, `^([a-zA-Z\d])([a-zA-Z\d-\_\.]{0,78})([a-zA-Z\d\_])$`); !m {
28+
errors = append(errors, fmt.Errorf("%s must be between 1 - 80 characters long, begin with a letter or number, end with a letter, number or underscore, and may contain only letters, numbers, periods, hyphens or underscores", k))
29+
}
30+
31+
return nil, errors
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Example: Private Endpoint
2+
3+
This example provisions a Private Endpoint which connects to a Private Link Service within Azure.
4+
5+
### Variables
6+
7+
* `prefix` - (Required) The prefix used for all resources in this example.
8+
9+
* `location` - (Required) The Azure Region in which all resources in this example should be created.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
provider "azurerm" {
2+
features {}
3+
}
4+
5+
resource "azurerm_resource_group" "example" {
6+
name = "${var.prefix}-resources"
7+
location = "${var.location}"
8+
}
9+
10+
resource "azurerm_virtual_network" "example" {
11+
name = "${var.prefix}-vnet"
12+
address_space = ["10.0.0.0/16"]
13+
location = azurerm_resource_group.example.location
14+
resource_group_name = azurerm_resource_group.example.name
15+
}
16+
17+
resource "azurerm_subnet" "endpoint" {
18+
name = "endpoint"
19+
resource_group_name = azurerm_resource_group.example.name
20+
virtual_network_name = azurerm_virtual_network.example.name
21+
address_prefix = "10.0.2.0/24"
22+
23+
enforce_private_link_endpoint_network_policies = true
24+
}
25+
26+
resource "azurerm_private_dns_zone" "example" {
27+
name = "privatelink.postgres.database.azure.com"
28+
resource_group_name = azurerm_resource_group.example.name
29+
}
30+
31+
resource "azurerm_postgresql_server" "example" {
32+
name = "${var.prefix}-postgresql"
33+
location = azurerm_resource_group.example.location
34+
resource_group_name = azurerm_resource_group.example.name
35+
36+
sku_name = "GP_Gen5_4"
37+
38+
storage_mb = 5120
39+
backup_retention_days = 7
40+
geo_redundant_backup_enabled = false
41+
auto_grow_enabled = true
42+
43+
administrator_login = "psqladminun"
44+
administrator_login_password = "H@Sh1CoR3!"
45+
version = "9.5"
46+
ssl_enforcement_enabled = true
47+
}
48+
49+
resource "azurerm_private_endpoint" "example" {
50+
name = "${var.prefix}-pe"
51+
location = azurerm_resource_group.example.location
52+
resource_group_name = azurerm_resource_group.example.name
53+
subnet_id = azurerm_subnet.endpoint.id
54+
55+
private_dns_zone_group {
56+
name = "private-dns-zone-group"
57+
private_dns_zone_ids = [azurerm_private_dns_zone.example.id]
58+
}
59+
60+
private_service_connection {
61+
name = "tfex-postgresql-connection"
62+
is_manual_connection = false
63+
private_connection_resource_id = azurerm_postgresql_server.example.id
64+
subresource_names = ["postgresqlServer"]
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
variable "prefix" {
2+
description = "The Prefix used for all resources in this example"
3+
}
4+
5+
variable "location" {
6+
description = "The Azure Region in which all resources in this example should be created."
7+
}

‎website/docs/r/private_dns_zone.html.markdown

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ The following arguments are supported:
2929

3030
* `name` - (Required) The name of the Private DNS Zone. Must be a valid domain name.
3131

32+
-> **NOTE:** If you are going to be using the Private DNS Zone with a Private Endpoint the name of the Private DNS Zone must follow the **Private DNS Zone name** schema in the [product documentation](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns#virtual-network-and-on-premises-workloads-using-a-dns-forwarder) in order for the two resources to be connected successfully.
33+
3234
* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created.
3335

3436
* `tags` - (Optional) A mapping of tags to assign to the resource.

‎website/docs/r/private_endpoint.html.markdown

+57
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,22 @@ The following arguments are supported:
109109

110110
* `subnet_id` - (Required) The ID of the Subnet from which Private IP Addresses will be allocated for this Private Endpoint. Changing this forces a new resource to be created.
111111

112+
* `private_dns_zone_group` - (Optional) A `private_dns_zone_group` block as defined below.
113+
112114
* `private_service_connection` - (Required) A `private_service_connection` block as defined below.
113115

114116
* `tags` - (Optional) A mapping of tags to assign to the resource.
115117

116118
---
117119

120+
A `private_dns_zone_group` supports the following:
121+
122+
* `name` - (Required) Specifies the Name of the Private Service Connection. Changing this forces the a new `private_dns_zone_group` to be created.
123+
124+
* `private_dns_zone_ids` - (Required) Specifies the list of Private DNS Zones to include within the `private_dns_zone_group`.
125+
126+
---
127+
118128
A `private_service_connection` supports the following:
119129

120130
* `name` - (Required) Specifies the Name of the Private Service Connection. Changing this forces a new resource to be created.
@@ -151,11 +161,58 @@ The following attributes are exported:
151161

152162
* `id` - The ID of the Private Endpoint.
153163

164+
---
165+
166+
A `private_dns_zone_group` block exports:
167+
168+
* `id` - The ID of the Private DNS Zone Group.
169+
170+
---
171+
172+
A `custom_dns_configs` block exports:
173+
174+
* `fqdn` - The fully qualified domain name to the `private_endpoint`.
175+
176+
* `ip_addresses` - A list of all IP Addresses that map to the `private_endpoint` fqdn.
177+
178+
-> **NOTE:** If a Private DNS Zone Group has been defined and is currently connected correctly this block will be empty.
179+
180+
---
181+
182+
A `private_dns_zone_configs` block exports:
183+
184+
* `name` - The name of the Private DNS Zone that the config belongs to.
185+
186+
* `id` - The ID of the Private DNS Zone Config.
187+
188+
* `private_dns_zone_id` - A list of IP Addresses
189+
190+
* `record_sets` - A `record_sets` block as defined below.
191+
192+
---
193+
194+
A `record_sets` block exports:
195+
196+
* `name` - The name of the Private DNS Zone that the config belongs to.
197+
198+
* `type` - The type of DNS record.
199+
200+
* `fqdn` - The fully qualified domain name to the `private_dns_zone`.
201+
202+
* `ttl` - The time to live for each connection to the `private_dns_zone`.
203+
204+
* `ip_addresses` - A list of all IP Addresses that map to the `private_dns_zone` fqdn.
205+
206+
-> **NOTE:** If a Private DNS Zone Group has not been configured correctly the `record_sets` attibutes will be empty.
207+
208+
---
209+
154210
## Example HCL Configurations
155211

156212
* How to connect a `Private Endpoint` to a [Cosmos MongoDB](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/private-endpoint/cosmos-db)
157213
* How to connect a `Private Endpoint` to a [PostgreSQL Server](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/private-endpoint/postgresql)
158214
* How to connect a `Private Endpoint` to a [Private Link Service](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/private-endpoint/private-link-service)
215+
* How to connect a `Private Endpoint` to a [Private DNS Group](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/private-endpoint/private-dns-group)
159216

160217
## Timeouts
161218

0 commit comments

Comments
 (0)
Please sign in to comment.