Skip to content
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

Merged
merged 45 commits into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
64bb60e
[WIP] Private Endpoint
WodansSon Oct 3, 2019
d445539
[WIP] Update datasource to network_interface_ids
WodansSon Oct 3, 2019
cf252b9
[WIP] Update documentation with correct value
WodansSon Oct 3, 2019
266fa1b
Rename resource and flatten schema
WodansSon Oct 8, 2019
3840307
Merge branch 'master' of https://github.com/terraform-providers/terra…
WodansSon Oct 9, 2019
7ce24b8
Update for terraform-plugin-sdk
WodansSon Oct 9, 2019
71133ca
Gofmt and some PR comment updates
WodansSon Oct 9, 2019
f965560
Some documentation updates
WodansSon Oct 9, 2019
87cb012
More doc updates
WodansSon Oct 10, 2019
3a4b263
Merge branch 'master' of https://github.com/terraform-providers/terra…
WodansSon Oct 12, 2019
fe67c8f
Update to include new terraform-plugin-sdk
WodansSon Oct 12, 2019
bd69625
Fixed lint error
WodansSon Oct 12, 2019
5ee333d
Update to endpoint
WodansSon Oct 23, 2019
57ce715
Refactor progress
WodansSon Oct 25, 2019
52fa425
Added private_ip_address as computed output
WodansSon Oct 26, 2019
61624f4
The resource is done, working on tests
WodansSon Oct 29, 2019
d5e8155
Merge branch 'master' into nr_private-end-point
WodansSon Oct 30, 2019
07452f5
A few more updates
WodansSon Oct 30, 2019
b24ac15
Working new data source
WodansSon Nov 7, 2019
0d8dcd9
Merge branch 'master' into nr_private-end-point
WodansSon Nov 7, 2019
39eef7d
Fixed documentation
WodansSon Nov 7, 2019
69bb2c0
Merge branch 'nr_private-end-point' of https://github.com/terraform-p…
WodansSon Nov 7, 2019
f0f071d
gofmt
WodansSon Nov 7, 2019
e9300b9
Fix lint errors
WodansSon Nov 7, 2019
a676a2f
Partial update for consistency
WodansSon Nov 12, 2019
255957d
Update subnet and documentation
WodansSon Nov 12, 2019
06990fc
Merge branch 'master' of https://github.com/terraform-providers/terra…
WodansSon Nov 21, 2019
227ebc9
Some fixes
WodansSon Nov 21, 2019
e0fde44
Commit changes for rebase with master
WodansSon Nov 22, 2019
c0a3c8e
Merge branch 'master' of https://github.com/terraform-providers/terra…
WodansSon Nov 22, 2019
4ba6e4e
Updates per PR comments
WodansSon Nov 22, 2019
817ca0f
Remove dead code
WodansSon Nov 22, 2019
33e7fdd
Updates per PR comments
WodansSon Nov 22, 2019
e73e10e
Merge branch 'nr_private-end-point' of https://github.com/terraform-p…
WodansSon Nov 22, 2019
b209b87
Updates per PR comments
WodansSon Nov 27, 2019
bb8a136
Remove endpoint data source from provider
WodansSon Nov 28, 2019
ae82096
Update service endpoint connections
WodansSon Nov 28, 2019
7ab6a68
Update to documentation
WodansSon Nov 28, 2019
261c704
Fix sample code
WodansSon Nov 28, 2019
541694f
data source update
WodansSon Nov 28, 2019
6d6a38f
Merge branch 'master' of https://github.com/terraform-providers/terra…
WodansSon Dec 2, 2019
d818bc6
Removed service connections datasource
WodansSon Dec 3, 2019
017b56c
Add the service connections datasource back in
WodansSon Dec 3, 2019
a8e0eac
Update test case
WodansSon Dec 3, 2019
527a2f1
make fmt and adjust comment location
katbyte Dec 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions azurerm/data_source_private_link_endpoint.go
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,
Copy link
Collaborator

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the nil check should be inside the flatten function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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)
}
187 changes: 187 additions & 0 deletions azurerm/data_source_private_link_endpoint_connection_status.go
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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be cleaner if

Suggested change
if props.NetworkInterfaces != nil && len(*props.NetworkInterfaces) > 0 {
if nics := props.NetworkInterfaces; nics != nil && len(*nics) > 0 {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

v := *props.NetworkInterfaces
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
v := *props.NetworkInterfaces
nic := *props.NetworkInterfaces[0]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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
}
73 changes: 73 additions & 0 deletions azurerm/data_source_private_link_endpoint_test.go
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)
}
Loading