Skip to content

Commit 69657fd

Browse files
authored
Merge pull request #1256 from MartinWa/farmer-eventgrid-monitor-alert
Event Grid: Add MonitorAlert support and delivery schema configuration
2 parents 3365a8d + 89c05b1 commit 69657fd

6 files changed

Lines changed: 283 additions & 12 deletions

File tree

‎RELEASE_NOTES.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Release Notes
22
=============
33

4+
## 1.9.29
5+
* Event Grid: Bump API version from `2022-06-15` to `2025-02-15`.
6+
* Event Grid: Add `MonitorAlert` endpoint type for event subscriptions with configurable action groups and severity (Sev0–Sev4).
7+
* Event Grid: Add `event_delivery_schema` keyword to configure the event delivery schema (EventGridSchema, CloudEventSchemaV1_0, CustomInputSchema).
8+
49
## 1.9.28
510
* AKS Cluster: Add native Azure CNI overlay support with `network_plugin_mode`, `network_dataplane`, and `pod_cidr` network profile options. The `pod_cidr` option is also available for kubenet.
611
* Container Apps: Add `resources` operation to the `container` builder to set both CPU and memory together using a `ConsumptionPlanResources` discriminated union. This ensures only valid consumption plan resource combinations can be selected at compile time. The individual `cpu_cores` and `memory` operations remain available for use with dedicated plans.

‎docs/content/api-overview/resources/event-grid.md‎

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ The Event Grid is a simple but powerful builder that links events from Azure ser
1616
|-|-|
1717
| topic_name | The name of the topic that will be created. |
1818
| source | Optional, defaults to the current resource group. The source of the events. See below for the full list of builder configurations that are supported. |
19+
| event_delivery_schema | Optional. Sets the event delivery schema for all subscriptions on this topic. Valid values: `EventGridSchema` (default), `CloudEventSchemaV1_0`, `CustomInputSchema`. |
1920
| add_queue_subscriber | Adds a new storage queue subscriber. Requires the storage account config that will receive the events, the queue name and the list of events to subscribe to. |
2021
| add_webhook_subscriber| Adds a new webhook (HTTP) subscriber. Requires the web app config that will receive the event, associated URI local path and the list of events to subscribe to. Also contains an overload that takes in a Web App name and the full Uri of the webhook. |
2122
| add_eventhub_subscriber| Adds a new event hub subscriber. Requires the event hub builder config that will receive the events and the list of events to subscribe to. |
2223
| add_function_subscriber| Adds a new Azure Functions subscriber. Requires the function app, the handler name and the list of events to subscribe to. |
24+
| add_monitor_alert_subscriber | Adds a new Azure Monitor Alert subscriber. Requires a list of action groups (either `ActionGroupConfig` list or `ResourceId` list), a severity level (`Sev0`–`Sev4`), and the list of events to subscribe to. |
2325

2426
### Supported Sources
2527
Farmer supports the following Event Grid sources using Farmer builders:
@@ -36,15 +38,58 @@ Farmer supports the following Event Grid sources using Farmer builders:
3638
| [IotHub](iot-hub) | SystemEvents.IotHub |
3739
| [EventHub](eventhub) | SystemEvents.EventHub |
3840

39-
### Suported Destinations
41+
### Supported Destinations
4042

41-
* EventHub (`add_eventhub_subscriber`),
42-
* StorageQueue (`add_queue_subscriber`),
43-
* WebHook (`add_webhook_subscriber`),
44-
* ServiceBus Queue (`add_servicebus_queue_subscriber`),
45-
* ServiceBus Topic (`add_servicebus_topic_subscriber`).
43+
* EventHub (`add_eventhub_subscriber`)
44+
* StorageQueue (`add_queue_subscriber`)
45+
* WebHook (`add_webhook_subscriber`)
46+
* ServiceBus Queue (`add_servicebus_queue_subscriber`)
47+
* ServiceBus Topic (`add_servicebus_topic_subscriber`)
48+
* Azure Monitor Alert (`add_monitor_alert_subscriber`)
49+
50+
#### Examples
51+
52+
The following sample routes Key Vault secret expiry events to Azure Monitor Alerts using the CloudEvent schema:
53+
54+
```fsharp
55+
open Farmer
56+
open Farmer.Builders
57+
open Farmer.Arm.EventGrid
58+
59+
let myKeyVault = keyVault { name "mykeyvault" }
60+
61+
// Reference an existing action group by resource ID
62+
let actionGroupId =
63+
Arm.ActionGroups.actionGroups.resourceId (ResourceName "myActionGroup")
64+
65+
let kvExpiryGrid = eventGrid {
66+
topic_name "kv-expiry-topic"
67+
source myKeyVault
68+
event_delivery_schema CloudEventSchemaV1_0
69+
add_monitor_alert_subscriber
70+
[ actionGroupId ]
71+
Sev3
72+
[ SystemEvents.KeyVault.SecretNearExpiry
73+
SystemEvents.KeyVault.SecretExpired ]
74+
}
75+
```
76+
77+
Alternatively, reference a Farmer-managed action group directly:
78+
79+
```fsharp
80+
let alertGroup = actionGroup {
81+
name "myActionGroup"
82+
short_name "myAG"
83+
}
84+
85+
let kvExpiryGrid = eventGrid {
86+
topic_name "kv-expiry-topic"
87+
source myKeyVault
88+
event_delivery_schema CloudEventSchemaV1_0
89+
add_monitor_alert_subscriber [ alertGroup ] Sev3 [ SystemEvents.KeyVault.SecretNearExpiry ]
90+
}
91+
```
4692

47-
#### Example
4893
The following sample creates a source storage account that emits events on the event grid topic, whilst two destinations are created: an event hub and a storage queue, each listening for different events.
4994

5095
```fsharp

‎src/Farmer/Arm/EventGrid.fs‎

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ module Farmer.Arm.EventGrid
44
open Farmer
55
open EventGrid
66

7-
let systemTopics = ResourceType("Microsoft.EventGrid/systemTopics", "2022-06-15")
7+
let systemTopics = ResourceType("Microsoft.EventGrid/systemTopics", "2025-02-15")
88

99
let eventSubscriptions =
10-
ResourceType("Microsoft.EventGrid/systemTopics/eventSubscriptions", "2022-06-15")
10+
ResourceType("Microsoft.EventGrid/systemTopics/eventSubscriptions", "2025-02-15")
1111

1212
type TopicType =
1313
| TopicType of ResourceType * topic: string
@@ -54,6 +54,37 @@ type AzureFunctionEndpointType = {
5454
PreferredBatchSizeInKilobytes: uint
5555
}
5656

57+
type MonitorAlertSeverity =
58+
| Sev0
59+
| Sev1
60+
| Sev2
61+
| Sev3
62+
| Sev4
63+
64+
member this.ArmValue =
65+
match this with
66+
| Sev0 -> "Sev0"
67+
| Sev1 -> "Sev1"
68+
| Sev2 -> "Sev2"
69+
| Sev3 -> "Sev3"
70+
| Sev4 -> "Sev4"
71+
72+
type MonitorAlertEndpointType = {
73+
ActionGroups: ResourceId list
74+
Severity: MonitorAlertSeverity
75+
}
76+
77+
type EventDeliverySchema =
78+
| EventGridSchema
79+
| CloudEventSchemaV1_0
80+
| CustomInputSchema
81+
82+
member this.ArmValue =
83+
match this with
84+
| EventGridSchema -> "EventGridSchema"
85+
| CloudEventSchemaV1_0 -> "CloudEventSchemaV1_0"
86+
| CustomInputSchema -> "CustomInputSchema"
87+
5788
type ServiceBusEndpointType =
5889
| Queue of Queue: ServiceBusQueueEndpointType
5990
| Topic of Topic: ServiceBusTopicEndpointType
@@ -64,6 +95,7 @@ type EndpointType =
6495
| StorageQueue of queue: ResourceName
6596
| ServiceBus of bus: ServiceBusEndpointType
6697
| AzureFunction of AzureFunctionEndpointType
98+
| MonitorAlert of MonitorAlertEndpointType
6799

68100
type Topic = {
69101
Name: ResourceName
@@ -96,6 +128,7 @@ type Subscription<'T> = {
96128
Destination: ResourceName
97129
DestinationEndpoint: EndpointType
98130
Events: EventGridEvent<'T> list
131+
EventDeliverySchema: EventDeliverySchema option
99132
} with
100133

101134
interface IArmResource with
@@ -114,6 +147,7 @@ type Subscription<'T> = {
114147
| WebHook _ -> None
115148
| ServiceBus(Queue { Queue = queue; Bus = bus }) -> Some(ServiceBus.queues.resourceId (bus, queue))
116149
| ServiceBus(Topic { Topic = topic; Bus = bus }) -> Some(ServiceBus.topics.resourceId (bus, topic))
150+
| MonitorAlert _ -> None
117151

118152
{|
119153
eventSubscriptions.Create(
@@ -169,11 +203,24 @@ type Subscription<'T> = {
169203
queueName = topic.Value
170204
|}
171205
|}
206+
| MonitorAlert alert ->
207+
{|
208+
endpointType = "MonitorAlert"
209+
properties = {|
210+
actionGroups = [
211+
for ag in alert.ActionGroups do
212+
ag.Eval()
213+
]
214+
severity = alert.Severity.ArmValue
215+
|}
216+
|}
217+
|> box
172218
filter = {|
173219
includedEventTypes = [
174220
for event in this.Events do
175221
event.Value
176222
]
177223
|}
224+
eventDeliverySchema = this.EventDeliverySchema |> Option.map _.ArmValue |> Option.toObj
178225
|}
179226
|}

‎src/Farmer/Builders/Builders.EventGrid.fs‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ type EventGridConfig<'T> = {
191191
Endpoint: EndpointType
192192
SystemEvents: EventGridEvent<'T> list
193193
|} list
194+
EventDeliverySchema: EventDeliverySchema option
194195
Tags: Map<string, string>
195196
} with
196197

@@ -213,6 +214,7 @@ type EventGridConfig<'T> = {
213214
Destination = sub.Destination
214215
DestinationEndpoint = sub.Endpoint
215216
Events = sub.SystemEvents
217+
EventDeliverySchema = this.EventDeliverySchema
216218
}
217219
]
218220

@@ -221,6 +223,7 @@ type EventGridBuilder() =
221223
TopicName = state.TopicName
222224
Source = source, topic
223225
Subscriptions = []
226+
EventDeliverySchema = None
224227
Tags = Map.empty
225228
}
226229

@@ -243,6 +246,7 @@ type EventGridBuilder() =
243246
TopicName = ResourceName.Empty
244247
Source = ResourceName("[resourceGroup().name]"), Topics.ResourceGroup
245248
Subscriptions = []
249+
EventDeliverySchema = None
246250
Tags = Map.empty
247251
}
248252

@@ -373,6 +377,50 @@ type EventGridBuilder() =
373377
let name = sprintf $"%s{bus.Name.Value}-servicebus-topic"
374378
EventGridBuilder.AddSub(state, name, topic.Name, endpoint, events)
375379

380+
[<CustomOperation "event_delivery_schema">]
381+
member _.EventDeliverySchema(state: EventGridConfig<'T>, schema: EventDeliverySchema) = {
382+
state with
383+
EventDeliverySchema = Some schema
384+
}
385+
386+
[<CustomOperation "add_monitor_alert_subscriber">]
387+
member _.AddMonitorAlertSubscription
388+
(
389+
state: EventGridConfig<'T>,
390+
actionGroups: ActionGroupConfig list,
391+
severity: MonitorAlertSeverity,
392+
events: EventGridEvent<_> list
393+
) =
394+
let ids =
395+
actionGroups
396+
|> List.map (fun ag -> Arm.ActionGroups.actionGroups.resourceId ag.Name)
397+
398+
let endpoint =
399+
MonitorAlert {
400+
ActionGroups = ids
401+
Severity = severity
402+
}
403+
404+
let destination = actionGroups |> List.head |> (fun ag -> ag.Name)
405+
EventGridBuilder.AddSub(state, "monitor-alert", destination, endpoint, events)
406+
407+
[<CustomOperation "add_monitor_alert_subscriber">]
408+
member _.AddMonitorAlertSubscription
409+
(
410+
state: EventGridConfig<'T>,
411+
actionGroupIds: ResourceId list,
412+
severity: MonitorAlertSeverity,
413+
events: EventGridEvent<_> list
414+
) =
415+
let endpoint =
416+
MonitorAlert {
417+
ActionGroups = actionGroupIds
418+
Severity = severity
419+
}
420+
421+
let destination = actionGroupIds |> List.head |> (fun id -> id.Name)
422+
EventGridBuilder.AddSub(state, "monitor-alert", destination, endpoint, events)
423+
376424
[<CustomOperation "add_tags">]
377425
member _.Tags(state: EventGridConfig<'T>, pairs) = {
378426
state with

0 commit comments

Comments
 (0)