This directory includes Bash scripts designed for deploying and testing the sample function app utilizing the azlocal CLI. For further details about the sample application, refer to the Azure Functions App with Service Bus Messaging.
Before deploying this solution, ensure you have the following tools installed:
- Azure Subscription
- LocalStack for Azure: Local Azure cloud emulator for development and testing
- Visual Studio Code: Code editor installed on one of the supported platforms
- Azure CLI: Azure command-line interface
- Azlocal CLI: LocalStack Azure CLI wrapper
- Azure Functions Core Tools is required to build, run, and deploy the Azure Functions app locally
- Docker: Container runtime required for LocalStack
- .NET SDK is required to compile and run the C# Azure Functions project
- jq: JSON processor for scripting and parsing command outputs
The deploy.sh Bash script uses the azlocal CLI to work with LocalStack. Install it using:
pip install azlocalFor more information, see Get started with the az tool on LocalStack.
This deploy.sh script creates the following Azure resources using Azure CLI commands:
- Azure Resource Group: A logical container scoping all resources in this sample.
- Azure Virtual Network: Hosts two subnets:
- app-subnet: Dedicated to regional VNet integration with the Function App.
- pe-subnet: Used for hosting Azure Private Endpoints.
- Azure Private DNS Zones: Provide internal DNS resolution so that resources within the virtual network can reach Private Endpoints by hostname rather than public addresses. There is a separate Azure Private DNS Zone for the following resource types:
- Azure Service Bus namespace
- Azure Blob Storage
- Azure Queue Storage
- Azure Table Storage
- Azure Private Endpoints: Provide secure, private network connectivity to Azure resources by exposing them through private IP addresses within the virtual network, eliminating the need for traffic to traverse the public internet. There is a separate Azure Private Endpoint for the following resources:
- Azure Service Bus namespace
- Azure Blob Storage
- Azure Queue Storage
- Azure Table Storage
- Azure NAT Gateway: Provides deterministic outbound connectivity and a stable public IP address for the Function App's outbound traffic. Included for architectural completeness; the sample app itself does not call any external services.
- Azure Network Security Group: Enforces inbound and outbound traffic rules across the virtual network's subnets.
- Azure Log Analytics Workspace: Centralizes diagnostic logs and metrics from all resources in the solution, enabling unified querying and analysis across the entire deployment.
- Azure App Service Plan: Defines the underlying compute tier and scaling behavior for the function app.
- Azure Functions App: Hosts the sample function app.
- Azure Application Insights: Provides application performance monitoring (APM), collecting and analyzing requests, traces, and metrics generated by the function app to surface performance bottlenecks and failures.
- Azure Service Bus: A fully managed enterprise message broker. This namespace hosts the
inputandoutputqueues used by the function app to exchange messages asynchronously. - Azure Storage Account: Provides durable storage used internally by the Azure Functions runtime for state management, including distributed locks, checkpoints, and timer trigger coordination.
- User-Assigned Managed Identity: This identity is assigned the necessary RBAC roles and is used by the function app to authenticate securely—without storing credentials—to the following Azure resources:
- Azure Service Bus namespace
- Azure Storage
- Azure Application Insights
For more information on the sample application, see Azure Functions App with Service Bus Messaging.
You can set up the Azure emulator by utilizing LocalStack for Azure Docker image. Before starting, ensure you have a valid LOCALSTACK_AUTH_TOKEN to access the Azure emulator. Refer to the Auth Token guide to obtain your Auth Token and specify it in the LOCALSTACK_AUTH_TOKEN environment variable. The Azure Docker image is available on the LocalStack Docker Hub. To pull the Azure Docker image, execute the following command:
docker pull localstack/localstack-azure-alphaStart the LocalStack Azure emulator using the localstack CLI, execute the following command:
# Set the authentication token
export LOCALSTACK_AUTH_TOKEN=<your_auth_token>
# Start the LocalStack Azure emulator
IMAGE_NAME=localstack/localstack-azure-alpha localstack start -d
localstack wait -t 60
# Route all Azure CLI calls to the LocalStack Azure emulator
azlocal start-interceptionNavigate to the scripts folder:
cd samples/function-app-service-bus/dotnet/scriptsMake the script executable:
chmod +x deploy.shRun the deployment script:
./deploy.shOnce the deployment completes, run the validate.sh script to confirm that all resources were provisioned and configured as expected:
#!/bin/bash
# Variables
PREFIX='local'
SUFFIX='test'
RESOURCE_GROUP_NAME="${PREFIX}-rg"
LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}"
FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}"
PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}"
NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}"
VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}"
APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}"
FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}"
SERVICE_BUS_NAMESPACE_NAME="${PREFIX}-service-bus-${SUFFIX}"
STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}"
APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}"
PRIVATE_DNS_ZONE_NAMES=(
"privatelink.servicebus.windows.net"
"privatelink.blob.core.windows.net"
"privatelink.queue.core.windows.net"
"privatelink.table.core.windows.net"
)
PE_NAMES=(
"${PREFIX}-service-bus-pe-${SUFFIX}"
"${PREFIX}-blob-storage-pe-${SUFFIX}"
"${PREFIX}-queue-storage-pe-${SUFFIX}"
"${PREFIX}-table-storage-pe-${SUFFIX}"
)
# Check resource group
echo -e "[$RESOURCE_GROUP_NAME] resource group:\n"
az group show \
--name "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# Check App Service Plan
echo -e "\n[$APP_SERVICE_PLAN_NAME] app service plan:\n"
az appservice plan show \
--resource-group "$RESOURCE_GROUP_NAME" \
--name "$APP_SERVICE_PLAN_NAME" \
--output table \
--only-show-errors
# Check Azure Functions App
echo -e "\n[$FUNCTION_APP_NAME] function app:\n"
az functionapp show \
--name "$FUNCTION_APP_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# Check Service Bus Namespace
echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus namespace:\n"
az servicebus namespace show \
--name "$SERVICE_BUS_NAMESPACE_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--query '{Name:name,ServiceBusEndpoint:serviceBusEndpoint}' \
--only-show-errors
# Check Service Bus Queues
echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus queues:\n"
az servicebus queue list \
--namespace-name "$SERVICE_BUS_NAMESPACE_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--query '[].{Name:name,Status:status}' \
--only-show-errors
# Check Application Insights
echo -e "\n[$APPLICATION_INSIGHTS_NAME] application insights:\n"
az monitor app-insights component show \
--app "$APPLICATION_INSIGHTS_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \
--output table \
--only-show-errors
# Check Storage Account
echo -e "\n[$STORAGE_ACCOUNT_NAME] storage account:\n"
az storage account show \
--name "$STORAGE_ACCOUNT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query '{Name:name,Location:primaryLocation,ResourceGroup:resourceGroup}' \
--output table \
--only-show-errors
# Check Log Analytics Workspace
echo -e "\n[$LOG_ANALYTICS_NAME] log analytics workspace:\n"
az monitor log-analytics workspace show \
--resource-group "$RESOURCE_GROUP_NAME" \
--workspace-name "$LOG_ANALYTICS_NAME" \
--query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \
--output table \
--only-show-errors
# Check NAT Gateway
echo -e "\n[$NAT_GATEWAY_NAME] nat gateway:\n"
az network nat gateway show \
--name "$NAT_GATEWAY_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# Check Virtual Network
echo -e "\n[$VIRTUAL_NETWORK_NAME] virtual network:\n"
az network vnet show \
--name "$VIRTUAL_NETWORK_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# Check Private DNS Zone
for PRIVATE_DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do
echo -e "\n[$PRIVATE_DNS_ZONE_NAME] private dns zone:\n"
az network private-dns zone show \
--name "$PRIVATE_DNS_ZONE_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query '{Name:name,ResourceGroup:resourceGroup,RecordSets:recordSets,VirtualNetworkLinks:virtualNetworkLinks}' \
--output table \
--only-show-errors
done
# Check Private Endpoint
for PRIVATE_ENDPOINT_NAME in "${PE_NAMES[@]}"; do
echo -e "\n[$PRIVATE_ENDPOINT_NAME] private endpoint:\n"
az network private-endpoint show \
--name "$PRIVATE_ENDPOINT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
done
# Check Functions App Subnet NSG
echo -e "\n[$FUNCTION_APP_SUBNET_NSG_NAME] network security group:\n"
az network nsg show \
--name "$FUNCTION_APP_SUBNET_NSG_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# Check Private Endpoint Subnet NSG
echo -e "\n[$PE_SUBNET_NSG_NAME] network security group:\n"
az network nsg show \
--name "$PE_SUBNET_NSG_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errors
# List resources
echo -e "\n[$RESOURCE_GROUP_NAME] all resources:\n"
az resource list \
--resource-group "$RESOURCE_GROUP_NAME" \
--output table \
--only-show-errorsTo destroy all created resources:
# Delete resource group and all contained resources
az group delete --name local-rg --yes --no-wait
# Verify deletion
az group list --output tableThis will remove all Azure resources created by the CLI deployment script.