Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ca9d9db
added terraform tests
DrisDary Jan 15, 2026
6fce1eb
added terraform configs for localstack
DrisDary Jan 15, 2026
7e9ed3e
corrected terraform cmd
DrisDary Jan 15, 2026
b8e0ee0
added logging
DrisDary Jan 15, 2026
004dc4d
added logging
DrisDary Jan 15, 2026
cc87599
added az creds
DrisDary Jan 15, 2026
373bf2b
extending configs
DrisDary Jan 15, 2026
4c98e89
disabled auth
DrisDary Jan 15, 2026
9691d33
add loggin
DrisDary Jan 15, 2026
7404edb
use az cli
DrisDary Jan 15, 2026
a5e56c1
added logs
DrisDary Jan 15, 2026
1394dce
reverts
DrisDary Jan 15, 2026
38d625f
reverts
DrisDary Jan 15, 2026
0bb72f0
added subscription
DrisDary Jan 15, 2026
257ba5c
removed unnecessary installation
DrisDary Jan 15, 2026
ef9b009
added tf installation
DrisDary Jan 15, 2026
68327f8
downgraded python to 3.12
DrisDary Jan 15, 2026
ccf9e39
destroy terraform resources after each test
DrisDary Jan 26, 2026
aefcd20
destroy terraform resources after each test at start
DrisDary Jan 26, 2026
7529dd0
differing resource group names
DrisDary Jan 26, 2026
c7b3db4
removed validate.sh for terraform tests
DrisDary Jan 26, 2026
dc10b61
updated resource group hardcoded value
DrisDary Jan 26, 2026
a195b4c
updated variables default names
DrisDary Jan 26, 2026
1ccb2e3
updated variables default names
DrisDary Jan 26, 2026
de337f0
updated main.tf
DrisDary Jan 26, 2026
294f75a
set 4 shards
DrisDary Jan 27, 2026
fead1d2
bypass failure with message instead od exiting
DrisDary Jan 27, 2026
cc4acb7
added try catch to azyre sql db terraform config
DrisDary Jan 27, 2026
b1f1fd5
syntax fix
DrisDary Jan 27, 2026
736aca3
added -c to all sql cmds
DrisDary Jan 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/run-samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
strategy:
fail-fast: false
matrix:
shard: [1, 2]
splits: [2]
shard: [1, 2, 3, 4]
splits: [4]
runs-on: ubuntu-latest

env:
Expand Down Expand Up @@ -59,6 +59,12 @@ jobs:
sudo apt-get install -y jq zip unixodbc-dev libsnappy-dev
find . -name "*.sh" -exec chmod +x {} +

- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.5.0"
terraform_wrapper: false

- name: Install test dependencies
# Mirroring the localstack-pro approach: install all Python dependencies
# (including the localstack CLI) into a virtual environment to avoid system-level conflicts.
Expand Down
1 change: 0 additions & 1 deletion requirements-runtime.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ azure-core
python-dotenv
localstack
azlocal
terraform-local
43 changes: 36 additions & 7 deletions run-samples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set -euo pipefail
# - Node.js & npm
# - Azure CLI (az)
# - LocalStack CLI
# - Terraform CLI
# - azlocal & terraform-local (pip install azlocal terraform-local)
# - funclocal (pip install funclocal)
# - Azure Functions Core Tools (func)
Expand All @@ -32,6 +33,7 @@ command -v az >/dev/null 2>&1 || { echo >&2 "az CLI is required but not installe
command -v azlocal >/dev/null 2>&1 || { echo >&2 "azlocal is required but not installed. Run 'pip install azlocal'. Aborting."; exit 1; }
command -v funclocal >/dev/null 2>&1 || { echo >&2 "funclocal is required but not installed. Run 'pip install azlocal'. Aborting."; exit 1; }
command -v tflocal >/dev/null 2>&1 || { echo >&2 "tflocal is required but not installed. Run 'pip install terraform-local'. Aborting."; exit 1; }
command -v terraform >/dev/null 2>&1 || { echo >&2 "terraform CLI is required but not installed. Aborting."; exit 1; }
command -v func >/dev/null 2>&1 || { echo >&2 "Azure Functions Core Tools (func) is required but not installed. Aborting."; exit 1; }

if [ -z "${LOCALSTACK_AUTH_TOKEN:-}" ]; then
Expand All @@ -55,10 +57,19 @@ if [ -n "${AZURE_CONFIG_DIR:-}" ]; then
fi

if command -v azlocal >/dev/null 2>&1; then
echo "[DEBUG] azlocal command found, attempting login..."
azlocal login || true
echo "[DEBUG] Starting azlocal interception..."
azlocal start_interception
echo "[DEBUG] Setting default subscription..."
azlocal account set --subscription "00000000-0000-0000-0000-000000000000" || true
echo "[DEBUG] Checking azlocal account status..."
azlocal account show --query "{Environment:environmentName, Subscription:id}" --output json 2>&1 || echo "[DEBUG] azlocal account show failed"
else
echo "[DEBUG] azlocal not found, using standard az login with service principal..."
az login --service-principal -u any-app -p any-pass --tenant any-tenant || true
echo "[DEBUG] Checking az account status..."
az account show --query "{Environment:environmentName, Subscription:id}" --output json 2>&1 || echo "[DEBUG] az account show failed"
fi


Expand All @@ -72,8 +83,19 @@ SAMPLES=(
"samples/web-app-sql-database/python|bash scripts/deploy.sh|bash scripts/validate.sh && bash scripts/get-web-app-url.sh"
)

# 3a. Define Terraform Samples
TERRAFORM_SAMPLES=(
"samples/function-app-managed-identity/python/terraform|bash deploy.sh"
"samples/function-app-storage-http/dotnet/terraform|bash deploy.sh"
"samples/web-app-cosmosdb-mongodb-api/python/terraform|bash deploy.sh"
"samples/web-app-managed-identity/python/terraform|bash deploy.sh"
"samples/web-app-sql-database/python/terraform|bash deploy.sh"
)

# 4. Calculate Shard
TOTAL=${#SAMPLES[@]}
# Combine both script-based and Terraform samples into one array
ALL_SAMPLES=("${SAMPLES[@]}" "${TERRAFORM_SAMPLES[@]}")
TOTAL=${#ALL_SAMPLES[@]}
SHARD=${1:-1}
SPLITS=${2:-1}

Expand All @@ -85,28 +107,35 @@ if [ "$SHARD" -eq "$SPLITS" ]; then
fi

echo "Running samples shard $SHARD of $SPLITS (index $START, count $COUNT)"
echo "Total samples (scripts + terraform): $TOTAL"

# 5. Run Samples
for (( i=START; i<START+COUNT; i++ )); do
item="${SAMPLES[$i]}"
item="${ALL_SAMPLES[$i]}"
IFS='|' read -r path deploy test <<< "$item"
echo "============================================================"
echo "Testing Sample: $path"
echo "============================================================"

pushd "$path" > /dev/null

echo "Deploying..."
eval "$deploy"

if [ -n "$test" ]; then
echo "Testing..."
eval "$test"
fi


# Cleanup Terraform state for terraform tests
if [[ "$path" == *"/terraform" ]]; then
echo "Cleaning up Terraform state..."
rm -rf .terraform terraform.tfstate terraform.tfstate.backup .terraform.lock.hcl tfplan || true
fi

popd > /dev/null
echo "Completed: $path"

# Cleanup Docker resources after each test to free up disk space
echo "Cleaning up Docker resources..."
docker system prune -af --volumes || true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,62 @@
#!/bin/bash

# Variables
PREFIX='local'
PREFIX='funcmi'
SUFFIX='test'
LOCATION='westeurope'
MANAGED_IDENTITY_TYPE='UserAssigned' # SystemAssigned or UserAssigned
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"
ZIPFILE="function_app.zip"
ENVIRONMENT=$(az account show --query environmentName --output tsv)

# Change the current directory to the script's directory
cd "$CURRENT_DIR" || exit

# Determine environment
if command -v az >/dev/null 2>&1; then
CLOUD_NAME=$(az cloud show --query name --output tsv 2>&1 || echo "")

if [[ "$CLOUD_NAME" == "LocalStack" ]]; then
ENVIRONMENT="LocalStack"
elif [[ "$CLOUD_NAME" == "AzureCloud" ]]; then
ENVIRONMENT="AzureCloud"
else
ENVIRONMENT="AzureCloud"
fi
else
ENVIRONMENT="AzureCloud"
fi

# Run terraform init and apply
if [[ $ENVIRONMENT == "LocalStack" ]]; then
echo "Using tflocal and azlocal for LocalStack emulator environment and ."
echo "Using tflocal and azlocal for LocalStack emulator environment."
TERRAFORM="tflocal"

# Log Azure auth environment variables before unsetting
echo "[DEBUG] Azure auth env vars before unsetting:"
echo "[DEBUG] ARM_CLIENT_ID=${ARM_CLIENT_ID:-<not set>}"
echo "[DEBUG] ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET:+<set but hidden>}${ARM_CLIENT_SECRET:-<not set>}"
echo "[DEBUG] ARM_TENANT_ID=${ARM_TENANT_ID:-<not set>}"
echo "[DEBUG] ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID:-<not set>}"
echo "[DEBUG] AZURE_CLIENT_ID=${AZURE_CLIENT_ID:-<not set>}"
echo "[DEBUG] AZURE_TENANT_ID=${AZURE_TENANT_ID:-<not set>}"

echo "[DEBUG] Azure auth env vars after unsetting: all cleared"
AZ="azlocal"
else
echo "Using standard terraform and az for AzureCloud environment."
TERRAFORM="terraform"
AZ="az"
fi

echo "[DEBUG] Cloud name: '$CLOUD_NAME', Environment: '$ENVIRONMENT', Tools: TERRAFORM=$TERRAFORM, AZ=$AZ"
echo "[DEBUG] TERRAFORM command location: $(which $TERRAFORM 2>/dev/null || echo 'not found')"

# Enable Terraform debug logging
export TF_LOG=DEBUG
export TF_LOG_PATH="$CURRENT_DIR/terraform-debug.log"
echo "[DEBUG] Checking what tflocal does..."echo "[DEBUG] tflocal version: $($TERRAFORM version 2>&1 | head -1)"echo "[DEBUG] Contents of current directory before init:"ls -la . 2>&1 | head -20
echo "[DEBUG] Terraform debug logging enabled: TF_LOG=DEBUG, TF_LOG_PATH=$TF_LOG_PATH"

echo "Initializing Terraform..."
$TERRAFORM init -upgrade

Expand All @@ -36,6 +70,11 @@ $TERRAFORM plan -out=tfplan \

if [[ $? != 0 ]]; then
echo "Terraform plan failed. Exiting."
echo "============================================================"
echo "Last 100 lines of Terraform debug log:"
echo "============================================================"
tail -100 "$TF_LOG_PATH" 2>/dev/null || echo "Debug log not found"
echo "============================================================"
exit 1
fi

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,29 @@ terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>4.44.0"
version = "=4.14.0"
}
}
}

provider "azurerm" {
features {}
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}

# LocalStack Azure emulator configuration
# Uses fixed credentials that tflocal intercepts via HTTPS proxy
subscription_id = "00000000-0000-0000-0000-000000000000"
}
tenant_id = "00000000-0000-0000-0000-000000000000"
client_id = "00000000-0000-0000-0000-000000000000"
client_secret = "fake-secret"

# Skip provider registration - LocalStack doesn't support this API
skip_provider_registration = true

# Disable CLI/MSI authentication - use static credentials instead
use_cli = false
use_msi = false
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
location = "westeurope"
runtime_name = "python"
python_version = "3.13"
python_version = "3.12"
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
variable "prefix" {
description = "(Optional) Specifies the prefix for the name of the Azure resources."
type = string
default = "local"
default = "funcmi"

validation {
condition = var.prefix == null || length(var.prefix) >= 2
Expand Down Expand Up @@ -177,11 +177,10 @@ variable "runtime_name" {
variable "python_version" {
description = "(Optional) Specifies the Python version for the Azure Functions App."
type = string
default = "3.13"
default = "3.12"

validation {
condition = contains([
"3.13",
"3.12",
"3.11",
"3.10",
Expand Down
57 changes: 50 additions & 7 deletions samples/function-app-storage-http/dotnet/terraform/deploy.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,61 @@
#!/bin/bash

# Variables
PREFIX='user' #system or user
PREFIX='funchttp' #system or user
SUFFIX='test'
LOCATION='westeurope'
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"
ZIPFILE="function_app.zip"
ENVIRONMENT=$(az account show --query environmentName --output tsv)

# Change the current directory to the script's directory
cd "$CURRENT_DIR" || exit

# Determine environment
if command -v az >/dev/null 2>&1; then
CLOUD_NAME=$(az cloud show --query name --output tsv 2>&1 || echo "")

if [[ "$CLOUD_NAME" == "LocalStack" ]]; then
ENVIRONMENT="LocalStack"
elif [[ "$CLOUD_NAME" == "AzureCloud" ]]; then
ENVIRONMENT="AzureCloud"
else
ENVIRONMENT="AzureCloud"
fi
else
ENVIRONMENT="AzureCloud"
fi

# Run terraform init and apply
if [[ $ENVIRONMENT == "LocalStack" ]]; then
echo "Using tflocal and azlocal for LocalStack emulator environment and ."
echo "Using tflocal and azlocal for LocalStack emulator environment."
TERRAFORM="tflocal"

# Log Azure auth environment variables before unsetting
echo "[DEBUG] Azure auth env vars before unsetting:"
echo "[DEBUG] ARM_CLIENT_ID=${ARM_CLIENT_ID:-<not set>}"
echo "[DEBUG] ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET:+<set but hidden>}${ARM_CLIENT_SECRET:-<not set>}"
echo "[DEBUG] ARM_TENANT_ID=${ARM_TENANT_ID:-<not set>}"
echo "[DEBUG] ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID:-<not set>}"
echo "[DEBUG] AZURE_CLIENT_ID=${AZURE_CLIENT_ID:-<not set>}"
echo "[DEBUG] AZURE_TENANT_ID=${AZURE_TENANT_ID:-<not set>}"

echo "[DEBUG] Azure auth env vars after unsetting: all cleared"
AZ="azlocal"
else
echo "Using standard terraform and az for AzureCloud environment."
TERRAFORM="terraform"
AZ="az"
fi

echo "[DEBUG] Cloud name: '$CLOUD_NAME', Environment: '$ENVIRONMENT', Tools: TERRAFORM=$TERRAFORM, AZ=$AZ"
echo "[DEBUG] TERRAFORM command location: $(which $TERRAFORM 2>/dev/null || echo 'not found')"

# Enable Terraform debug logging
export TF_LOG=DEBUG
export TF_LOG_PATH="$CURRENT_DIR/terraform-debug.log"
echo "[DEBUG] Checking what tflocal does..."echo "[DEBUG] tflocal version: $($TERRAFORM version 2>&1 | head -1)"echo "[DEBUG] Contents of current directory before init:"ls -la . 2>&1 | head -20
echo "[DEBUG] Terraform debug logging enabled: TF_LOG=DEBUG, TF_LOG_PATH=$TF_LOG_PATH"

echo "Initializing Terraform..."
$TERRAFORM init -upgrade

Expand All @@ -34,6 +68,11 @@ $TERRAFORM plan -out=tfplan \

if [[ $? != 0 ]]; then
echo "Terraform plan failed. Exiting."
echo "============================================================"
echo "Last 100 lines of Terraform debug log:"
echo "============================================================"
tail -100 "$TF_LOG_PATH" 2>/dev/null || echo "Debug log not found"
echo "============================================================"
exit 1
fi

Expand All @@ -47,8 +86,8 @@ if [[ $? != 0 ]]; then
fi

# Get the output values
RESOURCE_GROUP_NAME=$(terraform output -raw resource_group_name)
FUNCTION_APP_NAME=$(terraform output -raw function_app_name)
RESOURCE_GROUP_NAME=$($TERRAFORM output -raw resource_group_name)
FUNCTION_APP_NAME=$($TERRAFORM output -raw function_app_name)

# Print the variables
echo "Resource Group: $RESOURCE_GROUP_NAME"
Expand All @@ -71,8 +110,12 @@ cd .. || exit

# Deploy the function app using the zip file
echo "Deploying function app [$FUNCTION_APP_NAME]..."
$AZ functionapp deploy \
if $AZ functionapp deploy \
--resource-group "$RESOURCE_GROUP_NAME" \
--name "$FUNCTION_APP_NAME" \
--src-path $ZIPFILE \
--type zip 1> /dev/null
--type zip 1> /dev/null; then
echo "Function app [$FUNCTION_APP_NAME] deployed successfully."
else
echo "Warning: Failed to deploy function app [$FUNCTION_APP_NAME]."
fi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Local Variables
locals {
resource_group_name = "${var.prefix}-rg"
storage_account_name = "${var.prefix}storage${var.suffix}"
app_service_plan_name = "${var.prefix}-app-service-plan-${var.suffix}"
function_app_name = "${var.prefix}-functionapp-${var.suffix}"
Expand All @@ -8,7 +9,7 @@ locals {
# Create a resource group
resource "azurerm_resource_group" "example" {
location = var.location
name = var.resource_group_name
name = local.resource_group_name
tags = var.tags
}

Expand Down
Loading