From e8979a2317ee8bdd127ef85f369936c56e703c00 Mon Sep 17 00:00:00 2001 From: Robert Lippens Date: Wed, 3 Apr 2019 18:09:25 -0700 Subject: [PATCH 1/8] iothub IP filters --- azurerm/resource_arm_iothub.go | 70 +++++++++++++++++++++++++++++ azurerm/resource_arm_iothub_test.go | 55 +++++++++++++++++++++++ website/docs/r/iothub.html.markdown | 12 +++++ 3 files changed, 137 insertions(+) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index d2bb809f35b7..7a345839780e 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -323,6 +323,32 @@ func resourceArmIotHub() *schema.Resource { }, }, + "ip_filter_rule": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "ip_mask": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.CIDR, + }, + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(devices.Accept), + string(devices.Reject), + }, false), + }, + }, + }, + }, + "tags": tagsSchema(), }, } @@ -375,12 +401,14 @@ func resourceArmIotHubCreateUpdate(d *schema.ResourceData, meta interface{}) err } routes := expandIoTHubRoutes(d) + ipFilterRules := expandIPFilterRules(d) properties := devices.IotHubDescription{ Name: utils.String(name), Location: utils.String(location), Sku: skuInfo, Properties: &devices.IotHubProperties{ + IPFilterRules: ipFilterRules, Routing: &devices.RoutingProperties{ Endpoints: endpoints, Routes: routes, @@ -476,6 +504,12 @@ func resourceArmIotHubRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("fallback_route", fallbackRoute); err != nil { return fmt.Errorf("Error setting `fallbackRoute` in IoTHub %q: %+v", name, err) } + + ipFilterRules := flattenIPFilterRules((properties.IPFilterRules)) + if err := d.Set("ip_filter_rule", ipFilterRules); err != nil { + return fmt.Errorf("Error setting `ip_filter_rule` in IoTHub %q: %+v", name, err) + } + } d.Set("name", name) @@ -907,3 +941,39 @@ func validateIoTHubFileNameFormat(v interface{}, k string) (warnings []string, e return warnings, errors } +func expandIPFilterRules(d *schema.ResourceData) *[]devices.IPFilterRule { + ipFilterRuleList := d.Get("ip_filter_rule").([]interface{}) + if len(ipFilterRuleList) == 0 { + return nil + } + + rules := make([]devices.IPFilterRule, 0) + + for _, r := range ipFilterRuleList { + rawRule := r.(map[string]interface{}) + rule := &devices.IPFilterRule{ + FilterName: utils.String(rawRule["name"].(string)), + Action: devices.IPFilterActionType(rawRule["action"].(string)), + IPMask: utils.String(rawRule["ip_mask"].(string)), + } + + rules = append(rules, *rule) + } + return &rules +} + +func flattenIPFilterRules(in *[]devices.IPFilterRule) []interface{} { + rules := make([]interface{}, 0) + if in == nil { + return rules + } + + for _, r := range *in { + rawRule := make(map[string]interface{}, 0) + rawRule["name"] = *r.FilterName + rawRule["action"] = string(r.Action) + rawRule["ip_mask"] = *r.IPMask + rules = append(rules, rawRule) + } + return rules +} diff --git a/azurerm/resource_arm_iothub_test.go b/azurerm/resource_arm_iothub_test.go index 28dfaed2413e..209e146f33c0 100644 --- a/azurerm/resource_arm_iothub_test.go +++ b/azurerm/resource_arm_iothub_test.go @@ -35,6 +35,30 @@ func TestAccAzureRMIotHub_basic(t *testing.T) { }) } +func TestAccAzureRMIotHub_ipFilterRules(t *testing.T) { + resourceName := "azurerm_iothub.test" + rInt := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMIotHubDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMIotHub_ipFilterRules(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMIotHubExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMIotHub_requiresImport(t *testing.T) { if !requireResourcesToBeImported { t.Skip("Skipping since resources aren't required to be imported") @@ -271,6 +295,37 @@ resource "azurerm_iothub" "test" { `, rInt, location, rInt) } +func testAccAzureRMIotHub_ipFilterRules(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_iothub" "test" { + name = "acctestIoTHub-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + sku { + name = "S1" + tier = "Standard" + capacity = "1" + } + + ip_filter_rule { + name = "test" + ip_mask = "10.0.0.0/31" + action = "Accept" + } + + tags { + "purpose" = "testing" + } +} +`, rInt, location, rInt) +} + func testAccAzureRMIotHub_customRoutes(rInt int, rStr string, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/iothub.html.markdown b/website/docs/r/iothub.html.markdown index f3e99e327af6..d2e24d13f554 100644 --- a/website/docs/r/iothub.html.markdown +++ b/website/docs/r/iothub.html.markdown @@ -87,6 +87,8 @@ The following arguments are supported: * `endpoint` - (Optional) An `endpoint` block as defined below. +* `ip_filter_rule` - (Optional) One or more `ip_filter_rule` blocks as defined below. + * `route` - (Optional) A `route` block as defined below. * `fallback_route` - (Optional) A `fallback_route` block as defined below. If the fallback route is enabled, messages that don't match any of the supplied routes are automatically sent to this route. Defaults to messages/events. @@ -127,6 +129,16 @@ An `endpoint` block supports the following: --- +An `ip_filter_rule` block supports the following: + +* `name` - (Required) The name of the filter. + +* `ip_mask` - (Required) The IP address range in CIDR notation for the rule. + +* `action` - (Required) The desired action for requests captured by this rule. Possible values include: `Accept`, `Reject` + +--- + A `route` block supports the following: * `name` - (Required) The name of the route. From a493202bdc0958eca0f955a71277d49ec30746c7 Mon Sep 17 00:00:00 2001 From: Robert Lippens Date: Wed, 3 Apr 2019 18:35:17 -0700 Subject: [PATCH 2/8] fix rule violation --- azurerm/resource_arm_iothub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index 7a345839780e..5348b4d22c00 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -969,7 +969,7 @@ func flattenIPFilterRules(in *[]devices.IPFilterRule) []interface{} { } for _, r := range *in { - rawRule := make(map[string]interface{}, 0) + rawRule := make(map[string]interface{}) rawRule["name"] = *r.FilterName rawRule["action"] = string(r.Action) rawRule["ip_mask"] = *r.IPMask From c28ee595ec73c2fb996efb2539229ce26e745e19 Mon Sep 17 00:00:00 2001 From: Robert Lippens Date: Thu, 4 Apr 2019 01:01:00 -0700 Subject: [PATCH 3/8] docs adjustment --- website/docs/r/iothub.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/iothub.html.markdown b/website/docs/r/iothub.html.markdown index d2e24d13f554..397df1848b96 100644 --- a/website/docs/r/iothub.html.markdown +++ b/website/docs/r/iothub.html.markdown @@ -135,7 +135,7 @@ An `ip_filter_rule` block supports the following: * `ip_mask` - (Required) The IP address range in CIDR notation for the rule. -* `action` - (Required) The desired action for requests captured by this rule. Possible values include: `Accept`, `Reject` +* `action` - (Required) The desired action for requests captured by this rule. Possible values are `Accept`, `Reject` --- From 2b3598ea28a93d00a797b0b26d51987ea9749e16 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Thu, 4 Apr 2019 09:06:12 -0700 Subject: [PATCH 4/8] Update azurerm/resource_arm_iothub.go Co-Authored-By: Lucretius --- azurerm/resource_arm_iothub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index 5348b4d22c00..e2d435d9279f 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -324,7 +324,7 @@ func resourceArmIotHub() *schema.Resource { }, "ip_filter_rule": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ From eb8223ca83b83180ac690033f5e9af717b00efcd Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Thu, 4 Apr 2019 09:06:20 -0700 Subject: [PATCH 5/8] Update azurerm/resource_arm_iothub.go Co-Authored-By: Lucretius --- azurerm/resource_arm_iothub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index e2d435d9279f..63180efc5b4a 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -505,7 +505,7 @@ func resourceArmIotHubRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error setting `fallbackRoute` in IoTHub %q: %+v", name, err) } - ipFilterRules := flattenIPFilterRules((properties.IPFilterRules)) + ipFilterRules := flattenIPFilterRules(properties.IPFilterRules) if err := d.Set("ip_filter_rule", ipFilterRules); err != nil { return fmt.Errorf("Error setting `ip_filter_rule` in IoTHub %q: %+v", name, err) } From 3acf886fba9d75f658d50f3c590e7c3163f2eb79 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Thu, 4 Apr 2019 09:06:29 -0700 Subject: [PATCH 6/8] Update azurerm/resource_arm_iothub.go Co-Authored-By: Lucretius --- azurerm/resource_arm_iothub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index 63180efc5b4a..0d8d8a7cfc26 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -942,7 +942,7 @@ func validateIoTHubFileNameFormat(v interface{}, k string) (warnings []string, e return warnings, errors } func expandIPFilterRules(d *schema.ResourceData) *[]devices.IPFilterRule { - ipFilterRuleList := d.Get("ip_filter_rule").([]interface{}) + ipFilterRuleList := d.Get("ip_filter_rule").(*schema.Set).List() if len(ipFilterRuleList) == 0 { return nil } From 284acad4ac8ef597fb9248a44916f3e9a6965b8f Mon Sep 17 00:00:00 2001 From: Robert Lippens Date: Thu, 4 Apr 2019 09:09:20 -0700 Subject: [PATCH 7/8] add nil checks --- azurerm/resource_arm_iothub.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index 0d8d8a7cfc26..77964d6abf1f 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -970,9 +970,16 @@ func flattenIPFilterRules(in *[]devices.IPFilterRule) []interface{} { for _, r := range *in { rawRule := make(map[string]interface{}) - rawRule["name"] = *r.FilterName + + if r.FilterName != nil { + rawRule["name"] = *r.FilterName + } + rawRule["action"] = string(r.Action) - rawRule["ip_mask"] = *r.IPMask + + if r.IPMask != nil { + rawRule["ip_mask"] = *r.IPMask + } rules = append(rules, rawRule) } return rules From 9d1638bb46f8ae3c6470742aec7e011775eeca01 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Sat, 6 Apr 2019 10:18:40 +0200 Subject: [PATCH 8/8] r/iothub: adding validation to the ip_filter_rule name --- azurerm/resource_arm_iothub.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_iothub.go b/azurerm/resource_arm_iothub.go index 77964d6abf1f..af04842bef78 100755 --- a/azurerm/resource_arm_iothub.go +++ b/azurerm/resource_arm_iothub.go @@ -329,8 +329,9 @@ func resourceArmIotHub() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, "ip_mask": { Type: schema.TypeString,