Skip to content

Commit

Permalink
New Feature: azrurerm_iot_dps - add support for linked_hub (#3922)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbfrahry authored Aug 1, 2019
1 parent 2a290b3 commit bf492f5
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 5 deletions.
113 changes: 108 additions & 5 deletions azurerm/resource_arm_iot_dps.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"regexp"
"strconv"
"time"

Expand Down Expand Up @@ -84,6 +85,50 @@ func resourceArmIotDPS() *schema.Resource {
},
},

"linked_hub": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"connection_string": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
ForceNew: true,
// Azure returns the key as ****. We'll suppress that here.
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
secretKeyRegex := regexp.MustCompile("(SharedAccessKey)=[^;]+")
maskedNew := secretKeyRegex.ReplaceAllString(new, "$1=****")
return (new == d.Get(k).(string)) && (maskedNew == old)
},
Sensitive: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
StateFunc: azure.NormalizeLocation,
ForceNew: true,
},
"apply_allocation_policy": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"allocation_weight": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
ValidateFunc: validation.IntBetween(0, 1000),
},
"hostname": {
Type: schema.TypeString,
Computed: true,
},
},
},
},

"tags": tagsSchema(),
},
}
Expand All @@ -110,11 +155,13 @@ func resourceArmIotDPSCreateOrUpdate(d *schema.ResourceData, meta interface{}) e
}

iotdps := iothub.ProvisioningServiceDescription{
Location: utils.String(d.Get("location").(string)),
Name: utils.String(name),
Sku: expandIoTDPSSku(d),
Properties: &iothub.IotDpsPropertiesDescription{},
Tags: expandTags(d.Get("tags").(map[string]interface{})),
Location: utils.String(d.Get("location").(string)),
Name: utils.String(name),
Sku: expandIoTDPSSku(d),
Properties: &iothub.IotDpsPropertiesDescription{
IotHubs: expandIoTDPSIoTHubs(d.Get("linked_hub").([]interface{})),
},
Tags: expandTags(d.Get("tags").(map[string]interface{})),
}

future, err := client.CreateOrUpdate(ctx, resourceGroup, name, iotdps)
Expand Down Expand Up @@ -170,6 +217,13 @@ func resourceArmIotDPSRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("sku", sku); err != nil {
return fmt.Errorf("Error setting `sku`: %+v", err)
}

if props := resp.Properties; props != nil {
if err := d.Set("linked_hub", flattenIoTDPSLinkedHub(props.IotHubs)); err != nil {
return fmt.Errorf("Error setting `linked_hub`: %+v", err)
}
}

flattenAndSetTags(d, resp.Tags)

return nil
Expand Down Expand Up @@ -244,6 +298,24 @@ func expandIoTDPSSku(d *schema.ResourceData) *iothub.IotDpsSkuInfo {
}
}

func expandIoTDPSIoTHubs(input []interface{}) *[]iothub.DefinitionDescription {
linkedHubs := make([]iothub.DefinitionDescription, 0)

for _, attr := range input {
linkedHubConfig := attr.(map[string]interface{})
linkedHub := iothub.DefinitionDescription{
ConnectionString: utils.String(linkedHubConfig["connection_string"].(string)),
AllocationWeight: utils.Int32(int32(linkedHubConfig["allocation_weight"].(int))),
ApplyAllocationPolicy: utils.Bool((linkedHubConfig["apply_allocation_policy"].(bool))),
Location: utils.String(linkedHubConfig["location"].(string)),
}

linkedHubs = append(linkedHubs, linkedHub)
}

return &linkedHubs
}

func flattenIoTDPSSku(input *iothub.IotDpsSkuInfo) []interface{} {
output := make(map[string]interface{})

Expand All @@ -255,3 +327,34 @@ func flattenIoTDPSSku(input *iothub.IotDpsSkuInfo) []interface{} {

return []interface{}{output}
}

func flattenIoTDPSLinkedHub(input *[]iothub.DefinitionDescription) []interface{} {
linkedHubs := make([]interface{}, 0)
if input == nil {
return linkedHubs
}

for _, attr := range *input {
linkedHub := make(map[string]interface{})

if attr.Name != nil {
linkedHub["hostname"] = *attr.Name
}
if attr.ApplyAllocationPolicy != nil {
linkedHub["apply_allocation_policy"] = *attr.ApplyAllocationPolicy
}
if attr.AllocationWeight != nil {
linkedHub["allocation_weight"] = *attr.AllocationWeight
}
if attr.ConnectionString != nil {
linkedHub["connection_string"] = *attr.ConnectionString
}
if attr.Location != nil {
linkedHub["location"] = *attr.Location
}

linkedHubs = append(linkedHubs, linkedHub)
}

return linkedHubs
}
95 changes: 95 additions & 0 deletions azurerm/resource_arm_iot_dps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,41 @@ func TestAccAzureRMIotDPS_update(t *testing.T) {
})
}

func TestAccAzureRMIotDPS_linkedHubs(t *testing.T) {
resourceName := "azurerm_iot_dps.test"
rInt := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMIotDPSDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMIotDPS_linkedHubs(rInt, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMIotDPSExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAzureRMIotDPS_linkedHubsUpdated(rInt, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMIotDPSExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testCheckAzureRMIotDPSDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*ArmClient).iothub.DPSResourceClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext
Expand Down Expand Up @@ -216,3 +251,63 @@ resource "azurerm_iot_dps" "test" {
}
`, rInt, location, rInt)
}

func testAccAzureRMIotDPS_linkedHubs(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_iot_dps" "test" {
name = "acctestIoTDPS-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
sku {
name = "S1"
tier = "Standard"
capacity = "1"
}
linked_hub {
connection_string = "HostName=test.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=booo"
location = "${azurerm_resource_group.test.location}"
allocation_weight = 15
apply_allocation_policy = true
}
linked_hub {
connection_string = "HostName=test2.azure-devices.net;SharedAccessKeyName=iothubowner2;SharedAccessKey=key2"
location = "${azurerm_resource_group.test.location}"
}
}
`, rInt, location, rInt)
}

func testAccAzureRMIotDPS_linkedHubsUpdated(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_iot_dps" "test" {
name = "acctestIoTDPS-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
sku {
name = "S1"
tier = "Standard"
capacity = "1"
}
linked_hub {
connection_string = "HostName=test.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=booo"
location = "${azurerm_resource_group.test.location}"
allocation_weight = 150
}
}
`, rInt, location, rInt)
}
16 changes: 16 additions & 0 deletions website/docs/r/iot_dps.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ The following arguments are supported:

* `sku` - (Required) A `sku` block as defined below.

* `linked_hub` - (Optional) A `linked_hub` block as defined below.

* `tags` - (Optional) A mapping of tags to assign to the resource.

---
Expand All @@ -55,6 +57,20 @@ A `sku` block supports the following:

* `capacity` - (Required) The number of provisioned IoT Device Provisioning Service units.

---

A `linked_hub` block supports the following:

* `connection_string` - (Required) The connection string to connect to the IoT Hub. Changing this forces a new resource.

* `location` - (Required) The location of the IoT hub. Changing this forces a new resource.

* `apply_application_policy` - (Optional) Determines whether to apply application policies to the IoT Hub. Defaults to false.

* `allocation_weight` - (Optional) The weight applied to the IoT Hub. Defaults to 0.

* `hostname` - (Computed) The IoT Hub hostname.

## Attributes Reference

The following attributes are exported:
Expand Down

0 comments on commit bf492f5

Please sign in to comment.