Skip to content

Commit

Permalink
New Resource: azurerm_iothub_consumer_group (#2243)
Browse files Browse the repository at this point in the history
* iothub: refactoring

* New Resource: `azurerm_iothub_consumer_group`

Tests pass:
```
$ acctests azurerm TestAccAzureRMIotHubConsumerGroup_
=== RUN   TestAccAzureRMIotHubConsumerGroup_events
--- PASS: TestAccAzureRMIotHubConsumerGroup_events (280.43s)
=== RUN   TestAccAzureRMIotHubConsumerGroup_operationsMonitoringEvents
--- PASS: TestAccAzureRMIotHubConsumerGroup_operationsMonitoringEvents (211.24s)
PASS
ok  	github.com/terraform-providers/terraform-provider-azurerm/azurerm	493.476s
```

Fixes #2230

* adding validation for iothub names
Tests pass:

```
=== RUN   TestValidateIoTHubName
--- PASS: TestValidateIoTHubName (0.00s)
=== RUN   TestValidateIoTHubConsumerGroupName
--- PASS: TestValidateIoTHubConsumerGroupName (0.00s)
PASS
```

* fixing the alignment
  • Loading branch information
tombuildsstuff authored Nov 6, 2018
1 parent 0cfb7a8 commit aaaf121
Show file tree
Hide file tree
Showing 9 changed files with 475 additions and 41 deletions.
28 changes: 28 additions & 0 deletions azurerm/helpers/validate/iothub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package validate

import (
"fmt"
"regexp"
)

func IoTHubName(v interface{}, k string) (ws []string, es []error) {
value := v.(string)

// Portal: The value must contain only alphanumeric characters or the following: -
if matched := regexp.MustCompile(`^[0-9a-zA-Z-]{1,}$`).Match([]byte(value)); !matched {
es = append(es, fmt.Errorf("%q may only contain alphanumeric characters and dashes", k))
}

return
}

func IoTHubConsumerGroupName(v interface{}, k string) (ws []string, es []error) {
value := v.(string)

// Portal: The value must contain only alphanumeric characters or the following: - . _
if matched := regexp.MustCompile(`^[0-9a-zA-Z-._]{1,}$`).Match([]byte(value)); !matched {
es = append(es, fmt.Errorf("%q may only contain alphanumeric characters and dashes, periods and underscores", k))
}

return
}
63 changes: 63 additions & 0 deletions azurerm/helpers/validate/iothub_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package validate

import "testing"

func TestValidateIoTHubName(t *testing.T) {
validNames := []string{
"valid-name",
"valid02-name",
"validName1",
"-validname1",
"double-hyphen--valid",
}
for _, v := range validNames {
_, errors := IoTHubName(v, "example")
if len(errors) != 0 {
t.Fatalf("%q should be a valid IoT Hub Name: %q", v, errors)
}
}

invalidNames := []string{
"",
"invalid_name",
"invalid!",
"!@£",
"hello.world",
}
for _, v := range invalidNames {
_, errors := IoTHubName(v, "name")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid IoT Hub Name", v)
}
}
}

func TestValidateIoTHubConsumerGroupName(t *testing.T) {
validNames := []string{
"valid-name",
"valid02-name",
"validName1",
"-validname1",
"valid_name",
"double-hyphen--valid",
"hello.world",
}
for _, v := range validNames {
_, errors := IoTHubConsumerGroupName(v, "example")
if len(errors) != 0 {
t.Fatalf("%q should be a valid IoT Hub Consumer Group Name: %q", v, errors)
}
}

invalidNames := []string{
"",
"invalid!",
"!@£",
}
for _, v := range invalidNames {
_, errors := IoTHubConsumerGroupName(v, "name")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid IoT Hub Consumer Group Name", v)
}
}
}
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_function_app": resourceArmFunctionApp(),
"azurerm_image": resourceArmImage(),
"azurerm_iothub": resourceArmIotHub(),
"azurerm_iothub_consumer_group": resourceArmIotHubConsumerGroup(),
"azurerm_key_vault": resourceArmKeyVault(),
"azurerm_key_vault_access_policy": resourceArmKeyVaultAccessPolicy(),
"azurerm_key_vault_certificate": resourceArmKeyVaultCertificate(),
Expand Down
66 changes: 29 additions & 37 deletions azurerm/resource_arm_iothub.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,27 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmIotHub() *schema.Resource {
return &schema.Resource{
Create: resourceArmIotHubCreateAndUpdate,
Create: resourceArmIotHubCreateUpdate,
Read: resourceArmIotHubRead,
Update: resourceArmIotHubCreateAndUpdate,
Update: resourceArmIotHubCreateUpdate,
Delete: resourceArmIotHubDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.IoTHubName,
},

"location": locationSchema(),
Expand All @@ -48,7 +51,7 @@ func resourceArmIotHub() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: validation.StringInSlice([]string{
string(devices.B1),
string(devices.B2),
Expand All @@ -63,7 +66,7 @@ func resourceArmIotHub() *schema.Resource {
"tier": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: validation.StringInSlice([]string{
string(devices.Basic),
string(devices.Free),
Expand Down Expand Up @@ -186,7 +189,7 @@ func resourceArmIotHub() *schema.Resource {
"encoding": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: validation.StringInSlice([]string{
string(eventhub.Avro),
string(eventhub.AvroDeflate),
Expand Down Expand Up @@ -250,7 +253,7 @@ func resourceArmIotHub() *schema.Resource {

}

func resourceArmIotHubCreateAndUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceArmIotHubCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).iothubResourceClient
ctx := meta.(*ArmClient).StopContext
subscriptionID := meta.(*ArmClient).subscriptionId
Expand Down Expand Up @@ -283,21 +286,17 @@ func resourceArmIotHubCreateAndUpdate(d *schema.ResourceData, meta interface{})

routes := expandIoTHubRoutes(d)

routingProperties := devices.RoutingProperties{
Endpoints: endpoints,
Routes: routes,
}

iotHubProperties := devices.IotHubProperties{
Routing: &routingProperties,
}

properties := devices.IotHubDescription{
Name: utils.String(name),
Location: utils.String(location),
Sku: &skuInfo,
Tags: expandTags(tags),
Properties: &iotHubProperties,
Name: utils.String(name),
Location: utils.String(location),
Sku: skuInfo,
Properties: &devices.IotHubProperties{
Routing: &devices.RoutingProperties{
Endpoints: endpoints,
Routes: routes,
},
},
Tags: expandTags(tags),
}

future, err := client.CreateOrUpdate(ctx, resourceGroup, name, properties, "")
Expand Down Expand Up @@ -359,20 +358,13 @@ func resourceArmIotHubRead(d *schema.ResourceData, meta interface{}) error {
if v == nil {
continue
}

if k == "events" {
if v.Endpoint != nil {
d.Set("event_hub_events_endpoint", *v.Endpoint)
}
if v.Path != nil {
d.Set("event_hub_events_path", *v.Path)
}
d.Set("event_hub_events_endpoint", v.Endpoint)
d.Set("event_hub_events_path", v.Path)
} else if k == "operationsMonitoringEvents" {
if v.Endpoint != nil {
d.Set("event_hub_operations_endpoint", *v.Endpoint)
}
if v.Path != nil {
d.Set("event_hub_operations_path", *v.Path)
}
d.Set("event_hub_operations_endpoint", v.Endpoint)
d.Set("event_hub_operations_path", v.Path)
}

}
Expand Down Expand Up @@ -568,15 +560,15 @@ func expandIoTHubEndpoints(d *schema.ResourceData, subscriptionId string) (*devi
}, nil
}

func expandIoTHubSku(d *schema.ResourceData) devices.IotHubSkuInfo {
func expandIoTHubSku(d *schema.ResourceData) *devices.IotHubSkuInfo {
skuList := d.Get("sku").([]interface{})
skuMap := skuList[0].(map[string]interface{})
capacity := int64(skuMap["capacity"].(int))

name := skuMap["name"].(string)
tier := skuMap["tier"].(string)

return devices.IotHubSkuInfo{
return &devices.IotHubSkuInfo{
Name: devices.IotHubSku(name),
Tier: devices.IotHubSkuTier(tier),
Capacity: utils.Int64(capacity),
Expand Down
128 changes: 128 additions & 0 deletions azurerm/resource_arm_iothub_consumer_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package azurerm

import (
"fmt"
"log"

"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmIotHubConsumerGroup() *schema.Resource {
return &schema.Resource{
Create: resourceArmIotHubConsumerGroupCreate,
Read: resourceArmIotHubConsumerGroupRead,
Delete: resourceArmIotHubConsumerGroupDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.IoTHubConsumerGroupName,
},

"iothub_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.IoTHubName,
},

"eventhub_endpoint_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"resource_group_name": resourceGroupNameSchema(),
},
}
}

func resourceArmIotHubConsumerGroupCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).iothubResourceClient
ctx := meta.(*ArmClient).StopContext
log.Printf("[INFO] preparing arguments for AzureRM IoTHub Consumer Group creation.")

name := d.Get("name").(string)
iotHubName := d.Get("iothub_name").(string)
endpointName := d.Get("eventhub_endpoint_name").(string)
resourceGroup := d.Get("resource_group_name").(string)

_, err := client.CreateEventHubConsumerGroup(ctx, resourceGroup, iotHubName, endpointName, name)
if err != nil {
return err
}

read, err := client.GetEventHubConsumerGroup(ctx, resourceGroup, iotHubName, endpointName, name)
if err != nil {
return err
}

if read.ID == nil {
return fmt.Errorf("Cannot read IoTHub Consumer Group %q (Resource Group %q) ID", name, resourceGroup)
}

d.SetId(*read.ID)

return resourceArmIotHubConsumerGroupRead(d, meta)
}

func resourceArmIotHubConsumerGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).iothubResourceClient
ctx := meta.(*ArmClient).StopContext

id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resourceGroup := id.ResourceGroup
iotHubName := id.Path["IotHubs"]
endpointName := id.Path["eventHubEndpoints"]
name := id.Path["ConsumerGroups"]

resp, err := client.GetEventHubConsumerGroup(ctx, resourceGroup, iotHubName, endpointName, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
d.SetId("")
return nil
}
return fmt.Errorf("Error making Read request on IoTHub Consumer Group %s: %+v", name, err)
}

d.Set("name", name)
d.Set("iothub_name", iotHubName)
d.Set("eventhub_endpoint_name", endpointName)
d.Set("resource_group_name", resourceGroup)

return nil
}

func resourceArmIotHubConsumerGroupDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).iothubResourceClient
ctx := meta.(*ArmClient).StopContext

id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resourceGroup := id.ResourceGroup
iotHubName := id.Path["IotHubs"]
endpointName := id.Path["eventHubEndpoints"]
name := id.Path["ConsumerGroups"]

resp, err := client.DeleteEventHubConsumerGroup(ctx, resourceGroup, iotHubName, endpointName, name)

if err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("Error issuing delete request for IoTHub Consumer Group %q (Resource Group %q): %+v", name, resourceGroup, err)
}
}

return nil
}
Loading

0 comments on commit aaaf121

Please sign in to comment.