diff --git a/.gitignore b/.gitignore index b400c6f..bf1a654 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -function-app.zip *.terraform terraform.tfstate* *.swp settings.auto.tfvars .terraform.lock.hcl + +function-app.zip +function-app-*.zip +function-app-v1/host.json function-app-v1/ProviderRelay/function.json + venv diff --git a/function-app-v1/.gitignore b/function-app-v1/.gitignore deleted file mode 100644 index f15ac3f..0000000 --- a/function-app-v1/.gitignore +++ /dev/null @@ -1,48 +0,0 @@ -bin -obj -csx -.vs -edge -Publish - -*.user -*.suo -*.cscfg -*.Cache -project.lock.json - -/packages -/TestResults - -/tools/NuGet.exe -/App_Data -/secrets -/data -.secrets -appsettings.json -local.settings.json - -node_modules -dist - -# Local python packages -.python_packages/ - -# Python Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# Azurite artifacts -__blobstorage__ -__queuestorage__ -__azurite_db*__.json \ No newline at end of file diff --git a/function-app-v1/ProviderRelay/function.json.tmpl b/function-app-v1/ProviderRelay/function.json.tmpl deleted file mode 100644 index 0779428..0000000 --- a/function-app-v1/ProviderRelay/function.json.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{ - "scriptFile": "__init__.py", - "bindings": [ - { - "name": "msg", - "type": "queueTrigger", - "direction": "in", - "queueName": "${queue_name}", - "connection": "AzureWebJobsStorage" - } - ] -} diff --git a/function-app-v1/host.json b/function-app-v1/host.json deleted file mode 100644 index 068c8da..0000000 --- a/function-app-v1/host.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "2.0", - "logging": { - "applicationInsights": { - "samplingSettings": { - "isEnabled": true, - "excludedTypes": "Request" - } - } - }, - "functions": ["ProviderRelay"], - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[4.*, 5.0.0)" - } -} diff --git a/function-app-v1/requirements.txt b/function-app-v1/requirements.txt index c23d976..2c07908 100644 --- a/function-app-v1/requirements.txt +++ b/function-app-v1/requirements.txt @@ -18,6 +18,7 @@ # The Python Worker is managed by the Azure Functions platform # Manually managing azure-functions-worker may cause unexpected issues -azure-functions==1.14.0 -azure-identity==1.13.0 -boto3==1.26.142 +# Core function dependencies - updated for Python 3.12 compatibility +azure-functions==1.23.0 +azure-identity==1.23.0 +boto3==1.39.2 diff --git a/function.tf b/function.tf index c40e6f5..e50288c 100644 --- a/function.tf +++ b/function.tf @@ -31,38 +31,106 @@ resource "azurerm_service_plan" "stacklet" { tags = local.tags } +# Generate the function.json with queue name +resource "local_file" "function_json" { + content = jsonencode({ + scriptFile = "__init__.py" + bindings = [ + { + name = "msg" + type = "queueTrigger" + direction = "in" + queueName = azurerm_storage_queue.stacklet.name + connection = "AzureWebJobsStorage" + } + ] + }) + filename = "${path.module}/function-app-v1/ProviderRelay/function.json" +} + +# Create host.json with enhanced logging configuration +resource "local_file" "host_json" { + content = jsonencode({ + version = "2.0" + logging = { + applicationInsights = { + samplingSettings = { + isEnabled = true + excludedTypes = "Request" + } + } + logLevel = { + default = "Information" + "ProviderRelay" = "Information" + "azure.functions" = "Warning" + "azure.storage" = "Warning" + } + } + functions = ["ProviderRelay"] + extensionBundle = { + id = "Microsoft.Azure.Functions.ExtensionBundle" + version = "[4.*, 5.0.0)" + } + }) + filename = "${path.module}/function-app-v1/host.json" +} + +# Create the function app deployment package +data "archive_file" "function_app" { + depends_on = [local_file.function_json, local_file.host_json] + + type = "zip" + source_dir = "${path.module}/function-app-v1" + output_path = "${path.module}/function-app.zip" +} + +# azurerm_linux_function_app's zip_deploy_file will only redeploy the function +# when the path changes, so copy the zip to a versioned filename. +resource "local_file" "function_app_versioned" { + filename = "${path.module}/function-app-${data.archive_file.function_app.output_sha256}.zip" + source = "${path.module}/function-app.zip" +} + resource "azurerm_linux_function_app" "stacklet" { name = "stacklet-${var.prefix}-function-app-${substr(random_string.storage_account_suffix.result, 0, 15)}" resource_group_name = azurerm_resource_group.stacklet_rg.name location = azurerm_resource_group.stacklet_rg.location + service_plan_id = azurerm_service_plan.stacklet.id storage_account_name = azurerm_storage_account.stacklet.name storage_account_access_key = azurerm_storage_account.stacklet.primary_access_key - service_plan_id = azurerm_service_plan.stacklet.id + + # Deploy from zip file + zip_deploy_file = local_file.function_app_versioned.filename site_config { + application_insights_key = azurerm_application_insights.stacklet.instrumentation_key + application_stack { - python_version = "3.10" + python_version = "3.12" } - application_insights_key = azurerm_application_insights.stacklet.instrumentation_key } app_settings = { + # Build and deployment settings SCM_DO_BUILD_DURING_DEPLOYMENT = true - AZURE_CLIENT_ID = azurerm_user_assigned_identity.stacklet_identity.client_id - AZURE_AUDIENCE = local.audience - AZURE_STORAGE_QUEUE_NAME = azurerm_storage_queue.stacklet.name - AWS_TARGET_ACCOUNT = var.aws_target_account - AWS_TARGET_REGION = var.aws_target_region - AWS_TARGET_ROLE_NAME = var.aws_target_role_name - AWS_TARGET_PARTITION = var.aws_target_partition - AWS_TARGET_EVENT_BUS = var.aws_target_event_bus + + # Application configuration + AZURE_CLIENT_ID = azurerm_user_assigned_identity.stacklet_identity.client_id + AZURE_AUDIENCE = local.audience + AZURE_STORAGE_QUEUE_NAME = azurerm_storage_queue.stacklet.name + AWS_TARGET_ACCOUNT = var.aws_target_account + AWS_TARGET_REGION = var.aws_target_region + AWS_TARGET_ROLE_NAME = var.aws_target_role_name + AWS_TARGET_PARTITION = var.aws_target_partition + AWS_TARGET_EVENT_BUS = var.aws_target_event_bus } identity { type = "UserAssigned" identity_ids = [azurerm_user_assigned_identity.stacklet_identity.id] } + tags = local.tags lifecycle { @@ -71,27 +139,3 @@ resource "azurerm_linux_function_app" "stacklet" { ] } } - -resource "local_file" "function_json" { - content = templatefile( - "${path.module}/function-app-v1/ProviderRelay/function.json.tmpl", { queue_name = azurerm_storage_queue.stacklet.name }) - filename = "${path.module}/function-app-v1/ProviderRelay/function.json" -} - - -resource "null_resource" "function_deploy" { - depends_on = [azurerm_linux_function_app.stacklet, local_file.function_json] - # ensures that publish always runs - triggers = { - build_number = "${timestamp()}" - } - - # initial deployment of the function-app could race with provisioning, so sleep 10 seconds - provisioner "local-exec" { - command = <