Skip to main content
Jorge Bernhardt Jorge Bernhardt
  1. Posts/

Terraform - Azure Service Bus Queue Deployment

·1420 words·7 mins· 100 views · 5 likes ·
Terraform IaC Azure Service Bus Microsoft Azure

In the previous post, we started a series on using Terraform to deploy Azure Service Bus resources. We covered how to deploy namespaces in Azure Service Bus.

Now, in this second post, we will look at Azure Service Bus queues, a fundamental component for efficient message handling. Queues are essential for ensuring orderly and reliable communication between different parts of your application. They temporarily store messages in a ‘first in, first out’ manner, ensuring that messages are processed in the order they are received. This is particularly valuable in scenarios where the order of operations and message delivery guarantees are crucial.

As always, I’ll show you step by step how to set them up with Terraform.

By the end, you’ll know how to manage Service Bus queues effectively using Terraform. Let’s get started.

Prerequisites>

Prerequisites #

  • You need Terraform CLI on your local machine, if you’re new to using Terraform to deploy Microsoft Azure resources, then I recommend you check out this link.
  • A text editor or IDE of your choice (Visual Studio Code with terraform extension is my recommendation)
Declare Azure Provider in Terraform>

Declare Azure Provider in Terraform #

The provider.tf file in Terraform is used to specify and configure the providers used in your Terraform configuration. A provider is a service or platform where the resources will be managed. This could be a cloud provider like Microsoft Azure, AWS, Google Cloud, etc.

This file is important because it tells Terraform which provider’s API to use when creating, updating, and deleting resources. Without it, Terraform wouldn’t know where to manage your resources.

provider "azurerm" {
features {}
}
Deploy Azure Resources Using Terraform>

Deploy Azure Resources Using Terraform #

In the case of Azure Service Bus queues, the main.tf Terraform file includes several key components tailored to set up Service Bus queues effectively:

  • Resource Block for Azure Service Bus Queues: This is the core part where Azure Service Bus queues are actually created and configured. The block uses the for_each construct to iterate over each queue defined in var.servicebus_queues, creating a Service Bus queue for each. It maps each property from the variable like enable_partitioning, max_size_in_megabytes, lock_duration, etc., to the corresponding properties of the Azure Service Bus queue resource.
# Resource definition for Azure Service Bus Queues
resource "azurerm_servicebus_queue" "queue" {
  # Loop through each queue in the servicebus_queues variable
  for_each = { for sbq in var.servicebus_queues : sbq.name => sbq }

  # Assign values from each queue object to the respective Service Bus Queue properties
  name                                    = each.value.name
  namespace_id                            = each.value.namespace_id
  enable_partitioning                     = each.value.enable_partitioning
  max_size_in_megabytes                   = each.value.max_size_in_megabytes
  lock_duration                           = each.value.lock_duration
  max_message_size_in_kilobytes           = each.value.max_message_size_in_kilobytes != null ? each.value.max_message_size_in_kilobytes : null
  requires_duplicate_detection            = each.value.requires_duplicate_detection
  requires_session                        = each.value.requires_session
  default_message_ttl                     = each.value.default_message_ttl != null ? each.value.default_message_ttl : null
  dead_lettering_on_message_expiration    = each.value.dead_lettering_on_message_expiration
  duplicate_detection_history_time_window = each.value.duplicate_detection_history_time_window != null ? each.value.duplicate_detection_history_time_window : null
  max_delivery_count                      = each.value.max_delivery_count
  status                                  = each.value.status
  enable_batched_operations               = each.value.enable_batched_operations
  auto_delete_on_idle                     = each.value.auto_delete_on_idle != null ? each.value.auto_delete_on_idle : null
  enable_express                          = each.value.enable_express
  forward_to                              = each.value.forward_to != null ? each.value.forward_to : null
  forward_dead_lettered_messages_to       = each.value.forward_dead_lettered_messages_to != null ? each.value.forward_dead_lettered_messages_to : null
}
Declaration of input variables>

Declaration of input variables #

The variables.tf file in Terraform defines the variables you will use in the main.tf file for setting up Azure Service Bus queues. These variables enhance the flexibility and reusability of your code. In this case, the variables defined in the variables.tf include:

  • servicebus_queues: This variable is a list of objects, where each object represents the configuration for an Azure Service Bus queue. It includes various properties for each queue, such as namespace_id, name, enable_partitioning, and others. This structure allows for defining multiple queues with their specific configurations in a structured and reusable manner.
  • Validations: Within the variable definitions, there are validations to ensure that the input values meet specific criteria, they act as a first line of defense against configuration errors, enhancing the overall robustness of your infrastructure as code.
	# Variable definition for Service Bus Queues
variable "servicebus_queues" {
  description = "List of Service Bus Queues to be created"
  type = list(object({
    namespace_id                            = string
    name                                    = string
    enable_partitioning                     = bool
    max_size_in_megabytes                   = number
    lock_duration                           = string
    max_message_size_in_kilobytes           = number # Optional, default to null
    requires_duplicate_detection            = bool   # Optional, default to false
    requires_session                        = bool   # Optional, default to false
    default_message_ttl                     = string # Optional, default to null
    dead_lettering_on_message_expiration    = bool   # Optional, default to false
    duplicate_detection_history_time_window = string # Optional, default to null
    max_delivery_count                      = number # Optional, default to 10
    status                                  = string # Optional, default to "Active"
    enable_batched_operations               = bool   # Optional, default to true
    auto_delete_on_idle                     = string # Optional, default to null
    enable_express                          = bool   # Optional, default to false for Basic/Standard, true for Premium
    forward_to                              = string # Optional, default to null
    forward_dead_lettered_messages_to       = string # Optional, default to null
  }))
  default = []

  validation {
    condition     = alltrue([for q in var.servicebus_queues : can(regex("^[a-zA-Z0-9-]{3,50}$", q.name))])
    error_message = "All queue names must be between 3 and 50 characters and can only contain letters, numbers, and hyphens."
  }
  validation {
    condition     = alltrue([for q in var.servicebus_queues : contains([1024, 2048, 3072, 4096, 5120], q.enable_partitioning ? q.max_size_in_megabytes / 16 : q.max_size_in_megabytes)])
    error_message = "All max_size_in_megabytes values must be one of 1024, 2048, 3072, 4096, 5120 megabytes. If enable_partitioning is set to true, the specified queue size will be scaled by a factor of 16."
  }
  validation {
    condition = alltrue([
      for q in var.servicebus_queues :
      (q.lock_duration == null || can(regex("^PT([0-5]?[0-9]M)?$", q.lock_duration))) &&
      (q.auto_delete_on_idle == null || can(regex("^PT(([5-9]M)|([1-5]?[0-9][0-9]M)|([6-9]M[0-5]?[0-9]S)|([1-5]?[0-9][0-9]M[0-5]?[0-9]S)?)$", q.auto_delete_on_idle))) &&
      (q.default_message_ttl == null || can(regex("^PT([0-5]?[0-9]M([0-5]?[0-9]S)?)?$", q.default_message_ttl))) &&
      (q.duplicate_detection_history_time_window == null || can(regex("^PT([0-5]?[0-9]M([0-5]?[0-9]S)?)?$", q.duplicate_detection_history_time_window)))
    ])
    error_message = "The values for lock_duration, auto_delete_on_idle, default_message_ttl, and duplicate_detection_history_time_window must be either null or in ISO 8601 format."
  }
  validation {
    condition = alltrue([
      for q in var.servicebus_queues :
      q.status == null ||
      (q.status != null && (q.status == "Active" || q.status == "Creating" || q.status == "Deleting" || q.status == "Disabled" || q.status == "ReceiveDisabled" || q.status == "Renaming" || q.status == "SendDisabled" || q.status == "Unknown"))
    ])
    error_message = "The status must be either null or one of the following values: Active, Creating, Deleting, Disabled, ReceiveDisabled, Renaming, SendDisabled, Unknown."
  }
}
Declaration of output values>

Declaration of output values #

The output.tf file in Terraform extracts and displays information about the resources created or managed by your Terraform configuration. These outputs are defined using the output keyword and can be used to return information that can be useful for the user, for other Terraform configurations, or for programmatically using the information in scripts or other tools.

In this specific example, the output.tf file is configured to return information about the Azure Service Bus queues that were created. This is accomplished using the output keyword in Terraform:

  • A for loop is used within the output block to iterate over each Service Bus queue created in the azurerm_servicebus_queue resource.
  • For each queue, the output collects and displays the queue_id and queue_name.
# Output definition for Service Bus Queue details
output "servicebus_queue_details" {
  value = {
    for sbq in azurerm_servicebus_queue.queue : sbq.name => {
      queue_id   = sbq.id   # The unique identifier of the queue
      queue_name = sbq.name # The name of the queue
    }
  }
}
Executing the Terraform Deployment>

Executing the Terraform Deployment #

Now that you’ve declared the resources correctly, it’s time to take the following steps to deploy them in your Azure environment.

  • Initialization: To begin, execute the terraform init command. This will initialize your working directory that holds the .tf files and download the provider specified in the provider.tf file, and configure the Terraform backend. If you want to know how, check this link.

  • Planning: Next, execute the terraform plan. This command creates an execution plan and shows Terraform’s actions to achieve the desired state defined in your .tf files. This gives you a chance to review the changes before applying them.

  • Apply: When you’re satisfied with the plan, execute the terraform apply command. This will implement the required modifications to attain the intended infrastructure state. Before making any changes, you will be asked to confirm your decision.

  • Inspection: After applying the changes, you can use terraform show command to see the current state of your infrastructure.

  • Destroy (optional): when a project is no longer needed or when resources have become outdated. You can use the terraform destroy command. This will remove all the resources that Terraform has created.

References and useful links #

Thank you for taking the time to read my post. I sincerely hope that you find it helpful.