How to create a Service Bus Namespace and an Event Hub using a PowerShell script

This week I received the same two questions twice from two different customers: how can I create a Service Bus namespace from a PowerShell script? Moreover, after I created the Service Bus namespace, how can I create an event hub from a PowerShell script? The answer to the first question is easy: to create a new Azure Service Bus namespace you can use the New-AzureSBNamespace PowerShell cmdlet. The answer to the second question is also straightforward: to create a new Event Hub you can use the CreateEventHub method of the NamespaceManager class. The second question should be posed in a different way: how can I use the classes of the Microsoft.ServiceBus.dll assembly inside a PowerShell script? The following post shows a PowerShell script that you can use to create a Service Bus namespace, an Event Hub and a Consumer Group for the newly created Event Hub.

 <#
    .SYNOPSIS
    This script can be used to provision a namespace and an event hub.
            
    .DESCRIPTION
    This script can be used to provision a namespace and an event hub. 
    In particular, the script allows to specify the following parameters:
    -- Event Hub path
    -- Event hub message retention in days
    -- Event Hub partition count
    -- Event Hub user metadata
    -- Service Bus Namespace
    -- Azure Datacenter location
    
    .PARAMETER  Path
    Specifies the full path of the event hub.

    .PARAMETER  PartitionCount
    Specifies the current number of shards on the event hub.

    .PARAMETER  MessageRetentionInDays
    Specifies the number of days to retain the events for this event hub.

    .PARAMETER  UserMetadata
    Specifies the user metadata for the event hub.
    
    .PARAMETER  ConsumerGroupName
    Specifies the name of a custom consumer group.

    .PARAMETER  ConsumerGroupUserMetadata
    Specifies the user metadata for the custom consumer group.

    .PARAMETER  Namespace
    Specifies the name of the Service Bus namespace.

    .PARAMETER  CreateACSNamespace
    Specifies whether  to create an ACS namespace associated to the Service Bus namespace.

    .PARAMETER  Location
    Specifies the location to create the namespace in. The default value is "West Europe". 

    Valid values:
    -- East Asia
    -- East US
    -- North Central US
    -- North Europe
    -- West Europe
    -- West US
    
#>

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Path,                                  # required    needs to be alphanumeric    
    [Int]$PartitionCount = 16,                      # optional    default to 16
    [Int]$MessageRetentionInDays = 7,               # optional    default to 7
    [String]$UserMetadata = $null,                  # optional    default to $null
    [String]$ConsumerGroupName = "MyConsumerGroup", # optional    default to "MyConsumerGroup"
    [String]$ConsumerGroupUserMetadata = $null,     # optional    default to $null
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Namespace,                             # required    needs to be alphanumeric
    [Bool]$CreateACSNamespace = $False,             # optional    default to $false
    [String]$Location = "West Europe"               # optional    default to "West Europe"
    )

# Set the output level to verbose and make the script stop on error
$VerbosePreference = "Continue"
$ErrorActionPreference = "Stop"

# WARNING: Make sure to reference the latest version of the \Microsoft.ServiceBus.dll
Write-Output "Adding the [Microsoft.ServiceBus.dll] assembly to the script..."
Add-Type -Path "C:\Projects\Azure\ServiceBusExplorerNew\ServiceBusExplorer2.4Git\bin\Debug\Microsoft.ServiceBus.dll"
Write-Output "The [Microsoft.ServiceBus.dll] assembly has been successfully added to the script."

# Mark the start time of the script execution
$startTime = Get-Date

# Create Azure Service Bus namespace
$CurrentNamespace = Get-AzureSBNamespace -Name $Namespace


# Check if the namespace already exists or needs to be created
if ($CurrentNamespace)
{
    Write-Output "The namespace [$Namespace] already exists in the [$($CurrentNamespace.Region)] region." 
}
else
{
    Write-Host "The [$Namespace] namespace does not exist."
    Write-Output "Creating the [$Namespace] namespace in the [$Location] region..."
    New-AzureSBNamespace -Name $Namespace -Location $Location -CreateACSNamespace $CreateACSNamespace -NamespaceType Messaging
    $CurrentNamespace = Get-AzureSBNamespace -Name $Namespace
    Write-Host "The [$Namespace] namespace in the [$Location] region has been successfully created."
}

# Create the NamespaceManager object to create the event hub
Write-Host "Creating a NamespaceManager object for the [$Namespace] namespace..."
$NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($CurrentNamespace.ConnectionString);
Write-Host "NamespaceManager object for the [$Namespace] namespace has been successfully created."

# Check if the event hub already exists
if ($NamespaceManager.EventHubExists($Path))
{
    Write-Output "The [$Path] event hub already exists in the [$Namespace] namespace." 
}
else
{
    Write-Output "Creating the [$Path] event hub in the [$Namespace] namespace: PartitionCount=[$PartitionCount] MessageRetentionInDays=[$MessageRetentionInDays]..."
    $EventHubDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.EventHubDescription -ArgumentList $Path
    $EventHubDescription.PartitionCount = $PartitionCount
    $EventHubDescription.MessageRetentionInDays = $MessageRetentionInDays
    $EventHubDescription.UserMetadata = $UserMetadata
    $NamespaceManager.CreateEventHub($EventHubDescription);
    Write-Host "The [$Path] event hub in the [$Namespace] namespace has been successfully created."
}

# Create the consumer group if not exists
Write-Output "Creating the consumer group [$ConsumerGroupName] for the [$Path] event hub..."
$ConsumerGroupDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.ConsumerGroupDescription -ArgumentList $Path, $ConsumerGroupName
$ConsumerGroupDescription.UserMetadata = $ConsumerGroupUserMetadata
$NamespaceManager.CreateConsumerGroupIfNotExists($ConsumerGroupDescription);
Write-Host "The consumer group [$ConsumerGroupName] for the [$Path] event hub has been successfully created."

# Mark the finish time of the script execution
$finishTime = Get-Date

# Output the time consumed in seconds
$TotalTime = ($finishTime - $startTime).TotalSeconds
Write-Output "The script completed in $TotalTime seconds."

Note 1: as highlighted in the comments, make sure to load the latest version of the Microsoft.ServiceBus.dll assembly in the script.

Note 2: you can follow the same approach to create topics, queues, subscriptions and notification hubs instead of event hubs.

The picture below shows the result of the execution of the script with the following parameters:

powershell .\CreateEventHub.ps1 -Path ioteventhub -PartitionCount 32 -MessageRetentionInDays 3 -UserMetadata 'This event hub is used by the devices of the IoT solution' -ConsumerGroupName iotconsumergroup -ConsumerGroupUserMetadata 'This consumer group is used by the IoT solution' -Namespace iotsolution -Location 'West Europe'

CommandPrompt

I’d like to remark that this kind of scripts should be:

  • parametric to be reusable
  • included in the source control system (Visual Studio Online or GitHub) along with the solution and versioned as the application code
  • executed as part of the Continuous Delivery process used to automatically deploy the solution to a QA environment when a new version of the application is built

In fact, you probably heard the term DevOps more and more times. The term remarks the need to integrate development and operations tasks to build software solutions efficiently over time. This goal can be achieved using a process in which you develop an application, deploy it, learn from production usage of it, change it in response to what you learn, and repeat the cycle quickly and reliably.

To achieve this result, you have to build a development and deployment cycle that is repeatable, reliable, predictable, and has low cycle time. In particular, to create the staging and production environment for an Azure application and to deploy the solution in an automated way and integrate this task in the Continuous integration (CI) and Continuous delivery (CD) processes, you should use parametric PowerShell scripts.    

Note: Continuous integration (CI) means that whenever a developer checks in code to the source repository, a build is automatically triggered. Continuous delivery (CD) takes this one-step further: after a build and automated unit tests are successful, you automatically deploy the application to an environment where you can do more in-depth testing.

You can download the script along with the PowerShell scripts to create queues, topics and Subscription on MSDN Code Gallery: Service Bus PowerShell Scripts