From fac09ef6af530a159f3a8f1cb82de939d5d82515 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Mar 2026 11:01:53 +0000 Subject: [PATCH 01/15] destroy service bus on stop --- devops/scripts/control_tre.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index e2ae51214c..3d237e50ab 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -9,6 +9,7 @@ if [[ -z ${TRE_ID:-} ]]; then exit 1 fi +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" core_rg_name="rg-${TRE_ID}" fw_name="fw-${TRE_ID}" agw_name="agw-$TRE_ID" @@ -26,6 +27,19 @@ az config set extension.use_dynamic_install=yes_without_prompt az --version if [[ "$1" == *"start"* ]]; then + # Recreate Service Bus (Premium SKU) if it doesn't exist + if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") == 0 ]]; then + echo "Recreating Service Bus (Premium SKU)" + # shellcheck disable=SC2154 + "${SCRIPT_DIR}/terraform_wrapper.sh" \ + -d "${SCRIPT_DIR}/../../core/terraform" \ + -g "${TF_VAR_mgmt_resource_group_name}" \ + -s "${TF_VAR_mgmt_storage_account_name}" \ + -n "${TF_VAR_terraform_state_container_name}" \ + -k "${TRE_ID}" \ + -c "terraform apply -auto-approve" + fi + if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then CURRENT_PUBLIC_IP=$(az network firewall ip-config list -f "${fw_name}" -g "${core_rg_name}" --query "[0].publicIpAddress" -o tsv) if [ -z "$CURRENT_PUBLIC_IP" ]; then @@ -73,6 +87,19 @@ if [[ "$1" == *"start"* ]]; then # We don't start workspace VMs despite maybe stopping them because we don't know if they need to be on. elif [[ "$1" == *"stop"* ]]; then + # Destroy Service Bus (Premium SKU) + if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") != 0 ]]; then + echo "Destroying Service Bus (Premium SKU) to save costs" + # shellcheck disable=SC2154 + "${SCRIPT_DIR}/terraform_wrapper.sh" \ + -d "${SCRIPT_DIR}/../../core/terraform" \ + -g "${TF_VAR_mgmt_resource_group_name}" \ + -s "${TF_VAR_mgmt_storage_account_name}" \ + -n "${TF_VAR_terraform_state_container_name}" \ + -k "${TRE_ID}" \ + -c "terraform destroy -auto-approve -target=azurerm_servicebus_namespace.sb" + fi + if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then IPCONFIG_NAME=$(az network firewall ip-config list -f "${fw_name}" -g "${core_rg_name}" --query "[0].name" -o tsv) From 791674cda5fa079f106f44af4d1db4d442b37e54 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Mar 2026 12:26:41 +0000 Subject: [PATCH 02/15] changelog --- CHANGELOG.md | 3 ++- devops/version.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4233685092..0d39ca9997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ ## (Unreleased) -* _No changes yet_ +ENHANCEMENTS: +* Add Service Bus (Premium SKU) recreation and destruction to `tre-start` and `tre-stop` to save costs ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) ## (0.28.0) (March 2, 2026) **BREAKING CHANGES** diff --git a/devops/version.txt b/devops/version.txt index 63af88769b..364e7baed0 100644 --- a/devops/version.txt +++ b/devops/version.txt @@ -1 +1 @@ -__version__ = "0.6.3" +__version__ = "0.6.4" From 7695fb2338cfdbcbda730ea39304b71f585f6d96 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Mar 2026 12:29:45 +0000 Subject: [PATCH 03/15] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d39ca9997..995a3e1747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ENHANCEMENTS: * Add Service Bus (Premium SKU) recreation and destruction to `tre-start` and `tre-stop` to save costs ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) +BUG FIXES: + ## (0.28.0) (March 2, 2026) **BREAKING CHANGES** * Sonatype Nexus shared service now requires explicit EULA acceptance (`accept_nexus_eula: true`) when deploying. This ensures compliance with Sonatype Nexus Community Edition licensing. ([#4842](https://github.com/microsoft/AzureTRE/issues/4842)) From bf78c3358b29d6ef542ad69f59f6a61eef224c92 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Mar 2026 17:15:09 +0000 Subject: [PATCH 04/15] destroy service bus without cascading --- devops/scripts/control_tre.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 3d237e50ab..862d6f6599 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -90,14 +90,7 @@ elif [[ "$1" == *"stop"* ]]; then # Destroy Service Bus (Premium SKU) if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") != 0 ]]; then echo "Destroying Service Bus (Premium SKU) to save costs" - # shellcheck disable=SC2154 - "${SCRIPT_DIR}/terraform_wrapper.sh" \ - -d "${SCRIPT_DIR}/../../core/terraform" \ - -g "${TF_VAR_mgmt_resource_group_name}" \ - -s "${TF_VAR_mgmt_storage_account_name}" \ - -n "${TF_VAR_terraform_state_container_name}" \ - -k "${TRE_ID}" \ - -c "terraform destroy -auto-approve -target=azurerm_servicebus_namespace.sb" + az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & fi if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then From 4cbca2e74ed899baba69bb47e1eb11544768a7d6 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Mar 2026 17:39:38 +0000 Subject: [PATCH 05/15] reword message --- devops/scripts/control_tre.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 862d6f6599..9a92308ac5 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -89,7 +89,7 @@ if [[ "$1" == *"start"* ]]; then elif [[ "$1" == *"stop"* ]]; then # Destroy Service Bus (Premium SKU) if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") != 0 ]]; then - echo "Destroying Service Bus (Premium SKU) to save costs" + echo "Destroying Service Bus" az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & fi From 0b9ba6be38c302bb6efb1c6bc9cbafeff38da9fa Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 11:26:14 +0000 Subject: [PATCH 06/15] stop/start function apps and web apps --- devops/scripts/control_tre.sh | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 9a92308ac5..09340237a6 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -84,6 +84,20 @@ if [[ "$1" == *"start"* ]]; then az vm start --resource-group "${core_rg_name}" --name "${vm_name}" & done + echo "Starting Function Apps" + az functionapp list --resource-group "${core_rg_name}" --query "[?state=='Stopped'].name" -o tsv | + while read -r name; do + echo "Starting Function App ${name}" + az functionapp start --resource-group "${core_rg_name}" --name "${name}" & + done + + echo "Starting Web Apps" + az webapp list --resource-group "${core_rg_name}" --query "[?state=='Stopped'].name" -o tsv | + while read -r name; do + echo "Starting Web App ${name}" + az webapp start --resource-group "${core_rg_name}" --name "${name}" & + done + # We don't start workspace VMs despite maybe stopping them because we don't know if they need to be on. elif [[ "$1" == *"stop"* ]]; then @@ -93,6 +107,34 @@ elif [[ "$1" == *"stop"* ]]; then az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & fi + echo "Stopping Function Apps" + az functionapp list --resource-group "${core_rg_name}" --query "[?state=='Running'].name" -o tsv | + while read -r name; do + echo "Stopping Function App ${name}" + az functionapp stop --resource-group "${core_rg_name}" --name "${name}" & + done + + echo "Stopping Web Apps" + az webapp list --resource-group "${core_rg_name}" --query "[?state=='Running'].name" -o tsv | + while read -r name; do + echo "Stopping Web App ${name}" + az webapp stop --resource-group "${core_rg_name}" --name "${name}" & + done + + # Stopping all Function Apps in workspaces + az functionapp list --query "[?(starts_with(resourceGroup,'${core_rg_name}-ws') || starts_with(resourceGroup,'${core_rg_name^^}-WS')) && state=='Running'][name, resourceGroup]" -o tsv | + while read -r name rg; do + echo "Stopping Function App ${name} in ${rg}" + az functionapp stop --resource-group "${rg}" --name "${name}" & + done + + # Stopping all Web Apps in workspaces + az webapp list --query "[?(starts_with(resourceGroup,'${core_rg_name}-ws') || starts_with(resourceGroup,'${core_rg_name^^}-WS')) && state=='Running'][name, resourceGroup]" -o tsv | + while read -r name rg; do + echo "Stopping Web App ${name} in ${rg}" + az webapp stop --resource-group "${rg}" --name "${name}" & + done + if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then IPCONFIG_NAME=$(az network firewall ip-config list -f "${fw_name}" -g "${core_rg_name}" --query "[0].name" -o tsv) From 79d37d0e97e08a3c14b3193de666f293d6645831 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 11:27:38 +0000 Subject: [PATCH 07/15] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 995a3e1747..498c93cc68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## (Unreleased) ENHANCEMENTS: -* Add Service Bus (Premium SKU) recreation and destruction to `tre-start` and `tre-stop` to save costs ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) +* Reduce costs by starting and stopping Service Bus and function apps via `tre-start` and `tre-stop` ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) BUG FIXES: From 7400a6e648114285a6f9e5c29fe8ebfb9eb6bda1 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 11:54:16 +0000 Subject: [PATCH 08/15] key vault fix --- devops/scripts/control_tre.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 09340237a6..6a5b3930d9 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -26,10 +26,13 @@ fi az config set extension.use_dynamic_install=yes_without_prompt az --version +# shellcheck disable=SC1091 +source "${SCRIPT_DIR}/kv_add_network_exception.sh" + if [[ "$1" == *"start"* ]]; then - # Recreate Service Bus (Premium SKU) if it doesn't exist + # Recreate Service Bus if it doesn't exist if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") == 0 ]]; then - echo "Recreating Service Bus (Premium SKU)" + echo "Recreating Service Bus" # shellcheck disable=SC2154 "${SCRIPT_DIR}/terraform_wrapper.sh" \ -d "${SCRIPT_DIR}/../../core/terraform" \ From 9dbdb51bda22586fe5a101b8e6860d5b5d4a39e1 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 13:43:15 +0000 Subject: [PATCH 09/15] remove diagnostic settings from service bus --- devops/scripts/control_tre.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 6a5b3930d9..8caf241f59 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -32,6 +32,11 @@ source "${SCRIPT_DIR}/kv_add_network_exception.sh" if [[ "$1" == *"start"* ]]; then # Recreate Service Bus if it doesn't exist if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") == 0 ]]; then + echo "Ensuring Service Bus diagnostic settings are removed" + subscription_id=$(az account show --query id -o tsv) + diag_id="/subscriptions/${subscription_id}/resourceGroups/${core_rg_name}/providers/Microsoft.ServiceBus/namespaces/sb-${TRE_ID}/providers/microsoft.insights/diagnosticSettings/diagnostics-sb-${TRE_ID}" + az resource delete --ids "${diag_id}" 2>/dev/null || true + echo "Recreating Service Bus" # shellcheck disable=SC2154 "${SCRIPT_DIR}/terraform_wrapper.sh" \ @@ -105,7 +110,19 @@ if [[ "$1" == *"start"* ]]; then elif [[ "$1" == *"stop"* ]]; then # Destroy Service Bus (Premium SKU) - if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") != 0 ]]; then + sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) + if [[ -n "${sb_id}" ]]; then + echo "Deleting diagnostic settings for Service Bus" + # shellcheck disable=SC2015 + { az monitor diagnostic-settings list --resource "${sb_id}" --query "value[].name" -o tsv 2>/dev/null \ + && az monitor diagnostic-settings list --resource "${sb_id}" --query "[].name" -o tsv 2>/dev/null ; } | + while read -r diag_name; do + if [[ -n "${diag_name}" ]]; then + echo "Deleting diagnostic setting ${diag_name}" + az monitor diagnostic-settings delete --resource "${sb_id}" --name "${diag_name}" --output none || true + fi + done + echo "Destroying Service Bus" az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & fi From 84f930544bdae5989561406b6abeeac5eeac68e7 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 14:47:49 +0000 Subject: [PATCH 10/15] reorder sb destroy --- devops/scripts/control_tre.sh | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 8caf241f59..e49eac21a2 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -109,23 +109,6 @@ if [[ "$1" == *"start"* ]]; then # We don't start workspace VMs despite maybe stopping them because we don't know if they need to be on. elif [[ "$1" == *"stop"* ]]; then - # Destroy Service Bus (Premium SKU) - sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) - if [[ -n "${sb_id}" ]]; then - echo "Deleting diagnostic settings for Service Bus" - # shellcheck disable=SC2015 - { az monitor diagnostic-settings list --resource "${sb_id}" --query "value[].name" -o tsv 2>/dev/null \ - && az monitor diagnostic-settings list --resource "${sb_id}" --query "[].name" -o tsv 2>/dev/null ; } | - while read -r diag_name; do - if [[ -n "${diag_name}" ]]; then - echo "Deleting diagnostic setting ${diag_name}" - az monitor diagnostic-settings delete --resource "${sb_id}" --name "${diag_name}" --output none || true - fi - done - - echo "Destroying Service Bus" - az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & - fi echo "Stopping Function Apps" az functionapp list --resource-group "${core_rg_name}" --query "[?state=='Running'].name" -o tsv | @@ -155,6 +138,24 @@ elif [[ "$1" == *"stop"* ]]; then az webapp stop --resource-group "${rg}" --name "${name}" & done + # Destroy Service Bus + sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) + if [[ -n "${sb_id}" ]]; then + echo "Deleting diagnostic settings for Service Bus" + # shellcheck disable=SC2015 + { az monitor diagnostic-settings list --resource "${sb_id}" --query "value[].name" -o tsv 2>/dev/null \ + && az monitor diagnostic-settings list --resource "${sb_id}" --query "[].name" -o tsv 2>/dev/null ; } | + while read -r diag_name; do + if [[ -n "${diag_name}" ]]; then + echo "Deleting diagnostic setting ${diag_name}" + az monitor diagnostic-settings delete --resource "${sb_id}" --name "${diag_name}" --output none || true + fi + done + + echo "Destroying Service Bus" + az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & + fi + if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then IPCONFIG_NAME=$(az network firewall ip-config list -f "${fw_name}" -g "${core_rg_name}" --query "[0].name" -o tsv) From 5f98d1c86f186586c12b4e233e3276351f957405 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 15:56:13 +0000 Subject: [PATCH 11/15] don't stop workspace apps --- devops/scripts/control_tre.sh | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index e49eac21a2..5076faf3a1 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -124,20 +124,6 @@ elif [[ "$1" == *"stop"* ]]; then az webapp stop --resource-group "${core_rg_name}" --name "${name}" & done - # Stopping all Function Apps in workspaces - az functionapp list --query "[?(starts_with(resourceGroup,'${core_rg_name}-ws') || starts_with(resourceGroup,'${core_rg_name^^}-WS')) && state=='Running'][name, resourceGroup]" -o tsv | - while read -r name rg; do - echo "Stopping Function App ${name} in ${rg}" - az functionapp stop --resource-group "${rg}" --name "${name}" & - done - - # Stopping all Web Apps in workspaces - az webapp list --query "[?(starts_with(resourceGroup,'${core_rg_name}-ws') || starts_with(resourceGroup,'${core_rg_name^^}-WS')) && state=='Running'][name, resourceGroup]" -o tsv | - while read -r name rg; do - echo "Stopping Web App ${name} in ${rg}" - az webapp stop --resource-group "${rg}" --name "${name}" & - done - # Destroy Service Bus sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) if [[ -n "${sb_id}" ]]; then From b2951a726dd241a7d8e561ce1e29bd0757e82aa3 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 16:04:22 +0000 Subject: [PATCH 12/15] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 498c93cc68..71bc2973c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## (Unreleased) ENHANCEMENTS: -* Reduce costs by starting and stopping Service Bus and function apps via `tre-start` and `tre-stop` ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) +* Destroy Service Bus to reduce costs when using make `tre-stop`. This also stops function apps and web apps in core rg to prevent excessive error logs due to the missing service bus. ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) BUG FIXES: From f67b367b98cf33931d8f2d97ee3c85973fe94a2d Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 6 Mar 2026 17:28:14 +0000 Subject: [PATCH 13/15] make delete service bus optional --- Makefile | 3 +- devops/scripts/control_tre.sh | 65 ++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index aab487b2c6..d1aaab87fe 100644 --- a/Makefile +++ b/Makefile @@ -179,10 +179,11 @@ tre-start: ## ⏩ Start the TRE Service # Description: Stop the TRE Service. # # This will deallocate the Azure Firewall public IP and stop the Azure Application Gateway service, stopping billing of both services. # Example: make tre-stop +# Example: make tre-stop DELETE_SERVICE_BUS=true tre-stop: ## ⛔ Stop the TRE Service $(call target_title, "Stopping TRE") \ && . ${MAKEFILE_DIR}/devops/scripts/bootstrap_azure_env.sh \ - && ${MAKEFILE_DIR}/devops/scripts/control_tre.sh stop + && ${MAKEFILE_DIR}/devops/scripts/control_tre.sh stop $(shell if [ "$(DELETE_SERVICE_BUS)" = "true" ]; then echo "--delete-service-bus"; fi) # Description: Destroy the TRE Service. This will destroy all the resources of the TRE service, including the Azure Firewall and Application Gateway. # Example: make tre-destroy diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 5076faf3a1..9d32434e95 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -29,23 +29,22 @@ az --version # shellcheck disable=SC1091 source "${SCRIPT_DIR}/kv_add_network_exception.sh" -if [[ "$1" == *"start"* ]]; then - # Recreate Service Bus if it doesn't exist +DELETE_SERVICE_BUS=false +COMMAND="" +for arg in "$@"; do + case $arg in + *start*) COMMAND="start" ;; + *stop*) COMMAND="stop" ;; + --delete-service-bus) DELETE_SERVICE_BUS=true ;; + esac +done + +if [[ "$COMMAND" == "start" ]]; then + # Check if Service Bus exists if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") == 0 ]]; then - echo "Ensuring Service Bus diagnostic settings are removed" - subscription_id=$(az account show --query id -o tsv) - diag_id="/subscriptions/${subscription_id}/resourceGroups/${core_rg_name}/providers/Microsoft.ServiceBus/namespaces/sb-${TRE_ID}/providers/microsoft.insights/diagnosticSettings/diagnostics-sb-${TRE_ID}" - az resource delete --ids "${diag_id}" 2>/dev/null || true - - echo "Recreating Service Bus" - # shellcheck disable=SC2154 - "${SCRIPT_DIR}/terraform_wrapper.sh" \ - -d "${SCRIPT_DIR}/../../core/terraform" \ - -g "${TF_VAR_mgmt_resource_group_name}" \ - -s "${TF_VAR_mgmt_storage_account_name}" \ - -n "${TF_VAR_terraform_state_container_name}" \ - -k "${TRE_ID}" \ - -c "terraform apply -auto-approve" + echo -e "\e[31mService Bus namespace 'sb-${TRE_ID}' does not exist.\e[0m" + echo -e "\e[31mIf the TRE was stopped or never deployed, please run 'make tre-deploy' to provision the infrastructure.\e[0m" + exit 1 fi if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then @@ -108,7 +107,7 @@ if [[ "$1" == *"start"* ]]; then # We don't start workspace VMs despite maybe stopping them because we don't know if they need to be on. -elif [[ "$1" == *"stop"* ]]; then +elif [[ "$COMMAND" == "stop" ]]; then echo "Stopping Function Apps" az functionapp list --resource-group "${core_rg_name}" --query "[?state=='Running'].name" -o tsv | @@ -125,21 +124,23 @@ elif [[ "$1" == *"stop"* ]]; then done # Destroy Service Bus - sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) - if [[ -n "${sb_id}" ]]; then - echo "Deleting diagnostic settings for Service Bus" - # shellcheck disable=SC2015 - { az monitor diagnostic-settings list --resource "${sb_id}" --query "value[].name" -o tsv 2>/dev/null \ - && az monitor diagnostic-settings list --resource "${sb_id}" --query "[].name" -o tsv 2>/dev/null ; } | - while read -r diag_name; do - if [[ -n "${diag_name}" ]]; then - echo "Deleting diagnostic setting ${diag_name}" - az monitor diagnostic-settings delete --resource "${sb_id}" --name "${diag_name}" --output none || true - fi - done - - echo "Destroying Service Bus" - az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & + if [[ "${DELETE_SERVICE_BUS}" == "true" ]]; then + sb_id=$(az servicebus namespace show --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" --query id -o tsv 2>/dev/null || true) + if [[ -n "${sb_id}" ]]; then + echo "Deleting diagnostic settings for Service Bus" + # shellcheck disable=SC2015 + { az monitor diagnostic-settings list --resource "${sb_id}" --query "value[].name" -o tsv 2>/dev/null \ + && az monitor diagnostic-settings list --resource "${sb_id}" --query "[].name" -o tsv 2>/dev/null ; } | + while read -r diag_name; do + if [[ -n "${diag_name}" ]]; then + echo "Deleting diagnostic setting ${diag_name}" + az monitor diagnostic-settings delete --resource "${sb_id}" --name "${diag_name}" --output none || true + fi + done + + echo "Destroying Service Bus" + az servicebus namespace delete --name "sb-${TRE_ID}" --resource-group "${core_rg_name}" & + fi fi if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then From f0771b8e5009e7fc726d6ec5e8ccf1f752026b1a Mon Sep 17 00:00:00 2001 From: James Chapman Date: Mon, 9 Mar 2026 19:16:42 +0000 Subject: [PATCH 14/15] refine scripts --- Makefile | 4 ++-- devops/scripts/control_tre.sh | 21 ++++++--------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index d1aaab87fe..07d343b051 100644 --- a/Makefile +++ b/Makefile @@ -177,13 +177,13 @@ tre-start: ## ⏩ Start the TRE Service && ${MAKEFILE_DIR}/devops/scripts/control_tre.sh start # Description: Stop the TRE Service. +# Arguments: DELETE_SERVICE_BUS - if set to true, the service bus will also be deleted to save costs. # # This will deallocate the Azure Firewall public IP and stop the Azure Application Gateway service, stopping billing of both services. # Example: make tre-stop -# Example: make tre-stop DELETE_SERVICE_BUS=true tre-stop: ## ⛔ Stop the TRE Service $(call target_title, "Stopping TRE") \ && . ${MAKEFILE_DIR}/devops/scripts/bootstrap_azure_env.sh \ - && ${MAKEFILE_DIR}/devops/scripts/control_tre.sh stop $(shell if [ "$(DELETE_SERVICE_BUS)" = "true" ]; then echo "--delete-service-bus"; fi) + && ${MAKEFILE_DIR}/devops/scripts/control_tre.sh stop # Description: Destroy the TRE Service. This will destroy all the resources of the TRE service, including the Azure Firewall and Application Gateway. # Example: make tre-destroy diff --git a/devops/scripts/control_tre.sh b/devops/scripts/control_tre.sh index 9d32434e95..4e69733d16 100755 --- a/devops/scripts/control_tre.sh +++ b/devops/scripts/control_tre.sh @@ -9,7 +9,6 @@ if [[ -z ${TRE_ID:-} ]]; then exit 1 fi -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" core_rg_name="rg-${TRE_ID}" fw_name="fw-${TRE_ID}" agw_name="agw-$TRE_ID" @@ -27,24 +26,16 @@ az config set extension.use_dynamic_install=yes_without_prompt az --version # shellcheck disable=SC1091 -source "${SCRIPT_DIR}/kv_add_network_exception.sh" - -DELETE_SERVICE_BUS=false -COMMAND="" -for arg in "$@"; do - case $arg in - *start*) COMMAND="start" ;; - *stop*) COMMAND="stop" ;; - --delete-service-bus) DELETE_SERVICE_BUS=true ;; - esac -done +# source "${SCRIPT_DIR}/kv_add_network_exception.sh" + +COMMAND="${1:-}" +DELETE_SERVICE_BUS="${DELETE_SERVICE_BUS:-false}" if [[ "$COMMAND" == "start" ]]; then # Check if Service Bus exists if [[ $(az servicebus namespace list --resource-group "${core_rg_name}" --query "[?name=='sb-${TRE_ID}'] | length(@)") == 0 ]]; then - echo -e "\e[31mService Bus namespace 'sb-${TRE_ID}' does not exist.\e[0m" - echo -e "\e[31mIf the TRE was stopped or never deployed, please run 'make tre-deploy' to provision the infrastructure.\e[0m" - exit 1 + echo -e "\e[33mService Bus namespace 'sb-${TRE_ID}' does not exist.\e[0m" + echo -e "\e[33mIf you ran 'make tre-start' you will also need to run 'make deploy-core' to reprovision the Service Bus.\e[0m" fi if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then From 27fa7c1fa22e4c8f46172b54d366f79965c3451f Mon Sep 17 00:00:00 2001 From: James Chapman Date: Tue, 31 Mar 2026 15:44:55 +0000 Subject: [PATCH 15/15] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71bc2973c4..0376ac72f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## (Unreleased) ENHANCEMENTS: -* Destroy Service Bus to reduce costs when using make `tre-stop`. This also stops function apps and web apps in core rg to prevent excessive error logs due to the missing service bus. ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) +* new option to Destroy Service Bus to reduce costs when using make `tre-stop`. This also stops function apps and web apps in core rg to prevent excessive error logs due to the missing service bus. ([#3953](https://github.com/microsoft/AzureTRE/issues/3953)) BUG FIXES: