From ff83ab848c808eb6358620c136f689eca80ada4b Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Wed, 18 Dec 2024 16:53:39 +0100 Subject: [PATCH 1/3] add support for duarble --- .changeset/brown-ears-reply.md | 5 ++++ infra/modules/azure_function_app/README.md | 5 ++++ infra/modules/azure_function_app/data.tf | 7 ++++++ .../azure_function_app/function_app.tf | 3 ++- infra/modules/azure_function_app/locals.tf | 2 ++ .../modules/azure_function_app/networking.tf | 23 +++++++++++++++++++ infra/modules/azure_function_app/rbac.tf | 16 +++++++++++++ infra/modules/azure_function_app/variables.tf | 8 ++++++- yarn.lock | 6 +++++ 9 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 .changeset/brown-ears-reply.md diff --git a/.changeset/brown-ears-reply.md b/.changeset/brown-ears-reply.md new file mode 100644 index 000000000..12eaf0262 --- /dev/null +++ b/.changeset/brown-ears-reply.md @@ -0,0 +1,5 @@ +--- +"azure_function_app": minor +--- + +Add support for Durable Functions diff --git a/infra/modules/azure_function_app/README.md b/infra/modules/azure_function_app/README.md index bb5ad8ea1..faf5c7cca 100644 --- a/infra/modules/azure_function_app/README.md +++ b/infra/modules/azure_function_app/README.md @@ -26,13 +26,16 @@ | [azurerm_private_endpoint.st_blob](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_private_endpoint.st_file](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_private_endpoint.st_queue](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_private_endpoint.st_table](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_private_endpoint.staging_function_sites](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_role_assignment.function_storage_account_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_role_assignment.function_storage_blob_data_owner](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_role_assignment.function_storage_queue_data_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | +| [azurerm_role_assignment.function_storage_table_data_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_role_assignment.staging_function_storage_account_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_role_assignment.staging_function_storage_blob_data_owner](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_role_assignment.staging_function_storage_queue_data_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | +| [azurerm_role_assignment.staging_function_storage_table_data_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [azurerm_service_plan.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/service_plan) | resource | | [azurerm_storage_account.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) | resource | | [azurerm_storage_account_network_rules.st_network_rules](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account_network_rules) | resource | @@ -41,6 +44,7 @@ | [azurerm_private_dns_zone.storage_account_blob](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | | [azurerm_private_dns_zone.storage_account_file](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | | [azurerm_private_dns_zone.storage_account_queue](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| [azurerm_private_dns_zone.storage_account_table](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | | [azurerm_virtual_network.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | ## Inputs @@ -53,6 +57,7 @@ | [application\_insights\_connection\_string](#input\_application\_insights\_connection\_string) | (Optional) Application Insights connection string | `string` | `null` | no | | [application\_insights\_key](#input\_application\_insights\_key) | (Optional) Application Insights key | `string` | `null` | no | | [application\_insights\_sampling\_percentage](#input\_application\_insights\_sampling\_percentage) | (Optional) The sampling percentage of Application Insights. Default is 5 | `number` | `5` | no | +| [contains\_durable\_functions](#input\_contains\_durable\_functions) | (Optional) Enable if the Function App hosts Durable Functions | `bool` | `false` | no | | [environment](#input\_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | | [health\_check\_path](#input\_health\_check\_path) | Endpoint where health probe is exposed | `string` | n/a | yes | | [java\_version](#input\_java\_version) | Java version to use | `string` | `17` | no | diff --git a/infra/modules/azure_function_app/data.tf b/infra/modules/azure_function_app/data.tf index 55344630f..ed7dc4b5b 100644 --- a/infra/modules/azure_function_app/data.tf +++ b/infra/modules/azure_function_app/data.tf @@ -18,6 +18,13 @@ data "azurerm_private_dns_zone" "storage_account_queue" { resource_group_name = local.private_dns_zone.resource_group_name } +data "azurerm_private_dns_zone" "storage_account_table" { + count = local.function_app.has_durable + + name = "privatelink.table.core.windows.net" + resource_group_name = local.private_dns_zone.resource_group_name +} + data "azurerm_private_dns_zone" "function_app" { name = "privatelink.azurewebsites.net" resource_group_name = local.private_dns_zone.resource_group_name diff --git a/infra/modules/azure_function_app/function_app.tf b/infra/modules/azure_function_app/function_app.tf index 1ef1912fa..2b57b2702 100644 --- a/infra/modules/azure_function_app/function_app.tf +++ b/infra/modules/azure_function_app/function_app.tf @@ -81,5 +81,6 @@ resource "azurerm_linux_function_app" "this" { azurerm_private_endpoint.st_blob, azurerm_private_endpoint.st_file, azurerm_private_endpoint.st_queue, + azurerm_private_endpoint.st_table ] -} \ No newline at end of file +} diff --git a/infra/modules/azure_function_app/locals.tf b/infra/modules/azure_function_app/locals.tf index 7d2685e3c..f73b4545b 100644 --- a/infra/modules/azure_function_app/locals.tf +++ b/infra/modules/azure_function_app/locals.tf @@ -22,6 +22,7 @@ locals { pep_sites_staging = "${module.naming_convention.prefix}-staging-func-pep-${module.naming_convention.suffix}" alert = "${module.naming_convention.prefix}-func-${module.naming_convention.suffix}] Health Check Failed" worker_process_count = local.worker_process_count_mapping[local.tier] + has_durable = var.contains_durable_functions ? 1 : 0 } function_app_slot = { @@ -38,6 +39,7 @@ locals { pep_blob_name = "${module.naming_convention.prefix}-blob-pep-${module.naming_convention.suffix}" pep_file_name = "${module.naming_convention.prefix}-file-pep-${module.naming_convention.suffix}" pep_queue_name = "${module.naming_convention.prefix}-queue-pep-${module.naming_convention.suffix}" + pep_table_name = "${module.naming_convention.prefix}-table-pep-${module.naming_convention.suffix}" alert = "[${replace("${module.naming_convention.project}${replace(module.naming_convention.domain, "-", "")}${var.environment.app_name}stfn${module.naming_convention.suffix}", "-", "")}] Low Availability" } diff --git a/infra/modules/azure_function_app/networking.tf b/infra/modules/azure_function_app/networking.tf index 69c98bf3d..1460d64fa 100644 --- a/infra/modules/azure_function_app/networking.tf +++ b/infra/modules/azure_function_app/networking.tf @@ -61,6 +61,29 @@ resource "azurerm_private_endpoint" "st_queue" { tags = var.tags } +resource "azurerm_private_endpoint" "st_table" { + count = local.function_app.has_durable + + name = local.storage_account.pep_table_name + location = var.environment.location + resource_group_name = var.resource_group_name + subnet_id = var.subnet_pep_id + + private_service_connection { + name = local.storage_account.pep_table_name + private_connection_resource_id = azurerm_storage_account.this.id + is_manual_connection = false + subresource_names = ["table"] + } + + private_dns_zone_group { + name = "private-dns-zone-group" + private_dns_zone_ids = [data.azurerm_private_dns_zone.storage_account_table[0].id] + } + + tags = var.tags +} + resource "azurerm_private_endpoint" "function_sites" { name = local.function_app.pep_sites location = var.environment.location diff --git a/infra/modules/azure_function_app/rbac.tf b/infra/modules/azure_function_app/rbac.tf index 3973cc239..b1e508c38 100644 --- a/infra/modules/azure_function_app/rbac.tf +++ b/infra/modules/azure_function_app/rbac.tf @@ -41,3 +41,19 @@ resource "azurerm_role_assignment" "staging_function_storage_queue_data_contribu role_definition_name = "Storage Queue Data Contributor" principal_id = azurerm_linux_function_app_slot.this[0].identity[0].principal_id } + +resource "azurerm_role_assignment" "function_storage_table_data_contributor" { + count = local.function_app.has_durable + + scope = azurerm_storage_account.this.id + role_definition_name = "Storage Table Data Contributor" + principal_id = azurerm_linux_function_app.this.identity[0].principal_id +} + +resource "azurerm_role_assignment" "staging_function_storage_table_data_contributor" { + count = local.function_app.is_slot_enabled == 1 && local.function_app.has_durable == 1 ? 1 : 0 + + scope = azurerm_storage_account.this.id + role_definition_name = "Storage Table Data Contributor" + principal_id = azurerm_linux_function_app_slot.this[0].identity[0].principal_id +} diff --git a/infra/modules/azure_function_app/variables.tf b/infra/modules/azure_function_app/variables.tf index 61ec2bfea..65f78a926 100644 --- a/infra/modules/azure_function_app/variables.tf +++ b/infra/modules/azure_function_app/variables.tf @@ -168,4 +168,10 @@ variable "application_insights_key" { description = "(Optional) Application Insights key" sensitive = true default = null -} \ No newline at end of file +} + +variable "contains_durable_functions" { + type = bool + description = "(Optional) Enable if the Function App hosts Durable Functions" + default = false +} diff --git a/yarn.lock b/yarn.lock index 5181a0869..597cdb59e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4381,6 +4381,12 @@ __metadata: languageName: unknown linkType: soft +"azure_function_app_durable@workspace:infra/modules/azure_function_app_durable": + version: 0.0.0-use.local + resolution: "azure_function_app_durable@workspace:infra/modules/azure_function_app_durable" + languageName: unknown + linkType: soft + "azure_function_app_exposed@workspace:infra/modules/azure_function_app_exposed": version: 0.0.0-use.local resolution: "azure_function_app_exposed@workspace:infra/modules/azure_function_app_exposed" From c0529c356cc6cf87200294a3b10dcf97f9957d6c Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Wed, 18 Dec 2024 16:57:01 +0100 Subject: [PATCH 2/3] add comma --- infra/modules/azure_function_app/function_app.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/azure_function_app/function_app.tf b/infra/modules/azure_function_app/function_app.tf index 2b57b2702..0961d0b81 100644 --- a/infra/modules/azure_function_app/function_app.tf +++ b/infra/modules/azure_function_app/function_app.tf @@ -81,6 +81,6 @@ resource "azurerm_linux_function_app" "this" { azurerm_private_endpoint.st_blob, azurerm_private_endpoint.st_file, azurerm_private_endpoint.st_queue, - azurerm_private_endpoint.st_table + azurerm_private_endpoint.st_table, ] } From a9c1d99a644df300b0a727770f7f0488162f7e43 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Thu, 16 Jan 2025 16:41:06 +0100 Subject: [PATCH 3/3] rename var --- infra/modules/azure_function_app/README.md | 2 +- infra/modules/azure_function_app/locals.tf | 2 +- infra/modules/azure_function_app/variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/infra/modules/azure_function_app/README.md b/infra/modules/azure_function_app/README.md index faf5c7cca..2605a2e73 100644 --- a/infra/modules/azure_function_app/README.md +++ b/infra/modules/azure_function_app/README.md @@ -57,8 +57,8 @@ | [application\_insights\_connection\_string](#input\_application\_insights\_connection\_string) | (Optional) Application Insights connection string | `string` | `null` | no | | [application\_insights\_key](#input\_application\_insights\_key) | (Optional) Application Insights key | `string` | `null` | no | | [application\_insights\_sampling\_percentage](#input\_application\_insights\_sampling\_percentage) | (Optional) The sampling percentage of Application Insights. Default is 5 | `number` | `5` | no | -| [contains\_durable\_functions](#input\_contains\_durable\_functions) | (Optional) Enable if the Function App hosts Durable Functions | `bool` | `false` | no | | [environment](#input\_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | +| [has\_durable\_functions](#input\_has\_durable\_functions) | (Optional) Enable if the Function App hosts Durable Functions | `bool` | `false` | no | | [health\_check\_path](#input\_health\_check\_path) | Endpoint where health probe is exposed | `string` | n/a | yes | | [java\_version](#input\_java\_version) | Java version to use | `string` | `17` | no | | [node\_version](#input\_node\_version) | Node version to use | `number` | `20` | no | diff --git a/infra/modules/azure_function_app/locals.tf b/infra/modules/azure_function_app/locals.tf index f73b4545b..135497e03 100644 --- a/infra/modules/azure_function_app/locals.tf +++ b/infra/modules/azure_function_app/locals.tf @@ -22,7 +22,7 @@ locals { pep_sites_staging = "${module.naming_convention.prefix}-staging-func-pep-${module.naming_convention.suffix}" alert = "${module.naming_convention.prefix}-func-${module.naming_convention.suffix}] Health Check Failed" worker_process_count = local.worker_process_count_mapping[local.tier] - has_durable = var.contains_durable_functions ? 1 : 0 + has_durable = var.has_durable_functions ? 1 : 0 } function_app_slot = { diff --git a/infra/modules/azure_function_app/variables.tf b/infra/modules/azure_function_app/variables.tf index 65f78a926..214862a78 100644 --- a/infra/modules/azure_function_app/variables.tf +++ b/infra/modules/azure_function_app/variables.tf @@ -170,7 +170,7 @@ variable "application_insights_key" { default = null } -variable "contains_durable_functions" { +variable "has_durable_functions" { type = bool description = "(Optional) Enable if the Function App hosts Durable Functions" default = false