Skip to content

Commit

Permalink
Merge pull request #681 from terraform-providers/eventhub-capture-des…
Browse files Browse the repository at this point in the history
…cription

`azurerm_eventhub`: Adding support for CaptureDescription
  • Loading branch information
tombuildsstuff authored Jan 11, 2018
2 parents eaa3c9e + 9cba8ef commit 8833101
Show file tree
Hide file tree
Showing 4 changed files with 454 additions and 25 deletions.
25 changes: 25 additions & 0 deletions azurerm/import_arm_eventhub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,28 @@ func TestAccAzureRMEventHub_importBasic(t *testing.T) {
},
})
}

func TestAccAzureRMEventHub_importCaptureDescription(t *testing.T) {
resourceName := "azurerm_eventhub.test"

ri := acctest.RandInt()
rs := acctest.RandString(5)
config := testAccAzureRMEventHub_captureDescription(ri, rs, testLocation(), true)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMEventHubDestroy,
Steps: []resource.TestStep{
{
Config: config,
},

{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
244 changes: 221 additions & 23 deletions azurerm/resource_arm_eventhub.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package azurerm
import (
"fmt"
"log"
"net/http"

"strings"

"github.com/Azure/azure-sdk-for-go/arm/eventhub"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand Down Expand Up @@ -50,6 +52,73 @@ func resourceArmEventHub() *schema.Resource {
ValidateFunc: validateEventHubMessageRetentionCount,
},

"capture_description": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
},
"encoding": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
string(eventhub.Avro),
string(eventhub.AvroDeflate),
}, true),
},
"interval_in_seconds": {
Type: schema.TypeInt,
Optional: true,
Default: 300,
ValidateFunc: validation.IntBetween(60, 900),
},
"size_limit_in_bytes": {
Type: schema.TypeInt,
Optional: true,
Default: 314572800,
ValidateFunc: validation.IntBetween(10485760, 524288000),
},
"destination": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"EventHubArchive.AzureBlockBlob",
// TODO: support `EventHubArchive.AzureDataLake` once supported in the Swagger / SDK
// https://github.com/Azure/azure-rest-api-specs/issues/2255
// BlobContainerName & StorageAccountID can then become Optional
}, false),
},
"archive_name_format": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateEventHubArchiveNameFormat,
},
"blob_container_name": {
Type: schema.TypeString,
Required: true,
},
"storage_account_id": {
Type: schema.TypeString,
Required: true,
},
},
},
},
},
},
},

"partition_ids": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Expand All @@ -61,13 +130,12 @@ func resourceArmEventHub() *schema.Resource {
}

func resourceArmEventHubCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
eventhubClient := client.eventHubClient
client := meta.(*ArmClient).eventHubClient
log.Printf("[INFO] preparing arguments for Azure ARM EventHub creation.")

name := d.Get("name").(string)
namespaceName := d.Get("namespace_name").(string)
resGroup := d.Get("resource_group_name").(string)
resourceGroup := d.Get("resource_group_name").(string)
partitionCount := int64(d.Get("partition_count").(int))
messageRetention := int64(d.Get("message_retention").(int))

Expand All @@ -78,18 +146,27 @@ func resourceArmEventHubCreate(d *schema.ResourceData, meta interface{}) error {
},
}

_, err := eventhubClient.CreateOrUpdate(resGroup, namespaceName, name, parameters)
if _, ok := d.GetOk("capture_description"); ok {
captureDescription, err := expandEventHubCaptureDescription(d)
if err != nil {
return fmt.Errorf("Error expanding EventHub Capture Description: %s", err)
}

parameters.Properties.CaptureDescription = captureDescription
}

_, err := client.CreateOrUpdate(resourceGroup, namespaceName, name, parameters)
if err != nil {
return err
}

read, err := eventhubClient.Get(resGroup, namespaceName, name)
read, err := client.Get(resourceGroup, namespaceName, name)
if err != nil {
return err
}

if read.ID == nil {
return fmt.Errorf("Cannot read EventHub %s (resource group %s) ID", name, resGroup)
return fmt.Errorf("Cannot read EventHub %s (resource group %s) ID", name, resourceGroup)
}

d.SetId(*read.ID)
Expand All @@ -98,51 +175,60 @@ func resourceArmEventHubCreate(d *schema.ResourceData, meta interface{}) error {
}

func resourceArmEventHubRead(d *schema.ResourceData, meta interface{}) error {
eventhubClient := meta.(*ArmClient).eventHubClient

client := meta.(*ArmClient).eventHubClient
id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup

resourceGroup := id.ResourceGroup
namespaceName := id.Path["namespaces"]
name := id.Path["eventhubs"]

resp, err := eventhubClient.Get(resGroup, namespaceName, name)
resp, err := client.Get(resourceGroup, namespaceName, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
d.SetId("")
return nil
}
return fmt.Errorf("Error making Read request on Azure EventHub %s: %s", name, err)
return fmt.Errorf("Error making Read request on Azure EventHub %q (resource group %q): %+v", name, resourceGroup, err)
}

d.Set("name", resp.Name)
d.Set("namespace_name", namespaceName)
d.Set("resource_group_name", resGroup)
d.Set("resource_group_name", resourceGroup)

d.Set("partition_count", resp.Properties.PartitionCount)
d.Set("message_retention", resp.Properties.MessageRetentionInDays)
d.Set("partition_ids", resp.Properties.PartitionIds)
if props := resp.Properties; props != nil {
d.Set("partition_count", props.PartitionCount)
d.Set("message_retention", props.MessageRetentionInDays)
d.Set("partition_ids", props.PartitionIds)

captureDescription := flattenEventHubCaptureDescription(props.CaptureDescription)
if err := d.Set("capture_description", captureDescription); err != nil {
return err
}
}

return nil
}

func resourceArmEventHubDelete(d *schema.ResourceData, meta interface{}) error {
eventhubClient := meta.(*ArmClient).eventHubClient

client := meta.(*ArmClient).eventHubClient
id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup

resourceGroup := id.ResourceGroup
namespaceName := id.Path["namespaces"]
name := id.Path["eventhubs"]
resp, err := client.Delete(resourceGroup, namespaceName, name)

resp, err := eventhubClient.Delete(resGroup, namespaceName, name)
if err != nil {
if utils.ResponseWasNotFound(resp) {
return nil
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Error issuing Azure ARM delete request of EventHub'%s': %s", name, err)
return fmt.Errorf("Error issuing delete request for EventHub %q (resource group %q): %+v", name, resourceGroup, err)
}

return nil
Expand All @@ -165,3 +251,115 @@ func validateEventHubMessageRetentionCount(v interface{}, k string) (ws []string
}
return
}

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

requiredComponents := []string{
"{Namespace}",
"{EventHub}",
"{PartitionId}",
"{Year}",
"{Month}",
"{Day}",
"{Hour}",
"{Minute}",
"{Second}",
}

for _, component := range requiredComponents {
if !strings.Contains(value, component) {
errors = append(errors, fmt.Errorf("%s needs to contain %q", k, component))
}
}

return
}

func expandEventHubCaptureDescription(d *schema.ResourceData) (*eventhub.CaptureDescription, error) {
inputs := d.Get("capture_description").([]interface{})
input := inputs[0].(map[string]interface{})

enabled := input["enabled"].(bool)
encoding := input["encoding"].(string)
intervalInSeconds := input["interval_in_seconds"].(int)
sizeLimitInBytes := input["size_limit_in_bytes"].(int)

captureDescription := eventhub.CaptureDescription{
Enabled: utils.Bool(enabled),
Encoding: eventhub.EncodingCaptureDescription(encoding),
IntervalInSeconds: utils.Int32(int32(intervalInSeconds)),
SizeLimitInBytes: utils.Int32(int32(sizeLimitInBytes)),
}

if v, ok := input["destination"]; ok {
destinations := v.([]interface{})
if len(destinations) > 0 {
destination := destinations[0].(map[string]interface{})

destinationName := destination["name"].(string)
archiveNameFormat := destination["archive_name_format"].(string)
blobContainerName := destination["blob_container_name"].(string)
storageAccountId := destination["storage_account_id"].(string)

captureDescription.Destination = &eventhub.Destination{
Name: utils.String(destinationName),
DestinationProperties: &eventhub.DestinationProperties{
ArchiveNameFormat: utils.String(archiveNameFormat),
BlobContainer: utils.String(blobContainerName),
StorageAccountResourceID: utils.String(storageAccountId),
},
}
}
}

return &captureDescription, nil
}

func flattenEventHubCaptureDescription(description *eventhub.CaptureDescription) []interface{} {
results := make([]interface{}, 0)

if description != nil {
output := make(map[string]interface{}, 0)

if enabled := description.Enabled; enabled != nil {
output["enabled"] = *enabled
}

output["encoding"] = string(description.Encoding)

if interval := description.IntervalInSeconds; interval != nil {
output["interval_in_seconds"] = *interval
}

if size := description.SizeLimitInBytes; size != nil {
output["size_limit_in_bytes"] = *size
}

if destination := description.Destination; destination != nil {
destinationOutput := make(map[string]interface{}, 0)

if name := destination.Name; name != nil {
destinationOutput["name"] = *name
}

if props := destination.DestinationProperties; props != nil {
if archiveNameFormat := props.ArchiveNameFormat; archiveNameFormat != nil {
destinationOutput["archive_name_format"] = *archiveNameFormat
}
if blobContainerName := props.BlobContainer; blobContainerName != nil {
destinationOutput["blob_container_name"] = *blobContainerName
}
if storageAccountId := props.StorageAccountResourceID; storageAccountId != nil {
destinationOutput["storage_account_id"] = *storageAccountId
}
}

output["destination"] = []interface{}{destinationOutput}
}

results = append(results, output)
}

return results
}
Loading

0 comments on commit 8833101

Please sign in to comment.