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 48c82b9e..f7f3eea5 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 ede7f93c..e6cf3c05 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 197242cf..dbdfcf8f 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 b269c82b..803fe8f2 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 9773b08f..d1ca5da9 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 dd046396..43925aaf 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 02cea01c..e62c1ae4 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 6432874b..06015f16 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 4b9dd3ef..021bee62 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 674a8be0..22eeec39 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 c178a48d..7f08efdc 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 79ca6254..9a03d5ae 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 1268060c..98c47689 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 91a51fef..420add43 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 ae43236a..b3b75e04 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 7509c531..8fd6be2f 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 cf419507..14407925 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 74092917..2bf57033 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 84819032..7c16c926 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 6578b8f0..7263a26d 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 ee4a152a..f8847679 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 b521aed3..2a10e1b5 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 37d43781..8d10431a 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 b521aed3..2a10e1b5 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 59ee9639..41e010fc 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 cd7172f8..b3681de7 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 9c3945f0..3a902f65 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 eab28e61..921f5b79 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 fd2815c0..297ac8cc 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 fd202c95..050fc10c 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 80ffb4a1..cc1fcc1d 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 2a8cbbba..ba06a3b1 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 45e5ad2e..3a902f65 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 e4dc109f..832f603c 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 fd2815c0..297ac8cc 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 5a3e0dd1..d407122f 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 925da476..8a6f55df 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 a82964c0..b3eb7221 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 6c77fc63..ef3049fe 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 542412ad..2dcc342e 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 b9b28183..317275ca 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 a82964c0..b3eb7221 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 1adc0316..d21700ce 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 542412ad..2dcc342e 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 9c16125a..e90e37b9 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 0c771969..2641bb39 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 fbd7ada2..afa6a034 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 b58fb614..519f558a 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 63e42fb9..c9e826e9 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 9c16125a..e90e37b9 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 0c771969..2641bb39 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 fbd7ada2..afa6a034 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 b58fb614..519f558a 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 63e42fb9..c9e826e9 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 884eb97b..f4308a4c 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 6ce9027d..d4cc1981 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 71c0debc..c11db535 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 a82964c0..b3eb7221 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 a72c1c5d..af19a3f0 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 a5dc6564..eec215f2 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 a3182267..014aad18 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 67198f8f..92803306 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 25dbf65a..a5948101 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 79127510..970f8c22 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 149e1316..cc9020f7 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 71c0debc..c11db535 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 a82964c0..b3eb7221 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 a72c1c5d..af19a3f0 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 2850aa82..ca2facde 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 c688671c..b50054dd 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 67198f8f..92803306 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 4647b3f3..95695813 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 847b8bb8..97f1e5a5 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 6eacd283..4d276071 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 b521aed3..2a10e1b5 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 74e49211..ade1ba27 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 75383689..b5a09260 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 739e2e2e..d07794d3 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 275cf79a..4ccb3aca 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 0018e7ef..9d9c0567 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 b521aed3..2a10e1b5 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 3738fd1f..9787b814 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 75383689..b5a09260 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 b7eea101..d41747e6 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 dfdb347d..03755908 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 e136ff47..6391c139 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 b521aed3..2a10e1b5 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 71d5bdc3..275044e4 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 b76a6933..99f8575b 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 448d3158..0d1a388d 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 f811fb27..d842cafe 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 d4ed0a73..84146aa3 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 b521aed3..2a10e1b5 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 000d8b2a..01a75117 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 b76a6933..99f8575b 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 496637bb..161e616f 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 f6ebe9f8..419d2f81 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 47ce8129..67635faa 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 e7694dfd..096740f1 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 48ffaa80..4e3d4408 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 c6ca9bf4..50cd6884 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 2e1ab40d..42318704 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 1fe94e31..a57c52f7 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 efbe9a6c..178cb270 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 272c0f91..d253e722 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 47d00b71..35e080b9 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 c6ca9bf4..50cd6884 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 c64b9e17..13142719 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 98c47689..a8384f27 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 2bf57033..73f819b2 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 2a10e1b5..f98ceac3 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 2a10e1b5..f98ceac3 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 3a902f65..6620a4c8 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 3a902f65..6620a4c8 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 b3eb7221..6f4db112 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 b3eb7221..6f4db112 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 b3eb7221..6f4db112 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 b3eb7221..6f4db112 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 2a10e1b5..f98ceac3 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 2a10e1b5..f98ceac3 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 2a10e1b5..f98ceac3 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 2a10e1b5..f98ceac3 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 096740f1..b48418cc 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 d253e722..74bf6ff3 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 fe50b5f0..f8ba93b5 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 67635faa..2ae5eac9 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 31075edc..3cd236bf 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 178cb270..f3b6de11 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 f077acec..b12e0c83 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 cb87ebcc..b37a2e4b 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 98a764c3..4e95e22a 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 fd3ca0c9..bc634fc3 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