Skip to content

Commit

Permalink
Support for static IP configuration in azurerm_private_endpoint #13061 (
Browse files Browse the repository at this point in the history
#17864)

Co-authored-by: Noel Jones <[email protected]>
  • Loading branch information
Noel-Jones and Noel-Jones authored Aug 30, 2022
1 parent 4ab312c commit 8c8dcd3
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
76 changes: 76 additions & 0 deletions internal/services/network/private_endpoint_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,34 @@ func resourcePrivateEndpoint() *pluginsdk.Resource {
},
},

"ip_configuration": {
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.PrivateLinkName,
},
"private_ip_address": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"subresource_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
},
},

"custom_dns_configs": {
Type: pluginsdk.TypeList,
Computed: true,
Expand Down Expand Up @@ -269,6 +297,7 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{})
location := azure.NormalizeLocation(d.Get("location").(string))
privateDnsZoneGroup := d.Get("private_dns_zone_group").([]interface{})
privateServiceConnections := d.Get("private_service_connection").([]interface{})
ipConfigurations := d.Get("ip_configuration").([]interface{})
subnetId := d.Get("subnet_id").(string)

parameters := network.PrivateEndpoint{
Expand All @@ -279,6 +308,7 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{})
Subnet: &network.Subnet{
ID: utils.String(subnetId),
},
IPConfigurations: expandPrivateEndpointIPConfigurations(ipConfigurations),
},
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}
Expand Down Expand Up @@ -416,6 +446,7 @@ func resourcePrivateEndpointUpdate(d *pluginsdk.ResourceData, meta interface{})
location := azure.NormalizeLocation(d.Get("location").(string))
privateDnsZoneGroup := d.Get("private_dns_zone_group").([]interface{})
privateServiceConnections := d.Get("private_service_connection").([]interface{})
ipConfigurations := d.Get("ip_configuration").([]interface{})
subnetId := d.Get("subnet_id").(string)

// TODO: in future it'd be nice to support conditional updates here, but one problem at a time
Expand All @@ -427,6 +458,7 @@ func resourcePrivateEndpointUpdate(d *pluginsdk.ResourceData, meta interface{})
Subnet: &network.Subnet{
ID: utils.String(subnetId),
},
IPConfigurations: expandPrivateEndpointIPConfigurations(ipConfigurations),
},
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}
Expand Down Expand Up @@ -584,6 +616,11 @@ func resourcePrivateEndpointRead(d *pluginsdk.ResourceData, meta interface{}) er
return fmt.Errorf("setting `private_service_connection`: %+v", err)
}

flattenedipconfiguration := flattenPrivateEndpointIPConfigurations(props.IPConfigurations)
if err := d.Set("ip_configuration", flattenedipconfiguration); err != nil {
return fmt.Errorf("setting `ip_configuration`: %+v", err)
}

subnetId := ""
if props.Subnet != nil && props.Subnet.ID != nil {
subnetId = *props.Subnet.ID
Expand Down Expand Up @@ -703,6 +740,45 @@ func expandPrivateLinkEndpointServiceConnection(input []interface{}, parseManual
return &results
}

func expandPrivateEndpointIPConfigurations(input []interface{}) *[]network.PrivateEndpointIPConfiguration {
results := make([]network.PrivateEndpointIPConfiguration, 0)

for _, item := range input {
v := item.(map[string]interface{})
privateIPAddress := v["private_ip_address"].(string)
subResourceName := v["subresource_name"].(string)
name := v["name"].(string)
result := network.PrivateEndpointIPConfiguration{
Name: utils.String(name),
PrivateEndpointIPConfigurationProperties: &network.PrivateEndpointIPConfigurationProperties{
PrivateIPAddress: utils.String(privateIPAddress),
GroupID: utils.String(subResourceName),
MemberName: utils.String(subResourceName),
},
}
results = append(results, result)
}

return &results
}

func flattenPrivateEndpointIPConfigurations(ipConfigurations *[]network.PrivateEndpointIPConfiguration) []interface{} {
results := make([]interface{}, 0)
if ipConfigurations == nil {
return results
}

for _, item := range *ipConfigurations {
results = append(results, map[string]interface{}{
"name": item.Name,
"private_ip_address": item.PrivateIPAddress,
"subresource_name": item.GroupID,
})
}

return results
}

func flattenCustomDnsConfigs(customDnsConfigs *[]network.CustomDNSConfigPropertiesFormat) []interface{} {
results := make([]interface{}, 0)
if customDnsConfigs == nil {
Expand Down
22 changes: 22 additions & 0 deletions website/docs/r/private_endpoint.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ The following arguments are supported:

* `private_service_connection` - (Required) A `private_service_connection` block as defined below.

* `ip_configuration` - (Optional) An `ip_configuration` block as defined below. This allows a static IP address to be set for this Private Endpoint, otherwise an address is dynamically allocated from the Subnet. At most one IP configuration is allowed. Changing this forces a new resource to be created.

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

---
Expand Down Expand Up @@ -189,6 +191,16 @@ See the product [documentation](https://docs.microsoft.com/azure/private-link/pr

* `request_message` - (Optional) A message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource. The request message can be a maximum of `140` characters in length. Only valid if `is_manual_connection` is set to `true`.

---

An `ip_configuration` supports the following:

* `name` - (Required) Specifies the Name of the IP Configuration. Changing this forces a new resource to be created.

* `private_ip_address` - (Required) Specifies the static IP address within the private endpoint's subnet to be used. Changing this forces a new resource to be created.

* `subresource_name` - (Required) Specifies the subresource this IP address applies to. `subresource_names` corresponds to `group_id` and in this context is also used for `member_name`. Changing this forces a new resource to be created.

## Attributes Reference

The following attributes are exported:
Expand Down Expand Up @@ -239,6 +251,16 @@ A `private_service_connection` block exports:

---

An `ip_configuration` block exports:

* `name` - The Name of the IP Configuration.

* `private_ip_address` - The static IP address set by this configuration. It is recommended to use the private IP address exported in the `private_service_connection` block to obtain the address associated with the private endpoint.

* `subresource_name` - The subresource this IP address applies to, which corresponds to the `group_id`.

---

A `record_sets` block exports:

* `name` - The name of the Private DNS Zone that the config belongs to.
Expand Down

0 comments on commit 8c8dcd3

Please sign in to comment.