Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
resource "azurerm_monitor_metric_alert" "this" {
name = "${var.name}-availability-alert"
resource_group_name = var.resource_group_name

scopes = [azurerm_application_insights_standard_web_test.this.id, var.application_insights_id]
severity = 0

frequency = var.alert.frequency
window_size = var.alert.window_size
auto_mitigate = var.alert.auto_mitigate

application_insights_web_test_location_availability_criteria {
web_test_id = azurerm_application_insights_standard_web_test.this.id
component_id = var.application_insights_id
failed_location_count = 2
}

description = var.alert.description

action {
action_group_id = var.action_group_id
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ resource "azurerm_application_insights_standard_web_test" "this" {
enabled = true

request {
url = var.target_url
}

geo_locations = var.geo_locations
}
url = var.target_url
http_verb = var.http_verb

resource "azurerm_monitor_metric_alert" "this" {
name = "${var.name}-availability-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_application_insights_standard_web_test.this.id, var.application_insights_id]
description = "availability test alert"
severity = 0

application_insights_web_test_location_availability_criteria {
web_test_id = azurerm_application_insights_standard_web_test.this.id
component_id = var.application_insights_id
failed_location_count = 2
dynamic "header" {
for_each = var.headers
content {
name = header.key
value = header.value
}
}
}

action {
action_group_id = var.action_group_id
# SSL validation rules
dynamic "validation_rules" {
for_each = var.ssl_validation != null ? [1] : []
content {
expected_status_code = var.ssl_validation.expected_status_code
ssl_check_enabled = var.ssl_validation.ssl_check_enabled
ssl_cert_remaining_lifetime = var.ssl_validation.ssl_cert_remaining_lifetime
}
}

geo_locations = var.geo_locations
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,62 @@ Type: `number`

Default: `30`

### <a name="input_http_verb"></a> [http_verb](#input\_http\_verb)

Description: The HTTP verb used for the request.

Type: `string`

Allowed values: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

Default: GET

### <a name="input_headers"></a> [headers](#input\_headers)

Description: A map of HTTP request headers (name => value).

Type: `map(string)`

Default: {}

### <a name="input_ssl_validation"></a> [ssl_validation](#input\_ssl\_validation)

Description: SSL validation configuration for the availability test.

Type:
```hcl
object({
expected_status_code = optional(number, null)
ssl_check_enabled = optional(bool, true)
ssl_cert_remaining_lifetime = optional(number, null)
})
```

Default: null

Validations:
- expected_status_code must be 0 ('0' means 'response code < 400') or a valid HTTP status code (100–599)
- ssl_cert_remaining_lifetime must be null or between 1–365

### <a name="input_alert"></a> [alert](#input\_alert)

Description: Configuration for the availability alert rule.

Type:
```hcl
object({
description = optional(string, "Availability test alert")
frequency = optional(string, "PT1M")
window_size = optional(string, "PT5M")
auto_mitigate = optional(bool, true)
})
```

Defaults: {}

Validations:
- frequency must be one of: PT1M, PT5M, PT15M, PT30M, PT1H
- window_size must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D

## Resources

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,78 @@ variable "target_url" {
type = string
description = "The target URL for the restful endpoint to hit to validate the application is available"
}

variable "http_verb" {
description = "HTTP verb (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)"
type = string
default = "GET"
validation {
condition = contains(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"], var.http_verb)
error_message = "http_verb must be one of GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS."
}
}

variable "headers" {
description = "Map of request headers to send (name => value)"
type = map(string)
default = {}
}

variable "ssl_validation" {
description = "SSL validation configuration for the availability test."
type = object({
expected_status_code = optional(number, null)
ssl_check_enabled = optional(bool, true)
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it redundant with "enabled"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we even need enabled? Having ssl_validation non empty should be sufficient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it is redundant, I have removed enabled flag completely.

ssl_cert_remaining_lifetime = optional(number, null)
})

validation {
condition = (
var.ssl_validation == null ||
try(var.ssl_validation.expected_status_code, 0) == 0 ||
(try(var.ssl_validation.expected_status_code, 0) >= 100 &&
try(var.ssl_validation.expected_status_code, 0) < 600)
)
error_message = "The expected status code must be 0 ('0' means 'response code < 400') or a valid HTTP status code between 100 and 599."
}

validation {
condition = (
var.ssl_validation == null ||
try(var.ssl_validation.ssl_cert_remaining_lifetime, null) == null ||
(try(var.ssl_validation.ssl_cert_remaining_lifetime, 0) >= 1 &&
try(var.ssl_validation.ssl_cert_remaining_lifetime, 0) <= 365)
)
error_message = "The SSL certificate remaining lifetime must be null or an integer between 1 and 365."
}

default = null
nullable = true
}

variable "alert" {
type = object({
description = optional(string, "Availability test alert")
frequency = optional(string, "PT1M")
window_size = optional(string, "PT5M")
auto_mitigate = optional(bool, true)
})

validation {
condition = contains(
["PT1M", "PT5M", "PT15M", "PT30M", "PT1H"],
var.alert.frequency
)
error_message = "Frequency must be one of: PT1M, PT5M, PT15M, PT30M, PT1H"
}

validation {
condition = contains(
["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT6H", "PT12H", "P1D"],
var.alert.window_size
)
error_message = "Window size must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D"
}

default = {}
}