From c32062124043c82ff709f4798fd0e96944c8a999 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Tue, 24 Sep 2019 18:48:04 -0700 Subject: [PATCH 01/44] Add new resources and data sources --- azurerm/data_source_loadbalancer.go | 9 + azurerm/data_source_private_link_service.go | 236 +++++++ .../data_source_private_link_service_test.go | 46 ++ azurerm/data_source_subnet.go | 11 + azurerm/internal/services/network/client.go | 5 + azurerm/provider.go | 5 +- azurerm/resource_arm_loadbalancer.go | 9 + azurerm/resource_arm_private_link_service.go | 643 ++++++++++++++++++ .../resource_arm_private_link_service_test.go | 315 +++++++++ azurerm/resource_arm_subnet.go | 16 + .../private-link-service/README.md | 3 + .../private-link-service/main.tf | 64 ++ .../private-link-service/variables.tf | 7 + website/azurerm.erb | 26 +- website/docs/d/loadbalancer.html.markdown | 1 + .../docs/d/private_link_service.html.markdown | 133 ++++ website/docs/d/subnet.html.markdown | 1 + website/docs/r/loadbalancer.html.markdown | 1 + .../docs/r/private_link_service.html.markdown | 188 +++++ website/docs/r/subnet.html.markdown | 3 + 20 files changed, 1701 insertions(+), 21 deletions(-) create mode 100644 azurerm/data_source_private_link_service.go create mode 100644 azurerm/data_source_private_link_service_test.go create mode 100644 azurerm/resource_arm_private_link_service.go create mode 100644 azurerm/resource_arm_private_link_service_test.go create mode 100644 examples/virtual-networks/private-link-service/README.md create mode 100644 examples/virtual-networks/private-link-service/main.tf create mode 100644 examples/virtual-networks/private-link-service/variables.tf create mode 100644 website/docs/d/private_link_service.html.markdown create mode 100644 website/docs/r/private_link_service.html.markdown diff --git a/azurerm/data_source_loadbalancer.go b/azurerm/data_source_loadbalancer.go index a6d737baf14b..c507e50f9feb 100644 --- a/azurerm/data_source_loadbalancer.go +++ b/azurerm/data_source_loadbalancer.go @@ -63,6 +63,11 @@ func dataSourceArmLoadBalancer() *schema.Resource { }, "zones": azure.SchemaZonesComputed(), + + "id": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -151,6 +156,10 @@ func flattenLoadBalancerDataSourceFrontendIpConfiguration(ipConfigs *[]network.F ipConfig["name"] = *config.Name } + if config.ID != nil { + ipConfig["id"] = *config.ID + } + zones := make([]string, 0) if zs := config.Zones; zs != nil { zones = *zs diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go new file mode 100644 index 000000000000..9f86949a6aa3 --- /dev/null +++ b/azurerm/data_source_private_link_service.go @@ -0,0 +1,236 @@ +package azurerm + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmPrivateLinkService() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmPrivateLinkServiceRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "location": azure.SchemaLocationForDataSource(), + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "alias": { + Type: schema.TypeString, + Computed: true, + }, + + "auto_approval": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subscriptions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "fqdns": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "ip_configurations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "private_ip_allocation_method": { + Type: schema.TypeString, + Computed: true, + }, + "private_ip_address": { + Type: schema.TypeString, + Computed: true, + }, + "private_ip_address_version": { + Type: schema.TypeString, + Computed: true, + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "load_balancer_frontend_ip_configurations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "network_interfaces": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "private_endpoint_connections": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "private_endpoint": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "location": azure.SchemaLocationForDataSource(), + "tags": tagsForDataSourceSchema(), + }, + }, + }, + "private_link_service_connection_state": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_required": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + + "type": { + Type: schema.TypeString, + Computed: true, + }, + + "visibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subscriptions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "tags": tagsForDataSourceSchema(), + }, + } +} + +func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).network.PrivateLinkServiceClient + 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) { + return fmt.Errorf("Error: Private Link Service %q (Resource Group %q) was not found", name, resourceGroup) + } + return fmt.Errorf("Error reading Private Link Service %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 privateLinkServiceProperties := resp.PrivateLinkServiceProperties; privateLinkServiceProperties != nil { + d.Set("alias", privateLinkServiceProperties.Alias) + if err := d.Set("auto_approval", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { + return fmt.Errorf("Error setting `auto_approval`: %+v", err) + } + d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)) + if err := d.Set("ip_configurations", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `ip_configurations`: %+v", err) + } + if err := d.Set("load_balancer_frontend_ip_configurations", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configurations`: %+v", err) + } + if err := d.Set("network_interfaces", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interfaces`: %+v", err) + } + if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connections`: %+v", err) + } + if err := d.Set("visibility", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility`: %+v", err) + } + } + d.Set("type", resp.Type) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go new file mode 100644 index 000000000000..ffe480613947 --- /dev/null +++ b/azurerm/data_source_private_link_service_test.go @@ -0,0 +1,46 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccDataSourceAzureRMPrivateLinkService_basic(t *testing.T) { + dataSourceName := "data.azurerm_private_link_service.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourcePrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "fqdns.0", "testFqdns"), + resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configurations.#", "1"), + ), + }, + }, + }) +} + +func testAccDataSourcePrivateLinkService_basic(rInt int, location string) string { + config := testAccAzureRMPrivateLinkService_basic(rInt, location) + return fmt.Sprintf(` +%s + +data "azurerm_private_link_service" "test" { + resource_group_name = "${azurerm_private_link_service.test.resource_group_name}" + name = "${azurerm_private_link_service.test.name}" +} +`, config) +} diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index aee60e9dce2e..505183ee4351 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -56,6 +56,11 @@ func dataSourceArmSubnet() *schema.Resource { Type: schema.TypeString, }, }, + + "private_link_service_network_policies": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -84,6 +89,12 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) + if props.PrivateLinkServiceNetworkPolicies != nil { + d.Set("private_link_service_network_policies", props.PrivateLinkServiceNetworkPolicies) + } else { + d.Set("private_link_service_network_policies", "") + } + if props.NetworkSecurityGroup != nil { d.Set("network_security_group_id", props.NetworkSecurityGroup.ID) } else { diff --git a/azurerm/internal/services/network/client.go b/azurerm/internal/services/network/client.go index 81c0dba8add6..67291fd9eb10 100644 --- a/azurerm/internal/services/network/client.go +++ b/azurerm/internal/services/network/client.go @@ -33,6 +33,7 @@ type Client struct { VirtualWanClient *network.VirtualWansClient WatcherClient *network.WatchersClient WebApplicationFirewallPoliciesClient *network.WebApplicationFirewallPoliciesClient + PrivateLinkServiceClient *network.PrivateLinkServicesClient } func BuildClient(o *common.ClientOptions) *Client { @@ -88,6 +89,9 @@ func BuildClient(o *common.ClientOptions) *Client { PublicIPPrefixesClient := network.NewPublicIPPrefixesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&PublicIPPrefixesClient.Client, o.ResourceManagerAuthorizer) + PrivateLinkServiceClient := network.NewPrivateLinkServicesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&PrivateLinkServiceClient.Client, o.ResourceManagerAuthorizer) + RoutesClient := network.NewRoutesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&RoutesClient.Client, o.ResourceManagerAuthorizer) @@ -146,5 +150,6 @@ func BuildClient(o *common.ClientOptions) *Client { VirtualWanClient: &VirtualWanClient, WatcherClient: &WatcherClient, WebApplicationFirewallPoliciesClient: &WebApplicationFirewallPoliciesClient, + PrivateLinkServiceClient: &PrivateLinkServiceClient, } } diff --git a/azurerm/provider.go b/azurerm/provider.go index f5aa81c3090c..0d278ef0c444 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -111,7 +111,6 @@ func Provider() terraform.ResourceProvider { "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), "azurerm_public_ip": dataSourceArmPublicIP(), "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), "azurerm_redis_cache": dataSourceArmRedisCache(), @@ -140,6 +139,7 @@ func Provider() terraform.ResourceProvider { "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), } resources := map[string]*schema.Resource{ @@ -199,7 +199,6 @@ func Provider() terraform.ResourceProvider { "azurerm_bot_channel_slack": resourceArmBotChannelSlack(), "azurerm_bot_channels_registration": resourceArmBotChannelsRegistration(), "azurerm_bot_connection": resourceArmBotConnection(), - "azurerm_bot_web_app": resourceArmBotWebApp(), "azurerm_batch_pool": resourceArmBatchPool(), "azurerm_cdn_endpoint": resourceArmCdnEndpoint(), "azurerm_cdn_profile": resourceArmCdnProfile(), @@ -216,7 +215,6 @@ func Provider() terraform.ResourceProvider { "azurerm_cosmosdb_sql_container": resourceArmCosmosDbSQLContainer(), "azurerm_cosmosdb_sql_database": resourceArmCosmosDbSQLDatabase(), "azurerm_cosmosdb_table": resourceArmCosmosDbTable(), - "azurerm_dashboard": resourceArmDashboard(), "azurerm_data_factory": resourceArmDataFactory(), "azurerm_data_factory_dataset_mysql": resourceArmDataFactoryDatasetMySQL(), "azurerm_data_factory_dataset_postgresql": resourceArmDataFactoryDatasetPostgreSQL(), @@ -443,6 +441,7 @@ func Provider() terraform.ResourceProvider { "azurerm_virtual_network": resourceArmVirtualNetwork(), "azurerm_virtual_wan": resourceArmVirtualWan(), "azurerm_web_application_firewall_policy": resourceArmWebApplicationFirewallPolicy(), + "azurerm_private_link_service": resourceArmPrivateLinkService(), } // avoids this showing up in test output diff --git a/azurerm/resource_arm_loadbalancer.go b/azurerm/resource_arm_loadbalancer.go index 8f1abe0a666d..cafcf75068b7 100644 --- a/azurerm/resource_arm_loadbalancer.go +++ b/azurerm/resource_arm_loadbalancer.go @@ -134,6 +134,11 @@ func resourceArmLoadBalancer() *schema.Resource { }, "zones": azure.SchemaSingleZone(), + + "id": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -358,6 +363,10 @@ func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPC ipConfig["name"] = *config.Name } + if config.ID != nil { + ipConfig["id"] = *config.ID + } + zones := make([]string, 0) if zs := config.Zones; zs != nil { zones = *zs diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go new file mode 100644 index 000000000000..26c2d8d553b6 --- /dev/null +++ b/azurerm/resource_arm_private_link_service.go @@ -0,0 +1,643 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmPrivateLinkService() *schema.Resource { + return &schema.Resource{ + Create: resourceArmPrivateLinkServiceCreateUpdate, + Read: resourceArmPrivateLinkServiceRead, + Update: resourceArmPrivateLinkServiceCreateUpdate, + Delete: resourceArmPrivateLinkServiceDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "location": azure.SchemaLocation(), + + "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), + + "auto_approval": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subscriptions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "fqdns": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "ip_configurations": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "private_ip_allocation_method": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Static), + string(network.Dynamic), + }, false), + Default: string(network.Static), + }, + "private_ip_address": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "private_ip_address_version": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.IPv4), + string(network.IPv6), + }, false), + Default: string(network.IPv4), + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + }, + }, + + "load_balancer_frontend_ip_configurations": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + }, + }, + + "private_endpoint_connections": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + }, + "name": { + Type: schema.TypeString, + Optional: true, + }, + "private_endpoint": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + }, + "location": azure.SchemaLocation(), + "tags": tags.Schema(), + }, + }, + }, + "private_link_service_connection_state": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_required": { + Type: schema.TypeString, + Optional: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "status": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + + "visibility": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subscriptions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "alias": { + Type: schema.TypeString, + Computed: true, + }, + + "network_interfaces": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "type": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).network.PrivateLinkServiceClient + ctx := meta.(*ArmClient).StopContext + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + resp, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error checking for present of existing Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + if !utils.ResponseWasNotFound(resp.Response) { + return tf.ImportAsExistsError("azurerm_private_link_service", *resp.ID) + } + } + + location := azure.NormalizeLocation(d.Get("location").(string)) + autoApproval := d.Get("auto_approval").([]interface{}) + fqdns := d.Get("fqdns").([]interface{}) + ipConfigurations := d.Get("ip_configurations").([]interface{}) + loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configurations").([]interface{}) + privateEndpointConnections := d.Get("private_endpoint_connections").([]interface{}) + visibility := d.Get("visibility").([]interface{}) + t := d.Get("tags").(map[string]interface{}) + + parameters := network.PrivateLinkService{ + Location: utils.String(location), + PrivateLinkServiceProperties: &network.PrivateLinkServiceProperties{ + AutoApproval: expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(autoApproval), + Fqdns: utils.ExpandStringSlice(fqdns), + IPConfigurations: expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(ipConfigurations), + LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), + PrivateEndpointConnections: expandArmPrivateLinkServicePrivateEndpointConnection(privateEndpointConnections), + Visibility: expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(visibility), + }, + Tags: tags.Expand(t), + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters) + if err != nil { + return fmt.Errorf("Error creating Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for creation of Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + resp, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + return fmt.Errorf("Error retrieving Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read Private Link Service %q (Resource Group %q) ID", name, resourceGroup) + } + d.SetId(*resp.ID) + + return resourceArmPrivateLinkServiceRead(d, meta) +} + +func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).network.PrivateLinkServiceClient + ctx := meta.(*ArmClient).StopContext + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["privateLinkServices"] + + resp, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Private Link Service %q does not exist - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("Error reading Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if privateLinkServiceProperties := resp.PrivateLinkServiceProperties; privateLinkServiceProperties != nil { + d.Set("alias", privateLinkServiceProperties.Alias) + if err := d.Set("auto_approval", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { + return fmt.Errorf("Error setting `auto_approval`: %+v", err) + } + d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)) + if err := d.Set("ip_configurations", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `ip_configurations`: %+v", err) + } + if err := d.Set("load_balancer_frontend_ip_configurations", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configurations`: %+v", err) + } + if err := d.Set("network_interfaces", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interfaces`: %+v", err) + } + if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connections`: %+v", err) + } + if err := d.Set("visibility", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility`: %+v", err) + } + } + d.Set("type", resp.Type) + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).network.PrivateLinkServiceClient + ctx := meta.(*ArmClient).StopContext + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["privateLinkServices"] + + future, err := client.Delete(ctx, resourceGroup, name) + if err != nil { + if response.WasNotFound(future.Response()) { + return nil + } + return fmt.Errorf("Error deleting Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("Error waiting for deleting Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input []interface{}) *network.PrivateLinkServicePropertiesAutoApproval { + if len(input) == 0 { + return nil + } + v := input[0].(map[string]interface{}) + + subscriptions := v["subscriptions"].([]interface{}) + + result := network.PrivateLinkServicePropertiesAutoApproval{ + Subscriptions: utils.ExpandStringSlice(subscriptions), + } + return &result +} + +func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { + results := make([]network.PrivateLinkServiceIPConfiguration, 0) + for _, item := range input { + v := item.(map[string]interface{}) + privateIpAddress := v["private_ip_address"].(string) + privateIPAllocationMethod := v["private_ip_allocation_method"].(string) + subnetId := v["subnet_id"].(string) + privateIpAddressVersion := v["private_ip_address_version"].(string) + name := v["name"].(string) + + result := network.PrivateLinkServiceIPConfiguration{ + Name: utils.String(name), + PrivateLinkServiceIPConfigurationProperties: &network.PrivateLinkServiceIPConfigurationProperties{ + PrivateIPAddress: utils.String(privateIpAddress), + PrivateIPAddressVersion: network.IPVersion(privateIpAddressVersion), + PrivateIPAllocationMethod: network.IPAllocationMethod(privateIPAllocationMethod), + Subnet: &network.Subnet{ + ID: utils.String(subnetId), + }, + }, + } + + results = append(results, result) + } + return &results +} + +func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[]network.FrontendIPConfiguration { + results := make([]network.FrontendIPConfiguration, 0) + for _, item := range input { + v := item.(map[string]interface{}) + id := v["id"].(string) + + result := network.FrontendIPConfiguration{ + ID: utils.String(id), + } + + results = append(results, result) + } + return &results +} + +func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) *[]network.PrivateEndpointConnection { + results := make([]network.PrivateEndpointConnection, 0) + for _, item := range input { + v := item.(map[string]interface{}) + id := v["id"].(string) + privateEndpoint := v["private_endpoint"].([]interface{}) + privateLinkServiceConnectionState := v["private_link_service_connection_state"].([]interface{}) + name := v["name"].(string) + + result := network.PrivateEndpointConnection{ + ID: utils.String(id), + Name: utils.String(name), + PrivateEndpointConnectionProperties: &network.PrivateEndpointConnectionProperties{ + PrivateEndpoint: expandArmPrivateLinkServicePrivateEndpoint(privateEndpoint), + PrivateLinkServiceConnectionState: expandArmPrivateLinkServicePrivateLinkServiceConnectionState(privateLinkServiceConnectionState), + }, + } + + results = append(results, result) + } + return &results +} + +func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { + if len(input) == 0 { + return nil + } + v := input[0].(map[string]interface{}) + + subscriptions := v["subscriptions"].([]interface{}) + + result := network.PrivateLinkServicePropertiesVisibility{ + Subscriptions: utils.ExpandStringSlice(subscriptions), + } + return &result +} + +func expandArmPrivateLinkServicePrivateEndpoint(input []interface{}) *network.PrivateEndpoint { + if len(input) == 0 { + return nil + } + v := input[0].(map[string]interface{}) + + id := v["id"].(string) + location := azure.NormalizeLocation(v["location"].(string)) + t := v["tags"].(map[string]interface{}) + + result := network.PrivateEndpoint{ + ID: utils.String(id), + Location: utils.String(location), + Tags: tags.Expand(t), + } + return &result +} + +func expandArmPrivateLinkServicePrivateLinkServiceConnectionState(input []interface{}) *network.PrivateLinkServiceConnectionState { + if len(input) == 0 { + return nil + } + v := input[0].(map[string]interface{}) + + status := v["status"].(string) + description := v["description"].(string) + actionRequired := v["action_required"].(string) + + result := network.PrivateLinkServiceConnectionState{ + ActionRequired: utils.String(actionRequired), + Description: utils.String(description), + Status: utils.String(status), + } + return &result +} + +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + + result["subscriptions"] = utils.FlattenStringSlice(input.Subscriptions) + + return []interface{}{result} +} + +func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + v := make(map[string]interface{}) + + if name := item.Name; name != nil { + v["name"] = *name + } + if privateLinkServiceIPConfigurationProperties := item.PrivateLinkServiceIPConfigurationProperties; privateLinkServiceIPConfigurationProperties != nil { + v["private_ip_allocation_method"] = string(privateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod) + if privateIpAddress := privateLinkServiceIPConfigurationProperties.PrivateIPAddress; privateIpAddress != nil { + v["private_ip_address"] = *privateIpAddress + } + v["private_ip_address_version"] = string(privateLinkServiceIPConfigurationProperties.PrivateIPAddressVersion) + if subnet := privateLinkServiceIPConfigurationProperties.Subnet; subnet != nil { + if subnetId := subnet.ID; subnetId != nil { + v["subnet_id"] = *subnetId + } + } + } + + results = append(results, v) + } + + return results +} + +func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + v := make(map[string]interface{}) + + if id := item.ID; id != nil { + v["id"] = *id + } + + results = append(results, v) + } + + return results +} + +func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + v := make(map[string]interface{}) + + if id := item.ID; id != nil { + v["id"] = *id + } + + results = append(results, v) + } + + return results +} + +func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.PrivateEndpointConnection) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + v := make(map[string]interface{}) + + if id := item.ID; id != nil { + v["id"] = *id + } + if privateEndpointConnectionProperties := item.PrivateEndpointConnectionProperties; privateEndpointConnectionProperties != nil { + v["private_endpoint"] = flattenArmPrivateLinkServicePrivateEndpoint(privateEndpointConnectionProperties.PrivateEndpoint) + v["private_link_service_connection_state"] = flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(privateEndpointConnectionProperties.PrivateLinkServiceConnectionState) + } + + results = append(results, v) + } + + return results +} + +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + + result["subscriptions"] = utils.FlattenStringSlice(input.Subscriptions) + + return []interface{}{result} +} + +func flattenArmPrivateLinkServicePrivateEndpoint(input *network.PrivateEndpoint) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + + if id := input.ID; id != nil { + result["id"] = *id + } + if location := input.Location; location != nil { + result["location"] = azure.NormalizeLocation(*location) + } + + return []interface{}{result} +} + +func flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(input *network.PrivateLinkServiceConnectionState) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + + if actionRequired := input.ActionRequired; actionRequired != nil { + result["action_required"] = *actionRequired + } + if description := input.Description; description != nil { + result["description"] = *description + } + if status := input.Status; status != nil { + result["status"] = *status + } + + return []interface{}{result} +} diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go new file mode 100644 index 000000000000..153f18c34faf --- /dev/null +++ b/azurerm/resource_arm_private_link_service_test.go @@ -0,0 +1,315 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { + resourceName := "azurerm_private_link_service.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { + resourceName := "azurerm_private_link_service.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateLinkService_complete(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMPrivateLinkService_update(t *testing.T) { + resourceName := "azurerm_private_link_service.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_complete(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMPrivateLinkServiceExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Private Link Service not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + client := testAccProvider.Meta().(*ArmClient).network.PrivateLinkServiceClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + if resp, err := client.Get(ctx, resourceGroup, name, ""); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Private Link Service %q (Resource Group %q) does not exist", name, resourceGroup) + } + return fmt.Errorf("Bad: Get on network.PrivateLinkServiceClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).network.PrivateLinkServiceClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_private_link_service" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + if resp, err := client.Get(ctx, resourceGroup, name, ""); err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Get on network.PrivateLinkServiceClient: %+v", err) + } + } + + return nil + } + + return nil +} + +func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctestsnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.5.1.0/24" + private_link_service_network_policies = "Disabled" +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%d" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + allocation_method = "Static" +} + +resource "azurerm_lb" "test" { + name = "acctestlb-%d" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + frontend_ip_configuration { + name = "${azurerm_public_ip.test.name}" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } +} + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + fqdns = ["testFqdns"] + + ip_configurations { + name = "${azurerm_public_ip.test.name}" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + private_ip_allocation_method = "Static" + } + + load_balancer_frontend_ip_configurations { + id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" + } +} +`, rInt, location, rInt, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctestsnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.5.1.0/24" + private_link_service_network_policies = "Disabled" +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%d" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + allocation_method = "Static" +} + +resource "azurerm_lb" "test" { + name = "acctestlb-%d" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + frontend_ip_configuration { + name = "${azurerm_public_ip.test.name}" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } +} + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + fqdns = ["testFqdns2"] + + ip_configurations { + name = "${azurerm_public_ip.test.name}" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + private_ip_allocation_method = "Static" + } + + load_balancer_frontend_ip_configurations { + id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" + } + + tags = { + env = "test" + } +} +`, rInt, location, rInt, rInt, rInt, rInt, rInt) +} diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index db34e20e7353..22cdf82a6c0e 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -125,6 +125,11 @@ func resourceArmSubnet() *schema.Resource { }, }, }, + + "private_link_service_network_policies": { + Type: schema.TypeString, + Optional: true, + }, }, } } @@ -161,6 +166,11 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } + if v, ok := d.GetOk("private_link_service_network_policies"); ok { + privateLinkServiceNetworkPolicies := v.(string) + properties.PrivateLinkServiceNetworkPolicies = &privateLinkServiceNetworkPolicies + } + if v, ok := d.GetOk("network_security_group_id"); ok { nsgId := v.(string) properties.NetworkSecurityGroup = &network.SecurityGroup{ @@ -257,6 +267,12 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) + var privateLinkServiceNetworkPolicies *string + if props.PrivateLinkServiceNetworkPolicies != nil { + privateLinkServiceNetworkPolicies = props.PrivateLinkServiceNetworkPolicies + } + d.Set("private_link_service_network_policies", privateLinkServiceNetworkPolicies) + var securityGroupId *string if props.NetworkSecurityGroup != nil { securityGroupId = props.NetworkSecurityGroup.ID diff --git a/examples/virtual-networks/private-link-service/README.md b/examples/virtual-networks/private-link-service/README.md new file mode 100644 index 000000000000..83c9b22fb80d --- /dev/null +++ b/examples/virtual-networks/private-link-service/README.md @@ -0,0 +1,3 @@ +## Example: Private Link Service + + This example provisions a Private Link Service. \ No newline at end of file diff --git a/examples/virtual-networks/private-link-service/main.tf b/examples/virtual-networks/private-link-service/main.tf new file mode 100644 index 000000000000..8242c43a401c --- /dev/null +++ b/examples/virtual-networks/private-link-service/main.tf @@ -0,0 +1,64 @@ +resource "azurerm_resource_group" "test" { + name = "${var.resource_group_name}" + location = "${var.location}" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvnet" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctestsnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.5.1.0/24" + private_link_service_network_policies = "Disabled" +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + allocation_method = "Static" +} + +resource "azurerm_lb" "test" { + name = "acctestlb" + sku = "Standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + frontend_ip_configuration { + name = "${azurerm_public_ip.test.name}" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } +} + +resource "azurerm_private_link_service" "test" { + name = "acctestpls" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + fqdns = ["testFqdns2"] + + ip_configurations { + name = "${azurerm_public_ip.test.name}" + + subnet_id = "${azurerm_subnet.test.id}" + + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + private_ip_allocation_method = "Static" + } + + load_balancer_frontend_ip_configurations { + id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" + } + + tags = { + env = "test" + } +} \ No newline at end of file diff --git a/examples/virtual-networks/private-link-service/variables.tf b/examples/virtual-networks/private-link-service/variables.tf new file mode 100644 index 000000000000..4e6058ba349f --- /dev/null +++ b/examples/virtual-networks/private-link-service/variables.tf @@ -0,0 +1,7 @@ +variable "resource_group_name" { + description = "The name of the resource group the Private Link Service is located in." +} + +variable "location" { + description = "The Azure location where all resources in this example should be created." +} \ No newline at end of file diff --git a/website/azurerm.erb b/website/azurerm.erb index fdb9605fc58b..f58b9ca2b124 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -274,10 +274,6 @@ azurerm_policy_definition -
  • - azurerm_public_ip_prefix -
  • -
  • azurerm_public_ip
  • @@ -378,6 +374,10 @@ azurerm_virtual_network_gateway +
  • + azurerm_private_link_service +
  • + > azurerm_virtual_network_gateway_connection @@ -655,7 +655,6 @@
  • azurerm_bot_channel_slack
  • -
  • azurerm_bot_channels_registration
  • @@ -663,10 +662,6 @@
  • azurerm_bot_connection
  • - -
  • - azurerm_bot_web_app -
  • @@ -1540,6 +1535,10 @@ azurerm_web_application_firewall_policy +
  • + azurerm_private_link_service +
  • + > azurerm_virtual_wan @@ -1563,15 +1562,6 @@ -
  • - Portal Resources - -
  • -
  • Private DNS Resources
  • @@ -1562,6 +1571,15 @@ +
  • + Portal Resources + +
  • +
  • Private DNS Resources
  • @@ -1571,13 +1571,13 @@ -
  • - Portal Resources - +
  • + Portal Resources +
  • From 3ad72459c19e057d3f0f976714fe81c29019d399 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Tue, 24 Sep 2019 19:14:21 -0700 Subject: [PATCH 04/44] Examples fix --- examples/virtual-networks/private-link-service/main.tf | 2 +- examples/virtual-networks/private-link-service/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/virtual-networks/private-link-service/main.tf b/examples/virtual-networks/private-link-service/main.tf index 8242c43a401c..3138c4474437 100644 --- a/examples/virtual-networks/private-link-service/main.tf +++ b/examples/virtual-networks/private-link-service/main.tf @@ -61,4 +61,4 @@ resource "azurerm_private_link_service" "test" { tags = { env = "test" } -} \ No newline at end of file +} diff --git a/examples/virtual-networks/private-link-service/variables.tf b/examples/virtual-networks/private-link-service/variables.tf index 4e6058ba349f..9d83fdac9dfd 100644 --- a/examples/virtual-networks/private-link-service/variables.tf +++ b/examples/virtual-networks/private-link-service/variables.tf @@ -4,4 +4,4 @@ variable "resource_group_name" { variable "location" { description = "The Azure location where all resources in this example should be created." -} \ No newline at end of file +} From e86b1e51bff61e5296ab010375a6f2c088fee1ec Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Wed, 25 Sep 2019 20:05:05 -0700 Subject: [PATCH 05/44] [WIP] Current Progress --- azurerm/resource_arm_private_link_service.go | 201 +++++++++--------- .../private-link-service/main.tf | 45 ++-- 2 files changed, 121 insertions(+), 125 deletions(-) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 26c2d8d553b6..f76baa5e763a 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -39,20 +39,21 @@ func resourceArmPrivateLinkService() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), - "auto_approval": { + "auto_approval_subscription_ids": { Type: schema.TypeList, Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "subscriptions": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + + "visibility_subscription_ids": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, @@ -61,17 +62,18 @@ func resourceArmPrivateLinkService() *schema.Resource { Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, - "ip_configurations": { + "nat_ip_configuration": { Type: schema.TypeList, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, - Optional: true, + Required: true, ValidateFunc: validate.NoEmptyStrings, }, "private_ip_allocation_method": { @@ -81,7 +83,7 @@ func resourceArmPrivateLinkService() *schema.Resource { string(network.Static), string(network.Dynamic), }, false), - Default: string(network.Static), + Default: string(network.Dynamic), }, "private_ip_address": { Type: schema.TypeString, @@ -99,28 +101,23 @@ func resourceArmPrivateLinkService() *schema.Resource { }, "subnet_id": { Type: schema.TypeString, - Optional: true, + Required: true, ValidateFunc: validate.NoEmptyStrings, }, }, }, }, - "load_balancer_frontend_ip_configurations": { + "load_balancer_frontend_ip_configuration_ids": { Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.NoEmptyStrings, - }, - }, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, - "private_endpoint_connections": { + "private_endpoint_connection": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -128,10 +125,12 @@ func resourceArmPrivateLinkService() *schema.Resource { "id": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, "name": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, "private_endpoint": { Type: schema.TypeList, @@ -142,6 +141,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "id": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, "location": azure.SchemaLocation(), "tags": tags.Schema(), @@ -157,14 +157,17 @@ func resourceArmPrivateLinkService() *schema.Resource { "action_required": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, "description": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, "status": { Type: schema.TypeString, Optional: true, + ValidateFunc: validate.NoEmptyStrings, }, }, }, @@ -173,38 +176,16 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, - "visibility": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "subscriptions": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "alias": { Type: schema.TypeString, Computed: true, }, - "network_interfaces": { + "network_interface_ids": { Type: schema.TypeList, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, - }, + Elem: &schema.Schema{ + Type: schema.TypeString, }, }, @@ -238,12 +219,12 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte } location := azure.NormalizeLocation(d.Get("location").(string)) - autoApproval := d.Get("auto_approval").([]interface{}) + autoApproval := d.Get("auto_approval_subscription_ids").([]interface{}) fqdns := d.Get("fqdns").([]interface{}) - ipConfigurations := d.Get("ip_configurations").([]interface{}) - loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configurations").([]interface{}) - privateEndpointConnections := d.Get("private_endpoint_connections").([]interface{}) - visibility := d.Get("visibility").([]interface{}) + ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) + loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) + privateEndpointConnections := d.Get("private_endpoint_connection").([]interface{}) + visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) parameters := network.PrivateLinkService{ @@ -307,24 +288,24 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) } if privateLinkServiceProperties := resp.PrivateLinkServiceProperties; privateLinkServiceProperties != nil { d.Set("alias", privateLinkServiceProperties.Alias) - if err := d.Set("auto_approval", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { - return fmt.Errorf("Error setting `auto_approval`: %+v", err) + if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { + return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)) - if err := d.Set("ip_configurations", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `ip_configurations`: %+v", err) + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if err := d.Set("load_balancer_frontend_ip_configurations", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { - return fmt.Errorf("Error setting `load_balancer_frontend_ip_configurations`: %+v", err) + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) } - if err := d.Set("network_interfaces", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { - return fmt.Errorf("Error setting `network_interfaces`: %+v", err) + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } - if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connections`: %+v", err) + if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) } - if err := d.Set("visibility", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { - return fmt.Errorf("Error setting `visibility`: %+v", err) + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } } d.Set("type", resp.Type) @@ -364,18 +345,27 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input [ if len(input) == 0 { return nil } - v := input[0].(map[string]interface{}) + + subscriptions := make([]string, 0) - subscriptions := v["subscriptions"].([]interface{}) + for _, v := range input { + subscriptions = append(subscriptions, v.(string)) + } result := network.PrivateLinkServicePropertiesAutoApproval{ - Subscriptions: utils.ExpandStringSlice(subscriptions), + Subscriptions: &subscriptions, } + return &result } func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { + if len(input) == 0 { + return nil + } + results := make([]network.PrivateLinkServiceIPConfiguration, 0) + for _, item := range input { v := item.(map[string]interface{}) privateIpAddress := v["private_ip_address"].(string) @@ -402,17 +392,20 @@ func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interf } func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[]network.FrontendIPConfiguration { + if len(input) == 0 { + return nil + } + results := make([]network.FrontendIPConfiguration, 0) - for _, item := range input { - v := item.(map[string]interface{}) - id := v["id"].(string) + for _, item := range input { result := network.FrontendIPConfiguration{ - ID: utils.String(id), + ID: utils.String(item.(string)), } results = append(results, result) } + return &results } @@ -443,13 +436,17 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []i if len(input) == 0 { return nil } - v := input[0].(map[string]interface{}) - subscriptions := v["subscriptions"].([]interface{}) + subscriptions := make([]string, 0) + + for _, v := range input { + subscriptions = append(subscriptions, v.(string)) + } result := network.PrivateLinkServicePropertiesVisibility{ - Subscriptions: utils.ExpandStringSlice(subscriptions), + Subscriptions: &subscriptions, } + return &result } @@ -494,9 +491,13 @@ func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input return make([]interface{}, 0) } - result := make(map[string]interface{}) + result := make([]string, 0) - result["subscriptions"] = utils.FlattenStringSlice(input.Subscriptions) + for _, v := range *input.Subscriptions { + if subscription := v; subscription != "" { + result = append(result, subscription) + } + } return []interface{}{result} } @@ -533,41 +534,35 @@ func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]netw } func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []interface{} { - results := make([]interface{}, 0) if input == nil { - return results + return make([]interface{}, 0) } - for _, item := range *input { - v := make(map[string]interface{}) + results := make([]string, 0) + for _, item := range *input { if id := item.ID; id != nil { - v["id"] = *id + results = append(results, *id) } - - results = append(results, v) } - return results + return []interface{}{results} } func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []interface{} { - results := make([]interface{}, 0) if input == nil { - return results + return make([]interface{}, 0) } - for _, item := range *input { - v := make(map[string]interface{}) + results := make([]string, 0) + for _, item := range *input { if id := item.ID; id != nil { - v["id"] = *id + results = append(results, *id) } - - results = append(results, v) } - return results + return []interface{}{results} } func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.PrivateEndpointConnection) []interface{} { @@ -598,11 +593,15 @@ func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *n return make([]interface{}, 0) } - result := make(map[string]interface{}) + results := make([]string, 0) - result["subscriptions"] = utils.FlattenStringSlice(input.Subscriptions) + for _, v := range *input.Subscriptions { + if subscription := v; subscription != "" { + results = append(results, v) + } + } - return []interface{}{result} + return []interface{}{results} } func flattenArmPrivateLinkServicePrivateEndpoint(input *network.PrivateEndpoint) []interface{} { diff --git a/examples/virtual-networks/private-link-service/main.tf b/examples/virtual-networks/private-link-service/main.tf index 3138c4474437..2d6483b29038 100644 --- a/examples/virtual-networks/private-link-service/main.tf +++ b/examples/virtual-networks/private-link-service/main.tf @@ -1,19 +1,19 @@ resource "azurerm_resource_group" "test" { - name = "${var.resource_group_name}" - location = "${var.location}" + name = var.resource_group_name + location = var.location } resource "azurerm_virtual_network" "test" { name = "acctestvnet" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location address_space = ["10.5.0.0/16"] } resource "azurerm_subnet" "test" { name = "acctestsnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" private_link_service_network_policies = "Disabled" } @@ -21,42 +21,39 @@ resource "azurerm_subnet" "test" { resource "azurerm_public_ip" "test" { name = "acctestpip" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Static" } resource "azurerm_lb" "test" { name = "acctestlb" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name frontend_ip_configuration { - name = "${azurerm_public_ip.test.name}" - public_ip_address_id = "${azurerm_public_ip.test.id}" + name = azurerm_public_ip.test.name + public_ip_address_id = azurerm_public_ip.test.id } } resource "azurerm_private_link_service" "test" { name = "acctestpls" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name fqdns = ["testFqdns2"] - ip_configurations { - name = "${azurerm_public_ip.test.name}" - - subnet_id = "${azurerm_subnet.test.id}" - - private_ip_address = "10.5.1.17" - private_ip_address_version = "IPv4" + nat_ip_configuration { + name = azurerm_public_ip.test.name + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" private_ip_allocation_method = "Static" } - load_balancer_frontend_ip_configurations { - id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" - } + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] tags = { env = "test" From 99a9179d2d0eb8911124200233baca306567443a Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Thu, 26 Sep 2019 13:04:56 -0700 Subject: [PATCH 06/44] [WIP] Updates to code --- azurerm/data_source_private_link_service.go | 90 +++++++------------ .../data_source_private_link_service_test.go | 10 +-- azurerm/resource_arm_private_link_service.go | 44 ++++----- .../resource_arm_private_link_service_test.go | 16 ++-- 4 files changed, 71 insertions(+), 89 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 9f86949a6aa3..392942d76add 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -21,28 +21,23 @@ func dataSourceArmPrivateLinkService() *schema.Resource { ValidateFunc: validate.NoEmptyStrings, }, - "location": azure.SchemaLocationForDataSource(), + "location": azure.SchemaLocation(), - "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), - "alias": { - Type: schema.TypeString, + "auto_approval_subscription_ids": { + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - "auto_approval": { + "visibility_subscription_ids": { Type: schema.TypeList, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "subscriptions": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, + Elem: &schema.Schema{ + Type: schema.TypeString, }, }, @@ -54,62 +49,48 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "ip_configurations": { + "nat_ip_configuration": { Type: schema.TypeList, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, }, "private_ip_allocation_method": { Type: schema.TypeString, Computed: true, }, "private_ip_address": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, }, "private_ip_address_version": { Type: schema.TypeString, Computed: true, }, - "subnet_id": { - Type: schema.TypeString, + "primary": { + Type: schema.TypeBool, Computed: true, }, - }, - }, - }, - - "load_balancer_frontend_ip_configurations": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, + "subnet_id": { + Type: schema.TypeString, + Computed: true, }, }, }, }, - "network_interfaces": { + "load_balancer_frontend_ip_configuration_ids": { Type: schema.TypeList, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, - }, + Elem: &schema.Schema{ + Type: schema.TypeString, }, }, - "private_endpoint_connections": { + "private_endpoint_connection": { Type: schema.TypeList, Computed: true, Elem: &schema.Resource{ @@ -160,28 +141,25 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "type": { + "alias": { Type: schema.TypeString, Computed: true, }, - "visibility": { + "network_interface_ids": { Type: schema.TypeList, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "subscriptions": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, + Elem: &schema.Schema{ + Type: schema.TypeString, }, }, - "tags": tagsForDataSourceSchema(), + "type": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tags.Schema(), }, } } diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index ffe480613947..8678829e7d25 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -22,11 +22,11 @@ func TestAccDataSourceAzureRMPrivateLinkService_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(dataSourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, }, diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index f76baa5e763a..387443e01fa9 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -99,6 +99,11 @@ func resourceArmPrivateLinkService() *schema.Resource { }, false), Default: string(network.IPv4), }, + "primary": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, "subnet_id": { Type: schema.TypeString, Required: true, @@ -373,6 +378,7 @@ func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interf subnetId := v["subnet_id"].(string) privateIpAddressVersion := v["private_ip_address_version"].(string) name := v["name"].(string) + primary := v["primary"].(bool) result := network.PrivateLinkServiceIPConfiguration{ Name: utils.String(name), @@ -383,6 +389,7 @@ func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interf Subnet: &network.Subnet{ ID: utils.String(subnetId), }, + Primary: utils.Bool(primary), }, } @@ -486,20 +493,19 @@ func expandArmPrivateLinkServicePrivateLinkServiceConnectionState(input []interf return &result } -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []string { + result := make([]string, 0) if input == nil { - return make([]interface{}, 0) + return result } - result := make([]string, 0) - for _, v := range *input.Subscriptions { if subscription := v; subscription != "" { result = append(result, subscription) } } - return []interface{}{result} + return result } func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { @@ -525,6 +531,7 @@ func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]netw v["subnet_id"] = *subnetId } } + v["primary"] = bool(*item.PrivateLinkServiceIPConfigurationProperties.Primary) } results = append(results, v) @@ -533,36 +540,34 @@ func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]netw return results } -func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []interface{} { +func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []string { + results := make([]string, 0) if input == nil { - return make([]interface{}, 0) + return results } - results := make([]string, 0) - for _, item := range *input { if id := item.ID; id != nil { results = append(results, *id) } } - return []interface{}{results} + return results } -func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []interface{} { +func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []string { + results := make([]string, 0) if input == nil { - return make([]interface{}, 0) + return results } - results := make([]string, 0) - for _, item := range *input { if id := item.ID; id != nil { results = append(results, *id) } } - return []interface{}{results} + return results } func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.PrivateEndpointConnection) []interface{} { @@ -588,20 +593,19 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv return results } -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []string { + results := make([]string, 0) if input == nil { - return make([]interface{}, 0) + return results } - results := make([]string, 0) - for _, v := range *input.Subscriptions { if subscription := v; subscription != "" { results = append(results, v) } } - return []interface{}{results} + return results } func flattenArmPrivateLinkServicePrivateEndpoint(input *network.PrivateEndpoint) []interface{} { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 153f18c34faf..54e5c0ac3995 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -232,7 +232,7 @@ resource "azurerm_private_link_service" "test" { resource_group_name = "${azurerm_resource_group.test.name}" fqdns = ["testFqdns"] - ip_configurations { + nat_ip_configuration { name = "${azurerm_public_ip.test.name}" subnet_id = "${azurerm_subnet.test.id}" private_ip_address = "10.5.1.17" @@ -240,9 +240,9 @@ resource "azurerm_private_link_service" "test" { private_ip_allocation_method = "Static" } - load_balancer_frontend_ip_configurations { - id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" - } + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] } `, rInt, location, rInt, rInt, rInt, rInt, rInt) } @@ -295,7 +295,7 @@ resource "azurerm_private_link_service" "test" { resource_group_name = "${azurerm_resource_group.test.name}" fqdns = ["testFqdns2"] - ip_configurations { + nat_ip_configuration { name = "${azurerm_public_ip.test.name}" subnet_id = "${azurerm_subnet.test.id}" private_ip_address = "10.5.1.17" @@ -303,9 +303,9 @@ resource "azurerm_private_link_service" "test" { private_ip_allocation_method = "Static" } - load_balancer_frontend_ip_configurations { - id = "${azurerm_lb.test.frontend_ip_configuration.0.id}" - } + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] tags = { env = "test" From cfb7bc0c2ce5df5327212b3742945a2f596e5578 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Thu, 26 Sep 2019 13:06:36 -0700 Subject: [PATCH 07/44] [WIP] gofmt --- azurerm/data_source_private_link_service.go | 18 ++++---- azurerm/resource_arm_private_link_service.go | 46 ++++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 392942d76add..44225226bbc9 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -29,7 +29,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, }, }, @@ -37,7 +37,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, }, }, @@ -55,16 +55,16 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, }, "private_ip_allocation_method": { Type: schema.TypeString, Computed: true, }, "private_ip_address": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, }, "private_ip_address_version": { Type: schema.TypeString, @@ -75,8 +75,8 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Computed: true, }, "subnet_id": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, }, }, }, @@ -86,7 +86,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, }, }, diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 387443e01fa9..4d2678786500 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -43,8 +43,8 @@ func resourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, @@ -52,8 +52,8 @@ func resourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, @@ -61,7 +61,7 @@ func resourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, ValidateFunc: validate.NoEmptyStrings, }, }, @@ -100,9 +100,9 @@ func resourceArmPrivateLinkService() *schema.Resource { Default: string(network.IPv4), }, "primary": { - Type: schema.TypeBool, - Optional: true, - Default: true, + Type: schema.TypeBool, + Optional: true, + Default: true, }, "subnet_id": { Type: schema.TypeString, @@ -117,8 +117,8 @@ func resourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeList, Required: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, @@ -128,13 +128,13 @@ func resourceArmPrivateLinkService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, "name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, "private_endpoint": { @@ -144,8 +144,8 @@ func resourceArmPrivateLinkService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, "location": azure.SchemaLocation(), @@ -160,18 +160,18 @@ func resourceArmPrivateLinkService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "action_required": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, "status": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validate.NoEmptyStrings, }, }, @@ -350,7 +350,7 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input [ if len(input) == 0 { return nil } - + subscriptions := make([]string, 0) for _, v := range input { From b2b681e67932cfdd65a0c9ddc5cd391239e87ca5 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Fri, 27 Sep 2019 17:50:31 -0700 Subject: [PATCH 08/44] [WIP] Final changes --- .../data_source_private_link_service_test.go | 4 +- azurerm/resource_arm_private_link_service.go | 1 + .../resource_arm_private_link_service_test.go | 106 +++++++++--------- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 8678829e7d25..5cb3a41b97b4 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -39,8 +39,8 @@ func testAccDataSourcePrivateLinkService_basic(rInt int, location string) string %s data "azurerm_private_link_service" "test" { - resource_group_name = "${azurerm_private_link_service.test.resource_group_name}" - name = "${azurerm_private_link_service.test.name}" + resource_group_name = azurerm_private_link_service.test.resource_group_name + name = azurerm_private_link_service.test.name } `, config) } diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 4d2678786500..e9f75983e129 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -125,6 +125,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "private_endpoint_connection": { Type: schema.TypeList, Optional: true, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 54e5c0ac3995..b7a9b27a6494 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -26,11 +26,11 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), ), }, { @@ -58,11 +58,11 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), @@ -92,11 +92,11 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), ), }, { @@ -105,11 +105,11 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), @@ -120,11 +120,11 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configurations.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configurations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), ), }, { @@ -193,15 +193,15 @@ resource "azurerm_resource_group" "test" { resource "azurerm_virtual_network" "test" { name = "acctestvnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location address_space = ["10.5.0.0/16"] } resource "azurerm_subnet" "test" { name = "acctestsnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" private_link_service_network_policies = "Disabled" } @@ -209,32 +209,32 @@ resource "azurerm_subnet" "test" { resource "azurerm_public_ip" "test" { name = "acctestpip-%d" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Static" } resource "azurerm_lb" "test" { name = "acctestlb-%d" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name frontend_ip_configuration { - name = "${azurerm_public_ip.test.name}" - public_ip_address_id = "${azurerm_public_ip.test.id}" + name = azurerm_public_ip.test.name + public_ip_address_id = azurerm_public_ip.test.id } } resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name fqdns = ["testFqdns"] nat_ip_configuration { - name = "${azurerm_public_ip.test.name}" - subnet_id = "${azurerm_subnet.test.id}" + name = azurerm_public_ip.test.name + subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" private_ip_allocation_method = "Static" @@ -256,15 +256,15 @@ resource "azurerm_resource_group" "test" { resource "azurerm_virtual_network" "test" { name = "acctestvnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location address_space = ["10.5.0.0/16"] } resource "azurerm_subnet" "test" { name = "acctestsnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" private_link_service_network_policies = "Disabled" } @@ -272,32 +272,32 @@ resource "azurerm_subnet" "test" { resource "azurerm_public_ip" "test" { name = "acctestpip-%d" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Static" } resource "azurerm_lb" "test" { name = "acctestlb-%d" sku = "Standard" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name frontend_ip_configuration { - name = "${azurerm_public_ip.test.name}" - public_ip_address_id = "${azurerm_public_ip.test.id}" + name = azurerm_public_ip.test.name + public_ip_address_id = azurerm_public_ip.test.id } } resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name fqdns = ["testFqdns2"] nat_ip_configuration { - name = "${azurerm_public_ip.test.name}" - subnet_id = "${azurerm_subnet.test.id}" + name = azurerm_public_ip.test.name + subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" private_ip_allocation_method = "Static" From 5abd85a6b6026b78cc13189fd42d07587d2f563b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Fri, 27 Sep 2019 20:21:48 -0700 Subject: [PATCH 09/44] [WIP] Updated Tests and Docs --- .../resource_arm_private_link_service_test.go | 212 ++++++++++-------- .../docs/r/private_link_service.html.markdown | 54 ++--- 2 files changed, 143 insertions(+), 123 deletions(-) diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index b7a9b27a6494..334e57946ae8 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -24,13 +24,8 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), ), }, { @@ -42,7 +37,7 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { }) } -func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { +func TestAccAzureRMPrivateLinkService_update(t *testing.T) { resourceName := "azurerm_private_link_service.test" ri := tf.AccRandTimeInt() location := testLocation() @@ -52,21 +47,36 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { Providers: testAccProviders, CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + ), + }, { Config: testAccAzureRMPrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), }, + { + Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + ), + }, { ResourceName: resourceName, ImportState: true, @@ -76,7 +86,7 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { }) } -func TestAccAzureRMPrivateLinkService_update(t *testing.T) { +func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resourceName := "azurerm_private_link_service.test" ri := tf.AccRandTimeInt() location := testLocation() @@ -86,47 +96,21 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Providers: testAccProviders, CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, Steps: []resource.TestStep{ - { - Config: testAccAzureRMPrivateLinkService_basic(ri, location), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), - ), - }, { Config: testAccAzureRMPrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), }, - { - Config: testAccAzureRMPrivateLinkService_basic(ri, location), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration.#", "1"), - ), - }, { ResourceName: resourceName, ImportState: true, @@ -185,6 +169,42 @@ func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { } func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { + standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) + privateLink := testAccAzureRMPrivateLinkServiceTemplate_basic(rInt) + + return testAccAzureRMPrivateLinkServiceTemplate("", standardResources, privateLink) +} + +func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { + standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) + privateLink := testAccAzureRMPrivateLinkServiceTemplate_update(rInt) + + return testAccAzureRMPrivateLinkServiceTemplate("", standardResources, privateLink) +} + +func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { + subscriptionDataSource := testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() + standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) + privateLink := testAccAzureRMPrivateLinkServiceTemplate_basic(rInt) + + return testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSource, standardResources, privateLink) +} + +func testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSourceTemplate string, standardResourcesTemplate string, privateLinkTemplate string) string { + return fmt.Sprintf(` +%s + +%s + +%s +`,subscriptionDataSourceTemplate, standardResourcesTemplate, privateLinkTemplate) +} + +func testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() string { + return `data "azurerm_subscription" "current" {}` +} + +func testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -225,84 +245,82 @@ resource "azurerm_lb" "test" { public_ip_address_id = azurerm_public_ip.test.id } } +`,rInt, location, rInt, rInt, rInt, rInt) +} +func testAccAzureRMPrivateLinkServiceTemplate_basic(rInt int) string { + return fmt.Sprintf(` resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - fqdns = ["testFqdns"] + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name nat_ip_configuration { - name = azurerm_public_ip.test.name + name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.17" - private_ip_address_version = "IPv4" - private_ip_allocation_method = "Static" } load_balancer_frontend_ip_configuration_ids = [ azurerm_lb.test.frontend_ip_configuration.0.id ] } -`, rInt, location, rInt, rInt, rInt, rInt, rInt) +`, rInt, rInt) } -func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { +func testAccAzureRMPrivateLinkServiceTemplate_update(rInt int) string { return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvnet-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - address_space = ["10.5.0.0/16"] -} - -resource "azurerm_subnet" "test" { - name = "acctestsnet-%d" - resource_group_name = azurerm_resource_group.test.name - virtual_network_name = azurerm_virtual_network.test.name - address_prefix = "10.5.1.0/24" - private_link_service_network_policies = "Disabled" -} +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + fqdns = ["testFqdns2"] -resource "azurerm_public_ip" "test" { - name = "acctestpip-%d" - sku = "Standard" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - allocation_method = "Static" -} + nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + private_ip_allocation_method = "Static" + } -resource "azurerm_lb" "test" { - name = "acctestlb-%d" - sku = "Standard" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] - frontend_ip_configuration { - name = azurerm_public_ip.test.name - public_ip_address_id = azurerm_public_ip.test.id + tags = { + env = "test" } } +`, rInt, rInt) +} +func testAccAzureRMPrivateLinkServiceTemplate_complete(rInt int) string { + return fmt.Sprintf(` resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - fqdns = ["testFqdns2"] + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + fqdns = ["testFqdns2"] + auto_approval_subscription_ids = [data.azurerm_subscription.current.id,] + visibility_subscription_ids = [data.azurerm_subscription.current.id,] nat_ip_configuration { - name = azurerm_public_ip.test.name + name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" private_ip_allocation_method = "Static" } + nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + private_ip_allocation_method = "Static" + primary = false + } + load_balancer_frontend_ip_configuration_ids = [ azurerm_lb.test.frontend_ip_configuration.0.id ] @@ -311,5 +329,5 @@ resource "azurerm_private_link_service" "test" { env = "test" } } -`, rInt, location, rInt, rInt, rInt, rInt, rInt) +`, rInt, rInt, rInt) } diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 89699bc43737..9f318416b392 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -3,73 +3,73 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-resource-private-link-service" description: |- - Manage Azure PrivateLinkService instance. + Manages a Azure PrivateLinkService instance. --- # azurerm_private_link_service -Manage Azure PrivateLinkService instance. +Managea a Azure PrivateLinkService instance. ## Private Link Service Usage ```hcl resource "azurerm_resource_group" "example" { - name = "acctestRG" + name = "exampleRG" location = "Eastus2" } resource "azurerm_virtual_network" "example" { - name = "acctestvnet-%d" - resource_group_name = "${azurerm_resource_group.example.name}" - location = "${azurerm_resource_group.example.location}" + name = "example-avn" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location address_space = ["10.5.0.0/16"] } resource "azurerm_subnet" "example" { - name = "acctestsnet-%d" - resource_group_name = "${azurerm_resource_group.example.name}" - virtual_network_name = "${azurerm_virtual_network.example.name}" + name = "example-snet" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.5.1.0/24" } resource "azurerm_public_ip" "example" { - name = "acctestpip-%d" + name = "example-api" sku = "Standard" - location = "${azurerm_resource_group.example.location}" - resource_group_name = "${azurerm_resource_group.example.name}" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name allocation_method = "Static" } resource "azurerm_lb" "example" { - name = "acctestlb-%d" + name = "example-lb" sku = "Standard" - location = "${azurerm_resource_group.example.location}" - resource_group_name = "${azurerm_resource_group.example.name}" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name frontend_ip_configuration { - name = "${azurerm_public_ip.example.name}" - public_ip_address_id = "${azurerm_public_ip.example.id}" + name = azurerm_public_ip.example.name + public_ip_address_id = azurerm_public_ip.example.id } } resource "azurerm_private_link_service" "example" { - name = "acctestpls-%d" - location = "${azurerm_resource_group.example.location}" - resource_group_name = "${azurerm_resource_group.example.name}" + name = "example-pls" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name fqdns = ["testFqdns"] - ip_configurations { - name = "${azurerm_public_ip.example.name}" - subnet_id = "${azurerm_subnet.example.id}" + nat_ip_configuration { + name = "primaryIpConfiguration" + subnet_id = azurerm_subnet.example.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" private_ip_allocation_method = "Static" } - load_balancer_frontend_ip_configurations { - id = "${azurerm_lb.example.frontend_ip_configuration.0.id}" - } + load_balancer_frontend_ip_configuration_ids = [ + id = azurerm_lb.example.frontend_ip_configuration.0.id + ] } ``` @@ -107,6 +107,8 @@ The `auto_approval` block supports the following: The `ip_configuration` block supports the following: +* `primary` - (Optional) If the `ip_configuration` is the primary ip configuration or not. Defaults to true. + * `private_ip_address` - (Optional) The private IP address of the IP configuration. * `private_ip_allocation_method` - (Optional) The private IP address allocation method. Defaults to `Static`. From 19c8dfdf465840190d679a2c6a9638b0f345262b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Mon, 30 Sep 2019 18:05:27 -0700 Subject: [PATCH 10/44] [WIP] Updated test cases --- azurerm/resource_arm_private_link_service.go | 10 ++-- .../resource_arm_private_link_service_test.go | 51 +++++++++++-------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index e9f75983e129..031913d94baf 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -297,7 +297,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } - d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)) + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) + } + if err := d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)); err != nil { + return fmt.Errorf("Error setting `fqdns`: %+v", err) + } if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } @@ -310,9 +315,6 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) } - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { - return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) - } } d.Set("type", resp.Type) diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 334e57946ae8..0c844923ce1f 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -25,7 +25,8 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { @@ -52,19 +53,19 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { - Config: testAccAzureRMPrivateLinkService_complete(ri, location), + Config: testAccAzureRMPrivateLinkService_update(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "www.contoso.com"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), @@ -74,7 +75,8 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { @@ -100,13 +102,23 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { Config: testAccAzureRMPrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "testFqdns2"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "auto_approval_subscription_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "auto_approval_subscription_ids.0"), + resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), + resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "fqdns.0", "www.contoso.com"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.primary", "true"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.primary", "false"), + resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), @@ -201,7 +213,9 @@ func testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSourceTemplate str } func testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() string { - return `data "azurerm_subscription" "current" {}` + return `data "azurerm_subscription" "current" {} + +` } func testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt int, location string) string { @@ -273,14 +287,11 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - fqdns = ["testFqdns2"] + fqdns = ["www.contoso.com"] nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.17" - private_ip_address_version = "IPv4" - private_ip_allocation_method = "Static" } load_balancer_frontend_ip_configuration_ids = [ @@ -300,9 +311,9 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - fqdns = ["testFqdns2"] - auto_approval_subscription_ids = [data.azurerm_subscription.current.id,] - visibility_subscription_ids = [data.azurerm_subscription.current.id,] + fqdns = ["www.contoso.com"] + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] nat_ip_configuration { name = "primaryIpConfiguration-%d" From d4bd7e4549a7ada812b7cf5d27e8ae1eee2fdc78 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Mon, 30 Sep 2019 19:16:50 -0700 Subject: [PATCH 11/44] [WIP] fix test and lint --- azurerm/resource_arm_private_link_service.go | 2 +- azurerm/resource_arm_private_link_service_test.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 031913d94baf..4d728c989c11 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -534,7 +534,7 @@ func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]netw v["subnet_id"] = *subnetId } } - v["primary"] = bool(*item.PrivateLinkServiceIPConfigurationProperties.Primary) + v["primary"] = *item.PrivateLinkServiceIPConfigurationProperties.Primary } results = append(results, v) diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 0c844923ce1f..70ae12190ba3 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -197,7 +197,7 @@ func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { subscriptionDataSource := testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) - privateLink := testAccAzureRMPrivateLinkServiceTemplate_basic(rInt) + privateLink := testAccAzureRMPrivateLinkServiceTemplate_complete(rInt) return testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSource, standardResources, privateLink) } @@ -213,9 +213,7 @@ func testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSourceTemplate str } func testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() string { - return `data "azurerm_subscription" "current" {} - -` + return `data "azurerm_subscription" "current" {}` } func testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt int, location string) string { From 08695db41857b0182df26ba265543820261aa17c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Wed, 2 Oct 2019 19:33:40 -0700 Subject: [PATCH 12/44] [WIP] Update attribute --- azurerm/data_source_subnet.go | 12 +++---- .../resource_arm_private_link_service_test.go | 3 +- azurerm/resource_arm_subnet.go | 34 ++++++++++++++----- website/docs/d/subnet.html.markdown | 2 +- website/docs/r/subnet.html.markdown | 4 ++- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index 505183ee4351..ac987a061aed 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -57,8 +57,8 @@ func dataSourceArmSubnet() *schema.Resource { }, }, - "private_link_service_network_policies": { - Type: schema.TypeString, + "disable_private_link_service_network_policies": { + Type: schema.TypeBool, Computed: true, }, }, @@ -89,10 +89,10 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - if props.PrivateLinkServiceNetworkPolicies != nil { - d.Set("private_link_service_network_policies", props.PrivateLinkServiceNetworkPolicies) - } else { - d.Set("private_link_service_network_policies", "") + if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { + if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + return err + } } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 70ae12190ba3..a0f244c984e3 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -235,7 +235,8 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" - private_link_service_network_policies = "Disabled" + + disable_private_link_service_network_policies = true } resource "azurerm_public_ip" "test" { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index 22cdf82a6c0e..c7e570a8f73e 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -126,9 +126,10 @@ func resourceArmSubnet() *schema.Resource { }, }, - "private_link_service_network_policies": { - Type: schema.TypeString, + "disable_private_link_service_network_policies": { + Type: schema.TypeBool, Optional: true, + Default: false, }, }, } @@ -166,8 +167,18 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } - if v, ok := d.GetOk("private_link_service_network_policies"); ok { - privateLinkServiceNetworkPolicies := v.(string) + if v, ok := d.GetOk("disable_private_link_service_network_policies"); ok { + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + // + // To enable private endpoints you must disable the network policies for the + // subnet because Network policies like network security groups are not + // supported by private endpoints. + privateLinkServiceNetworkPolicies := "Enabled" + if v.(bool) { + privateLinkServiceNetworkPolicies := "Disabled" + } properties.PrivateLinkServiceNetworkPolicies = &privateLinkServiceNetworkPolicies } @@ -267,11 +278,18 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - var privateLinkServiceNetworkPolicies *string - if props.PrivateLinkServiceNetworkPolicies != nil { - privateLinkServiceNetworkPolicies = props.PrivateLinkServiceNetworkPolicies + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + // + // To enable private endpoints you must disable the network policies for the + // subnet because Network policies like network security groups are not + // supported by private endpoints. + if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { + if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + return err + } } - d.Set("private_link_service_network_policies", privateLinkServiceNetworkPolicies) var securityGroupId *string if props.NetworkSecurityGroup != nil { diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 2e073ba6bdae..60976ff08866 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -34,7 +34,7 @@ output "subnet_id" { * `id` - The ID of the Subnet. * `address_prefix` - The address prefix used for the subnet. -* `private_link_service_network_policies` - Enable or Disable apply network policies on private link service in the subnet. +* `disable_private_link_service_network_policies` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. * `ip_configurations` - The collection of IP Configurations with IPs within this subnet. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 1524dc963cc5..be097dd98bf7 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,7 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `private_link_service_network_policies` - (Optional) Enable or Disable apply network policies on private link service in the subnet. +* `disable_private_link_service_network_policies` - (Optional) Enable or Disable network policies on private link service in the subnet. Default is `false`. + +-> **NOTE:** In order to choose a source IP address for your Private Link service, an explicit disable setting `disable_private_link_service_network_policies` is required on the subnet. This setting is only applicable for the specific private IP address you chose as the source IP of the Private Link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From 80671918b98a90e661d74dcb15276f4713c9503b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 4 Oct 2019 11:55:23 -0700 Subject: [PATCH 13/44] [WIP] Progress --- azurerm/data_source_private_link_service.go | 6 +- azurerm/internal/services/network/validate.go | 61 +++++++++++++++++++ azurerm/resource_arm_private_link_service.go | 9 +-- 3 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 azurerm/internal/services/network/validate.go diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 44225226bbc9..875a42f64e46 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -21,9 +21,9 @@ func dataSourceArmPrivateLinkService() *schema.Resource { ValidateFunc: validate.NoEmptyStrings, }, - "location": azure.SchemaLocation(), + "location": azure.SchemaLocationForDataSource(), - "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), "auto_approval_subscription_ids": { Type: schema.TypeList, @@ -113,7 +113,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Computed: true, }, "location": azure.SchemaLocationForDataSource(), - "tags": tagsForDataSourceSchema(), + "tags": tags.SchemaDataSource(), }, }, }, diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go new file mode 100644 index 000000000000..fa1e26b793af --- /dev/null +++ b/azurerm/internal/services/network/validate.go @@ -0,0 +1,61 @@ +package network + +import ( + "fmt" + "strings" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" +) + +func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors []error) { + if m, regexErrs := validate.RegExHelper(i, k, `(^[\da-zA-Z]){1,}([\d\._\-a-zA-Z]{0,77})([\da-zA-Z_]$)`); !m { + errors = append(regexErrs, fmt.Errorf(`%q must be between 1 and 80 characters, begin with a letter or number, end with a letter, number or underscore, and may contain only letters, numbers, underscores, periods, or hyphens.`, k)) + } + + return nil, errors +} + +func ValidatePrivateLinkServiceSubsciptionGuid(i interface{}, k string) (_ []string, errors []error) { + if m, regexErrs := validate.RegExHelper(i, k, `(^([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$)`); !m { + errors = append(regexErrs, fmt.Errorf(`%q is an invalid subscription GUID.`, k)) + } + + return nil, errors +} + +func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + } + + if m, _ := validate.RegExHelper(i, k, `^(([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d])\.){1,}([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d\.]){1,}$`); !m { + errors = append(errors, fmt.Errorf(`%q is an invalid fqdn.`, k)) + } + + if len(v) > 253 { + errors = append(errors, fmt.Errorf(`FQDNs can not be longer than 253 characters in length, got %d characters.`, len(v))) + } + + // TODO: Remove empty entries, this is a bug with the trailing . format + segments := strings.Split(v, ".") + index := 0 + + for _,label := range segments { + index++ + fmt.Println(label) + + if index == len(segments) { + if label != "" && len(label) < 2 { + errors = append(errors,fmt.Errorf(`the last label of an FQDN must be at least 2 characters long, %q is only 1 character in length.`, label)) + } + } else { + if len(label) > 63 { + errors = append(errors,fmt.Errorf(`labels of an FQDN must not be longer than 63 characters, got %d character.`, len(label))) + } + } + } + + + return nil, errors +} \ No newline at end of file diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 4d728c989c11..f8bcae6a8cb0 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -13,6 +13,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + aznet "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -32,19 +33,19 @@ func resourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, "location": azure.SchemaLocation(), - "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), + "resource_group_name": azure.SchemaResourceGroupName(), "auto_approval_subscription_ids": { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceSubsciptionGuid, }, }, @@ -53,7 +54,7 @@ func resourceArmPrivateLinkService() *schema.Resource { Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceSubsciptionGuid, }, }, From 3ffd269e1c2d0b2e08f99d637e9613774911193a Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 4 Oct 2019 19:16:37 -0700 Subject: [PATCH 14/44] [WIP] Progress --- azurerm/data_source_private_link_service.go | 61 +++--- azurerm/internal/services/network/validate.go | 51 +++-- azurerm/resource_arm_private_link_service.go | 184 +++++++++--------- azurerm/resource_arm_subnet.go | 2 +- azurerm/utils/split.go | 22 +++ .../docs/d/private_link_service.html.markdown | 62 ++---- .../docs/r/private_link_service.html.markdown | 66 +++---- 7 files changed, 230 insertions(+), 218 deletions(-) create mode 100644 azurerm/utils/split.go diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 875a42f64e46..687406b8cbf5 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -41,13 +41,14 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "fqdns": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, + // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you + // "fqdns": { + // Type: schema.TypeList, + // Computed: true, + // Elem: &schema.Schema{ + // Type: schema.TypeString, + // }, + // }, "nat_ip_configuration": { Type: schema.TypeList, @@ -180,35 +181,47 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ } 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 privateLinkServiceProperties := resp.PrivateLinkServiceProperties; privateLinkServiceProperties != nil { - d.Set("alias", privateLinkServiceProperties.Alias) - if err := d.Set("auto_approval", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { - return fmt.Errorf("Error setting `auto_approval`: %+v", err) + if props := resp.PrivateLinkServiceProperties; props != nil { + if err := d.Set("alias", props.Alias); err != nil { + return fmt.Errorf("Error setting `alias`: %+v", err) } - d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)) - if err := d.Set("ip_configurations", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `ip_configurations`: %+v", err) + if props.AutoApproval != nil { + if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) + } } - if err := d.Set("load_balancer_frontend_ip_configurations", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { - return fmt.Errorf("Error setting `load_balancer_frontend_ip_configurations`: %+v", err) + if props.Visibility != nil { + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) + } } - if err := d.Set("network_interfaces", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { - return fmt.Errorf("Error setting `network_interfaces`: %+v", err) + // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you + // if props.Fqdns != nil { + // if err := d.Set("fqdns", utils.FlattenStringSlice(props.Fqdns)); err != nil { + // return fmt.Errorf("Error setting `fqdns`: %+v", err) + // } + // } + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connections`: %+v", err) + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) } - if err := d.Set("visibility", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { - return fmt.Errorf("Error setting `visibility`: %+v", err) + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } + if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(props.PrivateEndpointConnections)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + } + } + if err := d.Set("type", resp.Type); err != nil { + return fmt.Errorf("Error setting `type`: %+v", err) } - d.Set("type", resp.Type) return tags.FlattenAndSet(d, resp.Tags) } diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index fa1e26b793af..a6aef2230aa1 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -2,9 +2,11 @@ package network import ( "fmt" - "strings" + "net" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors []error) { @@ -30,32 +32,57 @@ func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []str } if m, _ := validate.RegExHelper(i, k, `^(([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d])\.){1,}([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d\.]){1,}$`); !m { - errors = append(errors, fmt.Errorf(`%q is an invalid fqdn.`, k)) + errors = append(errors, fmt.Errorf(`%q is an invalid FQDN`, v)) } - if len(v) > 253 { - errors = append(errors, fmt.Errorf(`FQDNs can not be longer than 253 characters in length, got %d characters.`, len(v))) + // I use 255 here because the string contains the upto three . characters in them + if len(v) > 255 { + errors = append(errors, fmt.Errorf(`FQDNs can not be longer than 255 characters in length, got %d characters`, len(v))) } - // TODO: Remove empty entries, this is a bug with the trailing . format - segments := strings.Split(v, ".") + segments := utils.SplitRemoveEmptyEntries(v, ".", false) index := 0 for _,label := range segments { index++ - fmt.Println(label) - if index == len(segments) { - if label != "" && len(label) < 2 { - errors = append(errors,fmt.Errorf(`the last label of an FQDN must be at least 2 characters long, %q is only 1 character in length.`, label)) + if len(label) < 2 { + errors = append(errors,fmt.Errorf(`the last label of an FQDN must be at least 2 characters, got 1 character`)) } } else { if len(label) > 63 { - errors = append(errors,fmt.Errorf(`labels of an FQDN must not be longer than 63 characters, got %d character.`, len(label))) + errors = append(errors,fmt.Errorf(`FQDN labels must not be longer than 63 characters, got %d characters`, len(label))) } } } return nil, errors -} \ No newline at end of file +} + +func ValidatePrivateLinkServiceIPv4Address(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + } + + result := net.ParseIP(v) + if result.To4() == nil { + errors = append(errors, fmt.Errorf("%q is not a valid IPv4 IP address", v)) + } + + return nil, errors +} + +func ValidatePrivateLinkServiceIsResourceId(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + } + + if _, err := azure.ParseAzureResourceID(v); err != nil { + return nil, []error{fmt.Errorf("%q is not a valid %q", v, k)} + } + + return nil, errors +} diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index f8bcae6a8cb0..39a7f7168a3a 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -58,14 +58,15 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, - "fqdns": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, - }, - }, + // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you + // "fqdns": { + // Type: schema.TypeList, + // Optional: true, + // Elem: &schema.Schema{ + // Type: schema.TypeString, + // ValidateFunc: validate.NoEmptyStrings, + // }, + // }, "nat_ip_configuration": { Type: schema.TypeList, @@ -86,10 +87,11 @@ func resourceArmPrivateLinkService() *schema.Resource { }, false), Default: string(network.Dynamic), }, + // Only IPv4 is supported by the API "private_ip_address": { Type: schema.TypeString, Optional: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceIPv4Address, }, "private_ip_address_version": { Type: schema.TypeString, @@ -108,7 +110,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "subnet_id": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, }, }, }, @@ -119,7 +121,7 @@ func resourceArmPrivateLinkService() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, }, }, @@ -132,7 +134,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "id": { Type: schema.TypeString, Optional: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, }, "name": { Type: schema.TypeString, @@ -148,7 +150,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "id": { Type: schema.TypeString, Optional: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, }, "location": azure.SchemaLocation(), "tags": tags.Schema(), @@ -214,20 +216,21 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte resourceGroup := d.Get("resource_group_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { - resp, err := client.Get(ctx, resourceGroup, name, "") + existing, err := client.Get(ctx, resourceGroup, name, "") if err != nil { - if !utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error checking for present of existing Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Private Link Service %q (Resource Group %q): %s", name, resourceGroup, err) } } - if !utils.ResponseWasNotFound(resp.Response) { - return tf.ImportAsExistsError("azurerm_private_link_service", *resp.ID) + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_private_link_service", *existing.ID) } } location := azure.NormalizeLocation(d.Get("location").(string)) autoApproval := d.Get("auto_approval_subscription_ids").([]interface{}) - fqdns := d.Get("fqdns").([]interface{}) + // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you + //fqdns := d.Get("fqdns").([]interface{}) ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) privateEndpointConnections := d.Get("private_endpoint_connection").([]interface{}) @@ -238,7 +241,7 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte Location: utils.String(location), PrivateLinkServiceProperties: &network.PrivateLinkServiceProperties{ AutoApproval: expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(autoApproval), - Fqdns: utils.ExpandStringSlice(fqdns), + //Fqdns: utils.ExpandStringSlice(fqdns), IPConfigurations: expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(ipConfigurations), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), PrivateEndpointConnections: expandArmPrivateLinkServicePrivateEndpointConnection(privateEndpointConnections), @@ -293,31 +296,42 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } - if privateLinkServiceProperties := resp.PrivateLinkServiceProperties; privateLinkServiceProperties != nil { - d.Set("alias", privateLinkServiceProperties.Alias) - if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(privateLinkServiceProperties.AutoApproval)); err != nil { - return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) + if props := resp.PrivateLinkServiceProperties; props != nil { + if err := d.Set("alias", props.Alias); err != nil { + return fmt.Errorf("Error setting `alias`: %+v", err) } - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(privateLinkServiceProperties.Visibility)); err != nil { - return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) + if props.AutoApproval != nil { + if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) + } } - if err := d.Set("fqdns", utils.FlattenStringSlice(privateLinkServiceProperties.Fqdns)); err != nil { - return fmt.Errorf("Error setting `fqdns`: %+v", err) + if props.Visibility != nil { + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) + } } - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(privateLinkServiceProperties.IPConfigurations)); err != nil { + // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you + // if props.Fqdns != nil { + // if err := d.Set("fqdns", utils.FlattenStringSlice(props.Fqdns)); err != nil { + // return fmt.Errorf("Error setting `fqdns`: %+v", err) + // } + // } + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(privateLinkServiceProperties.LoadBalancerFrontendIPConfigurations)); err != nil { + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) } - if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(privateLinkServiceProperties.NetworkInterfaces)); err != nil { + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } - if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(privateLinkServiceProperties.PrivateEndpointConnections)); err != nil { + if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(props.PrivateEndpointConnections)); err != nil { return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) } } - d.Set("type", resp.Type) + if err := d.Set("type", resp.Type); err != nil { + return fmt.Errorf("Error setting `type`: %+v", err) + } return tags.FlattenAndSet(d, resp.Tags) } @@ -355,14 +369,20 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input [ return nil } - subscriptions := make([]string, 0) + result := network.PrivateLinkServicePropertiesAutoApproval{ + Subscriptions: utils.ExpandStringSlice(input), + } - for _, v := range input { - subscriptions = append(subscriptions, v.(string)) + return &result +} + +func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { + if len(input) == 0 { + return nil } - result := network.PrivateLinkServicePropertiesAutoApproval{ - Subscriptions: &subscriptions, + result := network.PrivateLinkServicePropertiesVisibility{ + Subscriptions: utils.ExpandStringSlice(input), } return &result @@ -443,24 +463,6 @@ func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) * return &results } -func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { - if len(input) == 0 { - return nil - } - - subscriptions := make([]string, 0) - - for _, v := range input { - subscriptions = append(subscriptions, v.(string)) - } - - result := network.PrivateLinkServicePropertiesVisibility{ - Subscriptions: &subscriptions, - } - - return &result -} - func expandArmPrivateLinkServicePrivateEndpoint(input []interface{}) *network.PrivateEndpoint { if len(input) == 0 { return nil @@ -497,16 +499,27 @@ func expandArmPrivateLinkServicePrivateLinkServiceConnectionState(input []interf return &result } -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []string { - result := make([]string, 0) +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { + result := make([]interface{}, 0) if input == nil { return result } - for _, v := range *input.Subscriptions { - if subscription := v; subscription != "" { - result = append(result, subscription) - } + if input.Subscriptions != nil { + result = utils.FlattenStringSlice(input.Subscriptions) + } + + return result +} + +func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { + result := make([]interface{}, 0) + if input == nil { + return result + } + + if input.Subscriptions != nil { + result = utils.FlattenStringSlice(input.Subscriptions) } return result @@ -519,26 +532,26 @@ func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]netw } for _, item := range *input { - v := make(map[string]interface{}) + b := make(map[string]interface{}) if name := item.Name; name != nil { - v["name"] = *name + b["name"] = *name } - if privateLinkServiceIPConfigurationProperties := item.PrivateLinkServiceIPConfigurationProperties; privateLinkServiceIPConfigurationProperties != nil { - v["private_ip_allocation_method"] = string(privateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod) - if privateIpAddress := privateLinkServiceIPConfigurationProperties.PrivateIPAddress; privateIpAddress != nil { - v["private_ip_address"] = *privateIpAddress + if props := item.PrivateLinkServiceIPConfigurationProperties; props != nil { + b["private_ip_allocation_method"] = string(props.PrivateIPAllocationMethod) + if v := props.PrivateIPAddress; v != nil { + b["private_ip_address"] = *v } - v["private_ip_address_version"] = string(privateLinkServiceIPConfigurationProperties.PrivateIPAddressVersion) - if subnet := privateLinkServiceIPConfigurationProperties.Subnet; subnet != nil { - if subnetId := subnet.ID; subnetId != nil { - v["subnet_id"] = *subnetId + b["private_ip_address_version"] = string(props.PrivateIPAddressVersion) + if v := props.Subnet; v != nil { + if i := v.ID; i != nil { + b["subnet_id"] = *i } } - v["primary"] = *item.PrivateLinkServiceIPConfigurationProperties.Primary + b["primary"] = *props.Primary } - results = append(results, v) + results = append(results, b) } return results @@ -586,9 +599,9 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv if id := item.ID; id != nil { v["id"] = *id } - if privateEndpointConnectionProperties := item.PrivateEndpointConnectionProperties; privateEndpointConnectionProperties != nil { - v["private_endpoint"] = flattenArmPrivateLinkServicePrivateEndpoint(privateEndpointConnectionProperties.PrivateEndpoint) - v["private_link_service_connection_state"] = flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(privateEndpointConnectionProperties.PrivateLinkServiceConnectionState) + if props := item.PrivateEndpointConnectionProperties; props != nil { + v["private_endpoint"] = flattenArmPrivateLinkServicePrivateEndpoint(props.PrivateEndpoint) + v["private_link_service_connection_state"] = flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(props.PrivateLinkServiceConnectionState) } results = append(results, v) @@ -597,28 +610,12 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv return results } -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []string { - results := make([]string, 0) - if input == nil { - return results - } - - for _, v := range *input.Subscriptions { - if subscription := v; subscription != "" { - results = append(results, v) - } - } - - return results -} - func flattenArmPrivateLinkServicePrivateEndpoint(input *network.PrivateEndpoint) []interface{} { if input == nil { return make([]interface{}, 0) } result := make(map[string]interface{}) - if id := input.ID; id != nil { result["id"] = *id } @@ -635,7 +632,6 @@ func flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(input *networ } result := make(map[string]interface{}) - if actionRequired := input.ActionRequired; actionRequired != nil { result["action_required"] = *actionRequired } diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index c7e570a8f73e..415fccd466f8 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -177,7 +177,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err // supported by private endpoints. privateLinkServiceNetworkPolicies := "Enabled" if v.(bool) { - privateLinkServiceNetworkPolicies := "Disabled" + privateLinkServiceNetworkPolicies = "Disabled" } properties.PrivateLinkServiceNetworkPolicies = &privateLinkServiceNetworkPolicies } diff --git a/azurerm/utils/split.go b/azurerm/utils/split.go new file mode 100644 index 000000000000..500ab64e9f82 --- /dev/null +++ b/azurerm/utils/split.go @@ -0,0 +1,22 @@ +package utils + +import ( + "strings" +) + +func SplitRemoveEmptyEntries(input string, delimiter string, removeWhitespace bool) []string { + result := make([]string, 0) + + s := strings.Split(input, delimiter) + + for _, v := range s { + if removeWhitespace { + v = strings.TrimSpace(v) + } + if len(v) > 0 { + result = append(result, v) + } + } + + return result +} diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index 759bfd18a332..444d5f82dd0a 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -3,7 +3,7 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-datasource-private-link-service" description: |- - Gets information about an existing Private Link Service + Use this data source to access information about an existing Private Link Service. --- # Data Source: azurerm_private_link_service @@ -31,7 +31,7 @@ The following arguments are supported: * `name` - (Required) The name of the private link service. -* `resource_group_name` - (Required) The name of the resource group. +* `resource_group_name` - (Required) The name of the resource group where the private link is resides. Changing this forces a new resource to be created. ## Attributes Reference @@ -42,77 +42,58 @@ The following attributes are exported: * `alias` - The alias of the private link service. -* `auto_approval` - One `auto_approval` block defined below. +* `auto_approval_subscription_ids` - A list of subscription globally unique identifiers that will be auto approved to use this private link service. -* `fqdns` - The list of Fqdn. +* `ip_configurations` - One or more `ip_configuration` blocks as defined below. -* `ip_configurations` - One or more `ip_configuration` block defined below. +* `load_balancer_frontend_ip_configuration_ids` - A list of `Standard` Load Balancer resource IDs to direct the service network traffic toward. -* `load_balancer_frontend_ip_configurations` - One or more `load_balancer_frontend_ip_configuration` block defined below. +* `network_interfaces` - A list of network interface resource ids that are being used by the service. -* `network_interfaces` - One or more `network_interface` block defined below. - -* `private_endpoint_connections` - One or more `private_endpoint_connection` block defined below. +* `private_endpoint_connection` - One or more `private_endpoint_connection` blocks as defined below. * `type` - Resource type. -* `visibility` - One `visibility` block defined below. - -* `tags` - Resource tags. - - ---- +* `visibility_subscription_ids` - A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. -The `auto_approval` block contains the following: +* `tags` - A mapping of tags to assign to the resource. Changing this forces a new resource to be created -* `subscriptions` - The list of subscriptions. --- The `ip_configuration` block contains the following: -* `private_ip_address` - The private IP address of the IP configuration. - -* `private_ip_allocation_method` - The private IP address allocation method. - -* `subnet_id` - Resource ID. - -* `private_ip_address_version` - Available from Api-Version 2016-03-30 onwards, it represents whether the specific ipconfiguration is IPv4 or IPv6. Default is taken as IPv4. - * `name` - The name of private link service ip configuration. ---- - -The `load_balancer_frontend_ip_configuration` block contains the following: +* `private_ip_address` - The private IP address of the IP configuration. -* `id` - Resource ID. +* `private_ip_allocation_method` - The private IP address allocation method. ---- +* `subnet_id` - The resource ID of the subnet to be used by the service. -The `network_interface` block contains the following: +* `private_ip_address_version` - The ip address version of the `ip_configuration`. -* `id` - Resource ID. --- The `private_endpoint_connection` block contains the following: -* `id` - Resource ID. +* `id` - The resource ID of the `private_endpoint_connection`. -* `private_endpoint` - One `private_endpoint` block defined below. +* `name` - The name of the resource that is unique within a resource group. This name can be used to access the resource. -* `private_link_service_connection_state` - One `private_link_service_connection_state` block defined below. +* `private_endpoint` - One of the `private_endpoint` blocks as defined below. -* `name` - The name of the resource that is unique within a resource group. This name can be used to access the resource. +* `private_link_service_connection_state` - One of the `private_link_service_connection_state` blocks as defined below. --- The `private_endpoint` block contains the following: -* `id` - Resource ID. +* `id` - The Private Endpoint ID. -* `location` - Resource location. +* `location` - The resource location of the `private_endpoint`. * `tags` - Resource tags. @@ -126,8 +107,3 @@ The `private_link_service_connection_state` block contains the following: * `action_required` - A message indicating if changes on the service provider require any updates on the consumer. ---- - -The `visibility` block contains the following: - -* `subscriptions` - The list of subscriptions. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 9f318416b392..ed9690529818 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -3,12 +3,12 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-resource-private-link-service" description: |- - Manages a Azure PrivateLinkService instance. + Manages an Azure PrivateLinkService instance. --- # azurerm_private_link_service -Managea a Azure PrivateLinkService instance. +Managea an Azure PrivateLinkService instance. ## Private Link Service Usage @@ -83,70 +83,59 @@ The following arguments are supported: * `location` - (Optional) Resource location. Changing this forces a new resource to be created. -* `auto_approval` - (Optional) One `auto_approval` block defined below. +* `auto_approval_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be automatically be able to use this service. -* `fqdns` - (Optional) The list of Fqdn. +* `nat_ip_configuration` - (Optional) One or more `nat_ip_configuration` blocks as defined below. -* `ip_configurations` - (Optional) One or more `ip_configuration` block defined below. +* `load_balancer_frontend_ip_configuration_ids` - (Optional) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. -* `load_balancer_frontend_ip_configurations` - (Optional) One or more `load_balancer_frontend_ip_configuration` block defined below. +* `private_endpoint_connection` - (Optional) One or more `private_endpoint_connection` blocks as defined below. -* `private_endpoint_connections` - (Optional) One or more `private_endpoint_connection` block defined below. +* `visibility_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. -* `visibility` - (Optional) One `visibility` block defined below. - -* `tags` - (Optional) Resource tags. Changing this forces a new resource to be created. +* `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created. --- -The `auto_approval` block supports the following: - -* `subscriptions` - (Optional) The list of subscriptions. +The `nat_ip_configuration` block supports the following: ---- - -The `ip_configuration` block supports the following: +* `name` - (Optional) The name of private link service ip configuration. -* `primary` - (Optional) If the `ip_configuration` is the primary ip configuration or not. Defaults to true. +* `primary` - (Optional) If the `ip_configuration` is the primary ip configuration or not. Defaults to `true`. * `private_ip_address` - (Optional) The private IP address of the IP configuration. -* `private_ip_allocation_method` - (Optional) The private IP address allocation method. Defaults to `Static`. +* `private_ip_allocation_method` - (Optional) The private IP address allocation method, supported values are `Static` and `Dynamic`. Defaults to `Dynamic`. -* `subnet_id` - (Optional) Resource ID. +* `subnet_id` - (Optional) The resource ID of the subnet to be used by the service. -* `private_ip_address_version` - (Optional) Available from Api-Version 2016-03-30 onwards, it represents whether the specific ipconfiguration is IPv4 or IPv6. Default is taken as IPv4. Defaults to `IPv4`. +* `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, supported values are `IPv4` or `IPv6`. Defaults to `IPv4`. -* `name` - (Optional) The name of private link service ip configuration. - ---- +-> **NOTE:** Private Link Service Supports `IPv4` traffic only. -The `load_balancer_frontend_ip_configuration` block supports the following: - -* `id` - (Optional) Resource ID. --- The `private_endpoint_connection` block supports the following: -* `id` - (Optional) Resource ID. +* `id` - (Optional) The Resource ID of the `private_endpoint_connection`. + +* `name` - (Optional) The name of the resource that is unique within a resource group. This name can be used to access the resource. * `private_endpoint` - (Optional) One `private_endpoint` block defined below. * `private_link_service_connection_state` - (Optional) One `private_link_service_connection_state` block defined below. -* `name` - (Optional) The name of the resource that is unique within a resource group. This name can be used to access the resource. - --- The `private_endpoint` block supports the following: -* `id` - (Optional) Resource ID. +* `id` - (Optional) The resource ID of the `private_endpoint`. * `location` - (Optional) Resource location. Changing this forces a new resource to be created. -* `tags` - (Optional) Resource tags. +* `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created. --- @@ -158,33 +147,22 @@ The `private_link_service_connection_state` block supports the following: * `action_required` - (Optional) A message indicating if changes on the service provider require any updates on the consumer. ---- - -The `visibility` block supports the following: - -* `subscriptions` - (Optional) The list of subscriptions. ## Attributes Reference The following attributes are exported: -* `network_interfaces` - One or more `network_interface` block defined below. +* `network_interfaces` - A list of network interface resource ids that are being used by the service. * `alias` - The alias of the private link service. * `type` - Resource type. ---- - -The `network_interface` block contains the following: - -* `id` - Resource ID. - ## Import Private Link Service can be imported using the `resource id`, e.g. ```shell -$ terraform import azurerm_private_link_service.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/acctestRG/providers/Microsoft.Network/privateLinkServices/ +$ terraform import azurerm_private_link_service.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/acctestRG/providers/Microsoft.Network/privateLinkServices/privatelinkservicename ``` From 693df4b3da0e9ff7e2956deb65a1d0299c88b26a Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 7 Oct 2019 18:21:44 -0700 Subject: [PATCH 15/44] Updates per PR --- azurerm/data_source_private_link_service.go | 88 +++---- .../data_source_private_link_service_test.go | 12 +- azurerm/resource_arm_private_link_service.go | 221 ++++++------------ .../resource_arm_private_link_service_test.go | 42 +--- .../docs/d/private_link_service.html.markdown | 40 +--- .../docs/r/private_link_service.html.markdown | 53 ++--- 6 files changed, 167 insertions(+), 289 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 687406b8cbf5..0b4da9bb2328 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -93,6 +93,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { "private_endpoint_connection": { Type: schema.TypeList, + Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -104,39 +105,44 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "private_endpoint": { - Type: schema.TypeList, + "private_endpoint_id": { + Type: schema.TypeString, + Computed: true, + }, + "private_endpoint_location": azure.SchemaLocationForDataSource(), + "state_action_required": { + Type: schema.TypeString, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, - "location": azure.SchemaLocationForDataSource(), - "tags": tags.SchemaDataSource(), - }, - }, }, - "private_link_service_connection_state": { - Type: schema.TypeList, + "state_description": { + Type: schema.TypeString, + Computed: true, + }, + "state_status": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "private_link_service_connection_state": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_required": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_required": { - Type: schema.TypeString, - Computed: true, - }, - "description": { - Type: schema.TypeString, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, }, }, }, @@ -155,12 +161,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "type": { - Type: schema.TypeString, - Computed: true, - }, - - "tags": tags.Schema(), + "tags": tags.SchemaDataSource(), }, } } @@ -191,12 +192,12 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting `alias`: %+v", err) } if props.AutoApproval != nil { - if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } if props.Visibility != nil { - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } } @@ -206,7 +207,7 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ // return fmt.Errorf("Error setting `fqdns`: %+v", err) // } // } - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { @@ -215,13 +216,12 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } - if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(props.PrivateEndpointConnections)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { + if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + } } } - if err := d.Set("type", resp.Type); err != nil { - return fmt.Errorf("Error setting `type`: %+v", err) - } return tags.FlattenAndSet(d, resp.Tags) } diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 5cb3a41b97b4..53ba561b2620 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -8,7 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" ) -func TestAccDataSourceAzureRMPrivateLinkService_basic(t *testing.T) { +func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { dataSourceName := "data.azurerm_private_link_service.test" ri := tf.AccRandTimeInt() location := testLocation() @@ -18,11 +18,9 @@ func TestAccDataSourceAzureRMPrivateLinkService_basic(t *testing.T) { Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourcePrivateLinkService_basic(ri, location), + Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "fqdns.0", "testFqdns"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "2"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), @@ -33,8 +31,8 @@ func TestAccDataSourceAzureRMPrivateLinkService_basic(t *testing.T) { }) } -func testAccDataSourcePrivateLinkService_basic(rInt int, location string) string { - config := testAccAzureRMPrivateLinkService_basic(rInt, location) +func testAccDataSourcePrivateLinkService_complete(rInt int, location string) string { + config := testAccAzureRMPrivateLinkService_complete(rInt, location) return fmt.Sprintf(` %s diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 39a7f7168a3a..53e3ab1f91d0 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -12,8 +12,8 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" 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" ) @@ -87,18 +87,18 @@ func resourceArmPrivateLinkService() *schema.Resource { }, false), Default: string(network.Dynamic), }, - // Only IPv4 is supported by the API "private_ip_address": { Type: schema.TypeString, Optional: true, ValidateFunc: aznet.ValidatePrivateLinkServiceIPv4Address, }, + // Only IPv4 is supported by the API, but I am exposing this + // as they will support IPv6 in a future release. "private_ip_address_version": { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringInSlice([]string{ string(network.IPv4), - string(network.IPv6), }, false), Default: string(network.IPv4), }, @@ -132,54 +132,30 @@ func resourceArmPrivateLinkService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, + Type: schema.TypeString, + Computed: true, }, "name": { Type: schema.TypeString, - Optional: true, + Required: true, ValidateFunc: validate.NoEmptyStrings, }, - "private_endpoint": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, - }, - "location": azure.SchemaLocation(), - "tags": tags.Schema(), - }, - }, + "private_endpoint_id": { + Type: schema.TypeString, + Required: true, }, - "private_link_service_connection_state": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_required": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "description": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "status": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.NoEmptyStrings, - }, - }, - }, + "private_endpoint_location": azure.SchemaLocation(), + "state_action_required": { + Type: schema.TypeString, + Computed: true, + }, + "state_description": { + Type: schema.TypeString, + Computed: true, + }, + "state_status": { + Type: schema.TypeString, + Computed: true, }, }, }, @@ -198,11 +174,6 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, - "type": { - Type: schema.TypeString, - Computed: true, - }, - "tags": tags.Schema(), }, } @@ -240,12 +211,12 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte parameters := network.PrivateLinkService{ Location: utils.String(location), PrivateLinkServiceProperties: &network.PrivateLinkServiceProperties{ - AutoApproval: expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(autoApproval), - //Fqdns: utils.ExpandStringSlice(fqdns), - IPConfigurations: expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(ipConfigurations), + AutoApproval: expandArmPrivateLinkServicePropertiesAutoApproval(autoApproval), + Visibility: expandArmPrivateLinkServicePropertiesVisibility(visibility), + IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(ipConfigurations), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), PrivateEndpointConnections: expandArmPrivateLinkServicePrivateEndpointConnection(privateEndpointConnections), - Visibility: expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(visibility), + //Fqdns: utils.ExpandStringSlice(fqdns), }, Tags: tags.Expand(t), } @@ -301,12 +272,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error setting `alias`: %+v", err) } if props.AutoApproval != nil { - if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } if props.Visibility != nil { - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } } @@ -316,7 +287,7 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // return fmt.Errorf("Error setting `fqdns`: %+v", err) // } // } - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { @@ -325,13 +296,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } - if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(props.PrivateEndpointConnections)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { + if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + } } } - if err := d.Set("type", resp.Type); err != nil { - return fmt.Errorf("Error setting `type`: %+v", err) - } return tags.FlattenAndSet(d, resp.Tags) } @@ -364,7 +334,7 @@ func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{ return nil } -func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input []interface{}) *network.PrivateLinkServicePropertiesAutoApproval { +func expandArmPrivateLinkServicePropertiesAutoApproval(input []interface{}) *network.PrivateLinkServicePropertiesAutoApproval { if len(input) == 0 { return nil } @@ -376,7 +346,7 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input [ return &result } -func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { +func expandArmPrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { if len(input) == 0 { return nil } @@ -388,7 +358,7 @@ func expandArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input []i return &result } -func expandArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { +func expandArmPrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { if len(input) == 0 { return nil } @@ -445,16 +415,26 @@ func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) * for _, item := range input { v := item.(map[string]interface{}) id := v["id"].(string) - privateEndpoint := v["private_endpoint"].([]interface{}) - privateLinkServiceConnectionState := v["private_link_service_connection_state"].([]interface{}) name := v["name"].(string) + status := v["state_status"].(string) + description := v["state_description"].(string) + actionRequired := v["state_action_required"].(string) + privateEndpointId := v["private_endpoint_id"].(string) + privateEndpointLocation := azure.NormalizeLocation(v["private_endpoint_location"].(string)) result := network.PrivateEndpointConnection{ ID: utils.String(id), Name: utils.String(name), PrivateEndpointConnectionProperties: &network.PrivateEndpointConnectionProperties{ - PrivateEndpoint: expandArmPrivateLinkServicePrivateEndpoint(privateEndpoint), - PrivateLinkServiceConnectionState: expandArmPrivateLinkServicePrivateLinkServiceConnectionState(privateLinkServiceConnectionState), + PrivateEndpoint: &network.PrivateEndpoint{ + ID: utils.String(privateEndpointId), + Location: utils.String(privateEndpointLocation), + }, + PrivateLinkServiceConnectionState: &network.PrivateLinkServiceConnectionState{ + ActionRequired: utils.String(actionRequired), + Description: utils.String(description), + Status: utils.String(status), + }, }, } @@ -463,43 +443,7 @@ func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) * return &results } -func expandArmPrivateLinkServicePrivateEndpoint(input []interface{}) *network.PrivateEndpoint { - if len(input) == 0 { - return nil - } - v := input[0].(map[string]interface{}) - - id := v["id"].(string) - location := azure.NormalizeLocation(v["location"].(string)) - t := v["tags"].(map[string]interface{}) - - result := network.PrivateEndpoint{ - ID: utils.String(id), - Location: utils.String(location), - Tags: tags.Expand(t), - } - return &result -} - -func expandArmPrivateLinkServicePrivateLinkServiceConnectionState(input []interface{}) *network.PrivateLinkServiceConnectionState { - if len(input) == 0 { - return nil - } - v := input[0].(map[string]interface{}) - - status := v["status"].(string) - description := v["description"].(string) - actionRequired := v["action_required"].(string) - - result := network.PrivateLinkServiceConnectionState{ - ActionRequired: utils.String(actionRequired), - Description: utils.String(description), - Status: utils.String(status), - } - return &result -} - -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { +func flattenArmPrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { result := make([]interface{}, 0) if input == nil { return result @@ -512,7 +456,7 @@ func flattenArmPrivateLinkServicePrivateLinkServicePropertiesAutoApproval(input return result } -func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { +func flattenArmPrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { result := make([]interface{}, 0) if input == nil { return result @@ -525,7 +469,7 @@ func flattenArmPrivateLinkServicePrivateLinkServicePropertiesVisibility(input *n return result } -func flattenArmPrivateLinkServicePrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { +func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { results := make([]interface{}, 0) if input == nil { return results @@ -599,9 +543,31 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv if id := item.ID; id != nil { v["id"] = *id } + if name := item.Name; name != nil { + v["name"] = *name + } + if props := item.PrivateEndpointConnectionProperties; props != nil { - v["private_endpoint"] = flattenArmPrivateLinkServicePrivateEndpoint(props.PrivateEndpoint) - v["private_link_service_connection_state"] = flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(props.PrivateLinkServiceConnectionState) + + if p := props.PrivateEndpoint; p != nil { + if id := p.ID; id != nil { + v["private_endpoint_id"] = *id + } + if location := p.Location; location != nil { + v["private_endpoint_location"] = azure.NormalizeLocation(*location) + } + } + if s := props.PrivateLinkServiceConnectionState; s != nil { + if actionRequired := s.ActionRequired; actionRequired != nil { + v["state_action_required"] = *actionRequired + } + if description := s.Description; description != nil { + v["state_description"] = *description + } + if status := s.Status; status != nil { + v["state_status"] = *status + } + } } results = append(results, v) @@ -609,38 +575,3 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv return results } - -func flattenArmPrivateLinkServicePrivateEndpoint(input *network.PrivateEndpoint) []interface{} { - if input == nil { - return make([]interface{}, 0) - } - - result := make(map[string]interface{}) - if id := input.ID; id != nil { - result["id"] = *id - } - if location := input.Location; location != nil { - result["location"] = azure.NormalizeLocation(*location) - } - - return []interface{}{result} -} - -func flattenArmPrivateLinkServicePrivateLinkServiceConnectionState(input *network.PrivateLinkServiceConnectionState) []interface{} { - if input == nil { - return make([]interface{}, 0) - } - - result := make(map[string]interface{}) - if actionRequired := input.ActionRequired; actionRequired != nil { - result["action_required"] = *actionRequired - } - if description := input.Description; description != nil { - result["description"] = *description - } - if status := input.Status; status != nil { - result["status"] = *status - } - - return []interface{}{result} -} diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index a0f244c984e3..31f524cb51d8 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -61,8 +61,6 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_update(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "www.contoso.com"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), @@ -106,8 +104,6 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "auto_approval_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), - resource.TestCheckResourceAttr(resourceName, "fqdns.#", "1"), - resource.TestCheckResourceAttr(resourceName, "fqdns.0", "www.contoso.com"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), @@ -181,43 +177,21 @@ func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { } func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { - standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) - privateLink := testAccAzureRMPrivateLinkServiceTemplate_basic(rInt) - - return testAccAzureRMPrivateLinkServiceTemplate("", standardResources, privateLink) + return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_basic(rInt)) } func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { - standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) - privateLink := testAccAzureRMPrivateLinkServiceTemplate_update(rInt) - - return testAccAzureRMPrivateLinkServiceTemplate("", standardResources, privateLink) + return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_update(rInt)) } func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { - subscriptionDataSource := testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() - standardResources := testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt, location) - privateLink := testAccAzureRMPrivateLinkServiceTemplate_complete(rInt) - - return testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSource, standardResources, privateLink) + return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_complete(rInt)) } -func testAccAzureRMPrivateLinkServiceTemplate(subscriptionDataSourceTemplate string, standardResourcesTemplate string, privateLinkTemplate string) string { +func testAccAzureRMPrivateLinkServiceTemplate(rInt int, location string, privateLinkTemplate string) string { return fmt.Sprintf(` -%s - -%s - -%s -`,subscriptionDataSourceTemplate, standardResourcesTemplate, privateLinkTemplate) -} - -func testAccAzureRMPrivateLinkServiceTemplate_subscriptionDataSource() string { - return `data "azurerm_subscription" "current" {}` -} +data "azurerm_subscription" "current" {} -func testAccAzureRMPrivateLinkServiceTemplate_standardResources(rInt int, location string) string { - return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" location = "%s" @@ -258,7 +232,9 @@ resource "azurerm_lb" "test" { public_ip_address_id = azurerm_public_ip.test.id } } -`,rInt, location, rInt, rInt, rInt, rInt) + +%s +`, rInt, location, rInt, rInt, rInt, rInt, privateLinkTemplate) } func testAccAzureRMPrivateLinkServiceTemplate_basic(rInt int) string { @@ -286,7 +262,6 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - fqdns = ["www.contoso.com"] nat_ip_configuration { name = "primaryIpConfiguration-%d" @@ -310,7 +285,6 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - fqdns = ["www.contoso.com"] auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index 444d5f82dd0a..b06e83d2ba07 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -31,20 +31,20 @@ The following arguments are supported: * `name` - (Required) The name of the private link service. -* `resource_group_name` - (Required) The name of the resource group where the private link is resides. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which the private link service resides. Changing this forces a new resource to be created. ## Attributes Reference The following attributes are exported: -* `location` - Resource location. +* `location` - Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. * `alias` - The alias of the private link service. * `auto_approval_subscription_ids` - A list of subscription globally unique identifiers that will be auto approved to use this private link service. -* `ip_configurations` - One or more `ip_configuration` blocks as defined below. +* `nat_ip_configurations` - One or more `ip_configuration` blocks as defined below. * `load_balancer_frontend_ip_configuration_ids` - A list of `Standard` Load Balancer resource IDs to direct the service network traffic toward. @@ -52,8 +52,6 @@ The following attributes are exported: * `private_endpoint_connection` - One or more `private_endpoint_connection` blocks as defined below. -* `type` - Resource type. - * `visibility_subscription_ids` - A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. * `tags` - A mapping of tags to assign to the resource. Changing this forces a new resource to be created @@ -61,7 +59,7 @@ The following attributes are exported: --- -The `ip_configuration` block contains the following: +The `nat_ip_configuration` block contains the following: * `name` - The name of private link service ip configuration. @@ -73,37 +71,19 @@ The `ip_configuration` block contains the following: * `private_ip_address_version` - The ip address version of the `ip_configuration`. - --- The `private_endpoint_connection` block contains the following: -* `id` - The resource ID of the `private_endpoint_connection`. - -* `name` - The name of the resource that is unique within a resource group. This name can be used to access the resource. - -* `private_endpoint` - One of the `private_endpoint` blocks as defined below. +* `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. -* `private_link_service_connection_state` - One of the `private_link_service_connection_state` blocks as defined below. - - ---- - -The `private_endpoint` block contains the following: - -* `id` - The Private Endpoint ID. - -* `location` - The resource location of the `private_endpoint`. - -* `tags` - Resource tags. - ---- +* `private_endpoint_location` - (Required) The resource location of the `private_endpoint`. -The `private_link_service_connection_state` block contains the following: +* `private_endpoint_id` - (Required) The Private Endpoint ID. -* `status` - Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. +* `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. -* `description` - The reason for approval/rejection of the connection. +* `state_description` - (Computed) The reason for approval/rejection of the connection. -* `action_required` - A message indicating if changes on the service provider require any updates on the consumer. +* `state_status` - (Computed) Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index ed9690529818..9ba990269881 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -79,15 +79,15 @@ The following arguments are supported: * `name` - (Required) The name of the private link service. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which the private link service resides. Changing this forces a new resource to be created. -* `location` - (Optional) Resource location. Changing this forces a new resource to be created. +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. * `auto_approval_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be automatically be able to use this service. -* `nat_ip_configuration` - (Optional) One or more `nat_ip_configuration` blocks as defined below. +* `nat_ip_configuration` - (Required) One or more `nat_ip_configuration` blocks as defined below. -* `load_balancer_frontend_ip_configuration_ids` - (Optional) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. +* `load_balancer_frontend_ip_configuration_ids` - (Required) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. * `private_endpoint_connection` - (Optional) One or more `private_endpoint_connection` blocks as defined below. @@ -99,7 +99,7 @@ The following arguments are supported: The `nat_ip_configuration` block supports the following: -* `name` - (Optional) The name of private link service ip configuration. +* `name` - (Required) The name of private link service ip configuration. * `primary` - (Optional) If the `ip_configuration` is the primary ip configuration or not. Defaults to `true`. @@ -107,7 +107,7 @@ The `nat_ip_configuration` block supports the following: * `private_ip_allocation_method` - (Optional) The private IP address allocation method, supported values are `Static` and `Dynamic`. Defaults to `Dynamic`. -* `subnet_id` - (Optional) The resource ID of the subnet to be used by the service. +* `subnet_id` - (Required) The resource ID of the subnet to be used by the service. * `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, supported values are `IPv4` or `IPv6`. Defaults to `IPv4`. @@ -116,47 +116,42 @@ The `nat_ip_configuration` block supports the following: --- -The `private_endpoint_connection` block supports the following: +The `private_endpoint_connection` block contains the following: -* `id` - (Optional) The Resource ID of the `private_endpoint_connection`. +* `id` - (Computed) The resource ID of the `private_endpoint_connection`. -* `name` - (Optional) The name of the resource that is unique within a resource group. This name can be used to access the resource. +* `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. -* `private_endpoint` - (Optional) One `private_endpoint` block defined below. +* `private_endpoint_location` - (Required) The resource location of the `private_endpoint`. -* `private_link_service_connection_state` - (Optional) One `private_link_service_connection_state` block defined below. +* `private_endpoint_id` - (Required) The Private Endpoint ID. +* `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. ---- - -The `private_endpoint` block supports the following: - -* `id` - (Optional) The resource ID of the `private_endpoint`. - -* `location` - (Optional) Resource location. Changing this forces a new resource to be created. +* `state_description` - (Computed) The reason for approval/rejection of the connection. -* `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created. +* `state_status` - (Computed) Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. ---- -The `private_link_service_connection_state` block supports the following: +## Attributes Reference -* `status` - (Optional) Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. +The following attributes are exported: -* `description` - (Optional) The reason for approval/rejection of the connection. +* `alias` - The alias of the private link service. -* `action_required` - (Optional) A message indicating if changes on the service provider require any updates on the consumer. +* `network_interfaces` - A list of network interface resource ids that are being used by the service. +--- -## Attributes Reference +* A `private_endpoint_connection` block contains: -The following attributes are exported: +* `id` - The resource ID of the `private_endpoint_connection`. -* `network_interfaces` - A list of network interface resource ids that are being used by the service. +* `state_action_required` - A message indicating if changes on the service provider require any updates by the consumer. -* `alias` - The alias of the private link service. +* `state_description` - The reason for approval/rejection of the connection. -* `type` - Resource type. +* `state_status` - Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. ## Import From d54e0011507f9545ceaefccfd69c26aadb843b8c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 8 Oct 2019 12:11:49 -0700 Subject: [PATCH 16/44] Gofmt --- azurerm/data_source_subnet.go | 4 +-- azurerm/internal/services/network/validate.go | 7 ++--- azurerm/resource_arm_subnet.go | 30 +++++++++---------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index ac987a061aed..46b2a8166bf5 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -90,8 +90,8 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { - return err + if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + return err } } diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index a6aef2230aa1..c40527e2293a 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -43,20 +43,19 @@ func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []str segments := utils.SplitRemoveEmptyEntries(v, ".", false) index := 0 - for _,label := range segments { + for _, label := range segments { index++ if index == len(segments) { if len(label) < 2 { - errors = append(errors,fmt.Errorf(`the last label of an FQDN must be at least 2 characters, got 1 character`)) + errors = append(errors, fmt.Errorf(`the last label of an FQDN must be at least 2 characters, got 1 character`)) } } else { if len(label) > 63 { - errors = append(errors,fmt.Errorf(`FQDN labels must not be longer than 63 characters, got %d characters`, len(label))) + errors = append(errors, fmt.Errorf(`FQDN labels must not be longer than 63 characters, got %d characters`, len(label))) } } } - return nil, errors } diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index 415fccd466f8..3bf51b22b2e8 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -129,7 +129,7 @@ func resourceArmSubnet() *schema.Resource { "disable_private_link_service_network_policies": { Type: schema.TypeBool, Optional: true, - Default: false, + Default: false, }, }, } @@ -168,12 +168,12 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err } if v, ok := d.GetOk("disable_private_link_service_network_policies"); ok { - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + // + // To enable private endpoints you must disable the network policies for the + // subnet because Network policies like network security groups are not // supported by private endpoints. privateLinkServiceNetworkPolicies := "Enabled" if v.(bool) { @@ -278,16 +278,16 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + // + // To enable private endpoints you must disable the network policies for the + // subnet because Network policies like network security groups are not // supported by private endpoints. if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { - return err + if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + return err } } From 5422f4f050548e15b7f70cf8da582989b8c5be51 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 8 Oct 2019 17:06:10 -0700 Subject: [PATCH 17/44] Updates for the new terraform-plugin-sdk --- azurerm/data_source_private_link_service.go | 4 ++-- azurerm/data_source_private_link_service_test.go | 2 +- azurerm/resource_arm_private_link_service.go | 10 +++++----- azurerm/resource_arm_private_link_service_test.go | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 0b4da9bb2328..c285066cd974 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -3,7 +3,7 @@ package azurerm import ( "fmt" - "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -167,7 +167,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { } func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).network.PrivateLinkServiceClient + client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext name := d.Get("name").(string) diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 53ba561b2620..981f660bc060 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" ) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 53e3ab1f91d0..2d4e815cd8bf 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -5,8 +5,8 @@ import ( "log" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" @@ -180,7 +180,7 @@ func resourceArmPrivateLinkService() *schema.Resource { } func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).network.PrivateLinkServiceClient + client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext name := d.Get("name").(string) @@ -242,7 +242,7 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte } func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).network.PrivateLinkServiceClient + client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext id, err := azure.ParseAzureResourceID(d.Id()) @@ -307,7 +307,7 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) } func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).network.PrivateLinkServiceClient + client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext id, err := azure.ParseAzureResourceID(d.Id()) diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 31f524cb51d8..70c7fb64e2a9 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -138,7 +138,7 @@ func testCheckAzureRMPrivateLinkServiceExists(resourceName string) resource.Test name := rs.Primary.Attributes["name"] resourceGroup := rs.Primary.Attributes["resource_group_name"] - client := testAccProvider.Meta().(*ArmClient).network.PrivateLinkServiceClient + client := testAccProvider.Meta().(*ArmClient).Network.PrivateLinkServiceClient ctx := testAccProvider.Meta().(*ArmClient).StopContext if resp, err := client.Get(ctx, resourceGroup, name, ""); err != nil { @@ -153,7 +153,7 @@ func testCheckAzureRMPrivateLinkServiceExists(resourceName string) resource.Test } func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*ArmClient).network.PrivateLinkServiceClient + client := testAccProvider.Meta().(*ArmClient).Network.PrivateLinkServiceClient ctx := testAccProvider.Meta().(*ArmClient).StopContext for _, rs := range s.RootModule().Resources { From cf6a87680ad8d0dda52bfec330e6317f3e89d02f Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 8 Oct 2019 17:50:42 -0700 Subject: [PATCH 18/44] Removed leading newline --- azurerm/resource_arm_private_link_service.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 2d4e815cd8bf..524fbb314493 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -548,7 +548,6 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv } if props := item.PrivateEndpointConnectionProperties; props != nil { - if p := props.PrivateEndpoint; p != nil { if id := p.ID; id != nil { v["private_endpoint_id"] = *id From 44052c7fc6c3679985730cdce4a6ad95313ac0ff Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 10 Oct 2019 19:34:10 -0700 Subject: [PATCH 19/44] Updates per PR feedback --- azurerm/data_source_private_link_service.go | 44 ++----- .../data_source_private_link_service_test.go | 2 +- azurerm/data_source_subnet.go | 6 +- azurerm/helpers/validate/uuid.go | 3 + azurerm/internal/services/network/validate.go | 39 +----- azurerm/resource_arm_private_link_service.go | 105 +++++---------- .../resource_arm_private_link_service_test.go | 122 ++++++++---------- azurerm/resource_arm_subnet.go | 6 +- .../private-link-service/variables.tf | 2 + .../docs/d/private_link_service.html.markdown | 12 +- .../docs/r/private_link_service.html.markdown | 24 ++-- 11 files changed, 129 insertions(+), 236 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index c285066cd974..5265f8d1d1f5 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -91,7 +91,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "private_endpoint_connection": { + "private_link_endpoint_connection": { Type: schema.TypeList, Optional: true, Computed: true, @@ -105,11 +105,11 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "private_endpoint_id": { + "private_link_endpoint_id": { Type: schema.TypeString, Computed: true, }, - "private_endpoint_location": azure.SchemaLocationForDataSource(), + "private_link_endpoint_location": azure.SchemaLocationForDataSource(), "state_action_required": { Type: schema.TypeString, Computed: true, @@ -126,28 +126,6 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "private_link_service_connection_state": { - Type: schema.TypeList, - Computed: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_required": { - Type: schema.TypeString, - Computed: true, - }, - "description": { - Type: schema.TypeString, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "alias": { Type: schema.TypeString, Computed: true, @@ -180,17 +158,17 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ } return fmt.Errorf("Error reading Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) + } 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)) - } + d.Set("location", azure.NormalizeLocation(*location)) + if props := resp.PrivateLinkServiceProperties; props != nil { - if err := d.Set("alias", props.Alias); err != nil { - return fmt.Errorf("Error setting `alias`: %+v", err) - } + d.Set("alias", props.Alias) if props.AutoApproval != nil { if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) @@ -217,8 +195,8 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { - if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + if err := d.Set("private_link_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { + return fmt.Errorf("Error setting `private_link_endpoint_connection`: %+v", err) } } } diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 981f660bc060..d52a5911a89e 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -37,8 +37,8 @@ func testAccDataSourcePrivateLinkService_complete(rInt int, location string) str %s data "azurerm_private_link_service" "test" { - resource_group_name = azurerm_private_link_service.test.resource_group_name name = azurerm_private_link_service.test.name + resource_group_name = azurerm_private_link_service.test.resource_group_name } `, config) } diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index 7b0b12767629..e622dad7a56e 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -91,10 +91,8 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { - return err - } + if p := props.PrivateLinkServiceNetworkPolicies; p != nil { + d.Set("disable_private_link_service_network_policies", *p == "Disabled") } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/helpers/validate/uuid.go b/azurerm/helpers/validate/uuid.go index 93bba3ab3723..0556385244ea 100644 --- a/azurerm/helpers/validate/uuid.go +++ b/azurerm/helpers/validate/uuid.go @@ -23,6 +23,9 @@ func UUID(i interface{}, k string) (warnings []string, errors []error) { return warnings, errors } +func GUID(i interface{}, k string) (warnings []string, errors []error) { + return UUID(i, k) +} func UUIDOrEmpty(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(string) if !ok { diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index c40527e2293a..cc0cff09d0b4 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -4,8 +4,6 @@ import ( "fmt" "net" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -17,14 +15,6 @@ func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors return nil, errors } -func ValidatePrivateLinkServiceSubsciptionGuid(i interface{}, k string) (_ []string, errors []error) { - if m, regexErrs := validate.RegExHelper(i, k, `(^([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$)`); !m { - errors = append(regexErrs, fmt.Errorf(`%q is an invalid subscription GUID.`, k)) - } - - return nil, errors -} - func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(string) if !ok { @@ -35,7 +25,7 @@ func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []str errors = append(errors, fmt.Errorf(`%q is an invalid FQDN`, v)) } - // I use 255 here because the string contains the upto three . characters in them + // I use 255 here because the string contains the upto three . characters in it if len(v) > 255 { errors = append(errors, fmt.Errorf(`FQDNs can not be longer than 255 characters in length, got %d characters`, len(v))) } @@ -58,30 +48,3 @@ func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []str return nil, errors } - -func ValidatePrivateLinkServiceIPv4Address(i interface{}, k string) (_ []string, errors []error) { - v, ok := i.(string) - if !ok { - return nil, []error{fmt.Errorf("expected type of %q to be string", k)} - } - - result := net.ParseIP(v) - if result.To4() == nil { - errors = append(errors, fmt.Errorf("%q is not a valid IPv4 IP address", v)) - } - - return nil, errors -} - -func ValidatePrivateLinkServiceIsResourceId(i interface{}, k string) (_ []string, errors []error) { - v, ok := i.(string) - if !ok { - return nil, []error{fmt.Errorf("expected type of %q to be string", k)} - } - - if _, err := azure.ParseAzureResourceID(v); err != nil { - return nil, []error{fmt.Errorf("%q is not a valid %q", v, k)} - } - - return nil, errors -} diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 524fbb314493..ab158dc4ea02 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -45,7 +45,7 @@ func resourceArmPrivateLinkService() *schema.Resource { Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: aznet.ValidatePrivateLinkServiceSubsciptionGuid, + ValidateFunc: validate.GUID, }, }, @@ -54,7 +54,7 @@ func resourceArmPrivateLinkService() *schema.Resource { Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: aznet.ValidatePrivateLinkServiceSubsciptionGuid, + ValidateFunc: validate.GUID, }, }, @@ -90,7 +90,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "private_ip_address": { Type: schema.TypeString, Optional: true, - ValidateFunc: aznet.ValidatePrivateLinkServiceIPv4Address, + ValidateFunc: valadate.IPv4Address, }, // Only IPv4 is supported by the API, but I am exposing this // as they will support IPv6 in a future release. @@ -110,7 +110,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "subnet_id": { Type: schema.TypeString, Required: true, - ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, + ValidateFunc: azure.ValidateResourceID, }, }, }, @@ -121,11 +121,11 @@ func resourceArmPrivateLinkService() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: aznet.ValidatePrivateLinkServiceIsResourceId, + ValidateFunc: azure.ValidateResourceID, }, }, - "private_endpoint_connection": { + "private_link_endpoint_connection": { Type: schema.TypeList, Optional: true, Computed: true, @@ -140,11 +140,12 @@ func resourceArmPrivateLinkService() *schema.Resource { Required: true, ValidateFunc: validate.NoEmptyStrings, }, - "private_endpoint_id": { - Type: schema.TypeString, - Required: true, + "private_link_endpoint_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, }, - "private_endpoint_location": azure.SchemaLocation(), + "private_link_endpoint_location": azure.SchemaLocation(), "state_action_required": { Type: schema.TypeString, Computed: true, @@ -204,15 +205,19 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte //fqdns := d.Get("fqdns").([]interface{}) ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) - privateEndpointConnections := d.Get("private_endpoint_connection").([]interface{}) + privateEndpointConnections := d.Get("private_link_endpoint_connection").([]interface{}) visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) parameters := network.PrivateLinkService{ Location: utils.String(location), PrivateLinkServiceProperties: &network.PrivateLinkServiceProperties{ - AutoApproval: expandArmPrivateLinkServicePropertiesAutoApproval(autoApproval), - Visibility: expandArmPrivateLinkServicePropertiesVisibility(visibility), + AutoApproval: &network.PrivateLinkServicePropertiesAutoApproval{ + Subscriptions: utils.ExpandStringSlice(autoApproval), + }, + Visibility: &network.PrivateLinkServicePropertiesVisibility{ + Subscriptions: utils.ExpandStringSlice(visibility), + }, IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(ipConfigurations), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), PrivateEndpointConnections: expandArmPrivateLinkServicePrivateEndpointConnection(privateEndpointConnections), @@ -236,6 +241,10 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte if resp.ID == nil { return fmt.Errorf("Cannot read Private Link Service %q (Resource Group %q) ID", name, resourceGroup) } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) + } + d.SetId(*resp.ID) return resourceArmPrivateLinkServiceRead(d, meta) @@ -268,16 +277,14 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) d.Set("location", azure.NormalizeLocation(*location)) } if props := resp.PrivateLinkServiceProperties; props != nil { - if err := d.Set("alias", props.Alias); err != nil { - return fmt.Errorf("Error setting `alias`: %+v", err) - } + d.Set("alias", props.Alias) if props.AutoApproval != nil { - if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } if props.Visibility != nil { - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } } @@ -297,8 +304,8 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { - if err := d.Set("private_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { - return fmt.Errorf("Error setting `private_endpoint_connection`: %+v", err) + if err := d.Set("private_link_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { + return fmt.Errorf("Error setting `private_link_endpoint_connection`: %+v", err) } } } @@ -334,30 +341,6 @@ func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{ return nil } -func expandArmPrivateLinkServicePropertiesAutoApproval(input []interface{}) *network.PrivateLinkServicePropertiesAutoApproval { - if len(input) == 0 { - return nil - } - - result := network.PrivateLinkServicePropertiesAutoApproval{ - Subscriptions: utils.ExpandStringSlice(input), - } - - return &result -} - -func expandArmPrivateLinkServicePropertiesVisibility(input []interface{}) *network.PrivateLinkServicePropertiesVisibility { - if len(input) == 0 { - return nil - } - - result := network.PrivateLinkServicePropertiesVisibility{ - Subscriptions: utils.ExpandStringSlice(input), - } - - return &result -} - func expandArmPrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { if len(input) == 0 { return nil @@ -419,8 +402,8 @@ func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) * status := v["state_status"].(string) description := v["state_description"].(string) actionRequired := v["state_action_required"].(string) - privateEndpointId := v["private_endpoint_id"].(string) - privateEndpointLocation := azure.NormalizeLocation(v["private_endpoint_location"].(string)) + privateEndpointId := v["private_link_endpoint_id"].(string) + privateEndpointLocation := azure.NormalizeLocation(v["private_link_endpoint_location"].(string)) result := network.PrivateEndpointConnection{ ID: utils.String(id), @@ -443,32 +426,6 @@ func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) * return &results } -func flattenArmPrivateLinkServicePropertiesAutoApproval(input *network.PrivateLinkServicePropertiesAutoApproval) []interface{} { - result := make([]interface{}, 0) - if input == nil { - return result - } - - if input.Subscriptions != nil { - result = utils.FlattenStringSlice(input.Subscriptions) - } - - return result -} - -func flattenArmPrivateLinkServicePropertiesVisibility(input *network.PrivateLinkServicePropertiesVisibility) []interface{} { - result := make([]interface{}, 0) - if input == nil { - return result - } - - if input.Subscriptions != nil { - result = utils.FlattenStringSlice(input.Subscriptions) - } - - return result -} - func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { results := make([]interface{}, 0) if input == nil { @@ -550,10 +507,10 @@ func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.Priv if props := item.PrivateEndpointConnectionProperties; props != nil { if p := props.PrivateEndpoint; p != nil { if id := p.ID; id != nil { - v["private_endpoint_id"] = *id + v["private_link_endpoint_id"] = *id } if location := p.Location; location != nil { - v["private_endpoint_location"] = azure.NormalizeLocation(*location) + v["private_link_endpoint_location"] = azure.NormalizeLocation(*location) } } if s := props.PrivateLinkServiceConnectionState; s != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 70c7fb64e2a9..293dda8cd387 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -177,68 +177,9 @@ func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { } func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { - return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_basic(rInt)) -} - -func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { - return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_update(rInt)) -} - -func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { - return testAccAzureRMPrivateLinkServiceTemplate(rInt, location, testAccAzureRMPrivateLinkServiceTemplate_complete(rInt)) -} - -func testAccAzureRMPrivateLinkServiceTemplate(rInt int, location string, privateLinkTemplate string) string { - return fmt.Sprintf(` -data "azurerm_subscription" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvnet-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - address_space = ["10.5.0.0/16"] -} - -resource "azurerm_subnet" "test" { - name = "acctestsnet-%d" - resource_group_name = azurerm_resource_group.test.name - virtual_network_name = azurerm_virtual_network.test.name - address_prefix = "10.5.1.0/24" - - disable_private_link_service_network_policies = true -} - -resource "azurerm_public_ip" "test" { - name = "acctestpip-%d" - sku = "Standard" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - allocation_method = "Static" -} - -resource "azurerm_lb" "test" { - name = "acctestlb-%d" - sku = "Standard" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - - frontend_ip_configuration { - name = azurerm_public_ip.test.name - public_ip_address_id = azurerm_public_ip.test.id - } -} - + fmt.Sprintf(` %s -`, rInt, location, rInt, rInt, rInt, rInt, privateLinkTemplate) -} -func testAccAzureRMPrivateLinkServiceTemplate_basic(rInt int) string { - return fmt.Sprintf(` resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location @@ -253,11 +194,13 @@ resource "azurerm_private_link_service" "test" { azurerm_lb.test.frontend_ip_configuration.0.id ] } -`, rInt, rInt) +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt) } -func testAccAzureRMPrivateLinkServiceTemplate_update(rInt int) string { +func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { return fmt.Sprintf(` +%s + resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location @@ -276,11 +219,13 @@ resource "azurerm_private_link_service" "test" { env = "test" } } -`, rInt, rInt) +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt) } -func testAccAzureRMPrivateLinkServiceTemplate_complete(rInt int) string { +func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { return fmt.Sprintf(` +%s + resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location @@ -313,5 +258,52 @@ resource "azurerm_private_link_service" "test" { env = "test" } } -`, rInt, rInt, rInt) +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkServiceTemplate(rInt int, location string) string { + return fmt.Sprintf(` +data "azurerm_subscription" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvnet-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctestsnet-%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.5.1.0/24" + + disable_private_link_service_network_policies = true +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%d" + sku = "Standard" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Static" +} + +resource "azurerm_lb" "test" { + name = "acctestlb-%d" + sku = "Standard" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + frontend_ip_configuration { + name = azurerm_public_ip.test.name + public_ip_address_id = azurerm_public_ip.test.id + } +} +`, rInt, location, rInt, rInt, rInt, rInt) } diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index a121eb41c482..4a06d2e7c0b5 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -175,11 +175,11 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err // To enable private endpoints you must disable the network policies for the // subnet because Network policies like network security groups are not // supported by private endpoints. - privateLinkServiceNetworkPolicies := "Enabled" + p := "Enabled" if v.(bool) { - privateLinkServiceNetworkPolicies = "Disabled" + p = "Disabled" } - properties.PrivateLinkServiceNetworkPolicies = &privateLinkServiceNetworkPolicies + properties.PrivateLinkServiceNetworkPolicies = &p } if v, ok := d.GetOk("network_security_group_id"); ok { diff --git a/examples/virtual-networks/private-link-service/variables.tf b/examples/virtual-networks/private-link-service/variables.tf index 9d83fdac9dfd..032a322f8e43 100644 --- a/examples/virtual-networks/private-link-service/variables.tf +++ b/examples/virtual-networks/private-link-service/variables.tf @@ -1,7 +1,9 @@ variable "resource_group_name" { description = "The name of the resource group the Private Link Service is located in." + default = ["example-private-link-service"] } variable "location" { description = "The Azure location where all resources in this example should be created." + default = ["WestUS"] } diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index b06e83d2ba07..d7f78804f5b0 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -50,7 +50,7 @@ The following attributes are exported: * `network_interfaces` - A list of network interface resource ids that are being used by the service. -* `private_endpoint_connection` - One or more `private_endpoint_connection` blocks as defined below. +* `private_link_endpoint_connection` - One or more `private_link_endpoint_connection` blocks as defined below. * `visibility_subscription_ids` - A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. @@ -59,7 +59,7 @@ The following attributes are exported: --- -The `nat_ip_configuration` block contains the following: +The `nat_ip_configuration` block exports the following: * `name` - The name of private link service ip configuration. @@ -73,17 +73,17 @@ The `nat_ip_configuration` block contains the following: --- -The `private_endpoint_connection` block contains the following: +The `private_link_endpoint_connection` block exports the following: * `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. -* `private_endpoint_location` - (Required) The resource location of the `private_endpoint`. +* `private_link_endpoint_id` - (Required) The Private Link Endpoint ID. -* `private_endpoint_id` - (Required) The Private Endpoint ID. +* `private_link_endpoint_location` - (Required) The resource location of the `private_link_endpoint`. * `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. * `state_description` - (Computed) The reason for approval/rejection of the connection. -* `state_status` - (Computed) Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. +* `state_status` - (Computed) Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 9ba990269881..f52c56d5e72d 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -3,12 +3,12 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-resource-private-link-service" description: |- - Manages an Azure PrivateLinkService instance. + Manages an Azure Private Link Service. --- # azurerm_private_link_service -Managea an Azure PrivateLinkService instance. +Manages an Azure Private Link Service. ## Private Link Service Usage @@ -89,7 +89,7 @@ The following arguments are supported: * `load_balancer_frontend_ip_configuration_ids` - (Required) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. -* `private_endpoint_connection` - (Optional) One or more `private_endpoint_connection` blocks as defined below. +* `private_link_endpoint_connection` - (Optional) One or more `private_link_endpoint_connection` blocks as defined below. * `visibility_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. @@ -109,28 +109,28 @@ The `nat_ip_configuration` block supports the following: * `subnet_id` - (Required) The resource ID of the subnet to be used by the service. -* `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, supported values are `IPv4` or `IPv6`. Defaults to `IPv4`. +* `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, the supported value is `IPv4`. Defaults to `IPv4`. -> **NOTE:** Private Link Service Supports `IPv4` traffic only. --- -The `private_endpoint_connection` block contains the following: +The `private_link_endpoint_connection` block contains the following: -* `id` - (Computed) The resource ID of the `private_endpoint_connection`. +* `id` - (Computed) The resource ID of the `private_link_endpoint_connection`. * `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. -* `private_endpoint_location` - (Required) The resource location of the `private_endpoint`. +* `private_link_endpoint_id` - (Required) The Private Link Endpoint ID. -* `private_endpoint_id` - (Required) The Private Endpoint ID. +* `private_link_endpoint_location` - (Required) The resource location of the `private_link_endpoint`. * `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. * `state_description` - (Computed) The reason for approval/rejection of the connection. -* `state_status` - (Computed) Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. +* `state_status` - (Computed) Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. ## Attributes Reference @@ -143,15 +143,15 @@ The following attributes are exported: --- -* A `private_endpoint_connection` block contains: +* A `private_link_endpoint_connection` exports the following: -* `id` - The resource ID of the `private_endpoint_connection`. +* `id` - The resource ID of the `private_link_endpoint_connection`. * `state_action_required` - A message indicating if changes on the service provider require any updates by the consumer. * `state_description` - The reason for approval/rejection of the connection. -* `state_status` - Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service. +* `state_status` - Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. ## Import From 474375a315e9ccd0fdf29e9f88ce5caa3910ecfa Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 10 Oct 2019 19:49:55 -0700 Subject: [PATCH 20/44] A couple other things --- azurerm/data_source_private_link_service.go | 6 +++--- azurerm/internal/services/network/validate.go | 4 ++-- azurerm/resource_arm_private_link_service.go | 7 +++---- azurerm/resource_arm_private_link_service_test.go | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 5265f8d1d1f5..410582091ead 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -165,17 +165,17 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ d.SetId(*resp.ID) d.Set("name", resp.Name) d.Set("resource_group_name", resourceGroup) - d.Set("location", azure.NormalizeLocation(*location)) + d.Set("location", azure.NormalizeLocation(*resp.Location)) if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) if props.AutoApproval != nil { - if err := d.Set("auto_approval_subscription_ids", flattenArmPrivateLinkServicePropertiesAutoApproval(props.AutoApproval)); err != nil { + if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } if props.Visibility != nil { - if err := d.Set("visibility_subscription_ids", flattenArmPrivateLinkServicePropertiesVisibility(props.Visibility)); err != nil { + if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } } diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index cc0cff09d0b4..91d9f40c25f1 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -2,8 +2,8 @@ package network import ( "fmt" - "net" - + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index ab158dc4ea02..3d277beba66c 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -90,7 +90,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "private_ip_address": { Type: schema.TypeString, Optional: true, - ValidateFunc: valadate.IPv4Address, + ValidateFunc: validate.IPv4Address, }, // Only IPv4 is supported by the API, but I am exposing this // as they will support IPv6 in a future release. @@ -273,9 +273,8 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) d.Set("name", resp.Name) d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } + d.Set("location", azure.NormalizeLocation(*resp.Location)) + if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) if props.AutoApproval != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 293dda8cd387..9a983243c36e 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -177,7 +177,7 @@ func testCheckAzureRMPrivateLinkServiceDestroy(s *terraform.State) error { } func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { - fmt.Sprintf(` + return fmt.Sprintf(` %s resource "azurerm_private_link_service" "test" { From a1e79b266164fa1dbf1429478a7260e316691076 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 11 Oct 2019 11:54:44 -0700 Subject: [PATCH 21/44] Gofmt validate --- azurerm/internal/services/network/validate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 91d9f40c25f1..7ebe085f9046 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -2,7 +2,7 @@ package network import ( "fmt" - + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) From d1ae65083553b1ad754ac2efcf7d97a82c3f84d3 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 11 Oct 2019 12:02:22 -0700 Subject: [PATCH 22/44] Update Subnet documentation --- website/docs/r/subnet.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 56630ee755d8..352885c5b808 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,9 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `disable_private_link_service_network_policies` - (Optional) Enable or Disable network policies on private link service in the subnet. Default is `false`. +* `disable_private_link_service_network_policies` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. --> **NOTE:** In order to choose a source IP address for your Private Link service, an explicit disable setting `disable_private_link_service_network_policies` is required on the subnet. This setting is only applicable for the specific private IP address you chose as the source IP of the Private Link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. +-> **NOTE:** In order to choose a source IP address for your `private link service`, an explicit disable setting is required on the subnet(e.g. `disable_private_link_service_network_policies` = `True`). This setting is only applicable for the specific private IP address that you chose as the source IP of the `private link service`. For other resources in the subnet, access is controlled based on the Network Security Groups(NSG) rule definitions. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From 24d5986d5b72e795fa4543a6482515df5b91f59c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 22 Oct 2019 18:55:09 -0700 Subject: [PATCH 23/44] Fix schema and removed unused code refactor --- azurerm/data_source_private_link_service.go | 66 +++----- azurerm/internal/services/network/validate.go | 26 ++- azurerm/resource_arm_private_link_service.go | 149 ++---------------- 3 files changed, 56 insertions(+), 185 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 410582091ead..0900a0c8cd5d 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -91,41 +91,6 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "private_link_endpoint_connection": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, - "name": { - Type: schema.TypeString, - Computed: true, - }, - "private_link_endpoint_id": { - Type: schema.TypeString, - Computed: true, - }, - "private_link_endpoint_location": azure.SchemaLocationForDataSource(), - "state_action_required": { - Type: schema.TypeString, - Computed: true, - }, - "state_description": { - Type: schema.TypeString, - Computed: true, - }, - "state_status": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "alias": { Type: schema.TypeString, Computed: true, @@ -162,19 +127,18 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) } - d.SetId(*resp.ID) d.Set("name", resp.Name) d.Set("resource_group_name", resourceGroup) d.Set("location", azure.NormalizeLocation(*resp.Location)) if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) - if props.AutoApproval != nil { + if props.AutoApproval.Subscriptions != nil { if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } - if props.Visibility != nil { + if props.Visibility.Subscriptions != nil { if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } @@ -185,21 +149,27 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ // return fmt.Errorf("Error setting `fqdns`: %+v", err) // } // } - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) - } - if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { - return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) + if props.IPConfigurations != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) + } } - if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { - return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) + if props.LoadBalancerFrontendIPConfigurations != nil { + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) + } } - if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { - if err := d.Set("private_link_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { - return fmt.Errorf("Error setting `private_link_endpoint_connection`: %+v", err) + if props.NetworkInterfaces != nil { + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } } } + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("API returns a nil/empty id on Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + d.SetId(*resp.ID) + return tags.FlattenAndSet(d, resp.Tags) } diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 7ebe085f9046..cbc448368276 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -8,8 +8,28 @@ import ( ) func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors []error) { - if m, regexErrs := validate.RegExHelper(i, k, `(^[\da-zA-Z]){1,}([\d\._\-a-zA-Z]{0,77})([\da-zA-Z_]$)`); !m { - errors = append(regexErrs, fmt.Errorf(`%q must be between 1 and 80 characters, begin with a letter or number, end with a letter, number or underscore, and may contain only letters, numbers, underscores, periods, or hyphens.`, k)) + v, ok := i.(string) + if !ok { + return nil, append(errors, fmt.Errorf("expected type of %s to be string", k)) + } + + // The name attribute rules per the Nat Gateway service team are (Friday, October 18, 2019 4:20 PM): + // 1. Must not be empty. + // 2. Must be between 1 and 80 characters. + // 3. The attribute must: + // a) begin with a letter or number + // b) end with a letter, number or underscore + // c) may contain only letters, numbers, underscores, periods, or hyphens. + + if len(v) == 1 { + if m, _ := validate.RegExHelper(i, k, `^([a-zA-Z\d])`); !m { + errors = append(errors, fmt.Errorf("%s must begin with a letter or number", k)) + } + } else { + if m, _ := validate.RegExHelper(i, k, `^([a-zA-Z\d])([a-zA-Z\d-\_\.]{0,78})([a-zA-Z\d\_])$`); !m { + 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, underscores, periods, or hyphens", k)) + + } } return nil, errors @@ -18,7 +38,7 @@ func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors func ValidatePrivateLinkServiceSubsciptionFqdn(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(string) if !ok { - return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + return nil, append(errors, fmt.Errorf("expected type of %q to be string", k)) } if m, _ := validate.RegExHelper(i, k, `^(([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d])\.){1,}([a-zA-Z\d]|[a-zA-Z\d][a-zA-Z\d\-]*[a-zA-Z\d\.]){1,}$`); !m { diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 3d277beba66c..cc1e22f2e222 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -125,43 +125,6 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, - "private_link_endpoint_connection": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "private_link_endpoint_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - "private_link_endpoint_location": azure.SchemaLocation(), - "state_action_required": { - Type: schema.TypeString, - Computed: true, - }, - "state_description": { - Type: schema.TypeString, - Computed: true, - }, - "state_status": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "alias": { Type: schema.TypeString, Computed: true, @@ -205,7 +168,6 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte //fqdns := d.Get("fqdns").([]interface{}) ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) - privateEndpointConnections := d.Get("private_link_endpoint_connection").([]interface{}) visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) @@ -220,7 +182,6 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte }, IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(ipConfigurations), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), - PrivateEndpointConnections: expandArmPrivateLinkServicePrivateEndpointConnection(privateEndpointConnections), //Fqdns: utils.ExpandStringSlice(fqdns), }, Tags: tags.Expand(t), @@ -238,13 +199,9 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte if err != nil { return fmt.Errorf("Error retrieving Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) } - if resp.ID == nil { - return fmt.Errorf("Cannot read Private Link Service %q (Resource Group %q) ID", name, resourceGroup) - } - if resp.ID == nil { - return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("API returns a nil/empty id on Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) } - d.SetId(*resp.ID) return resourceArmPrivateLinkServiceRead(d, meta) @@ -277,12 +234,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) - if props.AutoApproval != nil { + if props.AutoApproval.Subscriptions != nil { if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } - if props.Visibility != nil { + if props.Visibility.Subscriptions != nil { if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } @@ -293,18 +250,19 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // return fmt.Errorf("Error setting `fqdns`: %+v", err) // } // } - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) - } - if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { - return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) + if props.IPConfigurations != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) + } } - if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { - return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) + if props.LoadBalancerFrontendIPConfigurations != nil { + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) + } } - if connectionProps := props.PrivateEndpointConnections; connectionProps != nil { - if err := d.Set("private_link_endpoint_connection", flattenArmPrivateLinkServicePrivateEndpointConnection(connectionProps)); err != nil { - return fmt.Errorf("Error setting `private_link_endpoint_connection`: %+v", err) + if props.NetworkInterfaces != nil { + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } } } @@ -392,39 +350,6 @@ func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[] return &results } -func expandArmPrivateLinkServicePrivateEndpointConnection(input []interface{}) *[]network.PrivateEndpointConnection { - results := make([]network.PrivateEndpointConnection, 0) - for _, item := range input { - v := item.(map[string]interface{}) - id := v["id"].(string) - name := v["name"].(string) - status := v["state_status"].(string) - description := v["state_description"].(string) - actionRequired := v["state_action_required"].(string) - privateEndpointId := v["private_link_endpoint_id"].(string) - privateEndpointLocation := azure.NormalizeLocation(v["private_link_endpoint_location"].(string)) - - result := network.PrivateEndpointConnection{ - ID: utils.String(id), - Name: utils.String(name), - PrivateEndpointConnectionProperties: &network.PrivateEndpointConnectionProperties{ - PrivateEndpoint: &network.PrivateEndpoint{ - ID: utils.String(privateEndpointId), - Location: utils.String(privateEndpointLocation), - }, - PrivateLinkServiceConnectionState: &network.PrivateLinkServiceConnectionState{ - ActionRequired: utils.String(actionRequired), - Description: utils.String(description), - Status: utils.String(status), - }, - }, - } - - results = append(results, result) - } - return &results -} - func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { results := make([]interface{}, 0) if input == nil { @@ -486,47 +411,3 @@ func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []string return results } - -func flattenArmPrivateLinkServicePrivateEndpointConnection(input *[]network.PrivateEndpointConnection) []interface{} { - results := make([]interface{}, 0) - if input == nil { - return results - } - - for _, item := range *input { - v := make(map[string]interface{}) - - if id := item.ID; id != nil { - v["id"] = *id - } - if name := item.Name; name != nil { - v["name"] = *name - } - - if props := item.PrivateEndpointConnectionProperties; props != nil { - if p := props.PrivateEndpoint; p != nil { - if id := p.ID; id != nil { - v["private_link_endpoint_id"] = *id - } - if location := p.Location; location != nil { - v["private_link_endpoint_location"] = azure.NormalizeLocation(*location) - } - } - if s := props.PrivateLinkServiceConnectionState; s != nil { - if actionRequired := s.ActionRequired; actionRequired != nil { - v["state_action_required"] = *actionRequired - } - if description := s.Description; description != nil { - v["state_description"] = *description - } - if status := s.Status; status != nil { - v["state_status"] = *status - } - } - } - - results = append(results, v) - } - - return results -} From 97f86ee4db7ce8b69ef8f947d8156cea36ba61c1 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 30 Oct 2019 16:54:02 -0700 Subject: [PATCH 24/44] Fixed conflict --- azurerm/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/provider.go b/azurerm/provider.go index 6c61af17fac9..f46e7fe04eb3 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -116,6 +116,7 @@ func Provider() terraform.ResourceProvider { "azurerm_platform_image": dataSourceArmPlatformImage(), "azurerm_policy_definition": dataSourceArmPolicyDefinition(), "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), "azurerm_public_ip": dataSourceArmPublicIP(), "azurerm_public_ips": dataSourceArmPublicIPs(), From 11cb0e212ef28a89114ffc1e74ef5bc0c98019e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 31 Oct 2019 19:00:13 -0700 Subject: [PATCH 25/44] Added some more validation --- azurerm/resource_arm_private_link_service.go | 24 +++++++++++++++++++ .../docs/r/private_link_service.html.markdown | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index cc1e22f2e222..dcb4c4deba83 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -68,6 +68,7 @@ func resourceArmPrivateLinkService() *schema.Resource { // }, // }, + // Required by the API you can't create the resource without at least one ip configuration "nat_ip_configuration": { Type: schema.TypeList, Required: true, @@ -116,6 +117,10 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, + // private_endpoint_connections have been removed but maybe useful for the end user to + // understand the state of entpoints connected to this service, create a datasource? + + // Required by the API you can't create the resource without at least one load balancer id "load_balancer_frontend_ip_configuration_ids": { Type: schema.TypeList, Required: true, @@ -204,6 +209,25 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte } d.SetId(*resp.ID) + // need to check to see if they attempted to reassign primary to a different ip_configuration + // this is not allowed, but the API allows it to be passed and doesn't error as expected, rather it + // ignores the passed value if it is different than the existing value. Once a primary value + // has been set it cannot be changed. + if props := resp.PrivateLinkServiceProperties; props != nil { + if i := props.IPConfigurations; i != nil { + for _, v := range *i { + ipName := *v.Name + ipPrimary := *v.PrivateLinkServiceIPConfigurationProperties.Primary + for _, o := range ipConfigurations { + c := o.(map[string]interface{}) + if c["name"].(string) == ipName && c["primary"].(bool) != ipPrimary { + return fmt.Errorf("once the primary ip configuration (name %q) has been set it cannot be changed Private Link Service %q (Resource Group %q)", ipName, name, resourceGroup) + } + } + } + } + } + return resourceArmPrivateLinkServiceRead(d, meta) } diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index f52c56d5e72d..36a69d0021a8 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -57,8 +57,7 @@ resource "azurerm_private_link_service" "example" { name = "example-pls" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - fqdns = ["testFqdns"] - + nat_ip_configuration { name = "primaryIpConfiguration" subnet_id = azurerm_subnet.example.id From 1870099b699ebf9bfff5a0324c16ee7a6c40ecb6 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 4 Nov 2019 18:56:35 -0800 Subject: [PATCH 26/44] Resource is good now --- azurerm/data_source_private_link_service.go | 38 +++- ...link_service_endpoint_connection_status.go | 149 +++++++++++++ azurerm/internal/services/network/validate.go | 40 ++++ azurerm/provider.go | 199 +++++++++--------- azurerm/resource_arm_private_link_service.go | 163 +++++++++----- 5 files changed, 431 insertions(+), 158 deletions(-) create mode 100644 azurerm/data_source_private_link_service_endpoint_connection_status.go diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 0900a0c8cd5d..513089d69d28 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -50,29 +50,47 @@ func dataSourceArmPrivateLinkService() *schema.Resource { // }, // }, - "nat_ip_configuration": { + "primary_nat_ip_configuration": { Type: schema.TypeList, Computed: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, Computed: true, }, - "private_ip_allocation_method": { + "private_ip_address": { Type: schema.TypeString, Computed: true, }, - "private_ip_address": { + "private_ip_address_version": { Type: schema.TypeString, Computed: true, }, - "private_ip_address_version": { + "subnet_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "secondary_nat_ip_configuration": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "private_ip_address": { Type: schema.TypeString, Computed: true, }, - "primary": { - Type: schema.TypeBool, + "private_ip_address_version": { + Type: schema.TypeString, Computed: true, }, "subnet_id": { @@ -150,8 +168,12 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ // } // } if props.IPConfigurations != nil { - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) + primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) + if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { + return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) + } + if err := d.Set("secondary_nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `secondary_nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { diff --git a/azurerm/data_source_private_link_service_endpoint_connection_status.go b/azurerm/data_source_private_link_service_endpoint_connection_status.go new file mode 100644 index 000000000000..10817fea4604 --- /dev/null +++ b/azurerm/data_source_private_link_service_endpoint_connection_status.go @@ -0,0 +1,149 @@ +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" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead, + + Schema: map[string]*schema.Schema{ + "private_link_service_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "private_endpoint_connections": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "connection_id": { + Type: schema.TypeString, + Computed: true, + }, + "connection_name": { + Type: schema.TypeString, + Computed: true, + }, + "private_endpoint_id": { + Type: schema.TypeString, + Computed: true, + }, + "private_endpoint_name": { + Type: schema.TypeString, + Computed: true, + }, + "action_required": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Network.PrivateLinkServiceClient + ctx := meta.(*ArmClient).StopContext + + id, err := azure.ParseAzureResourceID(d.Get("private_link_service_id").(string)) + if err != nil { + return err + } + + resourceGroup := id.ResourceGroup + name := id.Path["privateLinkServices"] + + resp, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Private Link Service %q (Resource Group %q) was not found", name, resourceGroup) + } + return fmt.Errorf("Error reading Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) + } + + if props := resp.PrivateLinkServiceProperties; props != nil { + if ip := props.PrivateEndpointConnections; ip != nil { + if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnections(ip)); err != nil { + return fmt.Errorf("Error setting `private_endpoint_connections`: %+v", err) + } + } + } + + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("API returns a nil/empty id on Private Link Service Endpoint Connection Status %q (Resource Group %q): %+v", name, resourceGroup, err) + } + d.SetId(*resp.ID) + + return nil +} + +func flattenArmPrivateLinkServicePrivateEndpointConnections(input *[]network.PrivateEndpointConnection) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + v := make(map[string]interface{}) + if id := item.ID; id != nil { + v["connection_id"] = *id + } + if name := item.Name; name != nil { + v["connection_name"] = *name + } + + if props := item.PrivateEndpointConnectionProperties; props != nil { + if p := props.PrivateEndpoint; p != nil { + if id := p.ID; id != nil { + v["private_endpoint_id"] = *id + + id, _ := azure.ParseAzureResourceID(*id) + name := id.Path["privateEndpoints"] + if name != "" { + v["private_endpoint_name"] = name + } + } + } + if s := props.PrivateLinkServiceConnectionState; s != nil { + if a := s.ActionRequired; a != nil { + v["action_required"] = *a + } else { + v["action_required"] = "none" + } + if d := s.Description; d != nil { + v["description"] = *d + } + if t := s.Status; t != nil { + v["status"] = *t + } + } + } + + results = append(results, v) + } + + return results +} diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index cbc448368276..2aa35867f22b 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -3,10 +3,50 @@ package network import ( "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +// ValidatePrivateLinkNatIpConfiguration - This rule makes sure that you can only go from a +// dynamic private ip address to a static private ip address. Once you have assigned a private +// ip address to a primary or secondary nat ip configuration block it is set in stone and can +// not become a dynamic private ip address again unless the resource is destroyed and recreated. +func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) + secondaryIpConfigurations := d.Get("secondary_nat_ip_configuration").([]interface{}) + + for i, item := range primaryIpConfiguration { + v := item.(map[string]interface{}) + p := fmt.Sprintf("primary_nat_ip_configuration.%d.private_ip_address", i) + in := v["name"].(string) + + if d.HasChange(p) { + o, n := d.GetChange(p) + if o != "" && n == "" { + return fmt.Errorf("Private Link Service %q (Resource Group %q) primary_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + } + } + } + + for i, item := range secondaryIpConfigurations { + v := item.(map[string]interface{}) + p := fmt.Sprintf("secondary_nat_ip_configuration.%d.private_ip_address", i) + in := v["name"].(string) + + if d.HasChange(p) { + o, n := d.GetChange(p) + if o != "" && n == "" { + return fmt.Errorf("Private Link Service %q (Resource Group %q) secondary_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + } + } + } + + return nil +} + func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(string) if !ok { diff --git a/azurerm/provider.go b/azurerm/provider.go index f46e7fe04eb3..efc90062998c 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -52,105 +52,106 @@ func Provider() terraform.ResourceProvider { } dataSources := map[string]*schema.Resource{ - "azurerm_api_management": dataSourceApiManagementService(), - "azurerm_api_management_api": dataSourceApiManagementApi(), - "azurerm_api_management_group": dataSourceApiManagementGroup(), - "azurerm_api_management_product": dataSourceApiManagementProduct(), - "azurerm_api_management_user": dataSourceArmApiManagementUser(), - "azurerm_app_service_plan": dataSourceAppServicePlan(), - "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), - "azurerm_app_service": dataSourceArmAppService(), - "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), - "azurerm_application_insights": dataSourceArmApplicationInsights(), - "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), - "azurerm_automation_account": dataSourceArmAutomationAccount(), - "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), - "azurerm_availability_set": dataSourceArmAvailabilitySet(), - "azurerm_azuread_application": dataSourceArmAzureADApplication(), - "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), - "azurerm_batch_account": dataSourceArmBatchAccount(), - "azurerm_batch_certificate": dataSourceArmBatchCertificate(), - "azurerm_batch_pool": dataSourceArmBatchPool(), - "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), - "azurerm_cdn_profile": dataSourceArmCdnProfile(), - "azurerm_client_config": dataSourceArmClientConfig(), - "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), - "azurerm_container_registry": dataSourceArmContainerRegistry(), - "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), - "azurerm_data_factory": dataSourceArmDataFactory(), - "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), - "azurerm_dev_test_lab": dataSourceArmDevTestLab(), - "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), - "azurerm_dns_zone": dataSourceArmDnsZone(), - "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), - "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), - "azurerm_firewall": dataSourceArmFirewall(), - "azurerm_image": dataSourceArmImage(), - "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), - "azurerm_healthcare_service": dataSourceArmHealthcareService(), - "azurerm_maps_account": dataSourceArmMapsAccount(), - "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), - "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), - "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), - "azurerm_key_vault": dataSourceArmKeyVault(), - "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), - "azurerm_lb": dataSourceArmLoadBalancer(), - "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), - "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), - "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), - "azurerm_managed_disk": dataSourceArmManagedDisk(), - "azurerm_management_group": dataSourceArmManagementGroup(), - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), - "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), - "azurerm_network_interface": dataSourceArmNetworkInterface(), - "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), - "azurerm_network_watcher": dataSourceArmNetworkWatcher(), - "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), - "azurerm_notification_hub": dataSourceNotificationHub(), - "azurerm_platform_image": dataSourceArmPlatformImage(), - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_postgresql_server": dataSourcePostgreSqlServer(), - "azurerm_private_link_service": dataSourceArmPrivateLinkService(), - "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), - "azurerm_public_ip": dataSourceArmPublicIP(), - "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_redis_cache": dataSourceArmRedisCache(), - "azurerm_resources": dataSourceArmResources(), - "azurerm_resource_group": dataSourceArmResourceGroup(), - "azurerm_role_definition": dataSourceArmRoleDefinition(), - "azurerm_route_table": dataSourceArmRouteTable(), - "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), - "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), - "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), - "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), - "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), - "azurerm_shared_image": dataSourceArmSharedImage(), - "azurerm_snapshot": dataSourceArmSnapshot(), - "azurerm_sql_server": dataSourceSqlServer(), - "azurerm_sql_database": dataSourceSqlDatabase(), - "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), - "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), - "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), - "azurerm_storage_account": dataSourceArmStorageAccount(), - "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), - "azurerm_subnet": dataSourceArmSubnet(), - "azurerm_subscription": dataSourceArmSubscription(), - "azurerm_subscriptions": dataSourceArmSubscriptions(), - "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), - "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), - "azurerm_virtual_machine": dataSourceArmVirtualMachine(), - "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), - "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), - "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_api": dataSourceApiManagementApi(), + "azurerm_api_management_group": dataSourceApiManagementGroup(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), + "azurerm_api_management_user": dataSourceArmApiManagementUser(), + "azurerm_app_service_plan": dataSourceAppServicePlan(), + "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), + "azurerm_app_service": dataSourceArmAppService(), + "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), + "azurerm_application_insights": dataSourceArmApplicationInsights(), + "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), + "azurerm_automation_account": dataSourceArmAutomationAccount(), + "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), + "azurerm_availability_set": dataSourceArmAvailabilitySet(), + "azurerm_azuread_application": dataSourceArmAzureADApplication(), + "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), + "azurerm_batch_account": dataSourceArmBatchAccount(), + "azurerm_batch_certificate": dataSourceArmBatchCertificate(), + "azurerm_batch_pool": dataSourceArmBatchPool(), + "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), + "azurerm_cdn_profile": dataSourceArmCdnProfile(), + "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), + "azurerm_container_registry": dataSourceArmContainerRegistry(), + "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), + "azurerm_data_factory": dataSourceArmDataFactory(), + "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), + "azurerm_dev_test_lab": dataSourceArmDevTestLab(), + "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), + "azurerm_dns_zone": dataSourceArmDnsZone(), + "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), + "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), + "azurerm_firewall": dataSourceArmFirewall(), + "azurerm_image": dataSourceArmImage(), + "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), + "azurerm_healthcare_service": dataSourceArmHealthcareService(), + "azurerm_maps_account": dataSourceArmMapsAccount(), + "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), + "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), + "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), + "azurerm_key_vault": dataSourceArmKeyVault(), + "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), + "azurerm_lb": dataSourceArmLoadBalancer(), + "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), + "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), + "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), + "azurerm_managed_disk": dataSourceArmManagedDisk(), + "azurerm_management_group": dataSourceArmManagementGroup(), + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), + "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), + "azurerm_network_interface": dataSourceArmNetworkInterface(), + "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), + "azurerm_network_watcher": dataSourceArmNetworkWatcher(), + "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), + "azurerm_notification_hub": dataSourceNotificationHub(), + "azurerm_platform_image": dataSourceArmPlatformImage(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), + "azurerm_private_link_service_endpoint_connection_status": dataSourceArmPrivateLinkServiceEndpointConnectionStatus(), + "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), + "azurerm_public_ip": dataSourceArmPublicIP(), + "azurerm_public_ips": dataSourceArmPublicIPs(), + "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_redis_cache": dataSourceArmRedisCache(), + "azurerm_resources": dataSourceArmResources(), + "azurerm_resource_group": dataSourceArmResourceGroup(), + "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_route_table": dataSourceArmRouteTable(), + "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), + "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), + "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), + "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), + "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), + "azurerm_shared_image": dataSourceArmSharedImage(), + "azurerm_snapshot": dataSourceArmSnapshot(), + "azurerm_sql_server": dataSourceSqlServer(), + "azurerm_sql_database": dataSourceSqlDatabase(), + "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), + "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), + "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), + "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), + "azurerm_subnet": dataSourceArmSubnet(), + "azurerm_subscription": dataSourceArmSubscription(), + "azurerm_subscriptions": dataSourceArmSubscriptions(), + "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), + "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), + "azurerm_virtual_machine": dataSourceArmVirtualMachine(), + "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), + "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), + "azurerm_virtual_network": dataSourceArmVirtualNetwork(), } resources := map[string]*schema.Resource{ diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index dcb4c4deba83..a3cb826f1248 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -69,24 +69,55 @@ func resourceArmPrivateLinkService() *schema.Resource { // }, // Required by the API you can't create the resource without at least one ip configuration - "nat_ip_configuration": { + // I had to split the schema because if you attempt to change the primary attribute it + // succeeds but doesn't change the attribute. Once primary is set it is set forever unless + // you destroy the resource and recreate it. + "primary_nat_ip_configuration": { Type: schema.TypeList, Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ForceNew: true, + ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, - "private_ip_allocation_method": { + "private_ip_address": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.IPv4Address, + }, + // Only IPv4 is supported by the API, but I am exposing this + // as they will support IPv6 in a future release. + "private_ip_address_version": { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.Static), - string(network.Dynamic), + string(network.IPv4), }, false), - Default: string(network.Dynamic), + Default: string(network.IPv4), + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + }, + }, + }, + + "secondary_nat_ip_configuration": { + Type: schema.TypeList, + Required: true, + MaxItems: 7, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, "private_ip_address": { Type: schema.TypeString, @@ -103,11 +134,6 @@ func resourceArmPrivateLinkService() *schema.Resource { }, false), Default: string(network.IPv4), }, - "primary": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, "subnet_id": { Type: schema.TypeString, Required: true, @@ -118,7 +144,7 @@ func resourceArmPrivateLinkService() *schema.Resource { }, // private_endpoint_connections have been removed but maybe useful for the end user to - // understand the state of entpoints connected to this service, create a datasource? + // understand the state of endpoints connected to this service, create a datasource? // Required by the API you can't create the resource without at least one load balancer id "load_balancer_frontend_ip_configuration_ids": { @@ -145,6 +171,14 @@ func resourceArmPrivateLinkService() *schema.Resource { "tags": tags.Schema(), }, + + CustomizeDiff: func(d *schema.ResourceDiff, v interface{}) error { + if err := aznet.ValidatePrivateLinkNatIpConfiguration(d); err != nil { + return err + } + + return nil + }, } } @@ -171,7 +205,8 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte autoApproval := d.Get("auto_approval_subscription_ids").([]interface{}) // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you //fqdns := d.Get("fqdns").([]interface{}) - ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) + primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) + secondaryIpConfigurations := d.Get("secondary_nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) @@ -185,7 +220,7 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte Visibility: &network.PrivateLinkServicePropertiesVisibility{ Subscriptions: utils.ExpandStringSlice(visibility), }, - IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(ipConfigurations), + IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(primaryIpConfiguration, secondaryIpConfigurations), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), //Fqdns: utils.ExpandStringSlice(fqdns), }, @@ -209,25 +244,6 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte } d.SetId(*resp.ID) - // need to check to see if they attempted to reassign primary to a different ip_configuration - // this is not allowed, but the API allows it to be passed and doesn't error as expected, rather it - // ignores the passed value if it is different than the existing value. Once a primary value - // has been set it cannot be changed. - if props := resp.PrivateLinkServiceProperties; props != nil { - if i := props.IPConfigurations; i != nil { - for _, v := range *i { - ipName := *v.Name - ipPrimary := *v.PrivateLinkServiceIPConfigurationProperties.Primary - for _, o := range ipConfigurations { - c := o.(map[string]interface{}) - if c["name"].(string) == ipName && c["primary"].(bool) != ipPrimary { - return fmt.Errorf("once the primary ip configuration (name %q) has been set it cannot be changed Private Link Service %q (Resource Group %q)", ipName, name, resourceGroup) - } - } - } - } - } - return resourceArmPrivateLinkServiceRead(d, meta) } @@ -275,8 +291,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // } // } if props.IPConfigurations != nil { - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) + primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) + if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { + return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) + } + if err := d.Set("secondary_nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `secondary_nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { @@ -322,37 +342,71 @@ func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{ return nil } -func expandArmPrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { - if len(input) == 0 { +func expandArmPrivateLinkServiceIPConfiguration(primaryInput []interface{}, secondaryInput []interface{}) *[]network.PrivateLinkServiceIPConfiguration { + if len(primaryInput) == 0 { return nil } results := make([]network.PrivateLinkServiceIPConfiguration, 0) - for _, item := range input { + for _, item := range primaryInput { v := item.(map[string]interface{}) privateIpAddress := v["private_ip_address"].(string) - privateIPAllocationMethod := v["private_ip_allocation_method"].(string) subnetId := v["subnet_id"].(string) privateIpAddressVersion := v["private_ip_address_version"].(string) name := v["name"].(string) - primary := v["primary"].(bool) result := network.PrivateLinkServiceIPConfiguration{ Name: utils.String(name), PrivateLinkServiceIPConfigurationProperties: &network.PrivateLinkServiceIPConfigurationProperties{ - PrivateIPAddress: utils.String(privateIpAddress), - PrivateIPAddressVersion: network.IPVersion(privateIpAddressVersion), - PrivateIPAllocationMethod: network.IPAllocationMethod(privateIPAllocationMethod), + PrivateIPAddress: utils.String(privateIpAddress), + PrivateIPAddressVersion: network.IPVersion(privateIpAddressVersion), Subnet: &network.Subnet{ ID: utils.String(subnetId), }, - Primary: utils.Bool(primary), + Primary: utils.Bool(true), }, } + if privateIpAddress != "" { + result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Static") + } else { + result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Dynamic") + } + results = append(results, result) } + + if len(secondaryInput) != 0 { + for _, item := range secondaryInput { + v := item.(map[string]interface{}) + privateIpAddress := v["private_ip_address"].(string) + subnetId := v["subnet_id"].(string) + privateIpAddressVersion := v["private_ip_address_version"].(string) + name := v["name"].(string) + + result := network.PrivateLinkServiceIPConfiguration{ + Name: utils.String(name), + PrivateLinkServiceIPConfigurationProperties: &network.PrivateLinkServiceIPConfigurationProperties{ + PrivateIPAddress: utils.String(privateIpAddress), + PrivateIPAddressVersion: network.IPVersion(privateIpAddressVersion), + Subnet: &network.Subnet{ + ID: utils.String(subnetId), + }, + Primary: utils.Bool(false), + }, + } + + if privateIpAddress != "" { + result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Static") + } else { + result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Dynamic") + } + + results = append(results, result) + } + } + return &results } @@ -374,10 +428,12 @@ func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[] return &results } -func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { - results := make([]interface{}, 0) +func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) ([]interface{}, []interface{}) { + primaryResults := make([]interface{}, 0) + secondaryResults := make([]interface{}, 0) + primary := false if input == nil { - return results + return primaryResults, secondaryResults } for _, item := range *input { @@ -387,7 +443,6 @@ func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkSer b["name"] = *name } if props := item.PrivateLinkServiceIPConfigurationProperties; props != nil { - b["private_ip_allocation_method"] = string(props.PrivateIPAllocationMethod) if v := props.PrivateIPAddress; v != nil { b["private_ip_address"] = *v } @@ -397,13 +452,19 @@ func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkSer b["subnet_id"] = *i } } - b["primary"] = *props.Primary + if v := props.Primary; v != nil { + primary = *v + } } - results = append(results, b) + if primary { + primaryResults = append(primaryResults, b) + } else { + secondaryResults = append(secondaryResults, b) + } } - return results + return primaryResults, secondaryResults } func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []string { From a2e93d821efb09d7aa16cd93c1a36142cb215453 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 4 Nov 2019 19:00:42 -0800 Subject: [PATCH 27/44] Update name all private link endpoint attributes --- ...vate_link_service_endpoint_connection_status.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azurerm/data_source_private_link_service_endpoint_connection_status.go b/azurerm/data_source_private_link_service_endpoint_connection_status.go index 10817fea4604..452ad7cda460 100644 --- a/azurerm/data_source_private_link_service_endpoint_connection_status.go +++ b/azurerm/data_source_private_link_service_endpoint_connection_status.go @@ -42,15 +42,15 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource Type: schema.TypeString, Computed: true, }, - "action_required": { + "private_endpoint_action_required": { Type: schema.TypeString, Computed: true, }, - "description": { + "private_endpoint_description": { Type: schema.TypeString, Computed: true, }, - "status": { + "private_endpoint_status": { Type: schema.TypeString, Computed: true, }, @@ -129,15 +129,15 @@ func flattenArmPrivateLinkServicePrivateEndpointConnections(input *[]network.Pri } if s := props.PrivateLinkServiceConnectionState; s != nil { if a := s.ActionRequired; a != nil { - v["action_required"] = *a + v["private_endpoint_action_required"] = *a } else { - v["action_required"] = "none" + v["private_endpoint_action_required"] = "none" } if d := s.Description; d != nil { - v["description"] = *d + v["private_endpoint_description"] = *d } if t := s.Status; t != nil { - v["status"] = *t + v["private_endpoint_status"] = *t } } } From bca2ca5714cc24ce3dc709b093e5cfefbae81c4c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 5 Nov 2019 15:56:57 -0800 Subject: [PATCH 28/44] New datasource and refactor done --- azurerm/data_source_private_link_service.go | 4 +- ...link_service_endpoint_connection_status.go | 44 +++++----- azurerm/resource_arm_private_link_service.go | 1 + website/azurerm.erb | 4 + .../docs/d/private_link_service.html.markdown | 38 ++++----- ...e_endpoint_connection_status.html.markdown | 69 ++++++++++++++++ .../docs/r/private_link_service.html.markdown | 80 ++++++++----------- 7 files changed, 148 insertions(+), 92 deletions(-) create mode 100644 website/docs/d/private_link_service_endpoint_connection_status.html.markdown diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 513089d69d28..431fedfee090 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + 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" ) @@ -18,7 +18,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, "location": azure.SchemaLocationForDataSource(), diff --git a/azurerm/data_source_private_link_service_endpoint_connection_status.go b/azurerm/data_source_private_link_service_endpoint_connection_status.go index 452ad7cda460..059e8298c879 100644 --- a/azurerm/data_source_private_link_service_endpoint_connection_status.go +++ b/azurerm/data_source_private_link_service_endpoint_connection_status.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + aznet "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" ) func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource { @@ -14,13 +15,16 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource Read: dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead, Schema: map[string]*schema.Schema{ - "private_link_service_id": { + "name": { Type: schema.TypeString, Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, + ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, + "location": azure.SchemaLocationForDataSource(), + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + "private_endpoint_connections": { Type: schema.TypeList, Computed: true, @@ -42,15 +46,15 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource Type: schema.TypeString, Computed: true, }, - "private_endpoint_action_required": { + "action_required": { Type: schema.TypeString, Computed: true, }, - "private_endpoint_description": { + "description": { Type: schema.TypeString, Computed: true, }, - "private_endpoint_status": { + "status": { Type: schema.TypeString, Computed: true, }, @@ -65,13 +69,8 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead(d *schema.Resou client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext - id, err := azure.ParseAzureResourceID(d.Get("private_link_service_id").(string)) - if err != nil { - return err - } - - resourceGroup := id.ResourceGroup - name := id.Path["privateLinkServices"] + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) resp, err := client.Get(ctx, resourceGroup, name, "") if err != nil { @@ -80,10 +79,14 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead(d *schema.Resou } return fmt.Errorf("Error reading Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) } - if resp.ID == nil { - return fmt.Errorf("Cannot read ID for Private Link Service %q (Resource Group %q)", name, resourceGroup) + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("API returns a nil/empty id on Private Link Service Endpoint Connection Status %q (Resource Group %q): %+v", name, resourceGroup, err) } + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + d.Set("location", azure.NormalizeLocation(*resp.Location)) + if props := resp.PrivateLinkServiceProperties; props != nil { if ip := props.PrivateEndpointConnections; ip != nil { if err := d.Set("private_endpoint_connections", flattenArmPrivateLinkServicePrivateEndpointConnections(ip)); err != nil { @@ -92,9 +95,6 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead(d *schema.Resou } } - if resp.ID == nil || *resp.ID == "" { - return fmt.Errorf("API returns a nil/empty id on Private Link Service Endpoint Connection Status %q (Resource Group %q): %+v", name, resourceGroup, err) - } d.SetId(*resp.ID) return nil @@ -129,15 +129,15 @@ func flattenArmPrivateLinkServicePrivateEndpointConnections(input *[]network.Pri } if s := props.PrivateLinkServiceConnectionState; s != nil { if a := s.ActionRequired; a != nil { - v["private_endpoint_action_required"] = *a + v["action_required"] = *a } else { - v["private_endpoint_action_required"] = "none" + v["action_required"] = "none" } if d := s.Description; d != nil { - v["private_endpoint_description"] = *d + v["description"] = *d } if t := s.Status; t != nil { - v["private_endpoint_status"] = *t + v["status"] = *t } } } diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index a3cb826f1248..ea528cf5f622 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -117,6 +117,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "name": { Type: schema.TypeString, Required: true, + ForceNew: true, ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, "private_ip_address": { diff --git a/website/azurerm.erb b/website/azurerm.erb index 27f581c1383a..46cb0f8f4673 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -410,6 +410,10 @@ azurerm_virtual_network_gateway
  • +
  • + azurerm_private_link_service_endpoint_connection_status +
  • +
  • azurerm_private_link_service
  • diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index d7f78804f5b0..2d7aa1a8cc9f 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -15,8 +15,8 @@ Use this data source to access information about an existing Private Link Servic ```hcl data "azurerm_private_link_service" "example" { - resource_group_name = "acctestRG" name = "acctestpls" + resource_group_name = "acctestRG" } output "private_link_service_id" { @@ -42,48 +42,42 @@ The following attributes are exported: * `alias` - The alias of the private link service. -* `auto_approval_subscription_ids` - A list of subscription globally unique identifiers that will be auto approved to use this private link service. +* `auto_approval_subscription_ids` - A list of subscription(s) globally unique identifiers that will be auto approved to use the private link service. -* `nat_ip_configurations` - One or more `ip_configuration` blocks as defined below. +* `visibility_subscription_ids` - A list of subscription(s) globally unique identifiers(GUID) that will be able to see the private link service. -* `load_balancer_frontend_ip_configuration_ids` - A list of `Standard` Load Balancer resource IDs to direct the service network traffic toward. +* `primary_nat_ip_configuration` - A `primary_nat_ip_configuration` block as defined below. -* `network_interfaces` - A list of network interface resource ids that are being used by the service. +* `secondary_nat_ip_configuration` - `secondary_nat_ip_configuration` blocks as defined below. -* `private_link_endpoint_connection` - One or more `private_link_endpoint_connection` blocks as defined below. +* `load_balancer_frontend_ip_configuration_ids` - A list of `Standard` Load Balancer resource IDs. -* `visibility_subscription_ids` - A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. +* `network_interfaces` - A list of network interface resource ids that are being used by the service. * `tags` - A mapping of tags to assign to the resource. Changing this forces a new resource to be created --- -The `nat_ip_configuration` block exports the following: +The `primary_nat_ip_configuration` block exports the following: -* `name` - The name of private link service ip configuration. +* `name` - The name of primary private link service NAT IP configuration. -* `private_ip_address` - The private IP address of the IP configuration. +* `private_ip_address` - The private IP address of the NAT IP configuration. -* `private_ip_allocation_method` - The private IP address allocation method. +* `private_ip_address_version` - The ip address version of the `ip_configuration`. * `subnet_id` - The resource ID of the subnet to be used by the service. -* `private_ip_address_version` - The ip address version of the `ip_configuration`. --- -The `private_link_endpoint_connection` block exports the following: +The `secondary_nat_ip_configuration` block exports the following: -* `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. +* `name` - The name of secondary private link service NAT IP configuration. -* `private_link_endpoint_id` - (Required) The Private Link Endpoint ID. +* `private_ip_address` - The private IP address of the NAT IP configuration. -* `private_link_endpoint_location` - (Required) The resource location of the `private_link_endpoint`. - -* `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. - -* `state_description` - (Computed) The reason for approval/rejection of the connection. - -* `state_status` - (Computed) Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. +* `private_ip_address_version` - The ip address version of the `ip_configuration`. +* `subnet_id` - The resource ID of the subnet to be used by the service. diff --git a/website/docs/d/private_link_service_endpoint_connection_status.html.markdown b/website/docs/d/private_link_service_endpoint_connection_status.html.markdown new file mode 100644 index 000000000000..9faced65a483 --- /dev/null +++ b/website/docs/d/private_link_service_endpoint_connection_status.html.markdown @@ -0,0 +1,69 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_private_link_service_endpoint_connection_status" +sidebar_current: "docs-azurerm-datasource-private-link-service-endpoint-connection-status" +description: |- + Use this data source to access endpoint connection information about an existing Private Link Service. +--- + +# Data Source: azurerm_private_link_service_endpoint_connection_status + +Use this data source to access endpoint connection information about an existing Private Link Service. + + +## Private Link Service Usage + +```hcl +data "azurerm_private_link_service_endpoint_connection_status" "example" { + name = azurerm_private_link_service.example.name + resource_group_name = azurerm_resource_group.example.name +} + +output "connection_name" { + value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.connection_name +} + +output "private_endpoint_endpoint_name" { + value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.private_endpoint_name +} + +output "private_endpoint_description" { + value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.description +} + +output "private_endpoint_status" { + value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.status +} + +output "private_endpoint_action_required" { + value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.action_required +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the private link service. + +* `resource_group_name` - (Required) The name of the resource group in which the private link service resides. + + +## Attributes Reference + +The `private_endpoint_connections` block exports the following: + +* `connection_id` - The resource id of the private link service connection between the private link service and the private link endpoint. + +* `connection_name` - The name of the connection between the private link service and the private link endpoint. + +* `private_endpoint_id` - The resource id of the private link endpoint. + +* `private_endpoint_name` - The name of the private link endpoint. + +* `action_required` - A message indicating if changes on the service provider require any updates or not. + +* `description` - The request for approval message or the reason for rejection message. + +* `status` - Indicates the state of the connection between the private link service and the private link endpoint, possible values are `Pending`, `Approved` or `Rejected`. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 36a69d0021a8..d17047f3a5cf 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -54,21 +54,27 @@ resource "azurerm_lb" "example" { } resource "azurerm_private_link_service" "example" { - name = "example-pls" - location = azurerm_resource_group.example.location + name = "myPrivateLinkService" resource_group_name = azurerm_resource_group.example.name - - nat_ip_configuration { - name = "primaryIpConfiguration" - subnet_id = azurerm_subnet.example.id - private_ip_address = "10.5.1.17" - private_ip_address_version = "IPv4" - private_ip_allocation_method = "Static" + location = azurerm_resource_group.example.location + + auto_approval_subscription_ids = ["00000000-0000-0000-0000-000000000000"] + visibility_subscription_ids = ["00000000-0000-0000-0000-000000000000"] + load_balancer_frontend_ip_configuration_ids = [azurerm_lb.example.frontend_ip_configuration.0.id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration" + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + subnet_id = azurerm_subnet.example.id } - load_balancer_frontend_ip_configuration_ids = [ - id = azurerm_lb.example.frontend_ip_configuration.0.id - ] + secondary_nat_ip_configuration { + name = "secondaryIpConfiguration" + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + subnet_id = azurerm_subnet.example.id + } } ``` @@ -84,52 +90,46 @@ The following arguments are supported: * `auto_approval_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be automatically be able to use this service. -* `nat_ip_configuration` - (Required) One or more `nat_ip_configuration` blocks as defined below. +* `visibility_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. + +* `primary_nat_ip_configuration` - (Required) A `primary_nat_ip_configuration` block as defined below. + +* `secondary_nat_ip_configuration` - (Optional) Supports upto seven additional `secondary_nat_ip_configuration` blocks as defined below. * `load_balancer_frontend_ip_configuration_ids` - (Required) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. * `private_link_endpoint_connection` - (Optional) One or more `private_link_endpoint_connection` blocks as defined below. -* `visibility_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. - * `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created. --- -The `nat_ip_configuration` block supports the following: - -* `name` - (Required) The name of private link service ip configuration. +The `primary_nat_ip_configuration` block supports the following: -* `primary` - (Optional) If the `ip_configuration` is the primary ip configuration or not. Defaults to `true`. +* `name` - (Required) The name of primary private link service NAT IP configuration. Changing this forces a new resource to be created. -* `private_ip_address` - (Optional) The private IP address of the IP configuration. - -* `private_ip_allocation_method` - (Optional) The private IP address allocation method, supported values are `Static` and `Dynamic`. Defaults to `Dynamic`. - -* `subnet_id` - (Required) The resource ID of the subnet to be used by the service. +* `private_ip_address` - (Optional) The private IP address of the NAT IP configuration. * `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, the supported value is `IPv4`. Defaults to `IPv4`. -> **NOTE:** Private Link Service Supports `IPv4` traffic only. +* `subnet_id` - (Required) The resource ID of the subnet to be used by the service. ---- - -The `private_link_endpoint_connection` block contains the following: -* `id` - (Computed) The resource ID of the `private_link_endpoint_connection`. +--- -* `name` - (Required) The name of the resource that is unique within a resource group. This name can be used to access the resource. +The `secondary_nat_ip_configuration` block supports the following: -* `private_link_endpoint_id` - (Required) The Private Link Endpoint ID. +* `name` - (Required) The name of secondary private link service NAT IP configuration. Changing this forces a new resource to be created. -* `private_link_endpoint_location` - (Required) The resource location of the `private_link_endpoint`. +* `private_ip_address` - (Optional) The private IP address of the NAT IP configuration. -* `state_action_required` - (Computed) A message indicating if changes on the service provider require any updates by the consumer. +* `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, the supported value is `IPv4`. Defaults to `IPv4`. -* `state_description` - (Computed) The reason for approval/rejection of the connection. +-> **NOTE:** Private Link Service Supports `IPv4` traffic only. -* `state_status` - (Computed) Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. +* `subnet_id` - (Required) The resource ID of the subnet to be used by the service. ## Attributes Reference @@ -140,18 +140,6 @@ The following attributes are exported: * `network_interfaces` - A list of network interface resource ids that are being used by the service. ---- - -* A `private_link_endpoint_connection` exports the following: - -* `id` - The resource ID of the `private_link_endpoint_connection`. - -* `state_action_required` - A message indicating if changes on the service provider require any updates by the consumer. - -* `state_description` - The reason for approval/rejection of the connection. - -* `state_status` - Indicates whether the connection has been `Approved`, `Rejected`, or `Removed` by the owner of the service. - ## Import From 1f68a541683e3998e08a8c5f3d3befa8cea26379 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 5 Nov 2019 17:01:52 -0800 Subject: [PATCH 29/44] Fix test and lint issues --- ...link_service_endpoint_connection_status.go | 2 +- .../data_source_private_link_service_test.go | 10 +++--- azurerm/internal/services/network/validate.go | 1 - azurerm/resource_arm_private_link_service.go | 2 +- .../resource_arm_private_link_service_test.go | 34 ++++++++----------- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/azurerm/data_source_private_link_service_endpoint_connection_status.go b/azurerm/data_source_private_link_service_endpoint_connection_status.go index 059e8298c879..258bf166a658 100644 --- a/azurerm/data_source_private_link_service_endpoint_connection_status.go +++ b/azurerm/data_source_private_link_service_endpoint_connection_status.go @@ -6,8 +6,8 @@ import ( "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" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" aznet "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource { diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index d52a5911a89e..76933bd8aa99 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -20,10 +20,12 @@ func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { { Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "2"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), + resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 2aa35867f22b..3bf2fd31ab4d 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -68,7 +68,6 @@ func ValidatePrivateLinkServiceName(i interface{}, k string) (_ []string, errors } else { if m, _ := validate.RegExHelper(i, k, `^([a-zA-Z\d])([a-zA-Z\d-\_\.]{0,78})([a-zA-Z\d\_])$`); !m { 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, underscores, periods, or hyphens", k)) - } } diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index ea528cf5f622..e8905ce043e4 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -110,7 +110,7 @@ func resourceArmPrivateLinkService() *schema.Resource { "secondary_nat_ip_configuration": { Type: schema.TypeList, - Required: true, + Optional: true, MaxItems: 7, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 9a983243c36e..38a4bc2822cd 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -24,7 +24,7 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -52,7 +52,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -61,7 +61,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_update(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -72,7 +72,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -104,15 +104,12 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "auto_approval_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.primary", "true"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_allocation_method", "Static"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.primary", "false"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -185,7 +182,7 @@ resource "azurerm_private_link_service" "test" { location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - nat_ip_configuration { + primary_nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id } @@ -206,7 +203,7 @@ resource "azurerm_private_link_service" "test" { location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - nat_ip_configuration { + primary_nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id } @@ -233,21 +230,18 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - nat_ip_configuration { + primary_nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" - private_ip_allocation_method = "Static" } - nat_ip_configuration { + secondary_nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" - private_ip_allocation_method = "Static" - primary = false } load_balancer_frontend_ip_configuration_ids = [ From ae318b6a89305a4af53f0d26028b845616d37a80 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 11 Nov 2019 18:29:31 -0800 Subject: [PATCH 30/44] Updates per PR comments --- azurerm/data_source_private_link_service.go | 6 +- ...vate_link_service_endpoint_connections.go} | 6 +- .../data_source_private_link_service_test.go | 6 +- azurerm/data_source_subnet.go | 4 +- azurerm/internal/services/network/validate.go | 6 +- azurerm/provider.go | 200 +++++----- azurerm/resource_arm_private_link_service.go | 10 +- .../resource_arm_private_link_service_test.go | 367 +++++++++++++++++- azurerm/resource_arm_subnet.go | 6 +- website/azurerm.erb | 2 +- .../docs/d/private_link_service.html.markdown | 12 +- ...ervice_endpoint_connections.html.markdown} | 28 +- website/docs/d/subnet.html.markdown | 2 +- .../docs/r/private_link_service.html.markdown | 10 +- website/docs/r/subnet.html.markdown | 4 +- 15 files changed, 503 insertions(+), 166 deletions(-) rename azurerm/{data_source_private_link_service_endpoint_connection_status.go => data_source_private_link_service_endpoint_connections.go} (93%) rename website/docs/d/{private_link_service_endpoint_connection_status.html.markdown => private_link_service_endpoint_connections.html.markdown} (61%) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 431fedfee090..1674cc086498 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -76,7 +76,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "secondary_nat_ip_configuration": { + "auxillery_nat_ip_configuration": { Type: schema.TypeList, Computed: true, Elem: &schema.Resource{ @@ -172,8 +172,8 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) } - if err := d.Set("secondary_nat_ip_configuration", secondaryIpConfig); err != nil { - return fmt.Errorf("Error setting `secondary_nat_ip_configuration`: %+v", err) + if err := d.Set("auxillery_nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `auxillery_nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { diff --git a/azurerm/data_source_private_link_service_endpoint_connection_status.go b/azurerm/data_source_private_link_service_endpoint_connections.go similarity index 93% rename from azurerm/data_source_private_link_service_endpoint_connection_status.go rename to azurerm/data_source_private_link_service_endpoint_connections.go index 258bf166a658..fa06f0fdff18 100644 --- a/azurerm/data_source_private_link_service_endpoint_connection_status.go +++ b/azurerm/data_source_private_link_service_endpoint_connections.go @@ -10,9 +10,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource { +func dataSourceArmPrivateLinkServiceEndpointConnections() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead, + Read: dataSourceArmPrivateLinkServiceEndpointConnectionsRead, Schema: map[string]*schema.Schema{ "name": { @@ -65,7 +65,7 @@ func dataSourceArmPrivateLinkServiceEndpointConnectionStatus() *schema.Resource } } -func dataSourceArmPrivateLinkServiceEndpointConnectionStatusRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceArmPrivateLinkServiceEndpointConnectionsRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Network.PrivateLinkServiceClient ctx := meta.(*ArmClient).StopContext diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 76933bd8aa99..dd88d7a5db0f 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -21,11 +21,11 @@ func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(dataSourceName, "secondary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index 7722ac47b120..31005dcc28ed 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -64,7 +64,7 @@ func dataSourceArmSubnet() *schema.Resource { }, }, - "disable_private_link_service_network_policies": { + "disable_network_policy_enforcement": { Type: schema.TypeBool, Computed: true, }, @@ -98,7 +98,7 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - d.Set("disable_private_link_service_network_policies", *p == "Disabled") + d.Set("disable_network_policy_enforcement", *p == "Disabled") } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 3bf2fd31ab4d..1cf1b39ad8cb 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -16,7 +16,7 @@ func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) - secondaryIpConfigurations := d.Get("secondary_nat_ip_configuration").([]interface{}) + secondaryIpConfigurations := d.Get("auxillery_nat_ip_configuration").([]interface{}) for i, item := range primaryIpConfiguration { v := item.(map[string]interface{}) @@ -33,13 +33,13 @@ func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { for i, item := range secondaryIpConfigurations { v := item.(map[string]interface{}) - p := fmt.Sprintf("secondary_nat_ip_configuration.%d.private_ip_address", i) + p := fmt.Sprintf("auxillery_nat_ip_configuration.%d.private_ip_address", i) in := v["name"].(string) if d.HasChange(p) { o, n := d.GetChange(p) if o != "" && n == "" { - return fmt.Errorf("Private Link Service %q (Resource Group %q) secondary_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + return fmt.Errorf("Private Link Service %q (Resource Group %q) auxillery_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) } } } diff --git a/azurerm/provider.go b/azurerm/provider.go index efc90062998c..6785d5388be5 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -52,106 +52,106 @@ func Provider() terraform.ResourceProvider { } dataSources := map[string]*schema.Resource{ - "azurerm_api_management": dataSourceApiManagementService(), - "azurerm_api_management_api": dataSourceApiManagementApi(), - "azurerm_api_management_group": dataSourceApiManagementGroup(), - "azurerm_api_management_product": dataSourceApiManagementProduct(), - "azurerm_api_management_user": dataSourceArmApiManagementUser(), - "azurerm_app_service_plan": dataSourceAppServicePlan(), - "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), - "azurerm_app_service": dataSourceArmAppService(), - "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), - "azurerm_application_insights": dataSourceArmApplicationInsights(), - "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), - "azurerm_automation_account": dataSourceArmAutomationAccount(), - "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), - "azurerm_availability_set": dataSourceArmAvailabilitySet(), - "azurerm_azuread_application": dataSourceArmAzureADApplication(), - "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), - "azurerm_batch_account": dataSourceArmBatchAccount(), - "azurerm_batch_certificate": dataSourceArmBatchCertificate(), - "azurerm_batch_pool": dataSourceArmBatchPool(), - "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), - "azurerm_cdn_profile": dataSourceArmCdnProfile(), - "azurerm_client_config": dataSourceArmClientConfig(), - "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), - "azurerm_container_registry": dataSourceArmContainerRegistry(), - "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), - "azurerm_data_factory": dataSourceArmDataFactory(), - "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), - "azurerm_dev_test_lab": dataSourceArmDevTestLab(), - "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), - "azurerm_dns_zone": dataSourceArmDnsZone(), - "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), - "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), - "azurerm_firewall": dataSourceArmFirewall(), - "azurerm_image": dataSourceArmImage(), - "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), - "azurerm_healthcare_service": dataSourceArmHealthcareService(), - "azurerm_maps_account": dataSourceArmMapsAccount(), - "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), - "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), - "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), - "azurerm_key_vault": dataSourceArmKeyVault(), - "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), - "azurerm_lb": dataSourceArmLoadBalancer(), - "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), - "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), - "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), - "azurerm_managed_disk": dataSourceArmManagedDisk(), - "azurerm_management_group": dataSourceArmManagementGroup(), - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), - "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), - "azurerm_network_interface": dataSourceArmNetworkInterface(), - "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), - "azurerm_network_watcher": dataSourceArmNetworkWatcher(), - "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), - "azurerm_notification_hub": dataSourceNotificationHub(), - "azurerm_platform_image": dataSourceArmPlatformImage(), - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_postgresql_server": dataSourcePostgreSqlServer(), - "azurerm_private_link_service": dataSourceArmPrivateLinkService(), - "azurerm_private_link_service_endpoint_connection_status": dataSourceArmPrivateLinkServiceEndpointConnectionStatus(), - "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), - "azurerm_public_ip": dataSourceArmPublicIP(), - "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_redis_cache": dataSourceArmRedisCache(), - "azurerm_resources": dataSourceArmResources(), - "azurerm_resource_group": dataSourceArmResourceGroup(), - "azurerm_role_definition": dataSourceArmRoleDefinition(), - "azurerm_route_table": dataSourceArmRouteTable(), - "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), - "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), - "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), - "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), - "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), - "azurerm_shared_image": dataSourceArmSharedImage(), - "azurerm_snapshot": dataSourceArmSnapshot(), - "azurerm_sql_server": dataSourceSqlServer(), - "azurerm_sql_database": dataSourceSqlDatabase(), - "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), - "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), - "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), - "azurerm_storage_account": dataSourceArmStorageAccount(), - "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), - "azurerm_subnet": dataSourceArmSubnet(), - "azurerm_subscription": dataSourceArmSubscription(), - "azurerm_subscriptions": dataSourceArmSubscriptions(), - "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), - "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), - "azurerm_virtual_machine": dataSourceArmVirtualMachine(), - "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), - "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), - "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_api": dataSourceApiManagementApi(), + "azurerm_api_management_group": dataSourceApiManagementGroup(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), + "azurerm_api_management_user": dataSourceArmApiManagementUser(), + "azurerm_app_service_plan": dataSourceAppServicePlan(), + "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), + "azurerm_app_service": dataSourceArmAppService(), + "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), + "azurerm_application_insights": dataSourceArmApplicationInsights(), + "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), + "azurerm_automation_account": dataSourceArmAutomationAccount(), + "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), + "azurerm_availability_set": dataSourceArmAvailabilitySet(), + "azurerm_azuread_application": dataSourceArmAzureADApplication(), + "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), + "azurerm_batch_account": dataSourceArmBatchAccount(), + "azurerm_batch_certificate": dataSourceArmBatchCertificate(), + "azurerm_batch_pool": dataSourceArmBatchPool(), + "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), + "azurerm_cdn_profile": dataSourceArmCdnProfile(), + "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), + "azurerm_container_registry": dataSourceArmContainerRegistry(), + "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), + "azurerm_data_factory": dataSourceArmDataFactory(), + "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), + "azurerm_dev_test_lab": dataSourceArmDevTestLab(), + "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), + "azurerm_dns_zone": dataSourceArmDnsZone(), + "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), + "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), + "azurerm_firewall": dataSourceArmFirewall(), + "azurerm_image": dataSourceArmImage(), + "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), + "azurerm_healthcare_service": dataSourceArmHealthcareService(), + "azurerm_maps_account": dataSourceArmMapsAccount(), + "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), + "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), + "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), + "azurerm_key_vault": dataSourceArmKeyVault(), + "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), + "azurerm_lb": dataSourceArmLoadBalancer(), + "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), + "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), + "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), + "azurerm_managed_disk": dataSourceArmManagedDisk(), + "azurerm_management_group": dataSourceArmManagementGroup(), + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), + "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), + "azurerm_network_interface": dataSourceArmNetworkInterface(), + "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), + "azurerm_network_watcher": dataSourceArmNetworkWatcher(), + "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), + "azurerm_notification_hub": dataSourceNotificationHub(), + "azurerm_platform_image": dataSourceArmPlatformImage(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), + "azurerm_private_link_service_endpoint_connections": dataSourceArmPrivateLinkServiceEndpointConnections(), + "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), + "azurerm_public_ip": dataSourceArmPublicIP(), + "azurerm_public_ips": dataSourceArmPublicIPs(), + "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_redis_cache": dataSourceArmRedisCache(), + "azurerm_resources": dataSourceArmResources(), + "azurerm_resource_group": dataSourceArmResourceGroup(), + "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_route_table": dataSourceArmRouteTable(), + "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), + "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), + "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), + "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), + "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), + "azurerm_shared_image": dataSourceArmSharedImage(), + "azurerm_snapshot": dataSourceArmSnapshot(), + "azurerm_sql_server": dataSourceSqlServer(), + "azurerm_sql_database": dataSourceSqlDatabase(), + "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), + "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), + "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), + "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), + "azurerm_subnet": dataSourceArmSubnet(), + "azurerm_subscription": dataSourceArmSubscription(), + "azurerm_subscriptions": dataSourceArmSubscriptions(), + "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), + "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), + "azurerm_virtual_machine": dataSourceArmVirtualMachine(), + "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), + "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), + "azurerm_virtual_network": dataSourceArmVirtualNetwork(), } resources := map[string]*schema.Resource{ diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index e8905ce043e4..50d40a2e3363 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -75,13 +75,13 @@ func resourceArmPrivateLinkService() *schema.Resource { "primary_nat_ip_configuration": { Type: schema.TypeList, Required: true, + ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: aznet.ValidatePrivateLinkServiceName, }, "private_ip_address": { @@ -108,7 +108,7 @@ func resourceArmPrivateLinkService() *schema.Resource { }, }, - "secondary_nat_ip_configuration": { + "auxillery_nat_ip_configuration": { Type: schema.TypeList, Optional: true, MaxItems: 7, @@ -207,7 +207,7 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you //fqdns := d.Get("fqdns").([]interface{}) primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) - secondaryIpConfigurations := d.Get("secondary_nat_ip_configuration").([]interface{}) + secondaryIpConfigurations := d.Get("auxillery_nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) @@ -296,8 +296,8 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) } - if err := d.Set("secondary_nat_ip_configuration", secondaryIpConfig); err != nil { - return fmt.Errorf("Error setting `secondary_nat_ip_configuration`: %+v", err) + if err := d.Set("auxillery_nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `auxillery_nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 38a4bc2822cd..c57ecd709aef 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -49,7 +49,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Config: testAccAzureRMPrivateLinkService_basicIp(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), @@ -62,6 +62,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -69,7 +70,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { ), }, { - Config: testAccAzureRMPrivateLinkService_basic(ri, location), + Config: testAccAzureRMPrivateLinkService_basicIp(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), @@ -86,6 +87,81 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { }) } +func TestAccAzureRMPrivateLinkService_move(t *testing.T) { + resourceName := "azurerm_private_link_service.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPrivateLinkServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateLinkService_moveSetup(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_moveAdd(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.20"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_moveChangeOne(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.21"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_moveChangeTwo(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.20"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.21"), + ), + }, + { + Config: testAccAzureRMPrivateLinkService_moveChangeThree(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.20"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.18"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resourceName := "azurerm_private_link_service.test" ri := tf.AccRandTimeInt() @@ -105,11 +181,11 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(resourceName, "secondary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -194,6 +270,29 @@ resource "azurerm_private_link_service" "test" { `, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt) } +func testAccAzureRMPrivateLinkService_basicIp(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt) +} + func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { return fmt.Sprintf(` %s @@ -202,10 +301,64 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] primary_nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "thirdaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.19" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "fourtharyIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.20" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] + + tags = { + env = "test" + } +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkService_moveSetup(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" } load_balancer_frontend_ip_configuration_ids = [ @@ -219,6 +372,206 @@ resource "azurerm_private_link_service" "test" { `, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt) } +func testAccAzureRMPrivateLinkService_moveAdd(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "thirdaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.19" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "fourtharyIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.20" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] + + tags = { + env = "test" + } +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkService_moveChangeOne(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "thirdaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.19" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "fourtharyIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.21" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] + + tags = { + env = "test" + } +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkService_moveChangeTwo(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.20" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "thirdaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.19" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "fourtharyIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.21" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] + + tags = { + env = "test" + } +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMPrivateLinkService_moveChangeThree(rInt int, location string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_private_link_service" "test" { + name = "acctestpls-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] + visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] + + primary_nat_ip_configuration { + name = "primaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.17" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "secondaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.20" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "thirdaryIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.19" + private_ip_address_version = "IPv4" + } + + auxillery_nat_ip_configuration { + name = "fourtharyIpConfiguration-%d" + subnet_id = azurerm_subnet.test.id + private_ip_address = "10.5.1.18" + private_ip_address_version = "IPv4" + } + + load_balancer_frontend_ip_configuration_ids = [ + azurerm_lb.test.frontend_ip_configuration.0.id + ] + + tags = { + env = "test" + } +} +`, testAccAzureRMPrivateLinkServiceTemplate(rInt, location), rInt, rInt, rInt, rInt, rInt) +} + func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string { return fmt.Sprintf(` %s @@ -237,7 +590,7 @@ resource "azurerm_private_link_service" "test" { private_ip_address_version = "IPv4" } - secondary_nat_ip_configuration { + auxillery_nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" @@ -277,7 +630,7 @@ resource "azurerm_subnet" "test" { virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" - disable_private_link_service_network_policies = true + disable_network_policy_enforcement = true } resource "azurerm_public_ip" "test" { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index 5a3dcecd7c6d..9ccc60f07fea 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -139,7 +139,7 @@ func resourceArmSubnet() *schema.Resource { }, }, - "disable_private_link_service_network_policies": { + "disable_network_policy_enforcement": { Type: schema.TypeBool, Optional: true, Default: false, @@ -181,7 +181,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } - if v, ok := d.GetOk("disable_private_link_service_network_policies"); ok { + if v, ok := d.GetOk("disable_network_policy_enforcement"); ok { // This is strange logic, but to get the schema to make sense for the end user // I exposed it with the same name that the Azure CLI does to be consistent // between the tool sets, which means true == Disabled. @@ -301,7 +301,7 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { // subnet because Network policies like network security groups are not // supported by private endpoints. if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_private_link_service_network_policies", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + if err := d.Set("disable_network_policy_enforcement", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { return err } } diff --git a/website/azurerm.erb b/website/azurerm.erb index 46cb0f8f4673..0b9dbdf0c24e 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -411,7 +411,7 @@
  • - azurerm_private_link_service_endpoint_connection_status + azurerm_private_link_service_endpoint_connections
  • diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index 2d7aa1a8cc9f..fd07994b5e4a 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -15,8 +15,8 @@ Use this data source to access information about an existing Private Link Servic ```hcl data "azurerm_private_link_service" "example" { - name = "acctestpls" - resource_group_name = "acctestRG" + name = "myPrivateLinkService" + resource_group_name = "PrivateLinkServiceRG" } output "private_link_service_id" { @@ -40,7 +40,7 @@ The following attributes are exported: * `location` - Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `alias` - The alias of the private link service. +* `alias` - The alias is a globally unique name for your private link service which Azure generates for you. Your can use this alias to request a connection to your private link service. * `auto_approval_subscription_ids` - A list of subscription(s) globally unique identifiers that will be auto approved to use the private link service. @@ -48,9 +48,9 @@ The following attributes are exported: * `primary_nat_ip_configuration` - A `primary_nat_ip_configuration` block as defined below. -* `secondary_nat_ip_configuration` - `secondary_nat_ip_configuration` blocks as defined below. +* `auxillery_nat_ip_configuration` - `auxillery_nat_ip_configuration` blocks as defined below. -* `load_balancer_frontend_ip_configuration_ids` - A list of `Standard` Load Balancer resource IDs. +* `load_balancer_frontend_ip_configuration_ids` - A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. * `network_interfaces` - A list of network interface resource ids that are being used by the service. @@ -72,7 +72,7 @@ The `primary_nat_ip_configuration` block exports the following: --- -The `secondary_nat_ip_configuration` block exports the following: +The `auxillery_nat_ip_configuration` block exports the following: * `name` - The name of secondary private link service NAT IP configuration. diff --git a/website/docs/d/private_link_service_endpoint_connection_status.html.markdown b/website/docs/d/private_link_service_endpoint_connections.html.markdown similarity index 61% rename from website/docs/d/private_link_service_endpoint_connection_status.html.markdown rename to website/docs/d/private_link_service_endpoint_connections.html.markdown index 9faced65a483..b151d5e11e45 100644 --- a/website/docs/d/private_link_service_endpoint_connection_status.html.markdown +++ b/website/docs/d/private_link_service_endpoint_connections.html.markdown @@ -1,42 +1,26 @@ --- layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_private_link_service_endpoint_connection_status" -sidebar_current: "docs-azurerm-datasource-private-link-service-endpoint-connection-status" +page_title: "Azure Resource Manager: azurerm_private_link_service_endpoint_connections" +sidebar_current: "docs-azurerm-datasource-private-link-service-endpoint-connections" description: |- Use this data source to access endpoint connection information about an existing Private Link Service. --- -# Data Source: azurerm_private_link_service_endpoint_connection_status +# Data Source: azurerm_private_link_service_endpoint_connections Use this data source to access endpoint connection information about an existing Private Link Service. -## Private Link Service Usage +## Private Link Service Endpoint Connections Usage ```hcl -data "azurerm_private_link_service_endpoint_connection_status" "example" { +data "azurerm_private_link_service_endpoint_connections" "example" { name = azurerm_private_link_service.example.name resource_group_name = azurerm_resource_group.example.name } -output "connection_name" { - value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.connection_name -} - -output "private_endpoint_endpoint_name" { - value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.private_endpoint_name -} - -output "private_endpoint_description" { - value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.description -} - output "private_endpoint_status" { - value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.status -} - -output "private_endpoint_action_required" { - value = data.azurerm_private_link_service_endpoint_connection_status.example.private_endpoint_connections.0.action_required + value = data.azurerm_private_link_service_endpoint_connections.example.private_endpoint_connections.0.status } ``` diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 60976ff08866..59ca42d1a0b0 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -34,7 +34,7 @@ output "subnet_id" { * `id` - The ID of the Subnet. * `address_prefix` - The address prefix used for the subnet. -* `disable_private_link_service_network_policies` - Enable or Disable network policies on private link service in the subnet. +* `disable_network_policy_enforcement` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. * `ip_configurations` - The collection of IP Configurations with IPs within this subnet. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index d17047f3a5cf..4a356fe2d91b 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -69,7 +69,7 @@ resource "azurerm_private_link_service" "example" { subnet_id = azurerm_subnet.example.id } - secondary_nat_ip_configuration { + auxillery_nat_ip_configuration { name = "secondaryIpConfiguration" private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" @@ -94,9 +94,9 @@ The following arguments are supported: * `primary_nat_ip_configuration` - (Required) A `primary_nat_ip_configuration` block as defined below. -* `secondary_nat_ip_configuration` - (Optional) Supports upto seven additional `secondary_nat_ip_configuration` blocks as defined below. +* `auxillery_nat_ip_configuration` - (Optional) Supports upto seven additional `auxillery_nat_ip_configuration` blocks as defined below. -* `load_balancer_frontend_ip_configuration_ids` - (Required) A list of `Standard` Load Balancer resource ids to direct the service network traffic toward. +* `load_balancer_frontend_ip_configuration_ids` - (Required) A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. * `private_link_endpoint_connection` - (Optional) One or more `private_link_endpoint_connection` blocks as defined below. @@ -119,7 +119,7 @@ The `primary_nat_ip_configuration` block supports the following: --- -The `secondary_nat_ip_configuration` block supports the following: +The `auxillery_nat_ip_configuration` block supports the following: * `name` - (Required) The name of secondary private link service NAT IP configuration. Changing this forces a new resource to be created. @@ -136,7 +136,7 @@ The `secondary_nat_ip_configuration` block supports the following: The following attributes are exported: -* `alias` - The alias of the private link service. +* `alias` - The alias is a globally unique name for your private link service which Azure generates for you. Your can use this alias to request a connection to your private link service. * `network_interfaces` - A list of network interface resource ids that are being used by the service. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 17d2214bee9e..0b5a2b448fda 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,9 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `disable_private_link_service_network_policies` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. +* `disable_network_policy_enforcement` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. --> **NOTE:** In order to choose a source IP address for your `private link service`, an explicit disable setting is required on the subnet(e.g. `disable_private_link_service_network_policies` = `True`). This setting is only applicable for the specific private IP address that you chose as the source IP of the `private link service`. For other resources in the subnet, access is controlled based on the Network Security Groups(NSG) rule definitions. +-> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `disable_network_policy_enforcement` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From 2526235073bbaeda3c6ad351565166bebab0df02 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 11 Nov 2019 19:11:50 -0800 Subject: [PATCH 31/44] Add subbcategory to docs --- website/docs/d/private_link_service.html.markdown | 1 + .../d/private_link_service_endpoint_connections.html.markdown | 1 + website/docs/r/private_link_service.html.markdown | 1 + 3 files changed, 3 insertions(+) diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index fd07994b5e4a..4e61b79937e2 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -1,4 +1,5 @@ --- +subcategory: "" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-datasource-private-link-service" diff --git a/website/docs/d/private_link_service_endpoint_connections.html.markdown b/website/docs/d/private_link_service_endpoint_connections.html.markdown index b151d5e11e45..e4f62be9a06e 100644 --- a/website/docs/d/private_link_service_endpoint_connections.html.markdown +++ b/website/docs/d/private_link_service_endpoint_connections.html.markdown @@ -1,4 +1,5 @@ --- +subcategory: "" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service_endpoint_connections" sidebar_current: "docs-azurerm-datasource-private-link-service-endpoint-connections" diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 4a356fe2d91b..a38a7785421d 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -1,4 +1,5 @@ --- +subcategory: "" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_private_link_service" sidebar_current: "docs-azurerm-resource-private-link-service" From 94e12d107ebe83d5adc2b50d6c885d09e4e56c14 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 11 Nov 2019 20:17:07 -0800 Subject: [PATCH 32/44] Updated name of policy enforcement --- azurerm/data_source_subnet.go | 4 ++-- azurerm/resource_arm_private_link_service_test.go | 2 +- azurerm/resource_arm_subnet.go | 10 ++++------ website/docs/d/subnet.html.markdown | 2 +- website/docs/r/subnet.html.markdown | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index 31005dcc28ed..178ac548efcf 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -64,7 +64,7 @@ func dataSourceArmSubnet() *schema.Resource { }, }, - "disable_network_policy_enforcement": { + "disable_private_link_service_network_policy_enforcement": { Type: schema.TypeBool, Computed: true, }, @@ -98,7 +98,7 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - d.Set("disable_network_policy_enforcement", *p == "Disabled") + d.Set("disable_private_link_service_network_policy_enforcement", *p == "Disabled") } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index c57ecd709aef..628a02b30736 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -630,7 +630,7 @@ resource "azurerm_subnet" "test" { virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" - disable_network_policy_enforcement = true + disable_private_link_service_network_policy_enforcement = true } resource "azurerm_public_ip" "test" { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index 9ccc60f07fea..df51d6a6f094 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -139,7 +139,7 @@ func resourceArmSubnet() *schema.Resource { }, }, - "disable_network_policy_enforcement": { + "disable_private_link_service_network_policy_enforcement": { Type: schema.TypeBool, Optional: true, Default: false, @@ -181,7 +181,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } - if v, ok := d.GetOk("disable_network_policy_enforcement"); ok { + if v, ok := d.GetOk("disable_private_link_service_network_policy_enforcement"); ok { // This is strange logic, but to get the schema to make sense for the end user // I exposed it with the same name that the Azure CLI does to be consistent // between the tool sets, which means true == Disabled. @@ -189,11 +189,9 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err // To enable private endpoints you must disable the network policies for the // subnet because Network policies like network security groups are not // supported by private endpoints. - p := "Enabled" if v.(bool) { - p = "Disabled" + properties.PrivateLinkServiceNetworkPolicies = utils.String("Disabled") } - properties.PrivateLinkServiceNetworkPolicies = &p } if v, ok := d.GetOk("network_security_group_id"); ok { @@ -301,7 +299,7 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { // subnet because Network policies like network security groups are not // supported by private endpoints. if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_network_policy_enforcement", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { + if err := d.Set("disable_private_link_service_network_policy_enforcement", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { return err } } diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 59ca42d1a0b0..8cb00dd2aff2 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -34,7 +34,7 @@ output "subnet_id" { * `id` - The ID of the Subnet. * `address_prefix` - The address prefix used for the subnet. -* `disable_network_policy_enforcement` - Enable or Disable network policies on private link service in the subnet. +* `disable_private_link_service_network_policy_enforcement` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. * `ip_configurations` - The collection of IP Configurations with IPs within this subnet. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 0b5a2b448fda..2ded7a7004ad 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,9 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `disable_network_policy_enforcement` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. +* `disable_private_link_service_network_policy_enforcement` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. --> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `disable_network_policy_enforcement` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. +-> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `disable_private_link_service_network_policy_enforcement` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From 627cf8429be4ef85d2bf2dc4038e7f5c52032cbe Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 11 Nov 2019 23:30:54 -0800 Subject: [PATCH 33/44] Fix docs and example --- examples/virtual-networks/private-link-service/main.tf | 4 +--- examples/virtual-networks/private-link-service/variables.tf | 4 ++-- website/docs/r/subnet.html.markdown | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/virtual-networks/private-link-service/main.tf b/examples/virtual-networks/private-link-service/main.tf index 2d6483b29038..0a5ab82cd514 100644 --- a/examples/virtual-networks/private-link-service/main.tf +++ b/examples/virtual-networks/private-link-service/main.tf @@ -42,13 +42,11 @@ resource "azurerm_private_link_service" "test" { name = "acctestpls" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - fqdns = ["testFqdns2"] - nat_ip_configuration { + primary_nat_ip_configuration { name = azurerm_public_ip.test.name subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" - private_ip_allocation_method = "Static" } load_balancer_frontend_ip_configuration_ids = [ diff --git a/examples/virtual-networks/private-link-service/variables.tf b/examples/virtual-networks/private-link-service/variables.tf index 032a322f8e43..9a3398bc66d8 100644 --- a/examples/virtual-networks/private-link-service/variables.tf +++ b/examples/virtual-networks/private-link-service/variables.tf @@ -1,9 +1,9 @@ variable "resource_group_name" { description = "The name of the resource group the Private Link Service is located in." - default = ["example-private-link-service"] + default = "example-private-link-service" } variable "location" { description = "The Azure location where all resources in this example should be created." - default = ["WestUS"] + default = "WestUS" } diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 2ded7a7004ad..df9044894830 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -103,7 +103,7 @@ The following attributes are exported: * `resource_group_name` - The name of the resource group in which the subnet is created in. * `virtual_network_name` - The name of the virtual network in which the subnet is created in * `address_prefix` - The address prefix for the subnet -* `private_link_service_network_policies` - Enable or Disable apply network policies on private link service in the subnet. + ## Import From 315128fe393515bdad7126782614ae7984b584f3 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 13 Nov 2019 07:52:19 +0800 Subject: [PATCH 34/44] in progress --- azurerm/data_source_private_link_service.go | 12 +- .../data_source_private_link_service_test.go | 12 +- azurerm/data_source_subnet.go | 5 +- azurerm/internal/services/network/validate.go | 12 +- azurerm/resource_arm_private_link_service.go | 71 ++++------ .../resource_arm_private_link_service_test.go | 123 +++++++++--------- azurerm/resource_arm_subnet.go | 11 +- .../private-link-service/main.tf | 2 +- .../docs/d/private_link_service.html.markdown | 8 +- website/docs/d/subnet.html.markdown | 2 +- .../docs/r/private_link_service.html.markdown | 12 +- website/docs/r/subnet.html.markdown | 4 +- 12 files changed, 126 insertions(+), 148 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 1674cc086498..c700c2c02af5 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -50,7 +50,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { // }, // }, - "primary_nat_ip_configuration": { + "nat_ip_configuration": { Type: schema.TypeList, Computed: true, MaxItems: 1, @@ -76,7 +76,7 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, }, - "auxillery_nat_ip_configuration": { + "nat_ip_configuration": { Type: schema.TypeList, Computed: true, Elem: &schema.Resource{ @@ -169,11 +169,11 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ // } if props.IPConfigurations != nil { primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) - if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { - return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) + if err := d.Set("nat_ip_configuration", primaryIpConfig); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if err := d.Set("auxillery_nat_ip_configuration", secondaryIpConfig); err != nil { - return fmt.Errorf("Error setting `auxillery_nat_ip_configuration`: %+v", err) + if err := d.Set("nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index dd88d7a5db0f..e772a64d424e 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -20,12 +20,12 @@ func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { { Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(dataSourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(dataSourceName, "auxillery_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index 178ac548efcf..c7ebc1002852 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -2,6 +2,7 @@ package azurerm import ( "fmt" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -64,7 +65,7 @@ func dataSourceArmSubnet() *schema.Resource { }, }, - "disable_private_link_service_network_policy_enforcement": { + "enforce_private_link_network_policies": { Type: schema.TypeBool, Computed: true, }, @@ -98,7 +99,7 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - d.Set("disable_private_link_service_network_policy_enforcement", *p == "Disabled") + d.Set("enforce_private_link_network_policies", strings.EqualsFold("Disabled", *p)) } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 1cf1b39ad8cb..8b5a1ffe4dd2 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -15,31 +15,31 @@ import ( func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) - secondaryIpConfigurations := d.Get("auxillery_nat_ip_configuration").([]interface{}) + primaryIpConfiguration := d.Get("nat_ip_configuration").([]interface{}) + secondaryIpConfigurations := d.Get("nat_ip_configuration").([]interface{}) for i, item := range primaryIpConfiguration { v := item.(map[string]interface{}) - p := fmt.Sprintf("primary_nat_ip_configuration.%d.private_ip_address", i) + p := fmt.Sprintf("nat_ip_configuration.%d.private_ip_address", i) in := v["name"].(string) if d.HasChange(p) { o, n := d.GetChange(p) if o != "" && n == "" { - return fmt.Errorf("Private Link Service %q (Resource Group %q) primary_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + return fmt.Errorf("Private Link Service %q (Resource Group %q) nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) } } } for i, item := range secondaryIpConfigurations { v := item.(map[string]interface{}) - p := fmt.Sprintf("auxillery_nat_ip_configuration.%d.private_ip_address", i) + p := fmt.Sprintf("nat_ip_configuration.%d.private_ip_address", i) in := v["name"].(string) if d.HasChange(p) { o, n := d.GetChange(p) if o != "" && n == "" { - return fmt.Errorf("Private Link Service %q (Resource Group %q) auxillery_nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + return fmt.Errorf("Private Link Service %q (Resource Group %q) nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) } } } diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 50d40a2e3363..55278f72d401 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "time" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -14,6 +15,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" 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/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -28,6 +30,13 @@ func resourceArmPrivateLinkService() *schema.Resource { State: schema.ImportStatePassthrough, }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -68,50 +77,17 @@ func resourceArmPrivateLinkService() *schema.Resource { // }, // }, + // TODO: Open bug on this API for this // Required by the API you can't create the resource without at least one ip configuration // I had to split the schema because if you attempt to change the primary attribute it // succeeds but doesn't change the attribute. Once primary is set it is set forever unless // you destroy the resource and recreate it. - "primary_nat_ip_configuration": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: aznet.ValidatePrivateLinkServiceName, - }, - "private_ip_address": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.IPv4Address, - }, - // Only IPv4 is supported by the API, but I am exposing this - // as they will support IPv6 in a future release. - "private_ip_address_version": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - string(network.IPv4), - }, false), - Default: string(network.IPv4), - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - }, - }, - }, - "auxillery_nat_ip_configuration": { + //TODO: Add custom diff to detect changes to primary config and force new on any changes + "nat_ip_configuration": { Type: schema.TypeList, - Optional: true, - MaxItems: 7, + Required: true, + MaxItems: 8, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -140,6 +116,11 @@ func resourceArmPrivateLinkService() *schema.Resource { Required: true, ValidateFunc: azure.ValidateResourceID, }, + "primary": { + Type: schema.TypeBool, + Required: true, + Default: false, + }, }, }, }, @@ -206,9 +187,9 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte autoApproval := d.Get("auto_approval_subscription_ids").([]interface{}) // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you //fqdns := d.Get("fqdns").([]interface{}) - primaryIpConfiguration := d.Get("primary_nat_ip_configuration").([]interface{}) - secondaryIpConfigurations := d.Get("auxillery_nat_ip_configuration").([]interface{}) + primaryIpConfiguration := d.Get("nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) + primary := d.Ge visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) @@ -221,7 +202,7 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte Visibility: &network.PrivateLinkServicePropertiesVisibility{ Subscriptions: utils.ExpandStringSlice(visibility), }, - IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(primaryIpConfiguration, secondaryIpConfigurations), + IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(primaryIpConfiguration), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), //Fqdns: utils.ExpandStringSlice(fqdns), }, @@ -293,11 +274,11 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // } if props.IPConfigurations != nil { primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) - if err := d.Set("primary_nat_ip_configuration", primaryIpConfig); err != nil { - return fmt.Errorf("Error setting `primary_nat_ip_configuration`: %+v", err) + if err := d.Set("nat_ip_configuration", primaryIpConfig); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if err := d.Set("auxillery_nat_ip_configuration", secondaryIpConfig); err != nil { - return fmt.Errorf("Error setting `auxillery_nat_ip_configuration`: %+v", err) + if err := d.Set("nat_ip_configuration", secondaryIpConfig); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } } if props.LoadBalancerFrontendIPConfigurations != nil { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 628a02b30736..cf274e13fddf 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -24,7 +24,7 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -52,7 +52,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basicIp(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -61,8 +61,8 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_update(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.primary", "true"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -73,7 +73,7 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basicIp(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), @@ -101,56 +101,54 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { Config: testAccAzureRMPrivateLinkService_moveSetup(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), ), }, { Config: testAccAzureRMPrivateLinkService_moveAdd(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.20"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.20"), ), }, { Config: testAccAzureRMPrivateLinkService_moveChangeOne(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.21"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.21"), ), }, { Config: testAccAzureRMPrivateLinkService_moveChangeTwo(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.20"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.21"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.20"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.21"), ), }, { Config: testAccAzureRMPrivateLinkService_moveChangeThree(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "3"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.20"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.1.private_ip_address", "10.5.1.19"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.2.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "3"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.20"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.18"), ), }, { @@ -180,12 +178,11 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "auto_approval_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "primary_nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(resourceName, "auxillery_nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -258,7 +255,7 @@ resource "azurerm_private_link_service" "test" { location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id } @@ -279,7 +276,7 @@ resource "azurerm_private_link_service" "test" { location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" @@ -304,28 +301,28 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" @@ -354,7 +351,7 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" @@ -383,28 +380,28 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" @@ -433,28 +430,28 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.21" @@ -483,28 +480,28 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.21" @@ -533,28 +530,28 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" @@ -583,14 +580,14 @@ resource "azurerm_private_link_service" "test" { auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] visibility_subscription_ids = [data.azurerm_subscription.current.subscription_id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" @@ -630,7 +627,7 @@ resource "azurerm_subnet" "test" { virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" - disable_private_link_service_network_policy_enforcement = true + enforce_private_link_network_policies = true } resource "azurerm_public_ip" "test" { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index df51d6a6f094..579d453380fe 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" @@ -139,7 +140,7 @@ func resourceArmSubnet() *schema.Resource { }, }, - "disable_private_link_service_network_policy_enforcement": { + "enforce_private_link_network_policies": { Type: schema.TypeBool, Optional: true, Default: false, @@ -181,7 +182,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } - if v, ok := d.GetOk("disable_private_link_service_network_policy_enforcement"); ok { + if v, ok := d.GetOk("enforce_private_link_network_policies"); ok { // This is strange logic, but to get the schema to make sense for the end user // I exposed it with the same name that the Azure CLI does to be consistent // between the tool sets, which means true == Disabled. @@ -298,10 +299,8 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { // To enable private endpoints you must disable the network policies for the // subnet because Network policies like network security groups are not // supported by private endpoints. - if privateLinkServiceNetworkPolicies := props.PrivateLinkServiceNetworkPolicies; privateLinkServiceNetworkPolicies != nil { - if err := d.Set("disable_private_link_service_network_policy_enforcement", *privateLinkServiceNetworkPolicies == "Disabled"); err != nil { - return err - } + if p := props.PrivateLinkServiceNetworkPolicies; p != nil { + d.Set("enforce_private_link_network_policies", strings.EqualsFold("Disabled", *p)) } var securityGroupId *string diff --git a/examples/virtual-networks/private-link-service/main.tf b/examples/virtual-networks/private-link-service/main.tf index 0a5ab82cd514..9aed70b3a642 100644 --- a/examples/virtual-networks/private-link-service/main.tf +++ b/examples/virtual-networks/private-link-service/main.tf @@ -43,7 +43,7 @@ resource "azurerm_private_link_service" "test" { location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - primary_nat_ip_configuration { + nat_ip_configuration { name = azurerm_public_ip.test.name subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index 4e61b79937e2..cfc487a9fa20 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -47,9 +47,9 @@ The following attributes are exported: * `visibility_subscription_ids` - A list of subscription(s) globally unique identifiers(GUID) that will be able to see the private link service. -* `primary_nat_ip_configuration` - A `primary_nat_ip_configuration` block as defined below. +* `nat_ip_configuration` - A `nat_ip_configuration` block as defined below. -* `auxillery_nat_ip_configuration` - `auxillery_nat_ip_configuration` blocks as defined below. +* `nat_ip_configuration` - `nat_ip_configuration` blocks as defined below. * `load_balancer_frontend_ip_configuration_ids` - A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. @@ -60,7 +60,7 @@ The following attributes are exported: --- -The `primary_nat_ip_configuration` block exports the following: +The `nat_ip_configuration` block exports the following: * `name` - The name of primary private link service NAT IP configuration. @@ -73,7 +73,7 @@ The `primary_nat_ip_configuration` block exports the following: --- -The `auxillery_nat_ip_configuration` block exports the following: +The `nat_ip_configuration` block exports the following: * `name` - The name of secondary private link service NAT IP configuration. diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 8cb00dd2aff2..497570d85d21 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -34,7 +34,7 @@ output "subnet_id" { * `id` - The ID of the Subnet. * `address_prefix` - The address prefix used for the subnet. -* `disable_private_link_service_network_policy_enforcement` - Enable or Disable network policies on private link service in the subnet. +* `enforce_private_link_network_policies` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. * `ip_configurations` - The collection of IP Configurations with IPs within this subnet. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index a38a7785421d..23743e9d7106 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -63,14 +63,14 @@ resource "azurerm_private_link_service" "example" { visibility_subscription_ids = ["00000000-0000-0000-0000-000000000000"] load_balancer_frontend_ip_configuration_ids = [azurerm_lb.example.frontend_ip_configuration.0.id] - primary_nat_ip_configuration { + nat_ip_configuration { name = "primaryIpConfiguration" private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" subnet_id = azurerm_subnet.example.id } - auxillery_nat_ip_configuration { + nat_ip_configuration { name = "secondaryIpConfiguration" private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" @@ -93,9 +93,9 @@ The following arguments are supported: * `visibility_subscription_ids` - (Optional) A list of subscription globally unique identifiers(GUID) that will be able to see this service. If left undefined all Azure subscriptions will be able to see this service. -* `primary_nat_ip_configuration` - (Required) A `primary_nat_ip_configuration` block as defined below. +* `nat_ip_configuration` - (Required) A `nat_ip_configuration` block as defined below. -* `auxillery_nat_ip_configuration` - (Optional) Supports upto seven additional `auxillery_nat_ip_configuration` blocks as defined below. +* `nat_ip_configuration` - (Optional) Supports upto seven additional `nat_ip_configuration` blocks as defined below. * `load_balancer_frontend_ip_configuration_ids` - (Required) A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. @@ -105,7 +105,7 @@ The following arguments are supported: --- -The `primary_nat_ip_configuration` block supports the following: +The `nat_ip_configuration` block supports the following: * `name` - (Required) The name of primary private link service NAT IP configuration. Changing this forces a new resource to be created. @@ -120,7 +120,7 @@ The `primary_nat_ip_configuration` block supports the following: --- -The `auxillery_nat_ip_configuration` block supports the following: +The `nat_ip_configuration` block supports the following: * `name` - (Required) The name of secondary private link service NAT IP configuration. Changing this forces a new resource to be created. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index df9044894830..c0d93a6c0767 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,9 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `disable_private_link_service_network_policy_enforcement` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. +* `enforce_private_link_network_policies` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. --> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `disable_private_link_service_network_policy_enforcement` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. +-> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `enforce_private_link_network_policies` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From d85ba9a49e24e69a5a16074956d13c61f1fd73cf Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 14 Nov 2019 13:20:16 +0800 Subject: [PATCH 35/44] Updates per Tom PR comment and test --- azurerm/data_source_private_link_service.go | 31 +----- azurerm/data_source_subnet.go | 4 +- azurerm/resource_arm_private_link_service.go | 95 +++++-------------- .../resource_arm_private_link_service_test.go | 31 +++++- azurerm/resource_arm_subnet.go | 6 +- .../docs/d/private_link_service.html.markdown | 16 +--- website/docs/d/subnet.html.markdown | 2 +- .../docs/r/private_link_service.html.markdown | 31 ++---- website/docs/r/subnet.html.markdown | 4 +- 9 files changed, 70 insertions(+), 150 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index c700c2c02af5..7b72d9c2093e 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -72,29 +72,8 @@ func dataSourceArmPrivateLinkService() *schema.Resource { Type: schema.TypeString, Computed: true, }, - }, - }, - }, - - "nat_ip_configuration": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - }, - "private_ip_address": { - Type: schema.TypeString, - Computed: true, - }, - "private_ip_address_version": { - Type: schema.TypeString, - Computed: true, - }, - "subnet_id": { - Type: schema.TypeString, + "primary": { + Type: schema.TypeBool, Computed: true, }, }, @@ -168,11 +147,7 @@ func dataSourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{ // } // } if props.IPConfigurations != nil { - primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) - if err := d.Set("nat_ip_configuration", primaryIpConfig); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) - } - if err := d.Set("nat_ip_configuration", secondaryIpConfig); err != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } } diff --git a/azurerm/data_source_subnet.go b/azurerm/data_source_subnet.go index c7ebc1002852..234a48ff94bd 100644 --- a/azurerm/data_source_subnet.go +++ b/azurerm/data_source_subnet.go @@ -65,7 +65,7 @@ func dataSourceArmSubnet() *schema.Resource { }, }, - "enforce_private_link_network_policies": { + "enforce_private_link_service_network_policies": { Type: schema.TypeBool, Computed: true, }, @@ -99,7 +99,7 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - d.Set("enforce_private_link_network_policies", strings.EqualsFold("Disabled", *p)) + d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *p)) } if props.NetworkSecurityGroup != nil { diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 55278f72d401..5131a7ea8874 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "time" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -15,7 +14,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" 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/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -30,13 +28,6 @@ func resourceArmPrivateLinkService() *schema.Resource { State: schema.ImportStatePassthrough, }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -77,10 +68,8 @@ func resourceArmPrivateLinkService() *schema.Resource { // }, // }, - // TODO: Open bug on this API for this - // Required by the API you can't create the resource without at least one ip configuration - // I had to split the schema because if you attempt to change the primary attribute it - // succeeds but doesn't change the attribute. Once primary is set it is set forever unless + // Required by the API you can't create the resource without at least + // one ip configuration once primary is set it is set forever unless // you destroy the resource and recreate it. //TODO: Add custom diff to detect changes to primary config and force new on any changes @@ -119,14 +108,14 @@ func resourceArmPrivateLinkService() *schema.Resource { "primary": { Type: schema.TypeBool, Required: true, - Default: false, + ForceNew: true, }, }, }, }, - // private_endpoint_connections have been removed but maybe useful for the end user to - // understand the state of endpoints connected to this service, create a datasource? + // private_endpoint_connections have been removed and placed inside the + // azurerm_private_link_service_endpoint_connections datasource. // Required by the API you can't create the resource without at least one load balancer id "load_balancer_frontend_ip_configuration_ids": { @@ -189,7 +178,6 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte //fqdns := d.Get("fqdns").([]interface{}) primaryIpConfiguration := d.Get("nat_ip_configuration").([]interface{}) loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) - primary := d.Ge visibility := d.Get("visibility_subscription_ids").([]interface{}) t := d.Get("tags").(map[string]interface{}) @@ -273,11 +261,7 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // } // } if props.IPConfigurations != nil { - primaryIpConfig, secondaryIpConfig := flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations) - if err := d.Set("nat_ip_configuration", primaryIpConfig); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) - } - if err := d.Set("nat_ip_configuration", secondaryIpConfig); err != nil { + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } } @@ -324,19 +308,20 @@ func resourceArmPrivateLinkServiceDelete(d *schema.ResourceData, meta interface{ return nil } -func expandArmPrivateLinkServiceIPConfiguration(primaryInput []interface{}, secondaryInput []interface{}) *[]network.PrivateLinkServiceIPConfiguration { - if len(primaryInput) == 0 { +func expandArmPrivateLinkServiceIPConfiguration(input []interface{}) *[]network.PrivateLinkServiceIPConfiguration { + if len(input) == 0 { return nil } results := make([]network.PrivateLinkServiceIPConfiguration, 0) - for _, item := range primaryInput { + for _, item := range input { v := item.(map[string]interface{}) privateIpAddress := v["private_ip_address"].(string) subnetId := v["subnet_id"].(string) privateIpAddressVersion := v["private_ip_address_version"].(string) name := v["name"].(string) + primary := v["primary"].(bool) result := network.PrivateLinkServiceIPConfiguration{ Name: utils.String(name), @@ -346,7 +331,7 @@ func expandArmPrivateLinkServiceIPConfiguration(primaryInput []interface{}, seco Subnet: &network.Subnet{ ID: utils.String(subnetId), }, - Primary: utils.Bool(true), + Primary: utils.Bool(primary), }, } @@ -359,36 +344,6 @@ func expandArmPrivateLinkServiceIPConfiguration(primaryInput []interface{}, seco results = append(results, result) } - if len(secondaryInput) != 0 { - for _, item := range secondaryInput { - v := item.(map[string]interface{}) - privateIpAddress := v["private_ip_address"].(string) - subnetId := v["subnet_id"].(string) - privateIpAddressVersion := v["private_ip_address_version"].(string) - name := v["name"].(string) - - result := network.PrivateLinkServiceIPConfiguration{ - Name: utils.String(name), - PrivateLinkServiceIPConfigurationProperties: &network.PrivateLinkServiceIPConfigurationProperties{ - PrivateIPAddress: utils.String(privateIpAddress), - PrivateIPAddressVersion: network.IPVersion(privateIpAddressVersion), - Subnet: &network.Subnet{ - ID: utils.String(subnetId), - }, - Primary: utils.Bool(false), - }, - } - - if privateIpAddress != "" { - result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Static") - } else { - result.PrivateLinkServiceIPConfigurationProperties.PrivateIPAllocationMethod = network.IPAllocationMethod("Dynamic") - } - - results = append(results, result) - } - } - return &results } @@ -410,43 +365,37 @@ func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[] return &results } -func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) ([]interface{}, []interface{}) { - primaryResults := make([]interface{}, 0) - secondaryResults := make([]interface{}, 0) - primary := false +func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkServiceIPConfiguration) []interface{} { + results := make([]interface{}, 0) if input == nil { - return primaryResults, secondaryResults + return results } for _, item := range *input { - b := make(map[string]interface{}) + c := make(map[string]interface{}) if name := item.Name; name != nil { - b["name"] = *name + c["name"] = *name } if props := item.PrivateLinkServiceIPConfigurationProperties; props != nil { if v := props.PrivateIPAddress; v != nil { - b["private_ip_address"] = *v + c["private_ip_address"] = *v } - b["private_ip_address_version"] = string(props.PrivateIPAddressVersion) + c["private_ip_address_version"] = string(props.PrivateIPAddressVersion) if v := props.Subnet; v != nil { if i := v.ID; i != nil { - b["subnet_id"] = *i + c["subnet_id"] = *i } } if v := props.Primary; v != nil { - primary = *v + c["primary"] = *v } } - if primary { - primaryResults = append(primaryResults, b) - } else { - secondaryResults = append(secondaryResults, b) - } + results = append(results, c) } - return primaryResults, secondaryResults + return results } func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []string { diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index cf274e13fddf..b7dcffea9c96 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -133,7 +133,6 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "3"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.20"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.21"), @@ -143,9 +142,8 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { Config: testAccAzureRMPrivateLinkService_moveChangeThree(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "3"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.20"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.2.private_ip_address", "10.5.1.19"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.18"), @@ -258,6 +256,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id + primary = true } load_balancer_frontend_ip_configuration_ids = [ @@ -281,6 +280,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } load_balancer_frontend_ip_configuration_ids = [ @@ -306,6 +306,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -313,6 +314,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -320,6 +322,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -327,6 +330,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -356,6 +360,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } load_balancer_frontend_ip_configuration_ids = [ @@ -385,6 +390,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -392,6 +398,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -399,6 +406,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -406,6 +414,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -435,6 +444,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -442,6 +452,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -449,6 +460,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -456,6 +468,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.21" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -485,6 +498,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -492,6 +506,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -499,6 +514,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -506,6 +522,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.21" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -535,6 +552,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -542,6 +560,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.20" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -549,6 +568,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.19" private_ip_address_version = "IPv4" + primary = false } nat_ip_configuration { @@ -556,6 +576,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -585,6 +606,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" + primary = true } nat_ip_configuration { @@ -592,6 +614,7 @@ resource "azurerm_private_link_service" "test" { subnet_id = azurerm_subnet.test.id private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" + primary = false } load_balancer_frontend_ip_configuration_ids = [ @@ -627,7 +650,7 @@ resource "azurerm_subnet" "test" { virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.5.1.0/24" - enforce_private_link_network_policies = true + enforce_private_link_service_network_policies = true } resource "azurerm_public_ip" "test" { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index 579d453380fe..ae5088b24292 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -140,7 +140,7 @@ func resourceArmSubnet() *schema.Resource { }, }, - "enforce_private_link_network_policies": { + "enforce_private_link_service_network_policies": { Type: schema.TypeBool, Optional: true, Default: false, @@ -182,7 +182,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err AddressPrefix: &addressPrefix, } - if v, ok := d.GetOk("enforce_private_link_network_policies"); ok { + if v, ok := d.GetOk("enforce_private_link_service_network_policies"); ok { // This is strange logic, but to get the schema to make sense for the end user // I exposed it with the same name that the Azure CLI does to be consistent // between the tool sets, which means true == Disabled. @@ -300,7 +300,7 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { // subnet because Network policies like network security groups are not // supported by private endpoints. if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - d.Set("enforce_private_link_network_policies", strings.EqualsFold("Disabled", *p)) + d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *p)) } var securityGroupId *string diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index cfc487a9fa20..f5a255abbb58 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -49,8 +49,6 @@ The following attributes are exported: * `nat_ip_configuration` - A `nat_ip_configuration` block as defined below. -* `nat_ip_configuration` - `nat_ip_configuration` blocks as defined below. - * `load_balancer_frontend_ip_configuration_ids` - A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. * `network_interfaces` - A list of network interface resource ids that are being used by the service. @@ -62,7 +60,7 @@ The following attributes are exported: The `nat_ip_configuration` block exports the following: -* `name` - The name of primary private link service NAT IP configuration. +* `name` - The name of private link service NAT IP configuration. * `private_ip_address` - The private IP address of the NAT IP configuration. @@ -70,15 +68,5 @@ The `nat_ip_configuration` block exports the following: * `subnet_id` - The resource ID of the subnet to be used by the service. +* `primary` - Value that indicates if the IP configuration is the primary configuration or not. ---- - -The `nat_ip_configuration` block exports the following: - -* `name` - The name of secondary private link service NAT IP configuration. - -* `private_ip_address` - The private IP address of the NAT IP configuration. - -* `private_ip_address_version` - The ip address version of the `ip_configuration`. - -* `subnet_id` - The resource ID of the subnet to be used by the service. diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 497570d85d21..cc9119e047c7 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -34,7 +34,7 @@ output "subnet_id" { * `id` - The ID of the Subnet. * `address_prefix` - The address prefix used for the subnet. -* `enforce_private_link_network_policies` - Enable or Disable network policies on private link service in the subnet. +* `enforce_private_link_service_network_policies` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. * `ip_configurations` - The collection of IP Configurations with IPs within this subnet. diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index 23743e9d7106..bc1ea7f03d08 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -28,10 +28,11 @@ resource "azurerm_virtual_network" "example" { } resource "azurerm_subnet" "example" { - name = "example-snet" - resource_group_name = azurerm_resource_group.example.name - virtual_network_name = azurerm_virtual_network.example.name - address_prefix = "10.5.1.0/24" + name = "example-snet" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefix = "10.5.1.0/24" + enforce_private_link_service_network_policies = true } resource "azurerm_public_ip" "example" { @@ -68,6 +69,7 @@ resource "azurerm_private_link_service" "example" { private_ip_address = "10.5.1.17" private_ip_address_version = "IPv4" subnet_id = azurerm_subnet.example.id + primary = true } nat_ip_configuration { @@ -75,6 +77,7 @@ resource "azurerm_private_link_service" "example" { private_ip_address = "10.5.1.18" private_ip_address_version = "IPv4" subnet_id = azurerm_subnet.example.id + primary = false } } ``` @@ -95,12 +98,8 @@ The following arguments are supported: * `nat_ip_configuration` - (Required) A `nat_ip_configuration` block as defined below. -* `nat_ip_configuration` - (Optional) Supports upto seven additional `nat_ip_configuration` blocks as defined below. - * `load_balancer_frontend_ip_configuration_ids` - (Required) A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. -* `private_link_endpoint_connection` - (Optional) One or more `private_link_endpoint_connection` blocks as defined below. - * `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created. --- @@ -117,21 +116,7 @@ The `nat_ip_configuration` block supports the following: * `subnet_id` - (Required) The resource ID of the subnet to be used by the service. - ---- - -The `nat_ip_configuration` block supports the following: - -* `name` - (Required) The name of secondary private link service NAT IP configuration. Changing this forces a new resource to be created. - -* `private_ip_address` - (Optional) The private IP address of the NAT IP configuration. - -* `private_ip_address_version` - (Optional) The ip address version of the `ip_configuration`, the supported value is `IPv4`. Defaults to `IPv4`. - --> **NOTE:** Private Link Service Supports `IPv4` traffic only. - -* `subnet_id` - (Required) The resource ID of the subnet to be used by the service. - +* `primary` - (Required) Specifies if the `nat_ip_configuration` block is the primary ip configuration for the service or not. Valid values are `true` or `false`. Changing this forces a new resource to be created. ## Attributes Reference diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index c0d93a6c0767..7225268225b5 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,9 +59,9 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `enforce_private_link_network_policies` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. +* `enforce_private_link_service_network_policies` - (Optional) Enable or Disable network policies on the `private link service` in the subnet. Default is `false`. --> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `enforce_private_link_network_policies` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. +-> **NOTE:** Network policies like network security groups (NSG) are not supported for the private link service. In order to deploy a private link service on a given subnet, an explicit disable setting is required on that subnet(e.g. `enforce_private_link_service_network_policies` = `true`). This setting is only applicable for the private link service. For other resources in the subnet, access is controlled based on Network Security Groups (NSG) security rules definition. * `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. From e635720e3dd1843bf0a59b9608c8d0c3393342d9 Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Mon, 18 Nov 2019 11:46:23 -0800 Subject: [PATCH 36/44] Update website/docs/r/subnet.html.markdown Co-Authored-By: kt --- website/docs/r/subnet.html.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 7225268225b5..507c593367c2 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -104,7 +104,6 @@ The following attributes are exported: * `virtual_network_name` - The name of the virtual network in which the subnet is created in * `address_prefix` - The address prefix for the subnet - ## Import Subnets can be imported using the `resource id`, e.g. From 8301465fb5ae5d7b6ededb91c6759cc74905051b Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Mon, 18 Nov 2019 11:47:39 -0800 Subject: [PATCH 37/44] Update website/docs/d/private_link_service.html.markdown Co-Authored-By: kt --- website/docs/d/private_link_service.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index f5a255abbb58..213d32d794bd 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -32,7 +32,7 @@ The following arguments are supported: * `name` - (Required) The name of the private link service. -* `resource_group_name` - (Required) The name of the resource group in which the private link service resides. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which the private link service resides. ## Attributes Reference From d55f49595f8c71637dbcf228263974c2b7da2788 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 18 Nov 2019 11:54:32 -0800 Subject: [PATCH 38/44] gofmt provider --- azurerm/provider.go | 200 ++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index ddd0cf96edc6..692d81e2c236 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -52,107 +52,107 @@ func Provider() terraform.ResourceProvider { } dataSources := map[string]*schema.Resource{ - "azurerm_api_management": dataSourceApiManagementService(), - "azurerm_api_management_api": dataSourceApiManagementApi(), - "azurerm_api_management_group": dataSourceApiManagementGroup(), - "azurerm_api_management_product": dataSourceApiManagementProduct(), - "azurerm_api_management_user": dataSourceArmApiManagementUser(), - "azurerm_app_service_plan": dataSourceAppServicePlan(), - "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), - "azurerm_app_service": dataSourceArmAppService(), - "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), - "azurerm_application_insights": dataSourceArmApplicationInsights(), - "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), - "azurerm_automation_account": dataSourceArmAutomationAccount(), - "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), - "azurerm_availability_set": dataSourceArmAvailabilitySet(), - "azurerm_azuread_application": dataSourceArmAzureADApplication(), - "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), - "azurerm_batch_account": dataSourceArmBatchAccount(), - "azurerm_batch_certificate": dataSourceArmBatchCertificate(), - "azurerm_batch_pool": dataSourceArmBatchPool(), - "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), - "azurerm_cdn_profile": dataSourceArmCdnProfile(), - "azurerm_client_config": dataSourceArmClientConfig(), - "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), - "azurerm_container_registry": dataSourceArmContainerRegistry(), - "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), - "azurerm_data_factory": dataSourceArmDataFactory(), - "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), - "azurerm_dev_test_lab": dataSourceArmDevTestLab(), - "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), - "azurerm_dns_zone": dataSourceArmDnsZone(), - "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), - "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), - "azurerm_firewall": dataSourceArmFirewall(), - "azurerm_image": dataSourceArmImage(), - "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), - "azurerm_healthcare_service": dataSourceArmHealthcareService(), - "azurerm_maps_account": dataSourceArmMapsAccount(), - "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), - "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), - "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), - "azurerm_key_vault": dataSourceArmKeyVault(), - "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), - "azurerm_lb": dataSourceArmLoadBalancer(), - "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), - "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), - "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), - "azurerm_managed_disk": dataSourceArmManagedDisk(), - "azurerm_management_group": dataSourceArmManagementGroup(), - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), - "azurerm_netapp_account": dataSourceArmNetAppAccount(), - "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), - "azurerm_network_interface": dataSourceArmNetworkInterface(), - "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), - "azurerm_network_watcher": dataSourceArmNetworkWatcher(), - "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), - "azurerm_notification_hub": dataSourceNotificationHub(), - "azurerm_platform_image": dataSourceArmPlatformImage(), - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_postgresql_server": dataSourcePostgreSqlServer(), - "azurerm_private_link_service": dataSourceArmPrivateLinkService(), + "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_api": dataSourceApiManagementApi(), + "azurerm_api_management_group": dataSourceApiManagementGroup(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), + "azurerm_api_management_user": dataSourceArmApiManagementUser(), + "azurerm_app_service_plan": dataSourceAppServicePlan(), + "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), + "azurerm_app_service": dataSourceArmAppService(), + "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), + "azurerm_application_insights": dataSourceArmApplicationInsights(), + "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), + "azurerm_automation_account": dataSourceArmAutomationAccount(), + "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), + "azurerm_availability_set": dataSourceArmAvailabilitySet(), + "azurerm_azuread_application": dataSourceArmAzureADApplication(), + "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), + "azurerm_batch_account": dataSourceArmBatchAccount(), + "azurerm_batch_certificate": dataSourceArmBatchCertificate(), + "azurerm_batch_pool": dataSourceArmBatchPool(), + "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), + "azurerm_cdn_profile": dataSourceArmCdnProfile(), + "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), + "azurerm_container_registry": dataSourceArmContainerRegistry(), + "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), + "azurerm_data_factory": dataSourceArmDataFactory(), + "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), + "azurerm_dev_test_lab": dataSourceArmDevTestLab(), + "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), + "azurerm_dns_zone": dataSourceArmDnsZone(), + "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), + "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), + "azurerm_firewall": dataSourceArmFirewall(), + "azurerm_image": dataSourceArmImage(), + "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), + "azurerm_healthcare_service": dataSourceArmHealthcareService(), + "azurerm_maps_account": dataSourceArmMapsAccount(), + "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), + "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), + "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), + "azurerm_key_vault": dataSourceArmKeyVault(), + "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), + "azurerm_lb": dataSourceArmLoadBalancer(), + "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), + "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), + "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), + "azurerm_managed_disk": dataSourceArmManagedDisk(), + "azurerm_management_group": dataSourceArmManagementGroup(), + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), + "azurerm_netapp_account": dataSourceArmNetAppAccount(), + "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), + "azurerm_network_interface": dataSourceArmNetworkInterface(), + "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), + "azurerm_network_watcher": dataSourceArmNetworkWatcher(), + "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), + "azurerm_notification_hub": dataSourceNotificationHub(), + "azurerm_platform_image": dataSourceArmPlatformImage(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), "azurerm_private_link_service_endpoint_connections": dataSourceArmPrivateLinkServiceEndpointConnections(), - "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), - "azurerm_public_ip": dataSourceArmPublicIP(), - "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_redis_cache": dataSourceArmRedisCache(), - "azurerm_resources": dataSourceArmResources(), - "azurerm_resource_group": dataSourceArmResourceGroup(), - "azurerm_role_definition": dataSourceArmRoleDefinition(), - "azurerm_route_table": dataSourceArmRouteTable(), - "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), - "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), - "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), - "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), - "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), - "azurerm_shared_image": dataSourceArmSharedImage(), - "azurerm_snapshot": dataSourceArmSnapshot(), - "azurerm_sql_server": dataSourceSqlServer(), - "azurerm_sql_database": dataSourceSqlDatabase(), - "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), - "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), - "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), - "azurerm_storage_account": dataSourceArmStorageAccount(), - "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), - "azurerm_subnet": dataSourceArmSubnet(), - "azurerm_subscription": dataSourceArmSubscription(), - "azurerm_subscriptions": dataSourceArmSubscriptions(), - "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), - "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), - "azurerm_virtual_machine": dataSourceArmVirtualMachine(), - "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), - "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), - "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), + "azurerm_public_ip": dataSourceArmPublicIP(), + "azurerm_public_ips": dataSourceArmPublicIPs(), + "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_redis_cache": dataSourceArmRedisCache(), + "azurerm_resources": dataSourceArmResources(), + "azurerm_resource_group": dataSourceArmResourceGroup(), + "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_route_table": dataSourceArmRouteTable(), + "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), + "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), + "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), + "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), + "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), + "azurerm_shared_image": dataSourceArmSharedImage(), + "azurerm_snapshot": dataSourceArmSnapshot(), + "azurerm_sql_server": dataSourceSqlServer(), + "azurerm_sql_database": dataSourceSqlDatabase(), + "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), + "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), + "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), + "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), + "azurerm_subnet": dataSourceArmSubnet(), + "azurerm_subscription": dataSourceArmSubscription(), + "azurerm_subscriptions": dataSourceArmSubscriptions(), + "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), + "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), + "azurerm_virtual_machine": dataSourceArmVirtualMachine(), + "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), + "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), + "azurerm_virtual_network": dataSourceArmVirtualNetwork(), } resources := map[string]*schema.Resource{ From 708d10c82acf9e4d4463aeebc1fb64f9c03a4d71 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 19 Nov 2019 13:42:04 -0800 Subject: [PATCH 39/44] Add private link service datasource --- azurerm/provider.go | 202 ++++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 100 deletions(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index 998aef64bc2e..ef34810b3a3d 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -52,106 +52,108 @@ func Provider() terraform.ResourceProvider { } dataSources := map[string]*schema.Resource{ - "azurerm_api_management": dataSourceApiManagementService(), - "azurerm_api_management_api": dataSourceApiManagementApi(), - "azurerm_api_management_group": dataSourceApiManagementGroup(), - "azurerm_api_management_product": dataSourceApiManagementProduct(), - "azurerm_api_management_user": dataSourceArmApiManagementUser(), - "azurerm_app_service_plan": dataSourceAppServicePlan(), - "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), - "azurerm_app_service": dataSourceArmAppService(), - "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), - "azurerm_application_insights": dataSourceArmApplicationInsights(), - "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), - "azurerm_automation_account": dataSourceArmAutomationAccount(), - "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), - "azurerm_availability_set": dataSourceArmAvailabilitySet(), - "azurerm_azuread_application": dataSourceArmAzureADApplication(), - "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), - "azurerm_batch_account": dataSourceArmBatchAccount(), - "azurerm_batch_certificate": dataSourceArmBatchCertificate(), - "azurerm_batch_pool": dataSourceArmBatchPool(), - "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), - "azurerm_cdn_profile": dataSourceArmCdnProfile(), - "azurerm_client_config": dataSourceArmClientConfig(), - "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), - "azurerm_container_registry": dataSourceArmContainerRegistry(), - "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), - "azurerm_data_factory": dataSourceArmDataFactory(), - "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), - "azurerm_dev_test_lab": dataSourceArmDevTestLab(), - "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), - "azurerm_dns_zone": dataSourceArmDnsZone(), - "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), - "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), - "azurerm_firewall": dataSourceArmFirewall(), - "azurerm_image": dataSourceArmImage(), - "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), - "azurerm_healthcare_service": dataSourceArmHealthcareService(), - "azurerm_maps_account": dataSourceArmMapsAccount(), - "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), - "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), - "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), - "azurerm_key_vault": dataSourceArmKeyVault(), - "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), - "azurerm_lb": dataSourceArmLoadBalancer(), - "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), - "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), - "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), - "azurerm_managed_disk": dataSourceArmManagedDisk(), - "azurerm_management_group": dataSourceArmManagementGroup(), - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), - "azurerm_netapp_account": dataSourceArmNetAppAccount(), - "azurerm_netapp_pool": dataSourceArmNetAppPool(), - "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), - "azurerm_network_interface": dataSourceArmNetworkInterface(), - "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), - "azurerm_network_watcher": dataSourceArmNetworkWatcher(), - "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), - "azurerm_notification_hub": dataSourceNotificationHub(), - "azurerm_platform_image": dataSourceArmPlatformImage(), - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_postgresql_server": dataSourcePostgreSqlServer(), - "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), - "azurerm_public_ip": dataSourceArmPublicIP(), - "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_redis_cache": dataSourceArmRedisCache(), - "azurerm_resources": dataSourceArmResources(), - "azurerm_resource_group": dataSourceArmResourceGroup(), - "azurerm_role_definition": dataSourceArmRoleDefinition(), - "azurerm_route_table": dataSourceArmRouteTable(), - "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), - "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), - "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), - "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), - "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), - "azurerm_shared_image": dataSourceArmSharedImage(), - "azurerm_snapshot": dataSourceArmSnapshot(), - "azurerm_sql_server": dataSourceSqlServer(), - "azurerm_sql_database": dataSourceSqlDatabase(), - "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), - "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), - "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), - "azurerm_storage_account": dataSourceArmStorageAccount(), - "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), - "azurerm_subnet": dataSourceArmSubnet(), - "azurerm_subscription": dataSourceArmSubscription(), - "azurerm_subscriptions": dataSourceArmSubscriptions(), - "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), - "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), - "azurerm_virtual_machine": dataSourceArmVirtualMachine(), - "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), - "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), - "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_api": dataSourceApiManagementApi(), + "azurerm_api_management_group": dataSourceApiManagementGroup(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), + "azurerm_api_management_user": dataSourceArmApiManagementUser(), + "azurerm_app_service_plan": dataSourceAppServicePlan(), + "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), + "azurerm_app_service": dataSourceArmAppService(), + "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), + "azurerm_application_insights": dataSourceArmApplicationInsights(), + "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), + "azurerm_automation_account": dataSourceArmAutomationAccount(), + "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), + "azurerm_availability_set": dataSourceArmAvailabilitySet(), + "azurerm_azuread_application": dataSourceArmAzureADApplication(), + "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), + "azurerm_batch_account": dataSourceArmBatchAccount(), + "azurerm_batch_certificate": dataSourceArmBatchCertificate(), + "azurerm_batch_pool": dataSourceArmBatchPool(), + "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), + "azurerm_cdn_profile": dataSourceArmCdnProfile(), + "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), + "azurerm_container_registry": dataSourceArmContainerRegistry(), + "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), + "azurerm_data_factory": dataSourceArmDataFactory(), + "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), + "azurerm_dev_test_lab": dataSourceArmDevTestLab(), + "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), + "azurerm_dns_zone": dataSourceArmDnsZone(), + "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), + "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), + "azurerm_firewall": dataSourceArmFirewall(), + "azurerm_image": dataSourceArmImage(), + "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), + "azurerm_healthcare_service": dataSourceArmHealthcareService(), + "azurerm_maps_account": dataSourceArmMapsAccount(), + "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), + "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), + "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), + "azurerm_key_vault": dataSourceArmKeyVault(), + "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), + "azurerm_lb": dataSourceArmLoadBalancer(), + "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), + "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), + "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), + "azurerm_managed_disk": dataSourceArmManagedDisk(), + "azurerm_management_group": dataSourceArmManagementGroup(), + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), + "azurerm_netapp_account": dataSourceArmNetAppAccount(), + "azurerm_netapp_pool": dataSourceArmNetAppPool(), + "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), + "azurerm_network_interface": dataSourceArmNetworkInterface(), + "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), + "azurerm_network_watcher": dataSourceArmNetworkWatcher(), + "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), + "azurerm_notification_hub": dataSourceNotificationHub(), + "azurerm_platform_image": dataSourceArmPlatformImage(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_private_link_service": dataSourceArmPrivateLinkService(), + "azurerm_private_link_service_endpoint_connections": dataSourceArmPrivateLinkServiceEndpointConnections(), + "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), + "azurerm_public_ip": dataSourceArmPublicIP(), + "azurerm_public_ips": dataSourceArmPublicIPs(), + "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_redis_cache": dataSourceArmRedisCache(), + "azurerm_resources": dataSourceArmResources(), + "azurerm_resource_group": dataSourceArmResourceGroup(), + "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_route_table": dataSourceArmRouteTable(), + "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), + "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), + "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), + "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), + "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), + "azurerm_shared_image": dataSourceArmSharedImage(), + "azurerm_snapshot": dataSourceArmSnapshot(), + "azurerm_sql_server": dataSourceSqlServer(), + "azurerm_sql_database": dataSourceSqlDatabase(), + "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), + "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), + "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), + "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), + "azurerm_subnet": dataSourceArmSubnet(), + "azurerm_subscription": dataSourceArmSubscription(), + "azurerm_subscriptions": dataSourceArmSubscriptions(), + "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), + "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), + "azurerm_virtual_machine": dataSourceArmVirtualMachine(), + "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), + "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), + "azurerm_virtual_network": dataSourceArmVirtualNetwork(), } resources := map[string]*schema.Resource{ From e05fc529301bee636b7007584459ac66bc334dac Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 19 Nov 2019 19:35:48 -0800 Subject: [PATCH 40/44] Updates per PR comments --- azurerm/data_source_private_link_service.go | 28 ++++------ ...ivate_link_service_endpoint_connections.go | 4 +- .../data_source_private_link_service_test.go | 7 +-- azurerm/internal/services/network/validate.go | 25 +++------ azurerm/resource_arm_private_link_service.go | 55 ++++++++----------- .../resource_arm_private_link_service_test.go | 48 ++++++++++------ azurerm/resource_arm_subnet.go | 11 +--- .../docs/d/private_link_service.html.markdown | 14 ++--- .../docs/r/private_link_service.html.markdown | 2 + 9 files changed, 91 insertions(+), 103 deletions(-) diff --git a/azurerm/data_source_private_link_service.go b/azurerm/data_source_private_link_service.go index 7b72d9c2093e..a9e760989905 100644 --- a/azurerm/data_source_private_link_service.go +++ b/azurerm/data_source_private_link_service.go @@ -26,19 +26,17 @@ func dataSourceArmPrivateLinkService() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), "auto_approval_subscription_ids": { - Type: schema.TypeList, + Type: schema.TypeSet, Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, "visibility_subscription_ids": { - Type: schema.TypeList, + Type: schema.TypeSet, Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you @@ -81,11 +79,10 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, "load_balancer_frontend_ip_configuration_ids": { - Type: schema.TypeList, + Type: schema.TypeSet, Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, "alias": { @@ -94,11 +91,10 @@ func dataSourceArmPrivateLinkService() *schema.Resource { }, "network_interface_ids": { - Type: schema.TypeList, + Type: schema.TypeSet, Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, "tags": tags.SchemaDataSource(), diff --git a/azurerm/data_source_private_link_service_endpoint_connections.go b/azurerm/data_source_private_link_service_endpoint_connections.go index fa06f0fdff18..b551c391a03f 100644 --- a/azurerm/data_source_private_link_service_endpoint_connections.go +++ b/azurerm/data_source_private_link_service_endpoint_connections.go @@ -3,7 +3,7 @@ package azurerm import ( "fmt" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-07-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" @@ -128,7 +128,7 @@ func flattenArmPrivateLinkServicePrivateEndpointConnections(input *[]network.Pri } } if s := props.PrivateLinkServiceConnectionState; s != nil { - if a := s.ActionRequired; a != nil { + if a := s.ActionsRequired; a != nil { v["action_required"] = *a } else { v["action_required"] = "none" diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index e772a64d424e..6f1e3c535be3 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -20,12 +20,11 @@ func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { { Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "2"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.18"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 8b5a1ffe4dd2..928627a17ea5 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -8,19 +8,16 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -// ValidatePrivateLinkNatIpConfiguration - This rule makes sure that you can only go from a -// dynamic private ip address to a static private ip address. Once you have assigned a private -// ip address to a primary or secondary nat ip configuration block it is set in stone and can -// not become a dynamic private ip address again unless the resource is destroyed and recreated. func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - primaryIpConfiguration := d.Get("nat_ip_configuration").([]interface{}) - secondaryIpConfigurations := d.Get("nat_ip_configuration").([]interface{}) + ipConfigurations := d.Get("nat_ip_configuration").([]interface{}) - for i, item := range primaryIpConfiguration { + for i, item := range ipConfigurations { v := item.(map[string]interface{}) p := fmt.Sprintf("nat_ip_configuration.%d.private_ip_address", i) + s := fmt.Sprintf("nat_ip_configuration.%d.subnet_id", i) + isPrimary := v["primary"].(bool) in := v["name"].(string) if d.HasChange(p) { @@ -29,17 +26,11 @@ func ValidatePrivateLinkNatIpConfiguration(d *schema.ResourceDiff) error { return fmt.Errorf("Private Link Service %q (Resource Group %q) nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) } } - } - - for i, item := range secondaryIpConfigurations { - v := item.(map[string]interface{}) - p := fmt.Sprintf("nat_ip_configuration.%d.private_ip_address", i) - in := v["name"].(string) - if d.HasChange(p) { - o, n := d.GetChange(p) - if o != "" && n == "" { - return fmt.Errorf("Private Link Service %q (Resource Group %q) nat_ip_configuration %q private_ip_address once assigned can not be removed", name, resourceGroup, in) + if isPrimary && d.HasChange(s) { + o, _ := d.GetChange(s) + if o != "" { + return fmt.Errorf("Private Link Service %q (Resource Group %q) nat_ip_configuration %q primary subnet_id once assigned can not be changed", name, resourceGroup, in) } } } diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 3eb7e060f023..b79590f1e602 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-07-01/network" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" @@ -67,8 +67,6 @@ func resourceArmPrivateLinkService() *schema.Resource { // Required by the API you can't create the resource without at least // one ip configuration once primary is set it is set forever unless // you destroy the resource and recreate it. - - //TODO: Add custom diff to detect changes to primary config and force new on any changes "nat_ip_configuration": { Type: schema.TypeList, Required: true, @@ -166,22 +164,22 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte } location := azure.NormalizeLocation(d.Get("location").(string)) - autoApproval := d.Get("auto_approval_subscription_ids").([]interface{}) + autoApproval := d.Get("auto_approval_subscription_ids").(*schema.Set) // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you //fqdns := d.Get("fqdns").([]interface{}) primaryIpConfiguration := d.Get("nat_ip_configuration").([]interface{}) - loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").([]interface{}) - visibility := d.Get("visibility_subscription_ids").([]interface{}) + loadBalancerFrontendIpConfigurations := d.Get("load_balancer_frontend_ip_configuration_ids").(*schema.Set) + visibility := d.Get("visibility_subscription_ids").(*schema.Set) t := d.Get("tags").(map[string]interface{}) parameters := network.PrivateLinkService{ Location: utils.String(location), PrivateLinkServiceProperties: &network.PrivateLinkServiceProperties{ AutoApproval: &network.PrivateLinkServicePropertiesAutoApproval{ - Subscriptions: utils.ExpandStringSlice(autoApproval), + Subscriptions: utils.ExpandStringSlice(autoApproval.List()), }, Visibility: &network.PrivateLinkServicePropertiesVisibility{ - Subscriptions: utils.ExpandStringSlice(visibility), + Subscriptions: utils.ExpandStringSlice(visibility.List()), }, IPConfigurations: expandArmPrivateLinkServiceIPConfiguration(primaryIpConfiguration), LoadBalancerFrontendIPConfigurations: expandArmPrivateLinkServiceFrontendIPConfiguration(loadBalancerFrontendIpConfigurations), @@ -237,12 +235,12 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) - if props.AutoApproval.Subscriptions != nil { + if props.AutoApproval != nil { if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } } - if props.Visibility.Subscriptions != nil { + if props.Visibility != nil { if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } @@ -253,20 +251,14 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) // return fmt.Errorf("Error setting `fqdns`: %+v", err) // } // } - if props.IPConfigurations != nil { - if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { - return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) - } + if err := d.Set("nat_ip_configuration", flattenArmPrivateLinkServiceIPConfiguration(props.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `nat_ip_configuration`: %+v", err) } - if props.LoadBalancerFrontendIPConfigurations != nil { - if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { - return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) - } + if err := d.Set("load_balancer_frontend_ip_configuration_ids", flattenArmPrivateLinkServiceFrontendIPConfiguration(props.LoadBalancerFrontendIPConfigurations)); err != nil { + return fmt.Errorf("Error setting `load_balancer_frontend_ip_configuration_ids`: %+v", err) } - if props.NetworkInterfaces != nil { - if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { - return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) - } + if err := d.Set("network_interface_ids", flattenArmPrivateLinkServiceInterface(props.NetworkInterfaces)); err != nil { + return fmt.Errorf("Error setting `network_interface_ids`: %+v", err) } } @@ -340,14 +332,15 @@ func expandArmPrivateLinkServiceIPConfiguration(input []interface{}) *[]network. return &results } -func expandArmPrivateLinkServiceFrontendIPConfiguration(input []interface{}) *[]network.FrontendIPConfiguration { - if len(input) == 0 { +func expandArmPrivateLinkServiceFrontendIPConfiguration(input *schema.Set) *[]network.FrontendIPConfiguration { + ids := input.List() + if len(ids) == 0 { return nil } results := make([]network.FrontendIPConfiguration, 0) - for _, item := range input { + for _, item := range ids { result := network.FrontendIPConfiguration{ ID: utils.String(item.(string)), } @@ -391,30 +384,30 @@ func flattenArmPrivateLinkServiceIPConfiguration(input *[]network.PrivateLinkSer return results } -func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) []string { - results := make([]string, 0) +func flattenArmPrivateLinkServiceFrontendIPConfiguration(input *[]network.FrontendIPConfiguration) *schema.Set { + results := &schema.Set{F: schema.HashString} if input == nil { return results } for _, item := range *input { if id := item.ID; id != nil { - results = append(results, *id) + results.Add(*id) } } return results } -func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) []string { - results := make([]string, 0) +func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) *schema.Set { + results := &schema.Set{F: schema.HashString} if input == nil { return results } for _, item := range *input { if id := item.ID; id != nil { - results = append(results, *id) + results.Add(*id) } } diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index b7dcffea9c96..98865a97fe80 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -24,9 +24,9 @@ func TestAccAzureRMPrivateLinkService_basic(t *testing.T) { Config: testAccAzureRMPrivateLinkService_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctestPLS-%d", ri)), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { @@ -54,7 +54,6 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { @@ -64,18 +63,21 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "4"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.primary", "true"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_basicIp(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), ), }, { @@ -116,6 +118,11 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.20"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_moveChangeOne(ri, location), Check: resource.ComposeTestCheckFunc( @@ -127,6 +134,11 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.21"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_moveChangeTwo(ri, location), Check: resource.ComposeTestCheckFunc( @@ -138,6 +150,11 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.3.private_ip_address", "10.5.1.21"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_moveChangeThree(ri, location), Check: resource.ComposeTestCheckFunc( @@ -173,16 +190,13 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMPrivateLinkServiceExists(resourceName), resource.TestCheckResourceAttr(resourceName, "auto_approval_subscription_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "auto_approval_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "visibility_subscription_ids.0"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), - resource.TestCheckResourceAttrSet(resourceName, "load_balancer_frontend_ip_configuration_ids.0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.env", "test"), ), @@ -249,7 +263,7 @@ func testAccAzureRMPrivateLinkService_basic(rInt int, location string) string { %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -271,7 +285,7 @@ func testAccAzureRMPrivateLinkService_basicIp(rInt int, location string) string %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -295,7 +309,7 @@ func testAccAzureRMPrivateLinkService_update(rInt int, location string) string { %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -349,7 +363,7 @@ func testAccAzureRMPrivateLinkService_moveSetup(rInt int, location string) strin %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -379,7 +393,7 @@ func testAccAzureRMPrivateLinkService_moveAdd(rInt int, location string) string %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -433,7 +447,7 @@ func testAccAzureRMPrivateLinkService_moveChangeOne(rInt int, location string) s %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -487,7 +501,7 @@ func testAccAzureRMPrivateLinkService_moveChangeTwo(rInt int, location string) s %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -541,7 +555,7 @@ func testAccAzureRMPrivateLinkService_moveChangeThree(rInt int, location string) %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -595,7 +609,7 @@ func testAccAzureRMPrivateLinkService_complete(rInt int, location string) string %s resource "azurerm_private_link_service" "test" { - name = "acctestpls-%d" + name = "acctestPLS-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name auto_approval_subscription_ids = [data.azurerm_subscription.current.subscription_id] @@ -633,7 +647,7 @@ func testAccAzureRMPrivateLinkServiceTemplate(rInt int, location string) string data "azurerm_subscription" "current" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-privatelinkservice-%d" location = "%s" } diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index d8596c8e29d1..ea90848fc3b6 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -183,10 +183,6 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err } if v, ok := d.GetOk("enforce_private_link_service_network_policies"); ok { - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // // To enable private endpoints you must disable the network policies for the // subnet because Network policies like network security groups are not // supported by private endpoints. @@ -292,14 +288,11 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // + if p := props.PrivateLinkServiceNetworkPolicies; p != nil { // To enable private endpoints you must disable the network policies for the // subnet because Network policies like network security groups are not // supported by private endpoints. - if p := props.PrivateLinkServiceNetworkPolicies; p != nil { + d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *p)) } diff --git a/website/docs/d/private_link_service.html.markdown b/website/docs/d/private_link_service.html.markdown index 213d32d794bd..cc4cda255f43 100644 --- a/website/docs/d/private_link_service.html.markdown +++ b/website/docs/d/private_link_service.html.markdown @@ -39,21 +39,21 @@ The following arguments are supported: The following attributes are exported: -* `location` - Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. +* `location` - The supported Azure location where the resource exists. * `alias` - The alias is a globally unique name for your private link service which Azure generates for you. Your can use this alias to request a connection to your private link service. -* `auto_approval_subscription_ids` - A list of subscription(s) globally unique identifiers that will be auto approved to use the private link service. +* `auto_approval_subscription_ids` - The list of subscription(s) globally unique identifiers that will be auto approved to use the private link service. -* `visibility_subscription_ids` - A list of subscription(s) globally unique identifiers(GUID) that will be able to see the private link service. +* `visibility_subscription_ids` - The list of subscription(s) globally unique identifiers(GUID) that will be able to see the private link service. -* `nat_ip_configuration` - A `nat_ip_configuration` block as defined below. +* `nat_ip_configuration` - The `nat_ip_configuration` block as defined below. -* `load_balancer_frontend_ip_configuration_ids` - A list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. +* `load_balancer_frontend_ip_configuration_ids` - The list of Standard Load Balancer(SLB) resource IDs. The Private Link service is tied to the frontend IP address of a SLB. All traffic destined for the private link service will reach the frontend of the SLB. You can configure SLB rules to direct this traffic to appropriate backend pools where your applications are running. -* `network_interfaces` - A list of network interface resource ids that are being used by the service. +* `network_interfaces` - The list of network interface resource ids that are being used by the service. -* `tags` - A mapping of tags to assign to the resource. Changing this forces a new resource to be created +* `tags` - A mapping of tags to assign to the resource. --- diff --git a/website/docs/r/private_link_service.html.markdown b/website/docs/r/private_link_service.html.markdown index bc1ea7f03d08..6748dcd74053 100644 --- a/website/docs/r/private_link_service.html.markdown +++ b/website/docs/r/private_link_service.html.markdown @@ -116,6 +116,8 @@ The `nat_ip_configuration` block supports the following: * `subnet_id` - (Required) The resource ID of the subnet to be used by the service. +-> **NOTE:** Verify that the subnets `enforce_private_link_service_network_policies` attribute is set to `true`. + * `primary` - (Required) Specifies if the `nat_ip_configuration` block is the primary ip configuration for the service or not. Valid values are `true` or `false`. Changing this forces a new resource to be created. ## Attributes Reference From 00bc22bd22b5d7db90bc6d7343e8e6bacba9133c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 20 Nov 2019 17:16:02 -0800 Subject: [PATCH 41/44] Updates per PR comments --- azurerm/internal/services/network/validate.go | 2 +- azurerm/provider.go | 202 +++++++++--------- azurerm/resource_arm_private_link_service.go | 40 ++-- azurerm/resource_arm_subnet.go | 6 +- 4 files changed, 129 insertions(+), 121 deletions(-) diff --git a/azurerm/internal/services/network/validate.go b/azurerm/internal/services/network/validate.go index 6746ea4219cc..d4b538ab7618 100644 --- a/azurerm/internal/services/network/validate.go +++ b/azurerm/internal/services/network/validate.go @@ -2,7 +2,7 @@ package network import ( "fmt" - "regexp" + "regexp" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" diff --git a/azurerm/provider.go b/azurerm/provider.go index c97dcb652121..4466a7e1699c 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -52,109 +52,109 @@ func Provider() terraform.ResourceProvider { } dataSources := map[string]*schema.Resource{ - "azurerm_api_management": dataSourceApiManagementService(), - "azurerm_api_management_api": dataSourceApiManagementApi(), - "azurerm_api_management_group": dataSourceApiManagementGroup(), - "azurerm_api_management_product": dataSourceApiManagementProduct(), - "azurerm_api_management_user": dataSourceArmApiManagementUser(), - "azurerm_app_service_plan": dataSourceAppServicePlan(), - "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), - "azurerm_app_service": dataSourceArmAppService(), - "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), - "azurerm_application_insights": dataSourceArmApplicationInsights(), - "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), - "azurerm_automation_account": dataSourceArmAutomationAccount(), - "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), - "azurerm_availability_set": dataSourceArmAvailabilitySet(), - "azurerm_azuread_application": dataSourceArmAzureADApplication(), - "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), - "azurerm_batch_account": dataSourceArmBatchAccount(), - "azurerm_batch_certificate": dataSourceArmBatchCertificate(), - "azurerm_batch_pool": dataSourceArmBatchPool(), - "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), - "azurerm_cdn_profile": dataSourceArmCdnProfile(), - "azurerm_client_config": dataSourceArmClientConfig(), - "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), - "azurerm_container_registry": dataSourceArmContainerRegistry(), - "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), - "azurerm_data_factory": dataSourceArmDataFactory(), - "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), - "azurerm_dev_test_lab": dataSourceArmDevTestLab(), - "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), - "azurerm_dns_zone": dataSourceArmDnsZone(), - "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), - "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), - "azurerm_firewall": dataSourceArmFirewall(), - "azurerm_image": dataSourceArmImage(), - "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), - "azurerm_healthcare_service": dataSourceArmHealthcareService(), - "azurerm_maps_account": dataSourceArmMapsAccount(), - "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), - "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), - "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), - "azurerm_key_vault": dataSourceArmKeyVault(), - "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), - "azurerm_lb": dataSourceArmLoadBalancer(), - "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), - "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), - "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), - "azurerm_managed_disk": dataSourceArmManagedDisk(), - "azurerm_management_group": dataSourceArmManagementGroup(), - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), - "azurerm_netapp_account": dataSourceArmNetAppAccount(), - "azurerm_netapp_pool": dataSourceArmNetAppPool(), - "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), - "azurerm_network_interface": dataSourceArmNetworkInterface(), - "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), - "azurerm_network_watcher": dataSourceArmNetworkWatcher(), - "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), - "azurerm_notification_hub": dataSourceNotificationHub(), - "azurerm_platform_image": dataSourceArmPlatformImage(), - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_postgresql_server": dataSourcePostgreSqlServer(), + "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_api": dataSourceApiManagementApi(), + "azurerm_api_management_group": dataSourceApiManagementGroup(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), + "azurerm_api_management_user": dataSourceArmApiManagementUser(), + "azurerm_app_service_plan": dataSourceAppServicePlan(), + "azurerm_app_service_certificate": dataSourceAppServiceCertificate(), + "azurerm_app_service": dataSourceArmAppService(), + "azurerm_app_service_certificate_order": dataSourceArmAppServiceCertificateOrder(), + "azurerm_application_insights": dataSourceArmApplicationInsights(), + "azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(), + "azurerm_automation_account": dataSourceArmAutomationAccount(), + "azurerm_automation_variable_bool": dataSourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": dataSourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": dataSourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": dataSourceArmAutomationVariableString(), + "azurerm_availability_set": dataSourceArmAvailabilitySet(), + "azurerm_azuread_application": dataSourceArmAzureADApplication(), + "azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(), + "azurerm_batch_account": dataSourceArmBatchAccount(), + "azurerm_batch_certificate": dataSourceArmBatchCertificate(), + "azurerm_batch_pool": dataSourceArmBatchPool(), + "azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(), + "azurerm_cdn_profile": dataSourceArmCdnProfile(), + "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_kubernetes_service_versions": dataSourceArmKubernetesServiceVersions(), + "azurerm_container_registry": dataSourceArmContainerRegistry(), + "azurerm_cosmosdb_account": dataSourceArmCosmosDbAccount(), + "azurerm_data_factory": dataSourceArmDataFactory(), + "azurerm_data_lake_store": dataSourceArmDataLakeStoreAccount(), + "azurerm_dev_test_lab": dataSourceArmDevTestLab(), + "azurerm_dev_test_virtual_network": dataSourceArmDevTestVirtualNetwork(), + "azurerm_dns_zone": dataSourceArmDnsZone(), + "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), + "azurerm_express_route_circuit": dataSourceArmExpressRouteCircuit(), + "azurerm_firewall": dataSourceArmFirewall(), + "azurerm_image": dataSourceArmImage(), + "azurerm_hdinsight_cluster": dataSourceArmHDInsightSparkCluster(), + "azurerm_healthcare_service": dataSourceArmHealthcareService(), + "azurerm_maps_account": dataSourceArmMapsAccount(), + "azurerm_key_vault_access_policy": dataSourceArmKeyVaultAccessPolicy(), + "azurerm_key_vault_key": dataSourceArmKeyVaultKey(), + "azurerm_key_vault_secret": dataSourceArmKeyVaultSecret(), + "azurerm_key_vault": dataSourceArmKeyVault(), + "azurerm_kubernetes_cluster": dataSourceArmKubernetesCluster(), + "azurerm_lb": dataSourceArmLoadBalancer(), + "azurerm_lb_backend_address_pool": dataSourceArmLoadBalancerBackendAddressPool(), + "azurerm_log_analytics_workspace": dataSourceLogAnalyticsWorkspace(), + "azurerm_logic_app_workflow": dataSourceArmLogicAppWorkflow(), + "azurerm_managed_disk": dataSourceArmManagedDisk(), + "azurerm_management_group": dataSourceArmManagementGroup(), + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), + "azurerm_netapp_account": dataSourceArmNetAppAccount(), + "azurerm_netapp_pool": dataSourceArmNetAppPool(), + "azurerm_network_ddos_protection_plan": dataSourceNetworkDDoSProtectionPlan(), + "azurerm_network_interface": dataSourceArmNetworkInterface(), + "azurerm_network_security_group": dataSourceArmNetworkSecurityGroup(), + "azurerm_network_watcher": dataSourceArmNetworkWatcher(), + "azurerm_notification_hub_namespace": dataSourceNotificationHubNamespace(), + "azurerm_notification_hub": dataSourceNotificationHub(), + "azurerm_platform_image": dataSourceArmPlatformImage(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_postgresql_server": dataSourcePostgreSqlServer(), "azurerm_private_link_service": dataSourceArmPrivateLinkService(), "azurerm_private_link_service_endpoint_connections": dataSourceArmPrivateLinkServiceEndpointConnections(), - "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), - "azurerm_public_ip": dataSourceArmPublicIP(), - "azurerm_public_ips": dataSourceArmPublicIPs(), - "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_redis_cache": dataSourceArmRedisCache(), - "azurerm_resources": dataSourceArmResources(), - "azurerm_resource_group": dataSourceArmResourceGroup(), - "azurerm_role_definition": dataSourceArmRoleDefinition(), - "azurerm_route_table": dataSourceArmRouteTable(), - "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), - "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), - "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), - "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), - "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), - "azurerm_shared_image": dataSourceArmSharedImage(), - "azurerm_snapshot": dataSourceArmSnapshot(), - "azurerm_sql_server": dataSourceSqlServer(), - "azurerm_sql_database": dataSourceSqlDatabase(), - "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), - "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), - "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), - "azurerm_storage_account": dataSourceArmStorageAccount(), - "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), - "azurerm_subnet": dataSourceArmSubnet(), - "azurerm_subscription": dataSourceArmSubscription(), - "azurerm_subscriptions": dataSourceArmSubscriptions(), - "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), - "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), - "azurerm_virtual_hub": dataSourceArmVirtualHub(), - "azurerm_virtual_machine": dataSourceArmVirtualMachine(), - "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), - "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), - "azurerm_virtual_network": dataSourceArmVirtualNetwork(), + "azurerm_proximity_placement_group": dataSourceArmProximityPlacementGroup(), + "azurerm_public_ip": dataSourceArmPublicIP(), + "azurerm_public_ips": dataSourceArmPublicIPs(), + "azurerm_public_ip_prefix": dataSourceArmPublicIpPrefix(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_redis_cache": dataSourceArmRedisCache(), + "azurerm_resources": dataSourceArmResources(), + "azurerm_resource_group": dataSourceArmResourceGroup(), + "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_route_table": dataSourceArmRouteTable(), + "azurerm_scheduler_job_collection": dataSourceArmSchedulerJobCollection(), + "azurerm_servicebus_namespace": dataSourceArmServiceBusNamespace(), + "azurerm_servicebus_namespace_authorization_rule": dataSourceArmServiceBusNamespaceAuthorizationRule(), + "azurerm_shared_image_gallery": dataSourceArmSharedImageGallery(), + "azurerm_shared_image_version": dataSourceArmSharedImageVersion(), + "azurerm_shared_image": dataSourceArmSharedImage(), + "azurerm_snapshot": dataSourceArmSnapshot(), + "azurerm_sql_server": dataSourceSqlServer(), + "azurerm_sql_database": dataSourceSqlDatabase(), + "azurerm_stream_analytics_job": dataSourceArmStreamAnalyticsJob(), + "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), + "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), + "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), + "azurerm_subnet": dataSourceArmSubnet(), + "azurerm_subscription": dataSourceArmSubscription(), + "azurerm_subscriptions": dataSourceArmSubscriptions(), + "azurerm_traffic_manager_geographical_location": dataSourceArmTrafficManagerGeographicalLocation(), + "azurerm_user_assigned_identity": dataSourceArmUserAssignedIdentity(), + "azurerm_virtual_hub": dataSourceArmVirtualHub(), + "azurerm_virtual_machine": dataSourceArmVirtualMachine(), + "azurerm_virtual_network_gateway": dataSourceArmVirtualNetworkGateway(), + "azurerm_virtual_network_gateway_connection": dataSourceArmVirtualNetworkGatewayConnection(), + "azurerm_virtual_network": dataSourceArmVirtualNetwork(), } resources := map[string]*schema.Resource{ diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index b79590f1e602..337341464ee6 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -43,15 +43,21 @@ func resourceArmPrivateLinkService() *schema.Resource { "auto_approval_subscription_ids": { Type: schema.TypeSet, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.GUID, + }, + Set: schema.HashString, }, "visibility_subscription_ids": { Type: schema.TypeSet, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.GUID, + }, + Set: schema.HashString, }, // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you @@ -115,8 +121,11 @@ func resourceArmPrivateLinkService() *schema.Resource { "load_balancer_frontend_ip_configuration_ids": { Type: schema.TypeSet, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + Set: schema.HashString, }, "alias": { @@ -127,8 +136,11 @@ func resourceArmPrivateLinkService() *schema.Resource { "network_interface_ids": { Type: schema.TypeSet, Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + Set: schema.HashString, }, "tags": tags.Schema(), @@ -235,15 +247,11 @@ func resourceArmPrivateLinkServiceRead(d *schema.ResourceData, meta interface{}) if props := resp.PrivateLinkServiceProperties; props != nil { d.Set("alias", props.Alias) - if props.AutoApproval != nil { - if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { - return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) - } + if err := d.Set("auto_approval_subscription_ids", utils.FlattenStringSlice(props.AutoApproval.Subscriptions)); err != nil { + return fmt.Errorf("Error setting `auto_approval_subscription_ids`: %+v", err) } - if props.Visibility != nil { - if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { - return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) - } + if err := d.Set("visibility_subscription_ids", utils.FlattenStringSlice(props.Visibility.Subscriptions)); err != nil { + return fmt.Errorf("Error setting `visibility_subscription_ids`: %+v", err) } // currently not implemented yet, timeline unknown, exact purpose unknown, maybe coming to a future API near you // if props.Fqdns != nil { diff --git a/azurerm/resource_arm_subnet.go b/azurerm/resource_arm_subnet.go index ea90848fc3b6..57b01c227c9e 100644 --- a/azurerm/resource_arm_subnet.go +++ b/azurerm/resource_arm_subnet.go @@ -289,9 +289,9 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("address_prefix", props.AddressPrefix) if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not - // supported by private endpoints. + // To enable private endpoints you must disable the network policies for the + // subnet because Network policies like network security groups are not + // supported by private endpoints. d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *p)) } From 8bc37dc0070b664bffdb8de881bf4be6063d721d Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 21 Nov 2019 12:35:42 -0800 Subject: [PATCH 42/44] Added state wait code --- azurerm/resource_arm_private_link_service.go | 33 +++++++++++++++++++ .../resource_arm_private_link_service_test.go | 10 ++++++ 2 files changed, 43 insertions(+) diff --git a/azurerm/resource_arm_private_link_service.go b/azurerm/resource_arm_private_link_service.go index 337341464ee6..6abd064bdfc1 100644 --- a/azurerm/resource_arm_private_link_service.go +++ b/azurerm/resource_arm_private_link_service.go @@ -1,10 +1,13 @@ package azurerm import ( + "context" "fmt" "log" + "time" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-07-01/network" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" @@ -215,6 +218,20 @@ func resourceArmPrivateLinkServiceCreateUpdate(d *schema.ResourceData, meta inte if resp.ID == nil || *resp.ID == "" { return fmt.Errorf("API returns a nil/empty id on Private Link Service %q (Resource Group %q): %+v", name, resourceGroup, err) } + + // we can't rely on the use of the Future here due to the resource being successfully completed but now the service is applying those values. + log.Printf("[DEBUG] Waiting for Private Link Service to %q (Resource Group %q) to finish applying", name, resourceGroup) + stateConf := &resource.StateChangeConf{ + Pending: []string{"Pending", "Updating", "Creating"}, + Target: []string{"Succeeded"}, + Refresh: privateLinkServiceWaitForReadyRefreshFunc(ctx, client, resourceGroup, name), + Timeout: 60 * time.Minute, + MinTimeout: 15 * time.Second, + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("Error waiting for Private Link Service %q (Resource Group %q) to complete: %s", name, resourceGroup, err) + } + d.SetId(*resp.ID) return resourceArmPrivateLinkServiceRead(d, meta) @@ -421,3 +438,19 @@ func flattenArmPrivateLinkServiceInterface(input *[]network.Interface) *schema.S return results } + +func privateLinkServiceWaitForReadyRefreshFunc(ctx context.Context, client *network.PrivateLinkServicesClient, resourceGroupName string, name string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + res, err := client.Get(ctx, resourceGroupName, name, "") + if err != nil { + return nil, "Error", fmt.Errorf("Error issuing read request in privateLinkServiceWaitForReadyRefreshFunc %q (Resource Group %q): %s", name, resourceGroupName, err) + } + if props := res.PrivateLinkServiceProperties; props != nil { + if state := props.ProvisioningState; state != "" { + return res, string(state), nil + } + } + + return res, "Pending", nil + } +} diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 98865a97fe80..13d12264d43a 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -56,6 +56,11 @@ func TestAccAzureRMPrivateLinkService_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_update(ri, location), Check: resource.ComposeTestCheckFunc( @@ -107,6 +112,11 @@ func TestAccAzureRMPrivateLinkService_move(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAzureRMPrivateLinkService_moveAdd(ri, location), Check: resource.ComposeTestCheckFunc( From 29a07fd0b1198bc0af50a8f53480bb4b5a5e771b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 21 Nov 2019 15:17:00 -0800 Subject: [PATCH 43/44] Fix test collision issue --- .../resource_arm_private_link_service_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/azurerm/resource_arm_private_link_service_test.go b/azurerm/resource_arm_private_link_service_test.go index 13d12264d43a..dcc51cf4348c 100644 --- a/azurerm/resource_arm_private_link_service_test.go +++ b/azurerm/resource_arm_private_link_service_test.go @@ -202,9 +202,9 @@ func TestAccAzureRMPrivateLinkService_complete(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "auto_approval_subscription_ids.#", "1"), resource.TestCheckResourceAttr(resourceName, "visibility_subscription_ids.#", "1"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.#", "2"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.40"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.41"), resource.TestCheckResourceAttr(resourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(resourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -302,7 +302,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.17" + private_ip_address = "10.5.1.30" private_ip_address_version = "IPv4" primary = true } @@ -328,7 +328,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.17" + private_ip_address = "10.5.1.30" private_ip_address_version = "IPv4" primary = true } @@ -336,7 +336,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.18" + private_ip_address = "10.5.1.22" private_ip_address_version = "IPv4" primary = false } @@ -344,7 +344,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "thirdaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.19" + private_ip_address = "10.5.1.23" private_ip_address_version = "IPv4" primary = false } @@ -352,7 +352,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "fourtharyIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.20" + private_ip_address = "10.5.1.24" private_ip_address_version = "IPv4" primary = false } @@ -628,7 +628,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "primaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.17" + private_ip_address = "10.5.1.40" private_ip_address_version = "IPv4" primary = true } @@ -636,7 +636,7 @@ resource "azurerm_private_link_service" "test" { nat_ip_configuration { name = "secondaryIpConfiguration-%d" subnet_id = azurerm_subnet.test.id - private_ip_address = "10.5.1.18" + private_ip_address = "10.5.1.41" private_ip_address_version = "IPv4" primary = false } From b2dec3030b717701373d65f114c4ff92884f5f6d Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 21 Nov 2019 15:34:10 -0800 Subject: [PATCH 44/44] Update data source validation --- azurerm/data_source_private_link_service_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/data_source_private_link_service_test.go b/azurerm/data_source_private_link_service_test.go index 6f1e3c535be3..700177adefec 100644 --- a/azurerm/data_source_private_link_service_test.go +++ b/azurerm/data_source_private_link_service_test.go @@ -21,9 +21,9 @@ func TestAccDataSourceAzureRMPrivateLinkService_complete(t *testing.T) { Config: testAccDataSourcePrivateLinkService_complete(ri, location), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.#", "2"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.17"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address", "10.5.1.40"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.18"), + resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.1.private_ip_address", "10.5.1.41"), resource.TestCheckResourceAttr(dataSourceName, "nat_ip_configuration.1.private_ip_address_version", "IPv4"), resource.TestCheckResourceAttr(dataSourceName, "load_balancer_frontend_ip_configuration_ids.#", "1"), ),