From e39ecc1dc0cb97e5a34e9e7feb11016a51920af7 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline Date: Fri, 12 Oct 2018 12:47:19 -0700 Subject: [PATCH] Exposed ignore_missing_vnet_service_endpoint attribute (#2056) * Exposed the ignore_missing_vnet_service_endpoint attribute * Updated documentation * Updated test cases * Moved optional attribute to bottom of schema definition * Add nil check and attribute validation in _IgnoreEndpointValid test case * fixed value check func * Removed nil check for VirtualNetworkRuleProperties * CnP Shenanigans * Updated language in documentation. * Removed is --- ...rm_postgresql_virtual_network_rule_test.go | 31 ------- ...rce_arm_postgresql_virtual_network_rule.go | 54 +++-------- ...rm_postgresql_virtual_network_rule_test.go | 93 ++++++++++++++++++- ...tgresql_virtual_network_rule.html.markdown | 17 ++-- 4 files changed, 113 insertions(+), 82 deletions(-) delete mode 100644 azurerm/import_arm_postgresql_virtual_network_rule_test.go diff --git a/azurerm/import_arm_postgresql_virtual_network_rule_test.go b/azurerm/import_arm_postgresql_virtual_network_rule_test.go deleted file mode 100644 index ed5232b296a6..000000000000 --- a/azurerm/import_arm_postgresql_virtual_network_rule_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package azurerm - -import ( - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" -) - -func TestAccAzureRMPostgreSQLVirtualNetworkRule_importBasic(t *testing.T) { - resourceName := "azurerm_postgresql_virtual_network_rule.test" - - ri := acctest.RandInt() - config := testAccAzureRMPostgreSQLVirtualNetworkRule_basic(ri, testLocation()) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMPostgreSQLVirtualNetworkRuleDestroy, - Steps: []resource.TestStep{ - { - Config: config, - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} diff --git a/azurerm/resource_arm_postgresql_virtual_network_rule.go b/azurerm/resource_arm_postgresql_virtual_network_rule.go index 72b882dc1ac9..ec5fbb6cd999 100644 --- a/azurerm/resource_arm_postgresql_virtual_network_rule.go +++ b/azurerm/resource_arm_postgresql_virtual_network_rule.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "strings" "time" "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" @@ -49,6 +48,11 @@ func resourceArmPostgreSQLVirtualNetworkRule() *schema.Resource { Required: true, ValidateFunc: azure.ValidateResourceID, }, + + "ignore_missing_vnet_service_endpoint": { + Type: schema.TypeBool, + Optional: true, + }, }, } } @@ -61,52 +65,21 @@ func resourceArmPostgreSQLVirtualNetworkRuleCreateUpdate(d *schema.ResourceData, serverName := d.Get("server_name").(string) resourceGroup := d.Get("resource_group_name").(string) subnetId := d.Get("subnet_id").(string) - - // due to a bug in the API we have to ensure the Subnet's configured correctly or the API call will timeout - // BUG: https://github.com/Azure/azure-rest-api-specs/issues/3719 - subnetsClient := meta.(*ArmClient).subnetClient - subnetParsedId, err := parseAzureResourceID(subnetId) - - subnetResourceGroup := subnetParsedId.ResourceGroup - virtualNetwork := subnetParsedId.Path["virtualNetworks"] - subnetName := subnetParsedId.Path["subnets"] - subnet, err := subnetsClient.Get(ctx, subnetResourceGroup, virtualNetwork, subnetName, "") - if err != nil { - if utils.ResponseWasNotFound(subnet.Response) { - return fmt.Errorf("Subnet with ID %q was not found: %+v", subnetId, err) - } - - return fmt.Errorf("Error obtaining Subnet %q (Virtual Network %q / Resource Group %q: %+v", subnetName, virtualNetwork, subnetResourceGroup, err) - } - - containsEndpoint := false - if props := subnet.SubnetPropertiesFormat; props != nil { - if endpoints := props.ServiceEndpoints; endpoints != nil { - for _, e := range *endpoints { - if e.Service == nil { - continue - } - - if strings.EqualFold(*e.Service, "Microsoft.Sql") { - containsEndpoint = true - break - } - } - } - } - - if !containsEndpoint { - return fmt.Errorf("Error creating PostgreSQL Virtual Network Rule: Subnet %q (Virtual Network %q / Resource Group %q) must contain a Service Endpoint for `Microsoft.Sql`", subnetName, virtualNetwork, subnetResourceGroup) - } + ignoreMissingVnetServiceEndpoint := d.Get("ignore_missing_vnet_service_endpoint").(bool) parameters := postgresql.VirtualNetworkRule{ VirtualNetworkRuleProperties: &postgresql.VirtualNetworkRuleProperties{ VirtualNetworkSubnetID: utils.String(subnetId), - IgnoreMissingVnetServiceEndpoint: utils.Bool(false), + IgnoreMissingVnetServiceEndpoint: utils.Bool(ignoreMissingVnetServiceEndpoint), }, } - _, err = client.CreateOrUpdate(ctx, resourceGroup, serverName, name, parameters) + future, err := client.CreateOrUpdate(ctx, resourceGroup, serverName, name, parameters) + if err != nil { + return fmt.Errorf("Error submitting PostgreSQL Virtual Network Rule %q (PostgreSQL Server: %q, Resource Group: %q): %+v", name, serverName, resourceGroup, err) + } + + err = future.WaitForCompletionRef(ctx, client.Client) if err != nil { return fmt.Errorf("Error creating PostgreSQL Virtual Network Rule %q (PostgreSQL Server: %q, Resource Group: %q): %+v", name, serverName, resourceGroup, err) } @@ -166,6 +139,7 @@ func resourceArmPostgreSQLVirtualNetworkRuleRead(d *schema.ResourceData, meta in if props := resp.VirtualNetworkRuleProperties; props != nil { d.Set("subnet_id", props.VirtualNetworkSubnetID) + d.Set("ignore_missing_vnet_service_endpoint", props.IgnoreMissingVnetServiceEndpoint) } return nil diff --git a/azurerm/resource_arm_postgresql_virtual_network_rule_test.go b/azurerm/resource_arm_postgresql_virtual_network_rule_test.go index d860cb74c1cf..ea36033dafd7 100644 --- a/azurerm/resource_arm_postgresql_virtual_network_rule_test.go +++ b/azurerm/resource_arm_postgresql_virtual_network_rule_test.go @@ -16,17 +16,24 @@ func TestAccAzureRMPostgreSQLVirtualNetworkRule_basic(t *testing.T) { resourceName := "azurerm_postgresql_virtual_network_rule.test" ri := acctest.RandInt() + config := testAccAzureRMPostgreSQLVirtualNetworkRule_basic(ri, testLocation()) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testCheckAzureRMPostgreSQLVirtualNetworkRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMPostgreSQLVirtualNetworkRule_basic(ri, testLocation()), + Config: config, Check: resource.ComposeTestCheckFunc( testCheckAzureRMPostgreSQLVirtualNetworkRuleExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -111,6 +118,27 @@ func TestAccAzureRMPostgreSQLVirtualNetworkRule_multipleSubnets(t *testing.T) { }) } +func TestAccAzureRMPostgreSQLVirtualNetworkRule_IgnoreEndpointValid(t *testing.T) { + resourceName := "azurerm_postgresql_virtual_network_rule.test" + ri := acctest.RandInt() + config := testAccAzureRMPostgreSQLVirtualNetworkRule_ignoreEndpointValid(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPostgreSQLVirtualNetworkRuleDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPostgreSQLVirtualNetworkRuleExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "ignore_missing_vnet_service_endpoint", "true"), + ), + }, + }, + }) +} + func testCheckAzureRMPostgreSQLVirtualNetworkRuleExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] @@ -128,7 +156,7 @@ func testCheckAzureRMPostgreSQLVirtualNetworkRuleExists(name string) resource.Te resp, err := client.Get(ctx, resourceGroup, serverName, ruleName) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Bad: PostgreSQL Firewall Rule %q (server %q / resource group %q) was not found", ruleName, serverName, resourceGroup) + return fmt.Errorf("Bad: PostgreSQL Virtual Network Rule %q (server %q / resource group %q) was not found", ruleName, serverName, resourceGroup) } return err @@ -160,7 +188,7 @@ func testCheckAzureRMPostgreSQLVirtualNetworkRuleDestroy(s *terraform.State) err return err } - return fmt.Errorf("Bad: PostgreSQL Firewall Rule %q (server %q / resource group %q) still exists: %+v", ruleName, serverName, resourceGroup, resp) + return fmt.Errorf("Bad: PostgreSQL Virtual Network Rule %q (server %q / resource group %q) still exists: %+v", ruleName, serverName, resourceGroup, resp) } return nil @@ -458,6 +486,7 @@ resource "azurerm_postgresql_virtual_network_rule" "rule1" { resource_group_name = "${azurerm_resource_group.test.name}" server_name = "${azurerm_postgresql_server.test.name}" subnet_id = "${azurerm_subnet.vnet1_subnet1.id}" + ignore_missing_vnet_service_endpoint = false } resource "azurerm_postgresql_virtual_network_rule" "rule2" { @@ -465,6 +494,7 @@ resource "azurerm_postgresql_virtual_network_rule" "rule2" { resource_group_name = "${azurerm_resource_group.test.name}" server_name = "${azurerm_postgresql_server.test.name}" subnet_id = "${azurerm_subnet.vnet1_subnet2.id}" + ignore_missing_vnet_service_endpoint = false } resource "azurerm_postgresql_virtual_network_rule" "rule3" { @@ -472,6 +502,63 @@ resource "azurerm_postgresql_virtual_network_rule" "rule3" { resource_group_name = "${azurerm_resource_group.test.name}" server_name = "${azurerm_postgresql_server.test.name}" subnet_id = "${azurerm_subnet.vnet2_subnet1.id}" + ignore_missing_vnet_service_endpoint = false } `, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt) } + +func testAccAzureRMPostgreSQLVirtualNetworkRule_ignoreEndpointValid(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" + address_space = ["10.7.29.0/29"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.7.29.0/29" + service_endpoints = ["Microsoft.Storage"] +} + +resource "azurerm_postgresql_server" "test" { + name = "acctestpostgresqlsvr-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "GP_Gen5_2" + capacity = 2 + tier = "GeneralPurpose" + family = "Gen5" + } + + storage_profile { + storage_mb = 51200 + backup_retention_days = 7 + geo_redundant_backup = "Disabled" + } + + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + version = "9.5" + ssl_enforcement = "Enabled" +} + +resource "azurerm_postgresql_virtual_network_rule" "test" { + name = "acctestpostgresqlvnetrule%d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_postgresql_server.test.name}" + subnet_id = "${azurerm_subnet.test.id}" + ignore_missing_vnet_service_endpoint = true +} +`, rInt, location, rInt, rInt, rInt, rInt) +} diff --git a/website/docs/r/postgresql_virtual_network_rule.html.markdown b/website/docs/r/postgresql_virtual_network_rule.html.markdown index cae70a8363af..0cff617067c0 100644 --- a/website/docs/r/postgresql_virtual_network_rule.html.markdown +++ b/website/docs/r/postgresql_virtual_network_rule.html.markdown @@ -53,17 +53,18 @@ resource "azurerm_postgresql_server" "test" { geo_redundant_backup = "Disabled" } - administrator_login = "psqladminun" + administrator_login = "psqladminun" administrator_login_password = "H@Sh1CoR3!" - version = "9.5" - ssl_enforcement = "Enabled" + version = "9.5" + ssl_enforcement = "Enabled" } resource "azurerm_postgresql_virtual_network_rule" "test" { - name = "postgresql-vnet-rule" - resource_group_name = "${azurerm_resource_group.test.name}" - server_name = "${azurerm_postgresql_server.test.name}" - subnet_id = "${azurerm_subnet.internal.id}" + name = "postgresql-vnet-rule" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_postgresql_server.test.name}" + subnet_id = "${azurerm_subnet.internal.id}" + ignore_missing_vnet_service_endpoint = true } ``` @@ -84,7 +85,7 @@ The following arguments are supported: * `subnet_id` - (Required) The ID of the subnet that the PostgreSQL server will be connected to. -~> **NOTE:** Due to [a bug in the Azure API](https://github.com/Azure/azure-rest-api-specs/issues/3719) this resource currently doesn't expose the `ignore_missing_vnet_service_endpoint` field and defaults this to `false`. Terraform will check during the provisioning of the Virtual Network Rule that the Subnet contains the Service Rule to verify that the Virtual Network Rule can be created. +* `ignore_missing_vnet_service_endpoint` - (Optional) Should the Virtual Network Rule be created before the Subnet has the Virtual Network Service Endpoint enabled? Defaults to `false`. ## Attributes Reference