From 1839f238e9ca63bdc8631057536da94dfd50357d Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 6 Oct 2026 18:40:50 +0200 Subject: [PATCH 1/5] Read the app's port from its container in the call scripts, and take PREFIX and SUFFIX from the environment The call scripts looked up the host port mapped to container port 80 and called the container IP on port 80 (or on a hard-coded 8000). The emulator serves an app on the port its WEBSITES_PORT app setting names, 8000 in several samples, so the host-port and container-IP calls of web-app-cosmosdb-mongodb-api/python failed, and every other script was one setting change away from the same failure. The scripts now read the port the app's container publishes, and the READMEs no longer tell readers to look for port 80. The deploy, call and validate scripts take PREFIX and SUFFIX from the environment, defaulting to local and test as before, so several deployments of the same sample can run side by side on one emulator and a redeployment does not run into the soft-deleted Key Vault of the previous one. The function-app-storage-http Bicep deployment now passes them to its template and names its resource group with the prefix. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm --- .../python/scripts/call-front-door.sh | 4 +- .../python/scripts/cleanup.sh | 2 +- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/system-managed-identity.sh | 4 +- .../python/scripts/test.sh | 4 +- .../python/scripts/user-managed-identity.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- .../function-app-service-bus/dotnet/README.md | 4 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-http-trigger.sh | 42 +++++++++++++++--- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../dotnet/bicep/deploy.sh | 10 +++-- .../dotnet/scripts/call-http-triggers.sh | 44 ++++++++++++++++--- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../dotnet/README.md | 2 +- .../dotnet/scripts/call-web-app.sh | 40 +++++++++++++++-- .../python/README.md | 2 +- .../python/scripts/call-web-app.sh | 40 +++++++++++++++-- .../dotnet/README.md | 2 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 42 +++++++++++++++--- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../python/README.md | 2 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/call-web-app.sh | 42 +++++++++++++++--- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- .../dotnet/README.md | 2 +- .../dotnet/scripts/call-web-app.sh | 42 +++++++++++++++--- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../python/README.md | 2 +- .../python/scripts/call-web-app.sh | 42 +++++++++++++++--- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 4 +- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/call-web-app.sh | 4 +- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- .../web-app-managed-identity/dotnet/README.md | 2 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/api.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 42 +++++++++++++++--- .../dotnet/scripts/cli.sh | 4 +- .../dotnet/scripts/system-assigned.sh | 4 +- .../dotnet/scripts/user-assigned.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../web-app-managed-identity/python/README.md | 2 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/api.sh | 4 +- .../python/scripts/call-web-app.sh | 42 +++++++++++++++--- .../python/scripts/cli.sh | 4 +- .../python/scripts/system-assigned.sh | 4 +- .../python/scripts/user-assigned.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- .../dotnet/README.md | 2 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 40 +++++++++++++++-- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../python/README.md | 2 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/call-web-app.sh | 40 +++++++++++++++-- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- .../dotnet/README.md | 2 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 40 +++++++++++++++-- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- .../python/README.md | 2 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/call-web-app.sh | 40 +++++++++++++++-- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- samples/web-app-sql-database/dotnet/README.md | 2 +- .../dotnet/bicep/deploy.sh | 4 +- .../dotnet/scripts/call-web-app.sh | 42 +++++++++++++++--- .../dotnet/scripts/deploy.sh | 4 +- .../dotnet/scripts/validate.sh | 4 +- .../dotnet/terraform/deploy.sh | 4 +- samples/web-app-sql-database/python/README.md | 2 +- .../python/bicep/deploy.sh | 4 +- .../python/scripts/call-web-app.sh | 42 +++++++++++++++--- .../python/scripts/deploy.sh | 4 +- .../python/scripts/validate.sh | 4 +- .../python/terraform/deploy.sh | 4 +- 108 files changed, 761 insertions(+), 245 deletions(-) diff --git a/samples/function-app-front-door/python/scripts/call-front-door.sh b/samples/function-app-front-door/python/scripts/call-front-door.sh index 48c82b9..f7f3eea 100755 --- a/samples/function-app-front-door/python/scripts/call-front-door.sh +++ b/samples/function-app-front-door/python/scripts/call-front-door.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" PROFILE_NAME="${PREFIX}-catalog-afd-${SUFFIX}" ENDPOINT_NAME="${PREFIX}-catalog-${SUFFIX}" diff --git a/samples/function-app-front-door/python/scripts/cleanup.sh b/samples/function-app-front-door/python/scripts/cleanup.sh index ede7f93..e6cf3c0 100755 --- a/samples/function-app-front-door/python/scripts/cleanup.sh +++ b/samples/function-app-front-door/python/scripts/cleanup.sh @@ -8,7 +8,7 @@ # accounts and the shared App Service plan are all inside it. # ============================================================================= -PREFIX='local' +PREFIX="${PREFIX:-local}" RESOURCE_GROUP_NAME="${PREFIX}-rg" CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" diff --git a/samples/function-app-front-door/python/scripts/deploy.sh b/samples/function-app-front-door/python/scripts/deploy.sh index 197242c..dbdfcf8 100755 --- a/samples/function-app-front-door/python/scripts/deploy.sh +++ b/samples/function-app-front-door/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" APP_SERVICE_PLAN_NAME="${PREFIX}-catalog-app-service-plan-${SUFFIX}" diff --git a/samples/function-app-front-door/python/scripts/validate.sh b/samples/function-app-front-door/python/scripts/validate.sh index b269c82..803fe8f 100755 --- a/samples/function-app-front-door/python/scripts/validate.sh +++ b/samples/function-app-front-door/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" PRIMARY_FUNCTION_APP_NAME="${PREFIX}-catalog-primary-${SUFFIX}" SECONDARY_FUNCTION_APP_NAME="${PREFIX}-catalog-secondary-${SUFFIX}" diff --git a/samples/function-app-managed-identity/python/bicep/deploy.sh b/samples/function-app-managed-identity/python/bicep/deploy.sh index 9773b08..d1ca5da 100755 --- a/samples/function-app-managed-identity/python/bicep/deploy.sh +++ b/samples/function-app-managed-identity/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="$PREFIX-rg" diff --git a/samples/function-app-managed-identity/python/scripts/system-managed-identity.sh b/samples/function-app-managed-identity/python/scripts/system-managed-identity.sh index dd04639..43925aa 100755 --- a/samples/function-app-managed-identity/python/scripts/system-managed-identity.sh +++ b/samples/function-app-managed-identity/python/scripts/system-managed-identity.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" FUNCTION_APP_NAME="${PREFIX}-functionapp-${SUFFIX}" diff --git a/samples/function-app-managed-identity/python/scripts/test.sh b/samples/function-app-managed-identity/python/scripts/test.sh index 02cea01..e62c1ae 100755 --- a/samples/function-app-managed-identity/python/scripts/test.sh +++ b/samples/function-app-managed-identity/python/scripts/test.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" FILE_PATH="input.txt" INPUT_CONTAINER_NAME="input" OUTPUT_CONTAINER_NAME="output" diff --git a/samples/function-app-managed-identity/python/scripts/user-managed-identity.sh b/samples/function-app-managed-identity/python/scripts/user-managed-identity.sh index 6432874..06015f1 100755 --- a/samples/function-app-managed-identity/python/scripts/user-managed-identity.sh +++ b/samples/function-app-managed-identity/python/scripts/user-managed-identity.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='northeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}" diff --git a/samples/function-app-managed-identity/python/scripts/validate.sh b/samples/function-app-managed-identity/python/scripts/validate.sh index 4b9dd3e..021bee6 100755 --- a/samples/function-app-managed-identity/python/scripts/validate.sh +++ b/samples/function-app-managed-identity/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" INPUT_STORAGE_CONTAINER_NAME='input' diff --git a/samples/function-app-managed-identity/python/terraform/deploy.sh b/samples/function-app-managed-identity/python/terraform/deploy.sh index 674a8be..22eeec3 100755 --- a/samples/function-app-managed-identity/python/terraform/deploy.sh +++ b/samples/function-app-managed-identity/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' MANAGED_IDENTITY_TYPE='UserAssigned' # SystemAssigned or UserAssigned CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" diff --git a/samples/function-app-service-bus/dotnet/README.md b/samples/function-app-service-bus/dotnet/README.md index c178a48..7f08efd 100644 --- a/samples/function-app-service-bus/dotnet/README.md +++ b/samples/function-app-service-bus/dotnet/README.md @@ -103,7 +103,9 @@ Found matching container [ls-local-func-test-tdkqjh] Container [ls-local-func-test-tdkqjh] found successfully Getting IP address for container [ls-local-func-test-tdkqjh]... IP address [172.17.0.7] retrieved successfully for container [ls-local-func-test-tdkqjh] -Getting the host port mapped to internal port 80 in container [ls-local-func-test-tdkqjh]... +Getting the port the function app listens on in container [ls-local-func-test-tdkqjh]... +Function app listens on port [80] in container [ls-local-func-test-tdkqjh] +Getting the host port mapped to port [80] in container [ls-local-func-test-tdkqjh]... Mapped host port [42330] retrieved successfully for container [ls-local-func-test-tdkqjh] Calling HTTP trigger function to retrieve the last [100] greetings via hostname [babo-func-test.azurewebsites.azure.localhost.localstack.cloud:4566]... { diff --git a/samples/function-app-service-bus/dotnet/bicep/deploy.sh b/samples/function-app-service-bus/dotnet/bicep/deploy.sh index 79ca625..9a03d5a 100755 --- a/samples/function-app-service-bus/dotnet/bicep/deploy.sh +++ b/samples/function-app-service-bus/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh index 1268060..98c4768 100755 --- a/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh +++ b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_http_trigger_function() { # Get the function app name echo "Getting function app name..." @@ -126,9 +148,19 @@ call_http_trigger_function() { exit 1 fi - # Get the mapped host port for function app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the function app listens on in its container + echo "Getting the port the function app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Function app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the function app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -145,10 +177,10 @@ call_http_trigger_function() { echo "Failed to retrieve function hostname" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the GetGreetings HTTP trigger function to retrieve the last greetings via the container IP address echo "Calling HTTP trigger function to retrieve the last [$greeting_count] greetings via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/api/greetings?count=$greeting_count" | jq + curl --max-time 10 -s "http://$container_ip:$container_port/api/greetings?count=$greeting_count" | jq else echo "Failed to retrieve container IP address" fi diff --git a/samples/function-app-service-bus/dotnet/scripts/deploy.sh b/samples/function-app-service-bus/dotnet/scripts/deploy.sh index 91a51fe..420add4 100755 --- a/samples/function-app-service-bus/dotnet/scripts/deploy.sh +++ b/samples/function-app-service-bus/dotnet/scripts/deploy.sh @@ -1,7 +1,7 @@ #!/bin/bash -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/function-app-service-bus/dotnet/scripts/validate.sh b/samples/function-app-service-bus/dotnet/scripts/validate.sh index ae43236..b3b75e0 100755 --- a/samples/function-app-service-bus/dotnet/scripts/validate.sh +++ b/samples/function-app-service-bus/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" diff --git a/samples/function-app-service-bus/dotnet/terraform/deploy.sh b/samples/function-app-service-bus/dotnet/terraform/deploy.sh index 7509c53..8fd6be2 100755 --- a/samples/function-app-service-bus/dotnet/terraform/deploy.sh +++ b/samples/function-app-service-bus/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" ZIPFILE="functionapp.zip" diff --git a/samples/function-app-storage-http/dotnet/bicep/deploy.sh b/samples/function-app-storage-http/dotnet/bicep/deploy.sh index cf41950..1440792 100755 --- a/samples/function-app-storage-http/dotnet/bicep/deploy.sh +++ b/samples/function-app-storage-http/dotnet/bicep/deploy.sh @@ -3,7 +3,9 @@ # Variables TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" -RESOURCE_GROUP_NAME="local-func-storage-rg" +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" +RESOURCE_GROUP_NAME="${PREFIX}-func-storage-rg" LOCATION="westeurope" VALIDATE_TEMPLATE=1 USE_WHAT_IF=0 @@ -45,7 +47,7 @@ if [[ $VALIDATE_TEMPLATE == 1 ]]; then --template-file $TEMPLATE \ --parameters $PARAMETERS \ --parameters \ - location=$LOCATION + location=$LOCATION prefix="$PREFIX" suffix="$SUFFIX" if [[ $? == 0 ]]; then echo "Bicep template [$TEMPLATE] validation succeeded" @@ -61,7 +63,7 @@ if [[ $VALIDATE_TEMPLATE == 1 ]]; then --template-file $TEMPLATE \ --parameters $PARAMETERS \ --parameters \ - location=$LOCATION) + location=$LOCATION prefix="$PREFIX" suffix="$SUFFIX") if [[ $? == 0 ]]; then echo "Bicep template [$TEMPLATE] validation succeeded" @@ -80,7 +82,7 @@ if DEPLOYMENT_OUTPUTS=$(az deployment group create \ --only-show-errors \ --template-file $TEMPLATE \ --parameters $PARAMETERS \ - --parameters location=$LOCATION \ + --parameters location=$LOCATION prefix="$PREFIX" suffix="$SUFFIX" \ --query 'properties.outputs' -o json); then echo "Bicep template [$TEMPLATE] deployed successfully. Outputs:" echo "$DEPLOYMENT_OUTPUTS" | jq . diff --git a/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh b/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh index 7409291..2bf5703 100755 --- a/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh +++ b/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_http_trigger_functions() { # Get the function app name echo "Getting function app name..." @@ -127,9 +149,19 @@ call_http_trigger_functions() { exit 1 fi - # Get the mapped host port for function app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the function app listens on in its container + echo "Getting the port the function app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Function app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the function app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -150,14 +182,14 @@ call_http_trigger_functions() { echo "Failed to retrieve function hostname" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the GET HTTP trigger function that returns a player status in a specified game session via the container IP address echo "Calling HTTP trigger function to retrieve player [$player_name] status in game session [$game_session] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/api/player/$game_session/$player_name/status" | jq + curl --max-time 10 -s "http://$container_ip:$container_port/api/player/$game_session/$player_name/status" | jq # Call the POST HTTP trigger function that returns the game session details via the container IP address echo "Calling HTTP trigger function to retrieve game session [$game_session] details via container IP address [$container_ip]..." - curl --max-time 10 -s -X POST -H "Content-Type: application/json" -d "{\"gameId\": $game_session}" "http://$container_ip/api/game/session" | jq + curl --max-time 10 -s -X POST -H "Content-Type: application/json" -d "{\"gameId\": $game_session}" "http://$container_ip:$container_port/api/game/session" | jq else echo "Failed to retrieve container IP address" fi diff --git a/samples/function-app-storage-http/dotnet/scripts/deploy.sh b/samples/function-app-storage-http/dotnet/scripts/deploy.sh index 8481903..7c16c92 100755 --- a/samples/function-app-storage-http/dotnet/scripts/deploy.sh +++ b/samples/function-app-storage-http/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" diff --git a/samples/function-app-storage-http/dotnet/terraform/deploy.sh b/samples/function-app-storage-http/dotnet/terraform/deploy.sh index 6578b8f..7263a26 100755 --- a/samples/function-app-storage-http/dotnet/terraform/deploy.sh +++ b/samples/function-app-storage-http/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' #system or user -SUFFIX='test' +PREFIX="${PREFIX:-local}" #system or user +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" ZIPFILE="function_app.zip" diff --git a/samples/web-app-app-configuration/dotnet/README.md b/samples/web-app-app-configuration/dotnet/README.md index ee4a152..f884767 100644 --- a/samples/web-app-app-configuration/dotnet/README.md +++ b/samples/web-app-app-configuration/dotnet/README.md @@ -104,7 +104,7 @@ The store and the vault have globally unique names: on Azure, export your own `S ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the seeded activities and can add, edit, and remove activities. diff --git a/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh b/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-app-configuration/python/README.md b/samples/web-app-app-configuration/python/README.md index 37d4378..8d10431 100644 --- a/samples/web-app-app-configuration/python/README.md +++ b/samples/web-app-app-configuration/python/README.md @@ -101,7 +101,7 @@ The store and the vault have globally unique names: on Azure, export your own `S ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the seeded activities and can add, edit, and remove activities. diff --git a/samples/web-app-app-configuration/python/scripts/call-web-app.sh b/samples/web-app-app-configuration/python/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-app-configuration/python/scripts/call-web-app.sh +++ b/samples/web-app-app-configuration/python/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/README.md b/samples/web-app-cosmosdb-mongodb-api/dotnet/README.md index 59ee963..41e010f 100644 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/README.md +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/README.md @@ -71,7 +71,7 @@ All deployment methods have been fully tested against Azure and the LocalStack f ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/deploy.sh index cd7172f..b3681de 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh index 9c3945f..3a902f6 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port 8000 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "8000") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -152,10 +184,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip:8000/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/deploy.sh index eab28e6..921f5b7 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/validate.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/validate.sh index fd2815c..297ac8c 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/validate.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/deploy.sh index fd202c9..050fc10 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" ZIPFILE="planner_website.zip" diff --git a/samples/web-app-cosmosdb-mongodb-api/python/README.md b/samples/web-app-cosmosdb-mongodb-api/python/README.md index 80ffb4a..cc1fcc1 100644 --- a/samples/web-app-cosmosdb-mongodb-api/python/README.md +++ b/samples/web-app-cosmosdb-mongodb-api/python/README.md @@ -71,7 +71,7 @@ All deployment methods have been fully tested against Azure and the LocalStack f ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-cosmosdb-mongodb-api/python/bicep/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/python/bicep/deploy.sh index 2a8cbbb..ba06a3b 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/bicep/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh b/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh index 45e5ad2..3a902f6 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -152,10 +184,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-cosmosdb-mongodb-api/python/scripts/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/python/scripts/deploy.sh index e4dc109..832f603 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/scripts/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-mongodb-api/python/scripts/validate.sh b/samples/web-app-cosmosdb-mongodb-api/python/scripts/validate.sh index fd2815c..297ac8c 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/scripts/validate.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-mongodb-api/python/terraform/deploy.sh b/samples/web-app-cosmosdb-mongodb-api/python/terraform/deploy.sh index 5a3e0dd..d407122 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/terraform/deploy.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" ZIPFILE="planner_website.zip" diff --git a/samples/web-app-cosmosdb-nosql-api/dotnet/README.md b/samples/web-app-cosmosdb-nosql-api/dotnet/README.md index 925da47..8a6f55d 100644 --- a/samples/web-app-cosmosdb-nosql-api/dotnet/README.md +++ b/samples/web-app-cosmosdb-nosql-api/dotnet/README.md @@ -50,7 +50,7 @@ Deploy the application to LocalStack for Azure using: ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh index a82964c..b3eb722 100755 --- a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -153,10 +185,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/deploy.sh b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/deploy.sh index 6c77fc6..ef3049f 100755 --- a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/deploy.sh +++ b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/validate.sh b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/validate.sh index 542412a..2dcc342 100755 --- a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/validate.sh +++ b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" WEB_APP_NAME="${PREFIX}-webapp-nosql-${SUFFIX}" APP_SERVICE_PLAN_NAME="${WEB_APP_NAME}" diff --git a/samples/web-app-cosmosdb-nosql-api/python/README.md b/samples/web-app-cosmosdb-nosql-api/python/README.md index b9b2818..317275c 100644 --- a/samples/web-app-cosmosdb-nosql-api/python/README.md +++ b/samples/web-app-cosmosdb-nosql-api/python/README.md @@ -50,7 +50,7 @@ Deploy the application to LocalStack for Azure using: ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh b/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh index a82964c..b3eb722 100755 --- a/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -153,10 +185,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-cosmosdb-nosql-api/python/scripts/deploy.sh b/samples/web-app-cosmosdb-nosql-api/python/scripts/deploy.sh index 1adc031..d21700c 100755 --- a/samples/web-app-cosmosdb-nosql-api/python/scripts/deploy.sh +++ b/samples/web-app-cosmosdb-nosql-api/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-cosmosdb-nosql-api/python/scripts/validate.sh b/samples/web-app-cosmosdb-nosql-api/python/scripts/validate.sh index 542412a..2dcc342 100755 --- a/samples/web-app-cosmosdb-nosql-api/python/scripts/validate.sh +++ b/samples/web-app-cosmosdb-nosql-api/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" WEB_APP_NAME="${PREFIX}-webapp-nosql-${SUFFIX}" APP_SERVICE_PLAN_NAME="${WEB_APP_NAME}" diff --git a/samples/web-app-custom-image/dotnet/bicep/deploy.sh b/samples/web-app-custom-image/dotnet/bicep/deploy.sh index 9c16125..e90e37b 100755 --- a/samples/web-app-custom-image/dotnet/bicep/deploy.sh +++ b/samples/web-app-custom-image/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" ACR_TEMPLATE="acr.bicep" ACR_PARAMETERS="acr.bicepparam" MAIN_TEMPLATE="main.bicep" diff --git a/samples/web-app-custom-image/dotnet/scripts/call-web-app.sh b/samples/web-app-custom-image/dotnet/scripts/call-web-app.sh index 0c77196..2641bb3 100755 --- a/samples/web-app-custom-image/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-custom-image/dotnet/scripts/call-web-app.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" WEB_APP_NAME="${PREFIX}-webapp-${SUFFIX}" diff --git a/samples/web-app-custom-image/dotnet/scripts/deploy.sh b/samples/web-app-custom-image/dotnet/scripts/deploy.sh index fbd7ada..afa6a03 100755 --- a/samples/web-app-custom-image/dotnet/scripts/deploy.sh +++ b/samples/web-app-custom-image/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" ACR_NAME="${PREFIX}acr${SUFFIX}" diff --git a/samples/web-app-custom-image/dotnet/scripts/validate.sh b/samples/web-app-custom-image/dotnet/scripts/validate.sh index b58fb61..519f558 100755 --- a/samples/web-app-custom-image/dotnet/scripts/validate.sh +++ b/samples/web-app-custom-image/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" ACR_NAME="${PREFIX}acr${SUFFIX}" MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}" diff --git a/samples/web-app-custom-image/dotnet/terraform/deploy.sh b/samples/web-app-custom-image/dotnet/terraform/deploy.sh index 63e42fb..c9e826e 100755 --- a/samples/web-app-custom-image/dotnet/terraform/deploy.sh +++ b/samples/web-app-custom-image/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" IMAGE_NAME="custom-image-webapp" diff --git a/samples/web-app-custom-image/python/bicep/deploy.sh b/samples/web-app-custom-image/python/bicep/deploy.sh index 9c16125..e90e37b 100755 --- a/samples/web-app-custom-image/python/bicep/deploy.sh +++ b/samples/web-app-custom-image/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" ACR_TEMPLATE="acr.bicep" ACR_PARAMETERS="acr.bicepparam" MAIN_TEMPLATE="main.bicep" diff --git a/samples/web-app-custom-image/python/scripts/call-web-app.sh b/samples/web-app-custom-image/python/scripts/call-web-app.sh index 0c77196..2641bb3 100755 --- a/samples/web-app-custom-image/python/scripts/call-web-app.sh +++ b/samples/web-app-custom-image/python/scripts/call-web-app.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" WEB_APP_NAME="${PREFIX}-webapp-${SUFFIX}" diff --git a/samples/web-app-custom-image/python/scripts/deploy.sh b/samples/web-app-custom-image/python/scripts/deploy.sh index fbd7ada..afa6a03 100755 --- a/samples/web-app-custom-image/python/scripts/deploy.sh +++ b/samples/web-app-custom-image/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" ACR_NAME="${PREFIX}acr${SUFFIX}" diff --git a/samples/web-app-custom-image/python/scripts/validate.sh b/samples/web-app-custom-image/python/scripts/validate.sh index b58fb61..519f558 100755 --- a/samples/web-app-custom-image/python/scripts/validate.sh +++ b/samples/web-app-custom-image/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" ACR_NAME="${PREFIX}acr${SUFFIX}" MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}" diff --git a/samples/web-app-custom-image/python/terraform/deploy.sh b/samples/web-app-custom-image/python/terraform/deploy.sh index 63e42fb..c9e826e 100755 --- a/samples/web-app-custom-image/python/terraform/deploy.sh +++ b/samples/web-app-custom-image/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" IMAGE_NAME="custom-image-webapp" diff --git a/samples/web-app-managed-identity/dotnet/README.md b/samples/web-app-managed-identity/dotnet/README.md index 884eb97..f4308a4 100644 --- a/samples/web-app-managed-identity/dotnet/README.md +++ b/samples/web-app-managed-identity/dotnet/README.md @@ -82,7 +82,7 @@ All deployment methods have been fully tested with both user-assigned and system ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-managed-identity/dotnet/bicep/deploy.sh b/samples/web-app-managed-identity/dotnet/bicep/deploy.sh index 6ce9027..d4cc198 100755 --- a/samples/web-app-managed-identity/dotnet/bicep/deploy.sh +++ b/samples/web-app-managed-identity/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="$PREFIX-rg" diff --git a/samples/web-app-managed-identity/dotnet/scripts/api.sh b/samples/web-app-managed-identity/dotnet/scripts/api.sh index 71c0deb..c11db53 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/api.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/api.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' NEW_LOCATION='northeurope' RANDOM_SUFFIX=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 4) diff --git a/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh b/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh index a82964c..b3eb722 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -153,10 +185,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-managed-identity/dotnet/scripts/cli.sh b/samples/web-app-managed-identity/dotnet/scripts/cli.sh index a72c1c5..af19a3f 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/cli.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/cli.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RANDOM_SUFFIX=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 4) MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}-${RANDOM_SUFFIX}" diff --git a/samples/web-app-managed-identity/dotnet/scripts/system-assigned.sh b/samples/web-app-managed-identity/dotnet/scripts/system-assigned.sh index a5dc656..eec215f 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/system-assigned.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/system-assigned.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-managed-identity/dotnet/scripts/user-assigned.sh b/samples/web-app-managed-identity/dotnet/scripts/user-assigned.sh index a318226..014aad1 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/user-assigned.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/user-assigned.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-managed-identity/dotnet/scripts/validate.sh b/samples/web-app-managed-identity/dotnet/scripts/validate.sh index 67198f8..9280330 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/validate.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" CONTAINER_NAME='activities' diff --git a/samples/web-app-managed-identity/dotnet/terraform/deploy.sh b/samples/web-app-managed-identity/dotnet/terraform/deploy.sh index 25dbf65..a594810 100755 --- a/samples/web-app-managed-identity/dotnet/terraform/deploy.sh +++ b/samples/web-app-managed-identity/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' MANAGED_IDENTITY_TYPE='UserAssigned' # SystemAssigned or UserAssigned CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" diff --git a/samples/web-app-managed-identity/python/README.md b/samples/web-app-managed-identity/python/README.md index 7912751..970f8c2 100644 --- a/samples/web-app-managed-identity/python/README.md +++ b/samples/web-app-managed-identity/python/README.md @@ -82,7 +82,7 @@ All deployment methods have been fully tested with both user-assigned and system ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-managed-identity/python/bicep/deploy.sh b/samples/web-app-managed-identity/python/bicep/deploy.sh index 149e131..cc9020f 100755 --- a/samples/web-app-managed-identity/python/bicep/deploy.sh +++ b/samples/web-app-managed-identity/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="$PREFIX-rg" diff --git a/samples/web-app-managed-identity/python/scripts/api.sh b/samples/web-app-managed-identity/python/scripts/api.sh index 71c0deb..c11db53 100755 --- a/samples/web-app-managed-identity/python/scripts/api.sh +++ b/samples/web-app-managed-identity/python/scripts/api.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' NEW_LOCATION='northeurope' RANDOM_SUFFIX=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 4) diff --git a/samples/web-app-managed-identity/python/scripts/call-web-app.sh b/samples/web-app-managed-identity/python/scripts/call-web-app.sh index a82964c..b3eb722 100755 --- a/samples/web-app-managed-identity/python/scripts/call-web-app.sh +++ b/samples/web-app-managed-identity/python/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Get the web app name echo "Getting web app name..." @@ -125,9 +147,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -153,10 +185,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-managed-identity/python/scripts/cli.sh b/samples/web-app-managed-identity/python/scripts/cli.sh index a72c1c5..af19a3f 100755 --- a/samples/web-app-managed-identity/python/scripts/cli.sh +++ b/samples/web-app-managed-identity/python/scripts/cli.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RANDOM_SUFFIX=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 4) MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}-${RANDOM_SUFFIX}" diff --git a/samples/web-app-managed-identity/python/scripts/system-assigned.sh b/samples/web-app-managed-identity/python/scripts/system-assigned.sh index 2850aa8..ca2facd 100755 --- a/samples/web-app-managed-identity/python/scripts/system-assigned.sh +++ b/samples/web-app-managed-identity/python/scripts/system-assigned.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-managed-identity/python/scripts/user-assigned.sh b/samples/web-app-managed-identity/python/scripts/user-assigned.sh index c688671..b50054d 100755 --- a/samples/web-app-managed-identity/python/scripts/user-assigned.sh +++ b/samples/web-app-managed-identity/python/scripts/user-assigned.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" APP_SERVICE_PLAN_NAME="${PREFIX}-app-service-plan-${SUFFIX}" diff --git a/samples/web-app-managed-identity/python/scripts/validate.sh b/samples/web-app-managed-identity/python/scripts/validate.sh index 67198f8..9280330 100755 --- a/samples/web-app-managed-identity/python/scripts/validate.sh +++ b/samples/web-app-managed-identity/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" CONTAINER_NAME='activities' diff --git a/samples/web-app-managed-identity/python/terraform/deploy.sh b/samples/web-app-managed-identity/python/terraform/deploy.sh index 4647b3f..9569581 100755 --- a/samples/web-app-managed-identity/python/terraform/deploy.sh +++ b/samples/web-app-managed-identity/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' MANAGED_IDENTITY_TYPE='UserAssigned' # SystemAssigned or UserAssigned CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" diff --git a/samples/web-app-mysql-flexible-server/dotnet/README.md b/samples/web-app-mysql-flexible-server/dotnet/README.md index 847b8bb..97f1e5a 100644 --- a/samples/web-app-mysql-flexible-server/dotnet/README.md +++ b/samples/web-app-mysql-flexible-server/dotnet/README.md @@ -64,7 +64,7 @@ All three variants provision the same topology: VNet + pe-subnet hosting a Priva ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the seeded activities and can add, edit, and remove activities. diff --git a/samples/web-app-mysql-flexible-server/dotnet/bicep/deploy.sh b/samples/web-app-mysql-flexible-server/dotnet/bicep/deploy.sh index 6eacd28..4d27607 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/bicep/deploy.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh b/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-mysql-flexible-server/dotnet/scripts/deploy.sh b/samples/web-app-mysql-flexible-server/dotnet/scripts/deploy.sh index 74e4921..ade1ba2 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/scripts/deploy.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-mysql-flexible-server/dotnet/scripts/validate.sh b/samples/web-app-mysql-flexible-server/dotnet/scripts/validate.sh index 7538368..b5a0926 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/scripts/validate.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-mysql-flexible-server/dotnet/terraform/deploy.sh b/samples/web-app-mysql-flexible-server/dotnet/terraform/deploy.sh index 739e2e2..d07794d 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/terraform/deploy.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' MYSQL_ADMIN_USER="${MYSQL_ADMIN_USER:-myadmin}" MYSQL_ADMIN_PASSWORD="${MYSQL_ADMIN_PASSWORD:-P@ssw0rd1234!}" diff --git a/samples/web-app-mysql-flexible-server/python/README.md b/samples/web-app-mysql-flexible-server/python/README.md index 275cf79..4ccb3ac 100644 --- a/samples/web-app-mysql-flexible-server/python/README.md +++ b/samples/web-app-mysql-flexible-server/python/README.md @@ -64,7 +64,7 @@ All three variants provision the same topology: VNet + pe-subnet hosting a Priva ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the seeded activities and can add, edit, and remove activities. diff --git a/samples/web-app-mysql-flexible-server/python/bicep/deploy.sh b/samples/web-app-mysql-flexible-server/python/bicep/deploy.sh index 0018e7e..9d9c056 100755 --- a/samples/web-app-mysql-flexible-server/python/bicep/deploy.sh +++ b/samples/web-app-mysql-flexible-server/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh b/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh +++ b/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-mysql-flexible-server/python/scripts/deploy.sh b/samples/web-app-mysql-flexible-server/python/scripts/deploy.sh index 3738fd1..9787b81 100755 --- a/samples/web-app-mysql-flexible-server/python/scripts/deploy.sh +++ b/samples/web-app-mysql-flexible-server/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-mysql-flexible-server/python/scripts/validate.sh b/samples/web-app-mysql-flexible-server/python/scripts/validate.sh index 7538368..b5a0926 100755 --- a/samples/web-app-mysql-flexible-server/python/scripts/validate.sh +++ b/samples/web-app-mysql-flexible-server/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-mysql-flexible-server/python/terraform/deploy.sh b/samples/web-app-mysql-flexible-server/python/terraform/deploy.sh index b7eea10..d41747e 100755 --- a/samples/web-app-mysql-flexible-server/python/terraform/deploy.sh +++ b/samples/web-app-mysql-flexible-server/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' MYSQL_ADMIN_USER="${MYSQL_ADMIN_USER:-myadmin}" MYSQL_ADMIN_PASSWORD="${MYSQL_ADMIN_PASSWORD:-P@ssw0rd1234!}" diff --git a/samples/web-app-postgresql-flexible-server/dotnet/README.md b/samples/web-app-postgresql-flexible-server/dotnet/README.md index dfdb347..0375590 100644 --- a/samples/web-app-postgresql-flexible-server/dotnet/README.md +++ b/samples/web-app-postgresql-flexible-server/dotnet/README.md @@ -64,7 +64,7 @@ All three variants provision the same topology: VNet + pe-subnet hosting a Priva ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the three seeded activities (*Go to Paris*, *Go to London*, *Go to Mexico*) and can add, edit, and remove activities. diff --git a/samples/web-app-postgresql-flexible-server/dotnet/bicep/deploy.sh b/samples/web-app-postgresql-flexible-server/dotnet/bicep/deploy.sh index e136ff4..6391c13 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/bicep/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh b/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-postgresql-flexible-server/dotnet/scripts/deploy.sh b/samples/web-app-postgresql-flexible-server/dotnet/scripts/deploy.sh index 71d5bdc..275044e 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/scripts/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-postgresql-flexible-server/dotnet/scripts/validate.sh b/samples/web-app-postgresql-flexible-server/dotnet/scripts/validate.sh index b76a693..99f8575 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/scripts/validate.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-postgresql-flexible-server/dotnet/terraform/deploy.sh b/samples/web-app-postgresql-flexible-server/dotnet/terraform/deploy.sh index 448d315..0d1a388 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/terraform/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' PG_ADMIN_USER="pgadmin" PG_ADMIN_PASSWORD="P@ssw0rd1234!" diff --git a/samples/web-app-postgresql-flexible-server/python/README.md b/samples/web-app-postgresql-flexible-server/python/README.md index f811fb2..d842caf 100644 --- a/samples/web-app-postgresql-flexible-server/python/README.md +++ b/samples/web-app-postgresql-flexible-server/python/README.md @@ -64,7 +64,7 @@ All three variants provision the same topology: VNet + pe-subnet hosting a Priva ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the *Vacation Planner* UI with the three seeded activities (*Go to Paris*, *Go to London*, *Go to Mexico*) and can add, edit, and remove activities. diff --git a/samples/web-app-postgresql-flexible-server/python/bicep/deploy.sh b/samples/web-app-postgresql-flexible-server/python/bicep/deploy.sh index d4ed0a7..84146aa 100755 --- a/samples/web-app-postgresql-flexible-server/python/bicep/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="${PREFIX}-rg" diff --git a/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh b/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh index b521aed..2a10e1b 100755 --- a/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh +++ b/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh @@ -65,9 +65,31 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + call_web_app() { # Web app port - local web_app_port=8000 + local web_app_port # Get the web app name echo "Getting web app name..." @@ -128,8 +150,18 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 8000) - echo "Getting the host port mapped to internal port $web_app_port in container [$container_name]..." + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + web_app_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$web_app_port" ]; then + echo "Web app listens on port [$web_app_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$web_app_port] in container [$container_name]..." host_port=$(get_docker_container_port_mapping "$container_name" "$web_app_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then @@ -155,7 +187,7 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$web_app_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." curl --max-time 10 -s "http://$container_ip:$web_app_port/" 1> /dev/null diff --git a/samples/web-app-postgresql-flexible-server/python/scripts/deploy.sh b/samples/web-app-postgresql-flexible-server/python/scripts/deploy.sh index 000d8b2..01a7511 100755 --- a/samples/web-app-postgresql-flexible-server/python/scripts/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" diff --git a/samples/web-app-postgresql-flexible-server/python/scripts/validate.sh b/samples/web-app-postgresql-flexible-server/python/scripts/validate.sh index b76a693..99f8575 100755 --- a/samples/web-app-postgresql-flexible-server/python/scripts/validate.sh +++ b/samples/web-app-postgresql-flexible-server/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" WEB_APP_SUBNET_NSG_NAME="${PREFIX}-webapp-subnet-nsg-${SUFFIX}" diff --git a/samples/web-app-postgresql-flexible-server/python/terraform/deploy.sh b/samples/web-app-postgresql-flexible-server/python/terraform/deploy.sh index 496637b..161e616 100755 --- a/samples/web-app-postgresql-flexible-server/python/terraform/deploy.sh +++ b/samples/web-app-postgresql-flexible-server/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' PG_ADMIN_USER="pgadmin" PG_ADMIN_PASSWORD="P@ssw0rd1234!" diff --git a/samples/web-app-sql-database/dotnet/README.md b/samples/web-app-sql-database/dotnet/README.md index f6ebe9f..419d2f8 100644 --- a/samples/web-app-sql-database/dotnet/README.md +++ b/samples/web-app-sql-database/dotnet/README.md @@ -90,7 +90,7 @@ All deployment methods have been fully tested against Azure and the LocalStack f ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. As an alternative, you can retrieve the URL using the following command and call the Web App using the HTTP or HTTPS protocol: ```bash diff --git a/samples/web-app-sql-database/dotnet/bicep/deploy.sh b/samples/web-app-sql-database/dotnet/bicep/deploy.sh index 47ce812..67635fa 100755 --- a/samples/web-app-sql-database/dotnet/bicep/deploy.sh +++ b/samples/web-app-sql-database/dotnet/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="$PREFIX-rg" diff --git a/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh b/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh index e7694df..096740f 100755 --- a/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + # Distinguished names are compared after normalization: OpenSSL 3 prints "CN = value", Key Vault # returns "CN=value" and OpenSSL 1 printed "/CN=value" - the same subject in three spellings, which # a literal comparison reports as a mismatch. @@ -133,9 +155,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -161,10 +193,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-sql-database/dotnet/scripts/deploy.sh b/samples/web-app-sql-database/dotnet/scripts/deploy.sh index 48ffaa8..4e3d440 100755 --- a/samples/web-app-sql-database/dotnet/scripts/deploy.sh +++ b/samples/web-app-sql-database/dotnet/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" SQL_SERVER_NAME="${PREFIX}-sqlserver-${SUFFIX}" diff --git a/samples/web-app-sql-database/dotnet/scripts/validate.sh b/samples/web-app-sql-database/dotnet/scripts/validate.sh index c6ca9bf..50cd688 100755 --- a/samples/web-app-sql-database/dotnet/scripts/validate.sh +++ b/samples/web-app-sql-database/dotnet/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" SQL_SERVER_NAME="${PREFIX}-sqlserver-${SUFFIX}" SQL_DATABASE_NAME='PlannerDB' diff --git a/samples/web-app-sql-database/dotnet/terraform/deploy.sh b/samples/web-app-sql-database/dotnet/terraform/deploy.sh index 2e1ab40..4231870 100755 --- a/samples/web-app-sql-database/dotnet/terraform/deploy.sh +++ b/samples/web-app-sql-database/dotnet/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' ADMIN_USER='sqladmin' ADMIN_PASSWORD='P@ssw0rd1234!' diff --git a/samples/web-app-sql-database/python/README.md b/samples/web-app-sql-database/python/README.md index 1fe94e3..a57c52f 100644 --- a/samples/web-app-sql-database/python/README.md +++ b/samples/web-app-sql-database/python/README.md @@ -90,7 +90,7 @@ All deployment methods have been fully tested against Azure and the LocalStack f ## Test -1. Retrieve the port published and mapped to port 80 by the Docker container hosting the emulated Web App. +1. Retrieve the host port Docker maps to the port the Web App listens on in its container, for example with `docker port ` (the container's name starts with `ls-`). Do not assume port 80: the app listens on the port its `WEBSITES_PORT` app setting names, when it has one. 2. Open a web browser and navigate to `http://localhost:`. 3. If the deployment was successful, you will see the following user interface for adding and removing activities: diff --git a/samples/web-app-sql-database/python/bicep/deploy.sh b/samples/web-app-sql-database/python/bicep/deploy.sh index efbe9a6..178cb27 100755 --- a/samples/web-app-sql-database/python/bicep/deploy.sh +++ b/samples/web-app-sql-database/python/bicep/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" TEMPLATE="main.bicep" PARAMETERS="main.bicepparam" RESOURCE_GROUP_NAME="$PREFIX-rg" diff --git a/samples/web-app-sql-database/python/scripts/call-web-app.sh b/samples/web-app-sql-database/python/scripts/call-web-app.sh index 272c0f9..d253e72 100755 --- a/samples/web-app-sql-database/python/scripts/call-web-app.sh +++ b/samples/web-app-sql-database/python/scripts/call-web-app.sh @@ -65,6 +65,28 @@ get_docker_container_port_mapping() { echo "$host_port" } +get_docker_container_app_port() { + local container_name="$1" + local container_port + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # The emulator publishes the port the app listens on in its container, which is not necessarily 80: + # an app listens on the port its WEBSITES_PORT app setting names. Read it from the container. + container_port=$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if $bindings}}{{println $port}}{{end}}{{end}}' "$container_name" | grep '/tcp$' | head -n 1) + container_port="${container_port%/tcp}" + + if [ -z "$container_port" ]; then + echo "Error: Container [$container_name] publishes no TCP port" >&2 + return 1 + fi + + echo "$container_port" +} + # Distinguished names are compared after normalization: OpenSSL 3 prints "CN = value", Key Vault # returns "CN=value" and OpenSSL 1 printed "/CN=value" - the same subject in three spellings, which # a literal comparison reports as a mismatch. @@ -133,9 +155,19 @@ call_web_app() { exit 1 fi - # Get the mapped host port for web app HTTP trigger (internal port 80) - echo "Getting the host port mapped to internal port 80 in container [$container_name]..." - host_port=$(get_docker_container_port_mapping "$container_name" "80") + # Get the port the web app listens on in its container + echo "Getting the port the web app listens on in container [$container_name]..." + container_port=$(get_docker_container_app_port "$container_name") + + if [ $? -eq 0 ] && [ -n "$container_port" ]; then + echo "Web app listens on port [$container_port] in container [$container_name]" + else + echo "Failed to get the port the web app listens on in container [$container_name]" + fi + + # Get the host port mapped to it + echo "Getting the host port mapped to port [$container_port] in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "$container_port") if [ $? -eq 0 ] && [ -n "$host_port" ]; then echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" @@ -161,10 +193,10 @@ call_web_app() { echo "Failed to retrieve LocalStack proxy port" fi - if [ -n "$container_ip" ]; then + if [ -n "$container_ip" ] && [ -n "$container_port" ]; then # Call the web app via the container IP address echo "Calling web app [$web_app_name] via container IP address [$container_ip]..." - curl --max-time 10 -s "http://$container_ip/" 1> /dev/null + curl --max-time 10 -s "http://$container_ip:$container_port/" 1> /dev/null if [ $? == 0 ]; then echo "Web app call via container IP address [$container_ip] succeeded." diff --git a/samples/web-app-sql-database/python/scripts/deploy.sh b/samples/web-app-sql-database/python/scripts/deploy.sh index 47d00b7..35e080b 100755 --- a/samples/web-app-sql-database/python/scripts/deploy.sh +++ b/samples/web-app-sql-database/python/scripts/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' RESOURCE_GROUP_NAME="${PREFIX}-rg" SQL_SERVER_NAME="${PREFIX}-sqlserver-${SUFFIX}" diff --git a/samples/web-app-sql-database/python/scripts/validate.sh b/samples/web-app-sql-database/python/scripts/validate.sh index c6ca9bf..50cd688 100755 --- a/samples/web-app-sql-database/python/scripts/validate.sh +++ b/samples/web-app-sql-database/python/scripts/validate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" RESOURCE_GROUP_NAME="${PREFIX}-rg" SQL_SERVER_NAME="${PREFIX}-sqlserver-${SUFFIX}" SQL_DATABASE_NAME='PlannerDB' diff --git a/samples/web-app-sql-database/python/terraform/deploy.sh b/samples/web-app-sql-database/python/terraform/deploy.sh index c64b9e1..1314271 100755 --- a/samples/web-app-sql-database/python/terraform/deploy.sh +++ b/samples/web-app-sql-database/python/terraform/deploy.sh @@ -1,8 +1,8 @@ #!/bin/bash # Variables -PREFIX='local' -SUFFIX='test' +PREFIX="${PREFIX:-local}" +SUFFIX="${SUFFIX:-test}" LOCATION='westeurope' ADMIN_USER='sqladmin' ADMIN_PASSWORD='P@ssw0rd1234!' From b94c02383eb1a5c75b618a55f9e11182a5a33f35 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 6 Oct 2026 19:09:53 +0200 Subject: [PATCH 2/5] Take the app name as an input in the call scripts instead of calling the first app listed The call scripts looked up the first web app or function app the Azure CLI listed, so with several deployments on one emulator (which taking PREFIX and SUFFIX from the environment allows) they could read the port from and call another deployment's app. A call script now takes the app name as its first argument, or from WEB_APP_NAME or FUNCTION_APP_NAME, and reads the resource group from that app. Without a name it calls the only app in the subscription, and stops with a message asking for the name when there are several. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm --- .../dotnet/scripts/call-http-trigger.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-http-triggers.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- .../dotnet/scripts/call-web-app.sh | 23 +++++++++++++++---- .../python/scripts/call-web-app.sh | 23 +++++++++++++++---- 16 files changed, 288 insertions(+), 80 deletions(-) diff --git a/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh index 98c4768..a8384f2 100755 --- a/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh +++ b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-http-trigger.sh [function-app-name] +# +# The function app to call is the one named by the first argument, else by FUNCTION_APP_NAME, else the only function app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_http_trigger_function() { - # Get the function app name - echo "Getting function app name..." - function_app_name=$(az functionapp list --query '[0].name' --output tsv) + # The function app to call: the one the caller named, else the only one in the subscription + function_app_name="$1" + if [ -z "$function_app_name" ]; then + echo "Getting the name of the only function app in the subscription..." + function_app_count=$(az functionapp list --query "length(@)" --output tsv) + if [ "$function_app_count" != "1" ]; then + echo "Error: Found [${function_app_count:-0}] function apps; name the one to call: $0 " + exit 1 + fi + function_app_name=$(az functionapp list --query "[0].name" --output tsv) + fi if [ -n "$function_app_name" ]; then echo "Function app [$function_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_http_trigger_function() { # Get the resource group name echo "Getting resource group name for function app [$function_app_name]..." - resource_group_name=$(az functionapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az functionapp list --query "[?name=='${function_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -194,4 +207,4 @@ call_http_trigger_function() { fi } -call_http_trigger_function \ No newline at end of file +call_http_trigger_function "${1:-${FUNCTION_APP_NAME:-}}" diff --git a/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh b/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh index 2bf5703..73f819b 100755 --- a/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh +++ b/samples/function-app-storage-http/dotnet/scripts/call-http-triggers.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-http-triggers.sh [function-app-name] +# +# The function app to call is the one named by the first argument, else by FUNCTION_APP_NAME, else the only function app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_http_trigger_functions() { - # Get the function app name - echo "Getting function app name..." - function_app_name=$(az functionapp list --query '[0].name' --output tsv) + # The function app to call: the one the caller named, else the only one in the subscription + function_app_name="$1" + if [ -z "$function_app_name" ]; then + echo "Getting the name of the only function app in the subscription..." + function_app_count=$(az functionapp list --query "length(@)" --output tsv) + if [ "$function_app_count" != "1" ]; then + echo "Error: Found [${function_app_count:-0}] function apps; name the one to call: $0 " + exit 1 + fi + function_app_name=$(az functionapp list --query "[0].name" --output tsv) + fi if [ -n "$function_app_name" ]; then echo "Function app [$function_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_http_trigger_functions() { # Get the resource group name echo "Getting resource group name for function app [$function_app_name]..." - resource_group_name=$(az functionapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az functionapp list --query "[?name=='${function_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -207,4 +220,4 @@ call_http_trigger_functions() { fi } -call_http_trigger_functions \ No newline at end of file +call_http_trigger_functions "${1:-${FUNCTION_APP_NAME:-}}" diff --git a/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh b/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-app-configuration/python/scripts/call-web-app.sh b/samples/web-app-app-configuration/python/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-app-configuration/python/scripts/call-web-app.sh +++ b/samples/web-app-app-configuration/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh index 3a902f6..6620a4c 100755 --- a/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -227,4 +240,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh b/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh index 3a902f6..6620a4c 100755 --- a/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-mongodb-api/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -227,4 +240,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh index b3eb722..6f4db11 100755 --- a/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-nosql-api/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -228,4 +241,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh b/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh index b3eb722..6f4db11 100755 --- a/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh +++ b/samples/web-app-cosmosdb-nosql-api/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -228,4 +241,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh b/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh index b3eb722..6f4db11 100755 --- a/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-managed-identity/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -228,4 +241,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-managed-identity/python/scripts/call-web-app.sh b/samples/web-app-managed-identity/python/scripts/call-web-app.sh index b3eb722..6f4db11 100755 --- a/samples/web-app-managed-identity/python/scripts/call-web-app.sh +++ b/samples/web-app-managed-identity/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -88,9 +93,17 @@ get_docker_container_app_port() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -101,7 +114,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -228,4 +241,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh b/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-mysql-flexible-server/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh b/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh +++ b/samples/web-app-mysql-flexible-server/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh b/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-postgresql-flexible-server/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh b/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh index 2a10e1b..f98ceac 100755 --- a/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh +++ b/samples/web-app-postgresql-flexible-server/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -91,9 +96,17 @@ call_web_app() { # Web app port local web_app_port - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -104,7 +117,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -230,4 +243,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh b/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh index 096740f..b48418c 100755 --- a/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh +++ b/samples/web-app-sql-database/dotnet/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -96,9 +101,17 @@ normalize_dn() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -109,7 +122,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -280,4 +293,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" diff --git a/samples/web-app-sql-database/python/scripts/call-web-app.sh b/samples/web-app-sql-database/python/scripts/call-web-app.sh index d253e72..74bf6ff 100755 --- a/samples/web-app-sql-database/python/scripts/call-web-app.sh +++ b/samples/web-app-sql-database/python/scripts/call-web-app.sh @@ -1,5 +1,10 @@ #!/bin/bash +# Usage: call-web-app.sh [web-app-name] +# +# The web app to call is the one named by the first argument, else by WEB_APP_NAME, else the only web app in the +# subscription. Name it when several are deployed. + get_docker_container_name_by_prefix() { local app_prefix="$1" local container_name @@ -96,9 +101,17 @@ normalize_dn() { } call_web_app() { - # Get the web app name - echo "Getting web app name..." - web_app_name=$(az webapp list --query '[0].name' --output tsv) + # The web app to call: the one the caller named, else the only one in the subscription + web_app_name="$1" + if [ -z "$web_app_name" ]; then + echo "Getting the name of the only web app in the subscription..." + web_app_count=$(az webapp list --query "length(@)" --output tsv) + if [ "$web_app_count" != "1" ]; then + echo "Error: Found [${web_app_count:-0}] web apps; name the one to call: $0 " + exit 1 + fi + web_app_name=$(az webapp list --query "[0].name" --output tsv) + fi if [ -n "$web_app_name" ]; then echo "Web app [$web_app_name] successfully retrieved." @@ -109,7 +122,7 @@ call_web_app() { # Get the resource group name echo "Getting resource group name for web app [$web_app_name]..." - resource_group_name=$(az webapp list --query '[0].resourceGroup' --output tsv) + resource_group_name=$(az webapp list --query "[?name=='${web_app_name}'] | [0].resourceGroup" --output tsv) if [ -n "$resource_group_name" ]; then echo "Resource group [$resource_group_name] successfully retrieved." @@ -283,4 +296,4 @@ call_web_app() { fi } -call_web_app \ No newline at end of file +call_web_app "${1:-${WEB_APP_NAME:-}}" From 8e006b3dfbffe76a4a8141c58e25da0420838f4c Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 6 Oct 2026 19:09:53 +0200 Subject: [PATCH 3/5] Remove the stopped emulator container before starting a new one in the samples workflow localstack stop does not wait for Docker to remove the container, so the start that followed failed with 'container named "localstack-main" already exists', and the retry of a failed sample never ran. The readiness loop and the retry step now remove the container and wait until it is gone before they start the emulator again. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm --- .github/workflows/run-samples.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/run-samples.yml b/.github/workflows/run-samples.yml index fe50b5f..f8ba93b 100644 --- a/.github/workflows/run-samples.yml +++ b/.github/workflows/run-samples.yml @@ -216,6 +216,10 @@ jobs: echo "::warning::Emulator was not ready within 400s (attempt ${attempt}/${attempts})." docker logs localstack-main --tail 100 2>&1 || true python -m localstack_cli.cli.main stop || true + # stop does not wait for Docker to remove the container, and a start that still finds it fails with + # 'container named "localstack-main" already exists'. + docker rm -f localstack-main >/dev/null 2>&1 || true + for _ in $(seq 1 30); do docker container inspect localstack-main >/dev/null 2>&1 || break; sleep 1; done done echo "::error::Emulator failed to become ready after ${attempts} attempts." exit 1 @@ -307,6 +311,10 @@ jobs: source .venv/bin/activate echo "::warning::${MATRIX_NAME} failed once; retrying on a fresh emulator." python -m localstack_cli.cli.main stop || true + # stop does not wait for Docker to remove the container, and a start that still finds it fails with + # 'container named "localstack-main" already exists'. + docker rm -f localstack-main >/dev/null 2>&1 || true + for _ in $(seq 1 30); do docker container inspect localstack-main >/dev/null 2>&1 || break; sleep 1; done python -m localstack_cli.cli.main start -d python -m localstack_cli.cli.main wait -t 600 make test SHARD="${SHARD}" SPLITS="${SPLITS}" From 8dff877f1f0c47176e7cf49c99aaee2bc3c15e3c Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 6 Oct 2026 20:27:00 +0200 Subject: [PATCH 4/5] Serve HTTPS on port 8443 in the SQL Database web app after every deployment method call-web-app.sh checks the certificate the web app serves on port 8443, and it failed in two cases. The Bicep deployments set no CERT_NAME, created no certificate and gave the web app no certificate permission on the Key Vault, so the app never served HTTPS. main.bicep now sets CERT_NAME and grants certificates/get, and deploy.sh creates the certificate in the Key Vault after the deployment and before the code is deployed (Bicep cannot create a Key Vault certificate). The Python app started its HTTPS listener only when run as `python app.py`, never under gunicorn, which is how App Service runs it. gunicorn.conf.py now starts that listener once in the gunicorn master when KEYVAULT_URI and CERT_NAME are set. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm --- .../dotnet/bicep/deploy.sh | 25 +++++++++++++++++++ .../dotnet/bicep/main.bicep | 8 ++++++ .../python/bicep/deploy.sh | 25 +++++++++++++++++++ .../python/bicep/main.bicep | 8 ++++++ .../python/src/gunicorn.conf.py | 25 +++++++++++++++++++ 5 files changed, 91 insertions(+) diff --git a/samples/web-app-sql-database/dotnet/bicep/deploy.sh b/samples/web-app-sql-database/dotnet/bicep/deploy.sh index 67635fa..2ae5eac 100755 --- a/samples/web-app-sql-database/dotnet/bicep/deploy.sh +++ b/samples/web-app-sql-database/dotnet/bicep/deploy.sh @@ -116,6 +116,8 @@ if DEPLOYMENT_OUTPUTS=$(az deployment group create \ echo "$DEPLOYMENT_JSON" | jq . APP_SERVICE_PLAN_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.appServicePlanName.value') WEB_APP_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.webAppName.value') + KEY_VAULT_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.keyVaultName.value') + CERT_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.certificateName.value') SQL_SERVER_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.sqlServerName.value') SQL_DATABASE_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.sqlDatabaseName.value') echo "Deployment details:" @@ -285,6 +287,29 @@ if [[ $DEPLOY_APP -eq 0 ]]; then exit 0 fi +# Create the certificate the web app serves HTTPS with on port 8443 (its CERT_NAME app setting), before the +# code is deployed and the app starts: Bicep cannot create a Key Vault certificate. +if az keyvault certificate show --vault-name "$KEY_VAULT_NAME" --name "$CERT_NAME" --only-show-errors &>/dev/null; then + echo "Certificate [$CERT_NAME] already exists in Key Vault [$KEY_VAULT_NAME]." +else + echo "Creating certificate [$CERT_NAME] in Key Vault [$KEY_VAULT_NAME]..." + if az keyvault certificate create \ + --vault-name "$KEY_VAULT_NAME" \ + --name "$CERT_NAME" \ + --policy '{ + "issuerParameters": {"name": "Self"}, + "keyProperties": {"exportable": true, "keySize": 2048, "keyType": "RSA", "reuseKey": false}, + "secretProperties": {"contentType": "application/x-pkcs12"}, + "x509CertificateProperties": {"subject": "CN=sample-web-app-sql", "validityInMonths": 12} + }' \ + --only-show-errors 1>/dev/null; then + echo "Certificate [$CERT_NAME] created successfully in Key Vault [$KEY_VAULT_NAME]." + else + echo "Failed to create certificate [$CERT_NAME] in Key Vault [$KEY_VAULT_NAME]." + exit 1 + fi +fi + # Change current directory to source folder cd "../src" || exit diff --git a/samples/web-app-sql-database/dotnet/bicep/main.bicep b/samples/web-app-sql-database/dotnet/bicep/main.bicep index 31075ed..3cd236b 100644 --- a/samples/web-app-sql-database/dotnet/bicep/main.bicep +++ b/samples/web-app-sql-database/dotnet/bicep/main.bicep @@ -321,6 +321,9 @@ var sqlServerName = '${prefix}-sqlserver-${suffix}' var webAppName = '${prefix}-webapp-${suffix}' var appServicePlanName = '${prefix}-app-service-plan-${suffix}' var keyVaultName = '${prefix}-kv-${suffix}' +// The TLS certificate the web app serves HTTPS with on port 8443. Bicep cannot create a Key Vault +// certificate, so deploy.sh creates it under this name after the deployment. +var certificateName = '${prefix}-cert-${suffix}' var sqlConnectionStringSecretName = '${prefix}-secret-${suffix}' var sqlServerIdentityName = '${prefix}-tde-identity-${suffix}' var tdeKeyName = '${prefix}-tde-key-${suffix}' @@ -458,6 +461,9 @@ resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = { 'get' 'list' ] + certificates: [ + 'get' + ] } } { @@ -522,6 +528,7 @@ resource configAppSettings 'Microsoft.Web/sites/config@2024-11-01' = { SECRET_NAME: sqlConnectionStringSecretName LOGIN_NAME: username KEYVAULT_URI: keyVault.properties.vaultUri + CERT_NAME: certificateName } } @@ -543,4 +550,5 @@ output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName output sqlDatabaseName string = sqlDatabase.name output keyVaultName string = keyVault.name output keyVaultUrl string = keyVault.properties.vaultUri +output certificateName string = certificateName output sqlConnectionStringSecretUri string = sqlConnectionStringSecret.properties.secretUri diff --git a/samples/web-app-sql-database/python/bicep/deploy.sh b/samples/web-app-sql-database/python/bicep/deploy.sh index 178cb27..f3b6de1 100755 --- a/samples/web-app-sql-database/python/bicep/deploy.sh +++ b/samples/web-app-sql-database/python/bicep/deploy.sh @@ -116,6 +116,8 @@ if DEPLOYMENT_OUTPUTS=$(az deployment group create \ echo "$DEPLOYMENT_JSON" | jq . APP_SERVICE_PLAN_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.appServicePlanName.value') WEB_APP_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.webAppName.value') + KEY_VAULT_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.keyVaultName.value') + CERT_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.certificateName.value') SQL_SERVER_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.sqlServerName.value') SQL_DATABASE_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.sqlDatabaseName.value') echo "Deployment details:" @@ -285,6 +287,29 @@ if [[ $DEPLOY_APP -eq 0 ]]; then exit 0 fi +# Create the certificate the web app serves HTTPS with on port 8443 (its CERT_NAME app setting), before the +# code is deployed and the app starts: Bicep cannot create a Key Vault certificate. +if az keyvault certificate show --vault-name "$KEY_VAULT_NAME" --name "$CERT_NAME" --only-show-errors &>/dev/null; then + echo "Certificate [$CERT_NAME] already exists in Key Vault [$KEY_VAULT_NAME]." +else + echo "Creating certificate [$CERT_NAME] in Key Vault [$KEY_VAULT_NAME]..." + if az keyvault certificate create \ + --vault-name "$KEY_VAULT_NAME" \ + --name "$CERT_NAME" \ + --policy '{ + "issuerParameters": {"name": "Self"}, + "keyProperties": {"exportable": true, "keySize": 2048, "keyType": "RSA", "reuseKey": false}, + "secretProperties": {"contentType": "application/x-pkcs12"}, + "x509CertificateProperties": {"subject": "CN=sample-web-app-sql", "validityInMonths": 12} + }' \ + --only-show-errors 1>/dev/null; then + echo "Certificate [$CERT_NAME] created successfully in Key Vault [$KEY_VAULT_NAME]." + else + echo "Failed to create certificate [$CERT_NAME] in Key Vault [$KEY_VAULT_NAME]." + exit 1 + fi +fi + # Change current directory to source folder cd "../src" || exit diff --git a/samples/web-app-sql-database/python/bicep/main.bicep b/samples/web-app-sql-database/python/bicep/main.bicep index f077ace..b12e0c8 100644 --- a/samples/web-app-sql-database/python/bicep/main.bicep +++ b/samples/web-app-sql-database/python/bicep/main.bicep @@ -320,6 +320,9 @@ var sqlServerName = '${prefix}-sqlserver-${suffix}' var webAppName = '${prefix}-webapp-${suffix}' var appServicePlanName = '${prefix}-app-service-plan-${suffix}' var keyVaultName = '${prefix}-kv-${suffix}' +// The TLS certificate the web app serves HTTPS with on port 8443. Bicep cannot create a Key Vault +// certificate, so deploy.sh creates it under this name after the deployment. +var certificateName = '${prefix}-cert-${suffix}' var sqlConnectionStringSecretName = '${prefix}-secret-${suffix}' var sqlServerIdentityName = '${prefix}-tde-identity-${suffix}' var tdeKeyName = '${prefix}-tde-key-${suffix}' @@ -457,6 +460,9 @@ resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = { 'get' 'list' ] + certificates: [ + 'get' + ] } } { @@ -521,6 +527,7 @@ resource configAppSettings 'Microsoft.Web/sites/config@2024-11-01' = { SECRET_NAME: sqlConnectionStringSecretName LOGIN_NAME: username KEYVAULT_URI: keyVault.properties.vaultUri + CERT_NAME: certificateName } } @@ -542,4 +549,5 @@ output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName output sqlDatabaseName string = sqlDatabase.name output keyVaultName string = keyVault.name output keyVaultUrl string = keyVault.properties.vaultUri +output certificateName string = certificateName output sqlConnectionStringSecretUri string = sqlConnectionStringSecret.properties.secretUri diff --git a/samples/web-app-sql-database/python/src/gunicorn.conf.py b/samples/web-app-sql-database/python/src/gunicorn.conf.py index cb87ebc..b37a2e4 100644 --- a/samples/web-app-sql-database/python/src/gunicorn.conf.py +++ b/samples/web-app-sql-database/python/src/gunicorn.conf.py @@ -1,4 +1,5 @@ import os +import threading def worker_int(worker): @@ -16,3 +17,27 @@ def worker_abort(worker): # traceback. The WORKER TIMEOUT log line above it is the real diagnostic; # exit at the C level to suppress the spurious trace. os._exit(1) + + +def when_ready(server): + # App Service starts the app with gunicorn, so the `if __name__ == '__main__'` branch of app.py, which serves + # HTTPS on port 8443 with the Key Vault certificate, never runs there. Start that listener here, once, in the + # gunicorn master, next to the HTTP port App Service proxies to. + vault_uri = os.environ.get("KEYVAULT_URI") + cert_name = os.environ.get("CERT_NAME") + if not (vault_uri and cert_name): + return + try: + from werkzeug.serving import make_server + + from app import app + from certificates import get_ssl_context_from_keyvault + + https_server = make_server( + "0.0.0.0", 8443, app, threaded=True, ssl_context=get_ssl_context_from_keyvault(vault_uri, cert_name) + ) + except Exception: + server.log.exception("HTTPS on port 8443 is disabled: certificate [%s] could not be loaded", cert_name) + return + threading.Thread(target=https_server.serve_forever, name="https-8443", daemon=True).start() + server.log.info("HTTPS enabled on port 8443 with Key Vault certificate [%s]", cert_name) From 7d531a2ac0a1378801bd2240fcc99c96dbd082a9 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 6 Oct 2026 20:45:21 +0200 Subject: [PATCH 5/5] Document the certificate the SQL Database Bicep deployment creates Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm --- samples/web-app-sql-database/dotnet/bicep/README.md | 2 ++ samples/web-app-sql-database/python/bicep/README.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/samples/web-app-sql-database/dotnet/bicep/README.md b/samples/web-app-sql-database/dotnet/bicep/README.md index 98a764c..4e95e22 100644 --- a/samples/web-app-sql-database/dotnet/bicep/README.md +++ b/samples/web-app-sql-database/dotnet/bicep/README.md @@ -43,6 +43,8 @@ The [deploy.sh](deploy.sh) script creates the [Azure Resource Group](https://lea 6. [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview): Stores the SQL connection string in a secret and the RSA key that serves as the [TDE protector](https://learn.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview) of the SQL server, registered by the [transparent-data-encryption.bicep](modules/transparent-data-encryption.bicep) module. 7. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): The identity the SQL server uses to reach its TDE protector key in Key Vault. +Bicep cannot create a Key Vault certificate, so after the deployment [deploy.sh](deploy.sh) creates the self-signed certificate the web app serves HTTPS with on port 8443, under the name of its `CERT_NAME` app setting, before it deploys the code. + The web app allows users to plan and manage vacation activities, storing all activity data in the `Activities` table in the `PlannerDB` database. For more information, see [Azure Web App with Azure SQL Database and Azure Key Vault](../README.md). ## Deployment diff --git a/samples/web-app-sql-database/python/bicep/README.md b/samples/web-app-sql-database/python/bicep/README.md index fd3ca0c..bc634fc 100644 --- a/samples/web-app-sql-database/python/bicep/README.md +++ b/samples/web-app-sql-database/python/bicep/README.md @@ -43,6 +43,8 @@ The [deploy.sh](deploy.sh) script creates the [Azure Resource Group](https://lea 6. [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview): Stores the SQL connection string in a secret and the RSA key that serves as the [TDE protector](https://learn.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview) of the SQL server, registered by the [transparent-data-encryption.bicep](modules/transparent-data-encryption.bicep) module. 7. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): The identity the SQL server uses to reach its TDE protector key in Key Vault. +Bicep cannot create a Key Vault certificate, so after the deployment [deploy.sh](deploy.sh) creates the self-signed certificate the web app serves HTTPS with on port 8443, under the name of its `CERT_NAME` app setting, before it deploys the code. + The web app allows users to plan and manage vacation activities, storing all activity data in the `Activities` table in the `PlannerDB` database. For more information, see [Azure Web App with Azure SQL Database and Azure Key Vault](../README.md). ## Deployment