From a9d81b445a2ba197a1384f05942c1fb358ea4b0f Mon Sep 17 00:00:00 2001 From: njucz Date: Wed, 24 Feb 2021 14:03:43 +0800 Subject: [PATCH 1/4] new resource "azurerm_kusto_eventgrid_data_connection" --- .../services/eventhub/eventhub_resource.go | 65 +++--- .../eventhub/eventhub_resource_test.go | 12 +- .../services/eventhub/parse/event_hub.go | 75 +++++++ .../services/eventhub/parse/event_hub_test.go | 128 +++++++++++ .../internal/services/eventhub/resourceids.go | 1 + .../eventhub/validate/event_hub_id.go | 23 ++ .../eventhub/validate/event_hub_id_test.go | 88 ++++++++ ...usto_eventgrid_data_connection_resource.go | 212 ++++++++++++++++++ ...eventgrid_data_connection_resource_test.go | 196 ++++++++++++++++ .../internal/services/kusto/registration.go | 1 + website/azurerm.erb | 3 + ...to_eventgrid_data_connection.html.markdown | 126 +++++++++++ 12 files changed, 885 insertions(+), 45 deletions(-) create mode 100644 azurerm/internal/services/eventhub/parse/event_hub.go create mode 100644 azurerm/internal/services/eventhub/parse/event_hub_test.go create mode 100644 azurerm/internal/services/eventhub/validate/event_hub_id.go create mode 100644 azurerm/internal/services/eventhub/validate/event_hub_id_test.go create mode 100644 azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go create mode 100644 azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go create mode 100644 website/docs/r/kusto_eventgrid_data_connection.html.markdown diff --git a/azurerm/internal/services/eventhub/eventhub_resource.go b/azurerm/internal/services/eventhub/eventhub_resource.go index 458e0c399221..a5519e295e03 100644 --- a/azurerm/internal/services/eventhub/eventhub_resource.go +++ b/azurerm/internal/services/eventhub/eventhub_resource.go @@ -5,14 +5,15 @@ import ( "log" "time" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/validate" - "github.com/Azure/azure-sdk-for-go/services/preview/eventhub/mgmt/2018-01-01-preview/eventhub" "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/services/eventhub/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/validate" + azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -26,9 +27,11 @@ func resourceEventHub() *schema.Resource { Read: resourceEventHubRead, Update: resourceEventHubCreateUpdate, Delete: resourceEventHubDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.EventHubID(id) + return err + }), Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), @@ -152,24 +155,24 @@ func resourceEventHub() *schema.Resource { func resourceEventHubCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Eventhub.EventHubsClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() + log.Printf("[INFO] preparing arguments for Azure ARM EventHub creation.") - name := d.Get("name").(string) - namespaceName := d.Get("namespace_name").(string) - resourceGroup := d.Get("resource_group_name").(string) + id := parse.NewEventHubID(subscriptionId, d.Get("resource_group_name").(string), d.Get("namespace_name").(string), d.Get("name").(string)) if d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, namespaceName, name) + existing, err := client.Get(ctx, id.ResourceGroup, id.NamespaceName, id.Name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing EventHub %q (Namespace %q / Resource Group %q): %s", name, namespaceName, resourceGroup, err) + return fmt.Errorf("checking for presence of existing %s: %s", id, err) } } - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_eventhub", *existing.ID) + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_eventhub", id.ID()) } } @@ -187,20 +190,11 @@ func resourceEventHubCreateUpdate(d *schema.ResourceData, meta interface{}) erro parameters.Properties.CaptureDescription = expandEventHubCaptureDescription(d) } - if _, err := client.CreateOrUpdate(ctx, resourceGroup, namespaceName, name, parameters); err != nil { + if _, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.NamespaceName, id.Name, parameters); err != nil { return err } - read, err := client.Get(ctx, resourceGroup, namespaceName, name) - if err != nil { - return err - } - - if read.ID == nil { - return fmt.Errorf("Cannot read EventHub %s (resource group %s) ID", name, resourceGroup) - } - - d.SetId(*read.ID) + d.SetId(id.ID()) return resourceEventHubRead(d, meta) } @@ -210,26 +204,23 @@ func resourceEventHubRead(d *schema.ResourceData, meta interface{}) error { ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + id, err := parse.EventHubID(d.Id()) if err != nil { return err } - resourceGroup := id.ResourceGroup - namespaceName := id.Path["namespaces"] - name := id.Path["eventhubs"] - resp, err := client.Get(ctx, resourceGroup, namespaceName, name) + resp, err := client.Get(ctx, id.ResourceGroup, id.NamespaceName, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Azure EventHub %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error making Read request on %s: %+v", id, err) } - d.Set("name", resp.Name) - d.Set("namespace_name", namespaceName) - d.Set("resource_group_name", resourceGroup) + d.Set("name", id.Name) + d.Set("namespace_name", id.NamespaceName) + d.Set("resource_group_name", id.ResourceGroup) if props := resp.Properties; props != nil { d.Set("partition_count", props.PartitionCount) @@ -249,21 +240,19 @@ func resourceEventHubDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Eventhub.EventHubsClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + + id, err := parse.EventHubID(d.Id()) if err != nil { return err } - resourceGroup := id.ResourceGroup - namespaceName := id.Path["namespaces"] - name := id.Path["eventhubs"] - resp, err := client.Delete(ctx, resourceGroup, namespaceName, name) + resp, err := client.Delete(ctx, id.ResourceGroup, id.NamespaceName, id.Name) if err != nil { if utils.ResponseWasNotFound(resp) { return nil } - return fmt.Errorf("Error issuing delete request for EventHub %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("deleting request for EventHub %q (resource group %q)s: %+v", id, err) } return nil diff --git a/azurerm/internal/services/eventhub/eventhub_resource_test.go b/azurerm/internal/services/eventhub/eventhub_resource_test.go index 514eb34fe40f..587d2ca0dda6 100644 --- a/azurerm/internal/services/eventhub/eventhub_resource_test.go +++ b/azurerm/internal/services/eventhub/eventhub_resource_test.go @@ -6,7 +6,8 @@ import ( "strconv" "testing" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -324,17 +325,14 @@ func TestAccEventHub_messageRetentionUpdate(t *testing.T) { } func (EventHubResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { - id, err := azure.ParseAzureResourceID(state.ID) + id, err := parse.EventHubID(state.ID) if err != nil { return nil, err } - namespaceName := id.Path["namespaces"] - name := id.Path["eventhubs"] - - resp, err := clients.Eventhub.EventHubsClient.Get(ctx, id.ResourceGroup, namespaceName, name) + resp, err := clients.Eventhub.EventHubsClient.Get(ctx, id.ResourceGroup, id.NamespaceName, id.Name) if err != nil { - return nil, fmt.Errorf("retrieving Event Hub %q (namespace %q / resource group: %q): %v", name, namespaceName, id.ResourceGroup, err) + return nil, fmt.Errorf("retrieving %s: %v", id, err) } return utils.Bool(resp.Properties != nil), nil diff --git a/azurerm/internal/services/eventhub/parse/event_hub.go b/azurerm/internal/services/eventhub/parse/event_hub.go new file mode 100644 index 000000000000..d50faeb05e03 --- /dev/null +++ b/azurerm/internal/services/eventhub/parse/event_hub.go @@ -0,0 +1,75 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type EventHubId struct { + SubscriptionId string + ResourceGroup string + NamespaceName string + Name string +} + +func NewEventHubID(subscriptionId, resourceGroup, namespaceName, name string) EventHubId { + return EventHubId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + NamespaceName: namespaceName, + Name: name, + } +} + +func (id EventHubId) String() string { + segments := []string{ + fmt.Sprintf("Name %q", id.Name), + fmt.Sprintf("Namespace Name %q", id.NamespaceName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Event Hub", segmentsStr) +} + +func (id EventHubId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.EventHub/namespaces/%s/eventhubs/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.NamespaceName, id.Name) +} + +// EventHubID parses a EventHub ID into an EventHubId struct +func EventHubID(input string) (*EventHubId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := EventHubId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + if resourceId.NamespaceName, err = id.PopSegment("namespaces"); err != nil { + return nil, err + } + if resourceId.Name, err = id.PopSegment("eventhubs"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/azurerm/internal/services/eventhub/parse/event_hub_test.go b/azurerm/internal/services/eventhub/parse/event_hub_test.go new file mode 100644 index 000000000000..e79aa2ac0117 --- /dev/null +++ b/azurerm/internal/services/eventhub/parse/event_hub_test.go @@ -0,0 +1,128 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid" +) + +var _ resourceid.Formatter = EventHubId{} + +func TestEventHubIDFormatter(t *testing.T) { + actual := NewEventHubID("12345678-1234-9876-4563-123456789012", "group1", "namespace1", "eventhub1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/eventhub1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestEventHubID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *EventHubId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing NamespaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/", + Error: true, + }, + + { + // missing value for NamespaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/", + Error: true, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/", + Error: true, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/eventhub1", + Expected: &EventHubId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "group1", + NamespaceName: "namespace1", + Name: "eventhub1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/GROUP1/PROVIDERS/MICROSOFT.EVENTHUB/NAMESPACES/NAMESPACE1/EVENTHUBS/EVENTHUB1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := EventHubID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.NamespaceName != v.Expected.NamespaceName { + t.Fatalf("Expected %q but got %q for NamespaceName", v.Expected.NamespaceName, actual.NamespaceName) + } + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + } +} diff --git a/azurerm/internal/services/eventhub/resourceids.go b/azurerm/internal/services/eventhub/resourceids.go index 4bab8fece9e7..a4ac02b58c86 100644 --- a/azurerm/internal/services/eventhub/resourceids.go +++ b/azurerm/internal/services/eventhub/resourceids.go @@ -1,6 +1,7 @@ package eventhub //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Cluster -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/clusters/cluster1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=EventHub -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/eventhub1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=EventHubConsumerGroup -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/eventhub1/consumergroups/consumergroup1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Namespace -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1 //go:generate go run ../../tools/generator-resource-id/main.go -rewrite=true -path=./ -name=NamespaceAuthorizationRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/authorizationRules/rule1 diff --git a/azurerm/internal/services/eventhub/validate/event_hub_id.go b/azurerm/internal/services/eventhub/validate/event_hub_id.go new file mode 100644 index 000000000000..675d2ee337c8 --- /dev/null +++ b/azurerm/internal/services/eventhub/validate/event_hub_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/parse" +) + +func EventHubID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.EventHubID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/azurerm/internal/services/eventhub/validate/event_hub_id_test.go b/azurerm/internal/services/eventhub/validate/event_hub_id_test.go new file mode 100644 index 000000000000..d42765731a09 --- /dev/null +++ b/azurerm/internal/services/eventhub/validate/event_hub_id_test.go @@ -0,0 +1,88 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestEventHubID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing NamespaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/", + Valid: false, + }, + + { + // missing value for NamespaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/", + Valid: false, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/", + Valid: false, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.EventHub/namespaces/namespace1/eventhubs/eventhub1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/GROUP1/PROVIDERS/MICROSOFT.EVENTHUB/NAMESPACES/NAMESPACE1/EVENTHUBS/EVENTHUB1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := EventHubID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go new file mode 100644 index 000000000000..5e67b4a316d8 --- /dev/null +++ b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go @@ -0,0 +1,212 @@ +package kusto + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2020-09-18/kusto" + "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/location" + eventhubValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/kusto/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/kusto/validate" + storageValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate" + azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceKustoEventGridDataConnection() *schema.Resource { + return &schema.Resource{ + Create: resourceKustoEventGridDataConnectionCreate, + Read: resourceKustoEventGridDataConnectionRead, + Delete: resourceKustoEventGridDataConnectionDelete, + + Importer: azSchema.ValidateResourceIDPriorToImportThen(func(id string) error { + _, err := parse.DataConnectionID(id) + return err + }, importDataConnection(kusto.KindEventGrid)), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(60 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Delete: schema.DefaultTimeout(60 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataConnectionName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "cluster_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ClusterName, + }, + + "database_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DatabaseName, + }, + + "storage_account_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: storageValidate.StorageAccountID, + }, + + "eventhub_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: eventhubValidate.EventHubID, + }, + + "consumer_group": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: eventhubValidate.ValidateEventHubConsumerName(), + }, + + "blob_storage_event_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: string(kusto.MicrosoftStorageBlobCreated), + ValidateFunc: validation.StringInSlice([]string{ + string(kusto.MicrosoftStorageBlobCreated), + string(kusto.MicrosoftStorageBlobRenamed), + }, false), + }, + + "ignore_first_record": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + }, + }, + } +} + +func resourceKustoEventGridDataConnectionCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Kusto.DataConnectionsClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for Azure Kusto Event Grid Data Connection creation.") + + id := parse.NewDataConnectionID(subscriptionId, d.Get("resource_group_name").(string), d.Get("cluster_name").(string), d.Get("database_name").(string), d.Get("name").(string)) + resp, err := client.Get(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) + } + } + + if !utils.ResponseWasNotFound(resp.Response) { + return tf.ImportAsExistsError("azurerm_kusto_eventgrid_data_connection", id.ID()) + } + + dataConnection := kusto.EventGridDataConnection{ + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + EventGridConnectionProperties: &kusto.EventGridConnectionProperties{ + StorageAccountResourceID: utils.String(d.Get("storage_account_id").(string)), + EventHubResourceID: utils.String(d.Get("eventhub_id").(string)), + ConsumerGroup: utils.String(d.Get("consumer_group").(string)), + IgnoreFirstRecord: utils.Bool(d.Get("ignore_first_record").(bool)), + BlobStorageEventType: kusto.BlobStorageEventType(d.Get("blob_storage_event_type").(string)), + }, + } + + future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name, dataConnection) + if err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for completion of %s: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceKustoEventGridDataConnectionRead(d, meta) +} + +func resourceKustoEventGridDataConnectionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Kusto.DataConnectionsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DataConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + d.Set("name", id.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("cluster_name", id.ClusterName) + d.Set("database_name", id.DatabaseName) + + if dataConnection, ok := resp.Value.(kusto.EventGridDataConnection); ok { + d.Set("location", location.NormalizeNilable(dataConnection.Location)) + if props := dataConnection.EventGridConnectionProperties; props != nil { + d.Set("storage_account_id", props.StorageAccountResourceID) + d.Set("eventhub_id", props.EventHubResourceID) + d.Set("consumer_group", props.ConsumerGroup) + d.Set("ignore_first_record", props.IgnoreFirstRecord) + d.Set("blob_storage_event_type", props.BlobStorageEventType) + } + } + + return nil +} + +func resourceKustoEventGridDataConnectionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Kusto.DataConnectionsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DataConnectionID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) + if err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for deletion of %s: %+v", id, err) + } + + return nil +} diff --git a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go new file mode 100644 index 000000000000..9fa175749526 --- /dev/null +++ b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go @@ -0,0 +1,196 @@ +package kusto_test + +import ( + "context" + "fmt" + "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/acceptance/check" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/kusto/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +type KustoEventGridDataConnectionResource struct { +} + +func TestAccKustoEventGridDataConnection_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_kusto_eventgrid_data_connection", "test") + r := KustoEventGridDataConnectionResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccKustoEventGridDataConnection_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_kusto_eventgrid_data_connection", "test") + r := KustoEventGridDataConnectionResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccKustoEventGridDataConnection_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_kusto_eventgrid_data_connection", "test") + r := KustoEventGridDataConnectionResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.complete(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (KustoEventGridDataConnectionResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { + id, err := parse.DataConnectionID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Kusto.DataConnectionsClient.Get(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %v", id.String(), err) + } + + value, ok := resp.Value.AsEventGridDataConnection() + if !ok { + return nil, fmt.Errorf("%s is not an Event Grid Data Connection", id.String()) + } + + return utils.Bool(value.EventGridConnectionProperties != nil), nil +} + +func (r KustoEventGridDataConnectionResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_kusto_eventgrid_data_connection" "test" { + name = "acctestkrgdc-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + cluster_name = azurerm_kusto_cluster.test.name + database_name = azurerm_kusto_database.test.name + storage_account_id = azurerm_storage_account.test.id + eventhub_id = azurerm_eventhub.test.id + consumer_group = azurerm_eventhub_consumer_group.test.name +} +`, r.template(data), data.RandomInteger) +} + +func (r KustoEventGridDataConnectionResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_kusto_eventgrid_data_connection" "import" { + name = azurerm_kusto_eventgrid_data_connection.test.name + resource_group_name = azurerm_kusto_eventgrid_data_connection.test.resource_group_name + location = azurerm_kusto_eventgrid_data_connection.test.location + cluster_name = azurerm_kusto_eventgrid_data_connection.test.cluster_name + database_name = azurerm_kusto_eventgrid_data_connection.test.database_name + storage_account_id = azurerm_kusto_eventgrid_data_connection.test.storage_account_id + eventhub_id = azurerm_kusto_eventgrid_data_connection.test.eventhub_id + consumer_group = azurerm_kusto_eventgrid_data_connection.test.consumer_group +} +`, r.basic(data)) +} + +func (r KustoEventGridDataConnectionResource) complete(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_kusto_eventgrid_data_connection" "test" { + name = "acctestkrgdc-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + cluster_name = azurerm_kusto_cluster.test.name + database_name = azurerm_kusto_database.test.name + storage_account_id = azurerm_storage_account.test.id + eventhub_id = azurerm_eventhub.test.id + consumer_group = azurerm_eventhub_consumer_group.test.name + + blob_storage_event_type = "Microsoft.Storage.BlobRenamed" + ignore_first_record = true +} +`, r.template(data), data.RandomInteger) +} + +func (KustoEventGridDataConnectionResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-SecurityCenter-%d" + location = "%s" +} + +resource "azurerm_kusto_cluster" "test" { + name = "acctestkc%s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku { + name = "Dev(No SLA)_Standard_D11_v2" + capacity = 1 + } +} + +resource "azurerm_kusto_database" "test" { + name = "acctestkd-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + cluster_name = azurerm_kusto_cluster.test.name +} + +resource "azurerm_storage_account" "test" { + name = "acctestacc%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_eventhub_namespace" "test" { + name = "acctesteventhubnamespace-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Standard" +} + +resource "azurerm_eventhub" "test" { + name = "acctesteventhub-%d" + namespace_name = azurerm_eventhub_namespace.test.name + resource_group_name = azurerm_resource_group.test.name + partition_count = 1 + message_retention = 1 +} + +resource "azurerm_eventhub_consumer_group" "test" { + name = "acctesteventhubcg-%d" + namespace_name = azurerm_eventhub_namespace.test.name + eventhub_name = azurerm_eventhub.test.name + resource_group_name = azurerm_resource_group.test.name +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} diff --git a/azurerm/internal/services/kusto/registration.go b/azurerm/internal/services/kusto/registration.go index 6a431c623ac2..4d1572669e9a 100644 --- a/azurerm/internal/services/kusto/registration.go +++ b/azurerm/internal/services/kusto/registration.go @@ -34,6 +34,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_kusto_database": resourceKustoDatabase(), "azurerm_kusto_database_principal": resourceKustoDatabasePrincipal(), "azurerm_kusto_database_principal_assignment": resourceKustoDatabasePrincipalAssignment(), + "azurerm_kusto_eventgrid_data_connection": resourceKustoEventGridDataConnection(), "azurerm_kusto_eventhub_data_connection": resourceKustoEventHubDataConnection(), "azurerm_kusto_iothub_data_connection": resourceKustoIotHubDataConnection(), "azurerm_kusto_attached_database_configuration": resourceKustoAttachedDatabaseConfiguration(), diff --git a/website/azurerm.erb b/website/azurerm.erb index ef53cb8dafc0..6e0fb42419da 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -1593,6 +1593,9 @@
  • azurerm_kusto_database_principal_assignment
  • +
  • + azurerm_kusto_eventgrid_data_connection +
  • azurerm_kusto_eventhub_data_connection
  • diff --git a/website/docs/r/kusto_eventgrid_data_connection.html.markdown b/website/docs/r/kusto_eventgrid_data_connection.html.markdown new file mode 100644 index 000000000000..d070403ce7e2 --- /dev/null +++ b/website/docs/r/kusto_eventgrid_data_connection.html.markdown @@ -0,0 +1,126 @@ +--- +subcategory: "Data Explorer" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_kusto_eventgrid_data_connection" +description: |- + Manages Kusto / Data Explorer Event Grid Data Connection +--- + +# azurerm_kusto_eventgrid_data_connection + +Manages a Kusto (also known as Azure Data Explorer) Event Grid Data Connection + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_kusto_cluster" "example" { + name = "example-kusto-cluster" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku { + name = "Standard_D13_v2" + capacity = 2 + } +} + +resource "azurerm_kusto_database" "example" { + name = "example-kusto-database" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + cluster_name = azurerm_kusto_cluster.example.name + hot_cache_period = "P7D" + soft_delete_period = "P31D" +} + +resource "azurerm_storage_account" "example" { + name = "storageaccountname" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + account_tier = "Standard" + account_replication_type = "GRS" +} + +resource "azurerm_eventhub_namespace" "test" { + name = "acctesteventhubnamespace-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Standard" +} + +resource "azurerm_eventhub" "test" { + name = "acctesteventhub-%d" + namespace_name = azurerm_eventhub_namespace.test.name + resource_group_name = azurerm_resource_group.test.name + partition_count = 1 + message_retention = 1 +} + +resource "azurerm_eventhub_consumer_group" "example" { + name = "acceptanceTestEventHubConsumerGroup" + namespace_name = azurerm_eventhub_namespace.example.name + eventhub_name = azurerm_eventhub.example.name + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_kusto_eventgrid_data_connection" "example" { + name = "my-kusto-eventgrid-data-connection" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + cluster_name = azurerm_kusto_cluster.example.name + database_name = azurerm_kusto_database.example.name + storage_account_id = azurerm_storage_account.example.id + eventhub_id = azurerm_eventhub.example.id + consumer_group = azurerm_eventhub_consumer_group.example.name +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Kusto Event Grid Data Connection to create. Changing this forces a new resource to be created. + +* `location` - (Required) The location where the Kusto Database should be created. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) Specifies the Resource Group where the Kusto Database should exist. Changing this forces a new resource to be created. + +* `cluster_name` - (Required) Specifies the name of the Kusto Cluster this data connection will be added to. Changing this forces a new resource to be created. + +* `database_name` - (Required) Specifies the name of the Kusto Database this data connection will be added to. Changing this forces a new resource to be created. + +* `storage_account_id` - (Required) Specifies the resource id of the Storage Account this data connection will use for ingestion. Changing this forces a new resource to be created. + +* `eventhub_id` - (Required) Specifies the resource id of the Event Hub this data connection will use for ingestion. Changing this forces a new resource to be created. + +* `consumer_group` - (Required) Specifies the Event Hub consumer group this data connection will use for ingestion. Changing this forces a new resource to be created. + +* `blob_storage_event_type` - (Optional) Specifies the blob storage event type that needs to be processed. Possible Values are `Microsoft.Storage.BlobCreated` and `Microsoft.Storage.BlobRenamed`. Defaults to `Microsoft.Storage.BlobCreated`. Changing this forces a new resource to be created. + +* `ignore_first_record` - (Optional) is the first record of every file ignored? Defaults to `false`. Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Kusto Event Grid Data Connection. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 60 minutes) Used when creating the Kusto Event Grid Data Connection. +* `read` - (Defaults to 5 minutes) Used when retrieving the Kusto Event Grid Data Connection. +* `delete` - (Defaults to 60 minutes) Used when deleting the Kusto Event Grid Data Connection. + +## Import + +Kusto Event Grid Data Connections can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_kusto_eventgrid_data_connection.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Kusto/Clusters/cluster1/Databases/database1/DataConnections/dataConnection1 +``` From e85b1390c985cbd1aabfb23a2f294ab3bf152478 Mon Sep 17 00:00:00 2001 From: njucz Date: Wed, 24 Feb 2021 15:18:52 +0800 Subject: [PATCH 2/4] update --- ...eventgrid_data_connection_resource_test.go | 19 +++++++++- ...to_eventgrid_data_connection.html.markdown | 35 +++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go index 9fa175749526..39fb2cf8ffe7 100644 --- a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go +++ b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go @@ -94,6 +94,8 @@ resource "azurerm_kusto_eventgrid_data_connection" "test" { storage_account_id = azurerm_storage_account.test.id eventhub_id = azurerm_eventhub.test.id consumer_group = azurerm_eventhub_consumer_group.test.name + + depends_on = [azurerm_eventgrid_event_subscription.test] } `, r.template(data), data.RandomInteger) } @@ -131,6 +133,8 @@ resource "azurerm_kusto_eventgrid_data_connection" "test" { blob_storage_event_type = "Microsoft.Storage.BlobRenamed" ignore_first_record = true + + depends_on = [azurerm_eventgrid_event_subscription.test] } `, r.template(data), data.RandomInteger) } @@ -192,5 +196,18 @@ resource "azurerm_eventhub_consumer_group" "test" { eventhub_name = azurerm_eventhub.test.name resource_group_name = azurerm_resource_group.test.name } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, data.RandomInteger) + +resource "azurerm_eventgrid_event_subscription" "test" { + name = "acctest-eg-%d" + scope = azurerm_storage_account.test.id + eventhub_endpoint_id = azurerm_eventhub.test.id + event_delivery_schema = "EventGridSchema" + included_event_types = ["Microsoft.Storage.BlobCreated", "Microsoft.Storage.BlobRenamed"] + + retry_policy { + event_time_to_live = 144 + max_delivery_attempts = 10 + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/website/docs/r/kusto_eventgrid_data_connection.html.markdown b/website/docs/r/kusto_eventgrid_data_connection.html.markdown index d070403ce7e2..bf3d87641fe2 100644 --- a/website/docs/r/kusto_eventgrid_data_connection.html.markdown +++ b/website/docs/r/kusto_eventgrid_data_connection.html.markdown @@ -46,36 +46,51 @@ resource "azurerm_storage_account" "example" { } resource "azurerm_eventhub_namespace" "test" { - name = "acctesteventhubnamespace-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name + name = "eventhubnamespace-example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name sku = "Standard" } resource "azurerm_eventhub" "test" { - name = "acctesteventhub-%d" - namespace_name = azurerm_eventhub_namespace.test.name - resource_group_name = azurerm_resource_group.test.name + name = "eventhub-example" + namespace_name = azurerm_eventhub_namespace.example.name + resource_group_name = azurerm_resource_group.example.name partition_count = 1 message_retention = 1 } resource "azurerm_eventhub_consumer_group" "example" { - name = "acceptanceTestEventHubConsumerGroup" + name = "consumergroup-example" namespace_name = azurerm_eventhub_namespace.example.name eventhub_name = azurerm_eventhub.example.name resource_group_name = azurerm_resource_group.example.name } +resource "azurerm_eventgrid_event_subscription" "example" { + name = "eventgrid-example" + scope = azurerm_storage_account.example.id + eventhub_endpoint_id = azurerm_eventhub.example.id + event_delivery_schema = "EventGridSchema" + included_event_types = ["Microsoft.Storage.BlobCreated", "Microsoft.Storage.BlobRenamed"] + + retry_policy { + event_time_to_live = 144 + max_delivery_attempts = 10 + } +} + resource "azurerm_kusto_eventgrid_data_connection" "example" { name = "my-kusto-eventgrid-data-connection" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location cluster_name = azurerm_kusto_cluster.example.name database_name = azurerm_kusto_database.example.name - storage_account_id = azurerm_storage_account.example.id - eventhub_id = azurerm_eventhub.example.id - consumer_group = azurerm_eventhub_consumer_group.example.name + storage_account_id = azurerm_storage_account.example.id + eventhub_id = azurerm_eventhub.example.id + consumer_group = azurerm_eventhub_consumer_group.example.name + + depends_on = [azurerm_eventgrid_event_subscription.example] } ``` From a7f92cf7f7312a83380437b4d812fe760c0f8a05 Mon Sep 17 00:00:00 2001 From: njucz Date: Wed, 24 Feb 2021 16:36:53 +0800 Subject: [PATCH 3/4] fix typo --- azurerm/internal/services/eventhub/eventhub_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/eventhub/eventhub_resource.go b/azurerm/internal/services/eventhub/eventhub_resource.go index a5519e295e03..b26c5cfdff49 100644 --- a/azurerm/internal/services/eventhub/eventhub_resource.go +++ b/azurerm/internal/services/eventhub/eventhub_resource.go @@ -252,7 +252,7 @@ func resourceEventHubDelete(d *schema.ResourceData, meta interface{}) error { return nil } - return fmt.Errorf("deleting request for EventHub %q (resource group %q)s: %+v", id, err) + return fmt.Errorf("deleting %s: %+v", id, err) } return nil From d9cdf03dec4e23a0388997574ce448e659b372fa Mon Sep 17 00:00:00 2001 From: njucz Date: Fri, 26 Feb 2021 15:53:50 +0800 Subject: [PATCH 4/4] update according to KT's suggestion --- ...usto_eventgrid_data_connection_resource.go | 38 ++++----- ...eventgrid_data_connection_resource_test.go | 79 +++++++++++++------ ...to_eventgrid_data_connection.html.markdown | 29 ++++--- 3 files changed, 91 insertions(+), 55 deletions(-) diff --git a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go index 5e67b4a316d8..9588f79de433 100644 --- a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go +++ b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource.go @@ -23,7 +23,8 @@ import ( func resourceKustoEventGridDataConnection() *schema.Resource { return &schema.Resource{ - Create: resourceKustoEventGridDataConnectionCreate, + Create: resourceKustoEventGridDataConnectionCreateUpdate, + Update: resourceKustoEventGridDataConnectionCreateUpdate, Read: resourceKustoEventGridDataConnectionRead, Delete: resourceKustoEventGridDataConnectionDelete, @@ -34,6 +35,7 @@ func resourceKustoEventGridDataConnection() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), Read: schema.DefaultTimeout(5 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, @@ -78,7 +80,7 @@ func resourceKustoEventGridDataConnection() *schema.Resource { ValidateFunc: eventhubValidate.EventHubID, }, - "consumer_group": { + "eventhub_consumer_group_name": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -88,7 +90,6 @@ func resourceKustoEventGridDataConnection() *schema.Resource { "blob_storage_event_type": { Type: schema.TypeString, Optional: true, - ForceNew: true, Default: string(kusto.MicrosoftStorageBlobCreated), ValidateFunc: validation.StringInSlice([]string{ string(kusto.MicrosoftStorageBlobCreated), @@ -96,34 +97,35 @@ func resourceKustoEventGridDataConnection() *schema.Resource { }, false), }, - "ignore_first_record": { + "skip_first_record": { Type: schema.TypeBool, Optional: true, Default: false, - ForceNew: true, }, }, } } -func resourceKustoEventGridDataConnectionCreate(d *schema.ResourceData, meta interface{}) error { +func resourceKustoEventGridDataConnectionCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Kusto.DataConnectionsClient subscriptionId := meta.(*clients.Client).Account.SubscriptionId - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() log.Printf("[INFO] preparing arguments for Azure Kusto Event Grid Data Connection creation.") id := parse.NewDataConnectionID(subscriptionId, d.Get("resource_group_name").(string), d.Get("cluster_name").(string), d.Get("database_name").(string), d.Get("name").(string)) - resp, err := client.Get(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) - if err != nil { - if !utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("checking for presence of existing %s: %s", id, err) + if d.IsNewResource() { + resp, err := client.Get(ctx, id.ResourceGroup, id.ClusterName, id.DatabaseName, id.Name) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) + } } - } - if !utils.ResponseWasNotFound(resp.Response) { - return tf.ImportAsExistsError("azurerm_kusto_eventgrid_data_connection", id.ID()) + if !utils.ResponseWasNotFound(resp.Response) { + return tf.ImportAsExistsError("azurerm_kusto_eventgrid_data_connection", id.ID()) + } } dataConnection := kusto.EventGridDataConnection{ @@ -131,8 +133,8 @@ func resourceKustoEventGridDataConnectionCreate(d *schema.ResourceData, meta int EventGridConnectionProperties: &kusto.EventGridConnectionProperties{ StorageAccountResourceID: utils.String(d.Get("storage_account_id").(string)), EventHubResourceID: utils.String(d.Get("eventhub_id").(string)), - ConsumerGroup: utils.String(d.Get("consumer_group").(string)), - IgnoreFirstRecord: utils.Bool(d.Get("ignore_first_record").(bool)), + ConsumerGroup: utils.String(d.Get("eventhub_consumer_group_name").(string)), + IgnoreFirstRecord: utils.Bool(d.Get("skip_first_record").(bool)), BlobStorageEventType: kusto.BlobStorageEventType(d.Get("blob_storage_event_type").(string)), }, } @@ -180,8 +182,8 @@ func resourceKustoEventGridDataConnectionRead(d *schema.ResourceData, meta inter if props := dataConnection.EventGridConnectionProperties; props != nil { d.Set("storage_account_id", props.StorageAccountResourceID) d.Set("eventhub_id", props.EventHubResourceID) - d.Set("consumer_group", props.ConsumerGroup) - d.Set("ignore_first_record", props.IgnoreFirstRecord) + d.Set("eventhub_consumer_group_name", props.ConsumerGroup) + d.Set("skip_first_record", props.IgnoreFirstRecord) d.Set("blob_storage_event_type", props.BlobStorageEventType) } } diff --git a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go index 39fb2cf8ffe7..153eccfe7449 100644 --- a/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go +++ b/azurerm/internal/services/kusto/kusto_eventgrid_data_connection_resource_test.go @@ -62,6 +62,35 @@ func TestAccKustoEventGridDataConnection_complete(t *testing.T) { }) } +func TestAccKustoEventGridDataConnection_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_kusto_eventgrid_data_connection", "test") + r := KustoEventGridDataConnectionResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.complete(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (KustoEventGridDataConnectionResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.DataConnectionID(state.ID) if err != nil { @@ -86,14 +115,14 @@ func (r KustoEventGridDataConnectionResource) basic(data acceptance.TestData) st %s resource "azurerm_kusto_eventgrid_data_connection" "test" { - name = "acctestkrgdc-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - cluster_name = azurerm_kusto_cluster.test.name - database_name = azurerm_kusto_database.test.name - storage_account_id = azurerm_storage_account.test.id - eventhub_id = azurerm_eventhub.test.id - consumer_group = azurerm_eventhub_consumer_group.test.name + name = "acctestkrgdc-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + cluster_name = azurerm_kusto_cluster.test.name + database_name = azurerm_kusto_database.test.name + storage_account_id = azurerm_storage_account.test.id + eventhub_id = azurerm_eventhub.test.id + eventhub_consumer_group_name = azurerm_eventhub_consumer_group.test.name depends_on = [azurerm_eventgrid_event_subscription.test] } @@ -105,14 +134,14 @@ func (r KustoEventGridDataConnectionResource) requiresImport(data acceptance.Tes %s resource "azurerm_kusto_eventgrid_data_connection" "import" { - name = azurerm_kusto_eventgrid_data_connection.test.name - resource_group_name = azurerm_kusto_eventgrid_data_connection.test.resource_group_name - location = azurerm_kusto_eventgrid_data_connection.test.location - cluster_name = azurerm_kusto_eventgrid_data_connection.test.cluster_name - database_name = azurerm_kusto_eventgrid_data_connection.test.database_name - storage_account_id = azurerm_kusto_eventgrid_data_connection.test.storage_account_id - eventhub_id = azurerm_kusto_eventgrid_data_connection.test.eventhub_id - consumer_group = azurerm_kusto_eventgrid_data_connection.test.consumer_group + name = azurerm_kusto_eventgrid_data_connection.test.name + resource_group_name = azurerm_kusto_eventgrid_data_connection.test.resource_group_name + location = azurerm_kusto_eventgrid_data_connection.test.location + cluster_name = azurerm_kusto_eventgrid_data_connection.test.cluster_name + database_name = azurerm_kusto_eventgrid_data_connection.test.database_name + storage_account_id = azurerm_kusto_eventgrid_data_connection.test.storage_account_id + eventhub_id = azurerm_kusto_eventgrid_data_connection.test.eventhub_id + eventhub_consumer_group_name = azurerm_kusto_eventgrid_data_connection.test.eventhub_consumer_group_name } `, r.basic(data)) } @@ -122,17 +151,17 @@ func (r KustoEventGridDataConnectionResource) complete(data acceptance.TestData) %s resource "azurerm_kusto_eventgrid_data_connection" "test" { - name = "acctestkrgdc-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - cluster_name = azurerm_kusto_cluster.test.name - database_name = azurerm_kusto_database.test.name - storage_account_id = azurerm_storage_account.test.id - eventhub_id = azurerm_eventhub.test.id - consumer_group = azurerm_eventhub_consumer_group.test.name + name = "acctestkrgdc-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + cluster_name = azurerm_kusto_cluster.test.name + database_name = azurerm_kusto_database.test.name + storage_account_id = azurerm_storage_account.test.id + eventhub_id = azurerm_eventhub.test.id + eventhub_consumer_group_name = azurerm_eventhub_consumer_group.test.name blob_storage_event_type = "Microsoft.Storage.BlobRenamed" - ignore_first_record = true + skip_first_record = true depends_on = [azurerm_eventgrid_event_subscription.test] } diff --git a/website/docs/r/kusto_eventgrid_data_connection.html.markdown b/website/docs/r/kusto_eventgrid_data_connection.html.markdown index bf3d87641fe2..6ab2222bbc4b 100644 --- a/website/docs/r/kusto_eventgrid_data_connection.html.markdown +++ b/website/docs/r/kusto_eventgrid_data_connection.html.markdown @@ -81,14 +81,14 @@ resource "azurerm_eventgrid_event_subscription" "example" { } resource "azurerm_kusto_eventgrid_data_connection" "example" { - name = "my-kusto-eventgrid-data-connection" - resource_group_name = azurerm_resource_group.example.name - location = azurerm_resource_group.example.location - cluster_name = azurerm_kusto_cluster.example.name - database_name = azurerm_kusto_database.example.name - storage_account_id = azurerm_storage_account.example.id - eventhub_id = azurerm_eventhub.example.id - consumer_group = azurerm_eventhub_consumer_group.example.name + name = "my-kusto-eventgrid-data-connection" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + cluster_name = azurerm_kusto_cluster.example.name + database_name = azurerm_kusto_database.example.name + storage_account_id = azurerm_storage_account.example.id + eventhub_id = azurerm_eventhub.example.id + eventhub_consumer_group_name = azurerm_eventhub_consumer_group.example.name depends_on = [azurerm_eventgrid_event_subscription.example] } @@ -110,13 +110,17 @@ The following arguments are supported: * `storage_account_id` - (Required) Specifies the resource id of the Storage Account this data connection will use for ingestion. Changing this forces a new resource to be created. -* `eventhub_id` - (Required) Specifies the resource id of the Event Hub this data connection will use for ingestion. Changing this forces a new resource to be created. +* `eventhub_id` - (Required) Specifies the resource id of the Event Hub this data connection will use for ingestion. + Changing this forces a new resource to be created. -* `consumer_group` - (Required) Specifies the Event Hub consumer group this data connection will use for ingestion. Changing this forces a new resource to be created. +* `eventhub_consumer_group_name` - (Required) Specifies the Event Hub consumer group this data connection will use for + ingestion. Changing this forces a new resource to be created. -* `blob_storage_event_type` - (Optional) Specifies the blob storage event type that needs to be processed. Possible Values are `Microsoft.Storage.BlobCreated` and `Microsoft.Storage.BlobRenamed`. Defaults to `Microsoft.Storage.BlobCreated`. Changing this forces a new resource to be created. +* `blob_storage_event_type` - (Optional) Specifies the blob storage event type that needs to be processed. Possible + Values are `Microsoft.Storage.BlobCreated` and `Microsoft.Storage.BlobRenamed`. Defaults + to `Microsoft.Storage.BlobCreated`. -* `ignore_first_record` - (Optional) is the first record of every file ignored? Defaults to `false`. Changing this forces a new resource to be created. +* `skip_first_record` - (Optional) is the first record of every file ignored? Defaults to `false`. ## Attributes Reference @@ -129,6 +133,7 @@ The following attributes are exported: The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: * `create` - (Defaults to 60 minutes) Used when creating the Kusto Event Grid Data Connection. +* `update` - (Defaults to 60 minutes) Used when updating the Kusto Event Grid Data Connection. * `read` - (Defaults to 5 minutes) Used when retrieving the Kusto Event Grid Data Connection. * `delete` - (Defaults to 60 minutes) Used when deleting the Kusto Event Grid Data Connection.