-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Resource: azurerm_private_link_endpoint
New Data Source: azurerm_private_link_endpoint_connection
and expose attibute in azurerm_subnet
#4493
Changes from 26 commits
64bb60e
d445539
cf252b9
266fa1b
3840307
7ce24b8
71133ca
f965560
87cb012
3a4b263
fe67c8f
bd69625
5ee333d
57ce715
52fa425
61624f4
d5e8155
07452f5
b24ac15
0d8dcd9
39eef7d
69bb2c0
f0f071d
e9300b9
a676a2f
255957d
06990fc
227ebc9
e0fde44
c0a3c8e
4ba6e4e
817ca0f
33e7fdd
e73e10e
b209b87
bb8a136
ae82096
7ab6a68
261c704
541694f
6d6a38f
d818bc6
017b56c
a8e0eac
527a2f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package azurerm | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
aznet "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func dataSourceArmPrivateLinkEndpoint() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceArmPrivateLinkEndpointRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: aznet.ValidatePrivateLinkEndpointName, | ||
}, | ||
|
||
"location": azure.SchemaLocationForDataSource(), | ||
|
||
"resource_group_name": azure.SchemaResourceGroupNameForDataSource(), | ||
|
||
"subnet_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"private_service_connection": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"is_manual_connection": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
"private_connection_resource_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"subresource_names": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"request_message": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"network_interface_ids": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
|
||
"tags": tags.SchemaDataSource(), | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceArmPrivateLinkEndpointRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).Network.PrivateEndpointClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
name := d.Get("name").(string) | ||
resourceGroup := d.Get("resource_group_name").(string) | ||
|
||
resp, err := client.Get(ctx, resourceGroup, name, "") | ||
if err != nil { | ||
if utils.ResponseWasNotFound(resp.Response) { | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("Error reading Private Link Endpoint %q (Resource Group %q): %+v", name, resourceGroup, err) | ||
} | ||
if resp.ID == nil || *resp.ID == "" { | ||
return fmt.Errorf("API returns a nil/empty id on Private Link Endpoint %q (Resource Group %q): %+v", name, resourceGroup, err) | ||
} | ||
|
||
d.SetId(*resp.ID) | ||
d.Set("name", resp.Name) | ||
d.Set("resource_group_name", resourceGroup) | ||
if location := resp.Location; location != nil { | ||
d.Set("location", azure.NormalizeLocation(*location)) | ||
} | ||
if props := resp.PrivateEndpointProperties; props != nil { | ||
if subnet := props.Subnet; subnet != nil { | ||
d.Set("subnet_id", subnet.ID) | ||
} | ||
if err := d.Set("private_service_connection", flattenArmPrivateLinkEndpointServiceConnection(props.PrivateLinkServiceConnections, props.ManualPrivateLinkServiceConnections)); err != nil { | ||
return fmt.Errorf("Error setting `private_service_connection`: %+v", err) | ||
} | ||
if props.NetworkInterfaces != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the nil check should be inside the flatten function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
if err := d.Set("network_interface_ids", flattenArmPrivateLinkEndpointInterface(props.NetworkInterfaces)); err != nil { | ||
return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) | ||
} | ||
} | ||
} | ||
|
||
return tags.FlattenAndSet(d, resp.Tags) | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,187 @@ | ||||||
package azurerm | ||||||
|
||||||
import ( | ||||||
"fmt" | ||||||
|
||||||
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" | ||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||||||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||||||
aznet "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" | ||||||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||||||
) | ||||||
|
||||||
func dataSourceArmPrivateLinkEndpointConnections() *schema.Resource { | ||||||
return &schema.Resource{ | ||||||
Read: dataSourceArmPrivateLinkEndpointConnectionsRead, | ||||||
|
||||||
Schema: map[string]*schema.Schema{ | ||||||
"name": { | ||||||
Type: schema.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: aznet.ValidatePrivateLinkEndpointName, | ||||||
}, | ||||||
|
||||||
"location": azure.SchemaLocationForDataSource(), | ||||||
|
||||||
"resource_group_name": azure.SchemaResourceGroupNameForDataSource(), | ||||||
|
||||||
"private_service_connection": { | ||||||
Type: schema.TypeList, | ||||||
Computed: true, | ||||||
MaxItems: 1, | ||||||
Elem: &schema.Resource{ | ||||||
Schema: map[string]*schema.Schema{ | ||||||
"name": { | ||||||
Type: schema.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
"request_response": { | ||||||
Type: schema.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
"status": { | ||||||
Type: schema.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
"private_ip_address": { | ||||||
Type: schema.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
}, | ||||||
}, | ||||||
}, | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func dataSourceArmPrivateLinkEndpointConnectionsRead(d *schema.ResourceData, meta interface{}) error { | ||||||
client := meta.(*ArmClient).Network.PrivateEndpointClient | ||||||
ctx := meta.(*ArmClient).StopContext | ||||||
|
||||||
name := d.Get("name").(string) | ||||||
resourceGroup := d.Get("resource_group_name").(string) | ||||||
|
||||||
resp, err := client.Get(ctx, resourceGroup, name, "") | ||||||
if err != nil { | ||||||
if utils.ResponseWasNotFound(resp.Response) { | ||||||
d.SetId("") | ||||||
return nil | ||||||
} | ||||||
return fmt.Errorf("Error reading Private Link Endpoint %q (Resource Group %q): %+v", name, resourceGroup, err) | ||||||
} | ||||||
if resp.ID == nil || *resp.ID == "" { | ||||||
return fmt.Errorf("API returns a nil/empty id on Private Link Endpoint %q (Resource Group %q): %+v", name, resourceGroup, err) | ||||||
} | ||||||
|
||||||
d.SetId(*resp.ID) | ||||||
d.Set("name", resp.Name) | ||||||
d.Set("resource_group_name", resourceGroup) | ||||||
if location := resp.Location; location != nil { | ||||||
d.Set("location", azure.NormalizeLocation(*location)) | ||||||
} | ||||||
|
||||||
if props := resp.PrivateEndpointProperties; props != nil { | ||||||
privateIpAddress := "" | ||||||
|
||||||
if props.NetworkInterfaces != nil && len(*props.NetworkInterfaces) > 0 { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this might be cleaner if
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||||||
v := *props.NetworkInterfaces | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||||||
if v[0].ID != nil && *(v[0].ID) != "" { | ||||||
privateIpAddress = getPrivateIpAddress(*(v[0].ID), meta) | ||||||
} | ||||||
} | ||||||
|
||||||
if err := d.Set("private_service_connection", flattenArmPrivateLinkEndpointServiceConnectionStatus(props.PrivateLinkServiceConnections, props.ManualPrivateLinkServiceConnections, privateIpAddress)); err != nil { | ||||||
return fmt.Errorf("Error setting `private_service_connection`: %+v", err) | ||||||
} | ||||||
} | ||||||
|
||||||
return nil | ||||||
} | ||||||
|
||||||
func getPrivateIpAddress(networkInterfaceId string, meta interface{}) string { | ||||||
privateIpAddress := "" | ||||||
id, err := azure.ParseAzureResourceID(networkInterfaceId) | ||||||
if err != nil { | ||||||
return privateIpAddress | ||||||
} | ||||||
name := id.Path["networkInterfaces"] | ||||||
|
||||||
client := meta.(*ArmClient).Network.InterfacesClient | ||||||
ctx := meta.(*ArmClient).StopContext | ||||||
|
||||||
resp, err := client.Get(ctx, id.ResourceGroup, name, "") | ||||||
if err != nil { | ||||||
return privateIpAddress | ||||||
} | ||||||
|
||||||
if props := resp.InterfacePropertiesFormat; props != nil { | ||||||
if configs := props.IPConfigurations; configs != nil { | ||||||
for i, config := range *configs { | ||||||
if propFmt := config.InterfaceIPConfigurationPropertiesFormat; propFmt != nil { | ||||||
if propFmt.PrivateIPAddress != nil && *propFmt.PrivateIPAddress != "" && i == 0 { | ||||||
privateIpAddress = *propFmt.PrivateIPAddress | ||||||
} | ||||||
break | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
return privateIpAddress | ||||||
} | ||||||
|
||||||
func flattenArmPrivateLinkEndpointServiceConnectionStatus(serviceConnections *[]network.PrivateLinkServiceConnection, manualServiceConnections *[]network.PrivateLinkServiceConnection, privateIpAddress string) []interface{} { | ||||||
results := make([]interface{}, 0) | ||||||
if serviceConnections == nil && manualServiceConnections == nil { | ||||||
return results | ||||||
} | ||||||
|
||||||
if serviceConnections != nil { | ||||||
for _, item := range *serviceConnections { | ||||||
result := make(map[string]interface{}) | ||||||
result["private_ip_address"] = privateIpAddress | ||||||
|
||||||
if v := item.Name; v != nil { | ||||||
result["name"] = *v | ||||||
} | ||||||
if props := item.PrivateLinkServiceConnectionProperties; props != nil { | ||||||
if v := props.PrivateLinkServiceConnectionState; v != nil { | ||||||
if s := v.Status; s != nil { | ||||||
result["status"] = *s | ||||||
} | ||||||
if d := v.Description; d != nil { | ||||||
result["request_response"] = *d | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
results = append(results, result) | ||||||
} | ||||||
} | ||||||
|
||||||
if manualServiceConnections != nil { | ||||||
for _, item := range *manualServiceConnections { | ||||||
result := make(map[string]interface{}) | ||||||
result["private_ip_address"] = privateIpAddress | ||||||
|
||||||
if v := item.Name; v != nil { | ||||||
result["name"] = *v | ||||||
} | ||||||
if props := item.PrivateLinkServiceConnectionProperties; props != nil { | ||||||
if v := props.PrivateLinkServiceConnectionState; v != nil { | ||||||
if s := v.Status; s != nil { | ||||||
result["status"] = *s | ||||||
} | ||||||
if d := v.Description; d != nil { | ||||||
result["request_response"] = *d | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
results = append(results, result) | ||||||
} | ||||||
} | ||||||
|
||||||
return results | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package azurerm | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" | ||
) | ||
|
||
func TestAccDataSourceAzureRMPrivateEndpoint_basic(t *testing.T) { | ||
dataSourceName := "data.azurerm_private_link_endpoint.test" | ||
ri := tf.AccRandTimeInt() | ||
location := testLocation() | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDataSourcePrivateEndpoint_basic(ri, location), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet(dataSourceName, "subnet_id"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccDataSourceAzureRMPrivateEndpoint_complete(t *testing.T) { | ||
dataSourceName := "data.azurerm_private_link_endpoint.test" | ||
ri := tf.AccRandTimeInt() | ||
location := testLocation() | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDataSourcePrivateEndpoint_complete(ri, location), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet(dataSourceName, "subnet_id"), | ||
resource.TestCheckResourceAttr(dataSourceName, "tags.%", "1"), | ||
resource.TestCheckResourceAttr(dataSourceName, "tags.env", "test"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDataSourcePrivateEndpoint_basic(rInt int, location string) string { | ||
config := testAccAzureRMPrivateEndpoint_basic(rInt, location) | ||
return fmt.Sprintf(` | ||
%s | ||
|
||
data "azurerm_private_link_endpoint" "test" { | ||
resource_group_name = "${azurerm_private_link_endpoint.test.resource_group_name}" | ||
name = "${azurerm_private_link_endpoint.test.name}" | ||
} | ||
`, config) | ||
} | ||
|
||
func testAccDataSourcePrivateEndpoint_complete(rInt int, location string) string { | ||
config := testAccAzureRMPrivateEndpoint_complete(rInt, location) | ||
return fmt.Sprintf(` | ||
%s | ||
|
||
data "azurerm_private_link_endpoint" "test" { | ||
resource_group_name = "${azurerm_private_link_endpoint.test.resource_group_name}" | ||
name = "${azurerm_private_link_endpoint.test.name}" | ||
} | ||
`, config) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this on a datasource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.