Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure Function support for Event Grid event subscription #7182

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -22,6 +22,7 @@ import (

func enpointPropertyNames() []string {
return []string{
"azure_function_endpoint",
"eventhub_endpoint",
"eventhub_endpoint_id",
"hybrid_connection_endpoint",
Expand Down Expand Up @@ -91,6 +92,30 @@ func resourceArmEventGridEventSubscription() *schema.Resource {
Computed: true,
},

"azure_function_endpoint": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add an acceptance test covering this new block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really like to do an acceptance test for it. Unfortunately, it's pretty much the same as the webhook endpoint, which is also hard to test. You would first have to be able to deploy a function with an input binding of type eventGridBinding out of Terraform. But that is currently not possible as there is no terraform resource for it. It is only possible to deploy a function app, which hosts multiple functions inside.

I started with an implementation of an azurerm_function resource to also be able to write acceptance tests for the function and webhook endpoints of the eventgrid_event_subscription, but it's not that easy to find a good schema design for it.

Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ConflictsWith: utils.RemoveFromStringArray(enpointPropertyNames(), "azure_function_endpoint"),
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"function_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: azure.ValidateResourceID,
},
"max_events_per_batch": {
Type: schema.TypeInt,
Optional: true,
},
"preferred_batch_size_in_kilobytes": {
Type: schema.TypeInt,
Optional: true,
},
},
},
},

"eventhub_endpoint_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -386,6 +411,11 @@ func resourceArmEventGridEventSubscriptionRead(d *schema.ResourceData, meta inte
d.Set("topic_name", props.Topic)
}

if azureFunctionEndpoint, ok := props.Destination.AsAzureFunctionEventSubscriptionDestination(); ok {
if err := d.Set("azure_function_endpoint", flattenEventGridEventSubscriptionAzureFunctionEndpoint(azureFunctionEndpoint)); err != nil {
return fmt.Errorf("Error setting `%q` for EventGrid Event Subscription %q (Scope %q): %s", "azure_function_endpoint", id.Name, id.Scope, err)
}
}
if v, ok := props.Destination.AsEventHubEventSubscriptionDestination(); ok {
if err := d.Set("eventhub_endpoint_id", v.ResourceID); err != nil {
return fmt.Errorf("Error setting `%q` for EventGrid Event Subscription %q (Scope %q): %s", "eventhub_endpoint_id", id.Name, id.Scope, err)
Expand Down Expand Up @@ -504,6 +534,10 @@ func expandEventGridExpirationTime(d *schema.ResourceData) (*date.Time, error) {
}

func expandEventGridEventSubscriptionDestination(d *schema.ResourceData) eventgrid.BasicEventSubscriptionDestination {
if v, ok := d.GetOk("azure_function_endpoint"); ok {
return expandEventGridEventSubscriptionAzureFunctionEndpoint(v)
}

if v, ok := d.GetOk("eventhub_endpoint_id"); ok {
return &eventgrid.EventHubEventSubscriptionDestination{
EndpointType: eventgrid.EndpointTypeEventHub,
Expand Down Expand Up @@ -593,6 +627,36 @@ func expandEventGridEventSubscriptionHybridConnectionEndpoint(d *schema.Resource
}
}

func expandEventGridEventSubscriptionAzureFunctionEndpoint(input interface{}) eventgrid.BasicEventSubscriptionDestination {
configs := input.([]interface{})

props := eventgrid.AzureFunctionEventSubscriptionDestinationProperties{}
azureFunctionDestination := &eventgrid.AzureFunctionEventSubscriptionDestination{
EndpointType: eventgrid.EndpointTypeAzureFunction,
AzureFunctionEventSubscriptionDestinationProperties: &props,
}

if len(configs) == 0 {
return azureFunctionDestination
}

config := configs[0].(map[string]interface{})

if v, ok := config["function_id"]; ok && v != "" {
props.ResourceID = utils.String(v.(string))
}

if v, ok := config["max_events_per_batch"]; ok && v != 0 {
props.MaxEventsPerBatch = utils.Int32(int32(v.(int)))
}

if v, ok := config["preferred_batch_size_in_kilobytes"]; ok && v != 0 {
props.PreferredBatchSizeInKilobytes = utils.Int32(int32(v.(int)))
}

return azureFunctionDestination
}

func expandEventGridEventSubscriptionWebhookEndpoint(d *schema.ResourceData) eventgrid.BasicEventSubscriptionDestination {
props := d.Get("webhook_endpoint").([]interface{})[0].(map[string]interface{})
url := props["url"].(string)
Expand Down Expand Up @@ -699,6 +763,35 @@ func flattenEventGridEventSubscriptionStorageQueueEndpoint(input *eventgrid.Stor
return []interface{}{result}
}

func flattenEventGridEventSubscriptionAzureFunctionEndpoint(input *eventgrid.AzureFunctionEventSubscriptionDestination) []interface{} {
results := make([]interface{}, 0)

if input == nil {
return results
}

functionID := ""
if input.ResourceID != nil {
functionID = *input.ResourceID
}

maxEventsPerBatch := 0
if input.MaxEventsPerBatch != nil {
maxEventsPerBatch = int(*input.MaxEventsPerBatch)
}

preferredBatchSize := 0
if input.PreferredBatchSizeInKilobytes != nil {
preferredBatchSize = int(*input.PreferredBatchSizeInKilobytes)
}

return append(results, map[string]interface{}{
"function_id": functionID,
"max_events_per_batch": maxEventsPerBatch,
"preferred_batch_size_in_kilobytes": preferredBatchSize,
})
}

func flattenEventGridEventSubscriptionWebhookEndpoint(input *eventgrid.EventSubscriptionFullURL) []interface{} {
if input == nil {
return nil
Expand Down
12 changes: 12 additions & 0 deletions website/docs/r/eventgrid_event_subscription.html.markdown
Expand Up @@ -59,6 +59,8 @@ The following arguments are supported:

* `event_delivery_schema` - (Optional) Specifies the event delivery schema for the event subscription. Possible values include: `EventGridSchema`, `CloudEventSchemaV1_0`, `CustomInputSchema`. Defaults to `EventGridSchema`. Changing this forces a new resource to be created.

* `azure_function_endpoint` - (Optional) An `azure_function_endpoint` block as defined below.

* `eventhub_endpoint` - (Optional / **Deprecated in favour of `eventhub_endpoint_id`**) A `eventhub_endpoint` block as defined below.

* `eventhub_endpoint_id` - (Optional) Specifies the id where the Event Hub is located.
Expand Down Expand Up @@ -97,6 +99,16 @@ A `storage_queue_endpoint` supports the following:

---

An `azure_function_endpoint` supports the following:

* `function_id` - (Required) Specifies the ID of the Function where the Event Subscription will receive events.

* `max_events_per_batch` - (Optional) Maximum number of events per batch.

* `preferred_batch_size_in_kilobytes` - (Optional) Preferred batch size in Kilobytes.

---

A `eventhub_endpoint` supports the following:

* `eventhub_id` - (Required) Specifies the id of the eventhub where the Event Subscription will receive events.
Expand Down