From 59c58c3f5d2065e7157c725b2e9ab0f2609ea308 Mon Sep 17 00:00:00 2001 From: Christian Pearce Date: Wed, 1 Apr 2020 23:36:14 -0400 Subject: [PATCH] Add azurerm_route_filter_rule for #1083 broken --- .../services/network/client/client.go | 5 + .../network/data_source_route_filter.go | 58 +++ .../internal/services/network/registration.go | 1 + .../network/resource_arm_route_filter.go | 2 + .../network/resource_arm_route_filter_rule.go | 204 +++++++++++ .../tests/data_source_route_filter_test.go | 35 ++ .../resource_arm_route_filter_rule_test.go | 336 ++++++++++++++++++ 7 files changed, 641 insertions(+) create mode 100644 azurerm/internal/services/network/resource_arm_route_filter_rule.go create mode 100644 azurerm/internal/services/network/tests/resource_arm_route_filter_rule_test.go diff --git a/azurerm/internal/services/network/client/client.go b/azurerm/internal/services/network/client/client.go index 7f67ca02abd6..4c9ec5eb0032 100644 --- a/azurerm/internal/services/network/client/client.go +++ b/azurerm/internal/services/network/client/client.go @@ -27,6 +27,7 @@ type Client struct { PublicIPPrefixesClient *network.PublicIPPrefixesClient RoutesClient *network.RoutesClient RouteFiltersClient *network.RouteFiltersClient + RouteFilterRulesClient *network.RouteFilterRulesClient RouteTablesClient *network.RouteTablesClient SecurityGroupClient *network.SecurityGroupsClient SecurityRuleClient *network.SecurityRulesClient @@ -121,6 +122,9 @@ func NewClient(o *common.ClientOptions) *Client { RouteFiltersClient := network.NewRouteFiltersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&RouteFiltersClient.Client, o.ResourceManagerAuthorizer) + RouteFilterRulesClient := network.NewRouteFilterRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&RouteFilterRulesClient.Client, o.ResourceManagerAuthorizer) + RouteTablesClient := network.NewRouteTablesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&RouteTablesClient.Client, o.ResourceManagerAuthorizer) @@ -179,6 +183,7 @@ func NewClient(o *common.ClientOptions) *Client { PublicIPPrefixesClient: &PublicIPPrefixesClient, RoutesClient: &RoutesClient, RouteFiltersClient: &RouteFiltersClient, + RouteFilterRulesClient: &RouteFilterRulesClient, RouteTablesClient: &RouteTablesClient, SecurityGroupClient: &SecurityGroupClient, SecurityRuleClient: &SecurityRuleClient, diff --git a/azurerm/internal/services/network/data_source_route_filter.go b/azurerm/internal/services/network/data_source_route_filter.go index f2b44cc3a6ce..cb520951b9db 100644 --- a/azurerm/internal/services/network/data_source_route_filter.go +++ b/azurerm/internal/services/network/data_source_route_filter.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-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" @@ -32,6 +33,37 @@ func dataSourceArmRouteFilter() *schema.Resource { "location": azure.SchemaLocationForDataSource(), + "rules": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + + "access": { + Type: schema.TypeString, + Computed: true, + }, + + "rule_type": { + Type: schema.TypeString, + Computed: true, + }, + + "communities": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "tags": tags.SchemaDataSource(), }, } @@ -60,6 +92,32 @@ func dataSourceArmRouteFilterRead(d *schema.ResourceData, meta interface{}) erro if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } + if props := resp.RouteFilterPropertiesFormat; props != nil { + if err := d.Set("rules", flattenRouteFilterDataSourceRules(props.Rules)); err != nil { + return err + } + } return tags.FlattenAndSet(d, resp.Tags) } + +func flattenRouteFilterDataSourceRules(input *[]network.RouteFilterRule) []interface{} { + results := make([]interface{}, 0) + + if rules := input; rules != nil { + for _, rule := range *rules { + r := make(map[string]interface{}) + + r["name"] = *rule.Name + if props := rule.RouteFilterRulePropertiesFormat; props != nil { + r["access"] = string(props.Access) + r["rule_type"] = *props.RouteFilterRuleType + r["communities"] = utils.FlattenStringSlice(props.Communities) + } + + results = append(results, r) + } + } + + return results +} diff --git a/azurerm/internal/services/network/registration.go b/azurerm/internal/services/network/registration.go index 283f2f11e351..e908ea02d3e5 100644 --- a/azurerm/internal/services/network/registration.go +++ b/azurerm/internal/services/network/registration.go @@ -92,6 +92,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_network_watcher_flow_log": resourceArmNetworkWatcherFlowLog(), "azurerm_network_watcher": resourceArmNetworkWatcher(), "azurerm_route_filter": resourceArmRouteFilter(), + "azurerm_route_filter_rule": resourceArmRouteFilterRule(), "azurerm_route_table": resourceArmRouteTable(), "azurerm_route": resourceArmRoute(), "azurerm_subnet_network_security_group_association": resourceArmSubnetNetworkSecurityGroupAssociation(), diff --git a/azurerm/internal/services/network/resource_arm_route_filter.go b/azurerm/internal/services/network/resource_arm_route_filter.go index cc9242a8a3e7..22fa6308c651 100644 --- a/azurerm/internal/services/network/resource_arm_route_filter.go +++ b/azurerm/internal/services/network/resource_arm_route_filter.go @@ -19,6 +19,8 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +var routeFilterResourceName = "azurerm_route_filter" + func resourceArmRouteFilter() *schema.Resource { return &schema.Resource{ Create: resourceArmRouteFilterCreateUpdate, diff --git a/azurerm/internal/services/network/resource_arm_route_filter_rule.go b/azurerm/internal/services/network/resource_arm_route_filter_rule.go new file mode 100644 index 000000000000..aff8cb7b08b3 --- /dev/null +++ b/azurerm/internal/services/network/resource_arm_route_filter_rule.go @@ -0,0 +1,204 @@ +package network + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-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" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmRouteFilterRule() *schema.Resource { + return &schema.Resource{ + Create: resourceArmRouteFilterRuleCreateUpdate, + Read: resourceArmRouteFilterRuleRead, + Update: resourceArmRouteFilterRuleCreateUpdate, + Delete: resourceArmRouteFilterRuleDelete, + + Importer: &schema.ResourceImporter{ + 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, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "route_filter_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "access": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Allow), + string(network.Deny), + }, false), + }, + + "rule_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Community", + }, false), + }, + + "communities": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + } +} + +func resourceArmRouteFilterRuleCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.RouteFilterRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + rfName := d.Get("route_filter_name").(string) + resGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, rfName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Route Filter Rule %q (Route Filter %q / Resource Group %q): %+v", name, rfName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_route_filter_rule", *existing.ID) + } + } + + access := d.Get("access").(string) + ruleType := d.Get("rule_type").(string) + communities := utils.ExpandStringSlice(d.Get("communities").([]interface{})) + + locks.ByName(rfName, routeFilterResourceName) + defer locks.UnlockByName(rfName, routeFilterResourceName) + + rule := network.RouteFilterRule{ + Name: &name, + RouteFilterRulePropertiesFormat: &network.RouteFilterRulePropertiesFormat{ + Access: network.Access(access), + RouteFilterRuleType: &ruleType, + Communities: communities, + }, + } + + future, err := client.CreateOrUpdate(ctx, resGroup, rfName, name, rule) + if err != nil { + return fmt.Errorf("Error Creating/Updating Route Filter Rule %q (Route Filter %q / Resource Group %q): %+v", name, rfName, resGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for completion for Route Filter Rule %q (Route Filter %q / Resource Group %q): %+v", name, rfName, resGroup, err) + } + + read, err := client.Get(ctx, resGroup, rfName, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read Route Filter Rule %q (Route Filter %q / Resource Group %q) ID", rfName, name, resGroup) + } + d.SetId(*read.ID) + + return resourceArmRouteFilterRuleRead(d, meta) +} + +func resourceArmRouteFilterRuleRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.RouteFilterRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + rfName := id.Path["routeFilters"] + ruleName := id.Path["routeFilterRules"] + + resp, err := client.Get(ctx, resGroup, rfName, ruleName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error making Read request on Azure Route Filter Rule %q: %+v", ruleName, err) + } + + d.Set("name", ruleName) + d.Set("resource_group_name", resGroup) + d.Set("route_filter_name", rfName) + + if props := resp.RouteFilterRulePropertiesFormat; props != nil { + d.Set("access", string(props.Access)) + d.Set("rule_type", props.RouteFilterRuleType) + d.Set("communities", utils.FlattenStringSlice(props.Communities)) + } + + return nil +} + +func resourceArmRouteFilterRuleDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.RouteFilterRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + rfName := id.Path["routeFilters"] + ruleName := id.Path["routeFilterRules"] + + locks.ByName(rfName, routeFilterResourceName) + defer locks.UnlockByName(rfName, routeFilterResourceName) + + future, err := client.Delete(ctx, resGroup, rfName, ruleName) + if err != nil { + return fmt.Errorf("Error deleting Route Filter Rule %q (Route Filter %q / Resource Group %q): %+v", ruleName, rfName, resGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for deletion of RouteFilterRule %q (RouteFilterRule Table %q / Resource Group %q): %+v", ruleName, rfName, resGroup, err) + } + + return nil +} diff --git a/azurerm/internal/services/network/tests/data_source_route_filter_test.go b/azurerm/internal/services/network/tests/data_source_route_filter_test.go index 5113031a8583..fc51e403950f 100644 --- a/azurerm/internal/services/network/tests/data_source_route_filter_test.go +++ b/azurerm/internal/services/network/tests/data_source_route_filter_test.go @@ -27,6 +27,29 @@ func TestAccDataSourceAzureRMRouteFilter_basic(t *testing.T) { }) } +func TestAccDataSourceAzureRMRouteFilter_singleRule(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_route_table", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMRouteFilter_singleRule(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(data.ResourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(data.ResourceName, "rule.0.access", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "rule.0.rule_type", "Community"), + resource.TestCheckResourceAttr(data.ResourceName, "rule.0.communities.0", "12076:53004"), + ), + }, + }, + }) +} + func testAccDataSourceAzureRMRouteFilter_basic(data acceptance.TestData) string { r := testAccAzureRMRouteFilter_basic(data) return fmt.Sprintf(` @@ -38,3 +61,15 @@ data "azurerm_route_filter" "test" { } `, r) } + +func testAccDataSourceAzureRMRouteFilter_singleRule(data acceptance.TestData) string { + r := testAccAzureRMRouteFilterRule_basic(data) + return fmt.Sprintf(` +%s + +data "azurerm_route_filter" "test" { + name = azurerm_route_filter.test.name + resource_group_name = azurerm_route_filter.test.resource_group_name +} +`, r) +} diff --git a/azurerm/internal/services/network/tests/resource_arm_route_filter_rule_test.go b/azurerm/internal/services/network/tests/resource_arm_route_filter_rule_test.go new file mode 100644 index 000000000000..d1aad5c66649 --- /dev/null +++ b/azurerm/internal/services/network/tests/resource_arm_route_filter_rule_test.go @@ -0,0 +1,336 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMRouteFilterRule_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_route_filter_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMRouteFilterRule_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists("azurerm_route_filter_rule.test"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMRouteFilterRule_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_route_filter_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMRouteFilterRule_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists(data.ResourceName), + ), + }, + { + Config: testAccAzureRMRouteFilterRule_requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_route_filter_rule"), + }, + }, + }) +} + +func TestAccAzureRMRouteFilterRule_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_route_filter_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMRouteFilterRule_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "access", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "rule_type", "Community"), + resource.TestCheckResourceAttr(data.ResourceName, "communities.0", "12076:53004"), + ), + }, + { + Config: testAccAzureRMRouteFilterRule_basicDeny(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "access", "Deny"), + resource.TestCheckResourceAttr(data.ResourceName, "rule_type", "Community"), + resource.TestCheckResourceAttr(data.ResourceName, "communities.0", "12076:52004"), + ), + }, + { + Config: testAccAzureRMRouteFilterRule_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "access", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "rule_type", "Community"), + resource.TestCheckResourceAttr(data.ResourceName, "communities.0", "12076:53004"), + ), + }, + }, + }) +} + +func TestAccAzureRMRouteFilterRule_disappears(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_route_filter_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMRouteFilterRule_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists("azurerm_route_filter_rule.test"), + testCheckAzureRMRouteFilterRuleDisappears("azurerm_route_filter_rule.test"), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAzureRMRouteFilterRule_multipleRouteFilterRules(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_route_filter_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMRouteFilterRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMRouteFilterRule_multipleRouteFilterRules(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRouteFilterRuleExists("azurerm_route_filter_rule.test1"), + testCheckAzureRMRouteFilterRuleExists("azurerm_route_filter_rule.test2"), + ), + }, + }, + }) +} + +func testCheckAzureRMRouteFilterRuleExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.RouteFilterRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %q", resourceName) + } + + name := rs.Primary.Attributes["name"] + rtName := rs.Primary.Attributes["route_filter_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for route_filter_rule: %q", name) + } + + resp, err := client.Get(ctx, resourceGroup, rtName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: RouteFilterRule %q (resource group: %q) does not exist", name, resourceGroup) + } + return fmt.Errorf("Bad: Get on route_filter_rulesClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMRouteFilterRuleDisappears(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.RouteFilterRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + rtName := rs.Primary.Attributes["route_filter_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for route_filter_rule: %s", name) + } + + future, err := client.Delete(ctx, resourceGroup, rtName, name) + if err != nil { + return fmt.Errorf("Error deleting RouteFilterRule %q (RouteFilterRule Table %q / Resource Group %q): %+v", name, rtName, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for deletion of RouteFilterRule %q (RouteFilterRule Table %q / Resource Group %q): %+v", name, rtName, resourceGroup, err) + } + + return nil + } +} + +func testCheckAzureRMRouteFilterRuleDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.RouteFilterRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_route_filter_rule" { + continue + } + + name := rs.Primary.Attributes["name"] + rtName := rs.Primary.Attributes["route_filter_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.Get(ctx, resourceGroup, rtName, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("RouteFilterRule still exists:\n%#v", resp.RouteFilterRulePropertiesFormat) + } + } + + return nil +} + +func testAccAzureRMRouteFilterRule_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_route_filter" "test" { + name = "acctestrf%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_route_filter_rule" "test" { + name = "acctestroute_filter_rule%d" + resource_group_name = azurerm_resource_group.test.name + route_filter_name = azurerm_route_filter.test.name + + access = "Allow" + rule_type = "Community" + communities = ["12076:53004"] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMRouteFilterRule_requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +resource "azurerm_route_filter_rule" "import" { + name = azurerm_route_filter_rule.test.name + resource_group_name = azurerm_route_filter_rule.test.resource_group_name + route_filter_name = azurerm_route_filter_rule.test.route_filter_name + + access = azurerm_route_filter_rule.test.access + rule_type = azurerm_route_filter_rule.test.rule_type + communities = azurerm_route_filter_rule.test.communities +} +`, testAccAzureRMRouteFilterRule_basic(data)) +} + +func testAccAzureRMRouteFilterRule_basicDeny(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_route_filter" "test" { + name = "acctestrf%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_route_filter_rule" "test" { + name = "acctestroute_filter_rule%d" + resource_group_name = azurerm_resource_group.test.name + route_filter_name = azurerm_route_filter.test.name + + access = "Deny" + rule_type = "Community" + communities = ["12076:52004"] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMRouteFilterRule_multipleRouteFilterRules(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_route_filter" "test" { + name = "acctestrf%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_route_filter_rule" "test1" { + name = "acctestroute_filter_rule1_%d" + resource_group_name = azurerm_resource_group.test.name + route_filter_name = azurerm_route_filter.test.name + + access = "Allow" + rule_type = "Community" + communities = ["12076:52005","12076:52006"] +} + +resource "azurerm_route_filter_rule" "test2" { + name = "acctestroute_filter_rule2_%d" + resource_group_name = azurerm_resource_group.test.name + route_filter_name = azurerm_route_filter.test.name + + access = "Deny" + rule_type = "Community" + communities = ["12076:53005","12076:53006"] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +}