Skip to content

Commit c838d1a

Browse files
committed
DTOSS-8565: Create a Terraform module for Azure Service Bus
1 parent aa2910e commit c838d1a

File tree

10 files changed

+231
-2
lines changed

10 files changed

+231
-2
lines changed

infrastructure/modules/monitor-action-group/examples/example.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ monitor_action_group = {
6262
}
6363

6464
}
65+

infrastructure/modules/monitor-action-group/examples/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ locals {
3232
for object in local.monitor_action_group_object_list : "${object.action_group_key}-${object.region}" => object
3333
}
3434
}
35+

infrastructure/modules/monitor-action-group/examples/variables.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ variable "monitor_action_group" {
4848
})))
4949

5050
}))
51-
}
51+
}
52+

infrastructure/modules/monitor-action-group/main.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ resource "azurerm_monitor_action_group" "this" {
5050
}
5151
}
5252

53-
}
53+
}
54+

infrastructure/modules/monitor-action-group/variables.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ variable "tags" {
7979
type = map(string)
8080
default = {}
8181
}
82+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
regions = {
2+
uksouth = {
3+
is_primary_region = true
4+
address_space = "10.113.0.0/16"
5+
connect_peering = false
6+
subnets = {}
7+
}
8+
}
9+
10+
service_bus = {
11+
dtoss-breast-screening = {
12+
capacity = 1
13+
sku_tier = "Premium"
14+
max_payload_size = "100mb"
15+
topics = {
16+
episode_uploaded = {},
17+
episode_created = {},
18+
episode_cancelled = {}
19+
}
20+
},
21+
dtoss-bowel-screening = {
22+
namespace_name = "bowel-screening-for-all"
23+
capacity = 1
24+
sku_tier = "Premium"
25+
max_payload_size = "100mb"
26+
topics = {
27+
episode_uploaded = {},
28+
episode_created = {},
29+
episode_cancelled = {}
30+
}
31+
}
32+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module "azure_service_bus" {
2+
for_each = local.azure_service_bus_map
3+
4+
source = "../../../dtos-devops-templates/infrastructure/modules/service-bus"
5+
6+
servicebus_topic_map = each.value.topics
7+
# The namespace defaults to the object key unless a namespace is specified, then it overwrites it.
8+
servicebus_namespace_name = coalesce(each.value.namespace_name, each.key)
9+
resource_group_name = azurerm_resource_group.core[each.value.region].name
10+
location = each.value.region
11+
capacity = each.value.capacity
12+
sku_tier = each.value.sku_tier
13+
14+
tags = var.tags
15+
}
16+
17+
locals {
18+
19+
azure_service_bus_object_list = flatten([
20+
for region in keys(var.regions) : [
21+
for service_bus_key, service_bus_details in var.service_bus : merge(
22+
{
23+
region = region
24+
service_bus_key = service_bus_key
25+
},
26+
service_bus_details
27+
)
28+
]
29+
])
30+
31+
# ...then project the list of objects into a map with unique keys (combining the iterators), for consumption by a for_each meta argument
32+
azure_service_bus_map = {
33+
for object in local.azure_service_bus_object_list : "${object.service_bus_key}-${object.region}" => object
34+
}
35+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
variable "regions" {
2+
type = map(object({
3+
address_space = optional(string)
4+
is_primary_region = bool
5+
connect_peering = optional(bool, false)
6+
subnets = optional(map(object({
7+
cidr_newbits = string
8+
cidr_offset = string
9+
create_nsg = optional(bool, true) # defaults to true
10+
name = optional(string) # Optional name override
11+
delegation_name = optional(string)
12+
service_delegation_name = optional(string)
13+
service_delegation_actions = optional(list(string))
14+
})))
15+
}))
16+
}
17+
18+
variable "service_bus" {
19+
description = "Configuration for Service Bus namespaces and their topics"
20+
type = map(object({
21+
namespace_name = optional(string)
22+
capacity = number
23+
sku_tier = string
24+
max_payload_size = string
25+
topics = map(object({
26+
auto_delete_on_idle = optional(string, "P10675199DT2H48M5.4775807S")
27+
batched_operations_enabled = optional(bool, false)
28+
default_message_ttl = optional(string, "P10675199DT2H48M5.4775807S")
29+
duplicate_detection_history_time_window = optional(string)
30+
partitioning_enabled = optional(bool, false)
31+
max_message_size_in_kilobytes = optional(number, 1024)
32+
max_size_in_megabytes = optional(number, 5120)
33+
requires_duplicate_detection = optional(bool, false)
34+
support_ordering = optional(bool)
35+
status = optional(string, "Active")
36+
topic_name = optional(string)
37+
}))
38+
}))
39+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
resource "azurerm_servicebus_namespace" "this" {
2+
name = var.servicebus_namespace_name
3+
location = var.location
4+
resource_group_name = var.resource_group_name
5+
sku = var.sku_tier
6+
capacity = var.capacity
7+
premium_messaging_partitions = var.premium_messaging_partitions
8+
public_network_access_enabled = var.public_network_access_enabled
9+
10+
tags = var.tags
11+
}
12+
13+
resource "azurerm_servicebus_topic" "this" {
14+
for_each = var.servicebus_topic_map
15+
16+
name = coalesce(each.value.topic_name, each.key)
17+
namespace_id = azurerm_servicebus_namespace.this.id
18+
auto_delete_on_idle = each.value.auto_delete_on_idle
19+
batched_operations_enabled = each.value.batched_operations_enabled
20+
default_message_ttl = each.value.default_message_ttl
21+
duplicate_detection_history_time_window = each.value.duplicate_detection_history_time_window
22+
partitioning_enabled = each.value.partitioning_enabled
23+
max_message_size_in_kilobytes = each.value.max_message_size_in_kilobytes
24+
max_size_in_megabytes = each.value.max_size_in_megabytes
25+
requires_duplicate_detection = each.value.requires_duplicate_detection
26+
support_ordering = each.value.support_ordering
27+
status = each.value.status
28+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
variable "capacity" {
2+
description = "When sku is Premium, capacity can be 1, 2, 4, 8 or 16. When sku is Basic or Standard, capacity must be 0."
3+
type = number
4+
default = 0
5+
validation {
6+
condition = (
7+
(var.sku_tier == "Premium" && contains([1, 2, 4, 8, 16], var.capacity)) ||
8+
((var.sku_tier == "Basic" || var.sku_tier == "Standard") && var.capacity == 0)
9+
)
10+
error_message = "Invalid capacity: Premium allows 1, 2, 4, 8 or 16. Basic and Standard must have capacity 0."
11+
}
12+
}
13+
14+
variable "location" {
15+
description = "The location/region where the Service Bus namespace will be created."
16+
type = string
17+
default = "uksouth"
18+
validation {
19+
condition = contains(["uksouth", "ukwest"], var.location)
20+
error_message = "The location must be either uksouth or ukwest."
21+
}
22+
}
23+
24+
variable "premium_messaging_partitions" {
25+
description = "Boolean flag which controls whether to enable the topic to be partitioned across multiple message brokers. Changing this forces a new resource to be created."
26+
type = number
27+
default = 1
28+
}
29+
30+
variable "public_network_access_enabled" {
31+
type = bool
32+
default = false
33+
}
34+
35+
variable "partitioning_enabled" {
36+
description = "Boolean flag which controls whether to enable the topic to be partitioned across multiple message brokers. Changing this forces a new resource to be created."
37+
type = bool
38+
default = false
39+
}
40+
41+
variable "resource_group_name" {
42+
type = string
43+
description = "The name of the resource group in which to create the Event Grid. Changing this forces a new resource to be created."
44+
validation {
45+
condition = can(regex("^[-\\w\\._\\(\\)]+$", var.resource_group_name)) && length(var.resource_group_name) > 0
46+
error_message = "The resource group name must be a non-empty string using only alphanumeric characters, dashes, underscores, periods, or parentheses."
47+
}
48+
}
49+
50+
variable "servicebus_namespace_name" {
51+
description = "The name of the Service Bus namespace."
52+
type = string
53+
validation {
54+
condition = can(regex("^[a-zA-Z0-9][a-zA-Zq0-9-]{6,49}$", var.servicebus_namespace_name))
55+
error_message = "The Service Bus namespace name must be between 7 and 50 characters and can contain only letters, numbers, and hyphens. It must start with a letter or number."
56+
}
57+
}
58+
59+
variable "servicebus_topic_map" {
60+
type = map(object({
61+
auto_delete_on_idle = optional(string, "P10675199DT2H48M5.4775807S")
62+
batched_operations_enabled = optional(bool, false)
63+
default_message_ttl = optional(string, "P10675199DT2H48M5.4775807S")
64+
duplicate_detection_history_time_window = optional(string)
65+
partitioning_enabled = optional(bool, false)
66+
max_message_size_in_kilobytes = optional(number, 1024)
67+
max_size_in_megabytes = optional(number, 5120)
68+
requires_duplicate_detection = optional(bool, false)
69+
support_ordering = optional(bool)
70+
status = optional(string, "Active")
71+
topic_name = optional(string)
72+
}))
73+
default = {}
74+
}
75+
76+
variable "sku_tier" {
77+
description = "The tier of the SKU."
78+
type = string
79+
default = "Standard"
80+
validation {
81+
condition = contains(["Basic", "Standard", "Premium"], var.sku_tier)
82+
error_message = "The SKU name must be either Basic, Standard or Premium."
83+
}
84+
}
85+
86+
variable "tags" {
87+
description = "A mapping of tags to assign to the resource."
88+
type = map(string)
89+
default = {}
90+
}

0 commit comments

Comments
 (0)