Skip to content

Commit f088066

Browse files
feat: convert to azapi (#258)
* feat: convert to azapi * chore: remove unused azapi_client_config data source * improvements * save changes * PRE COMMIT * savwe changes * update var docs * break out locals * update api versions * pre-commit * chore: avm pre-commit * improve docs and allow tests to run * tidy redundant code and replace missing inputs * fix api version * fix api version * fix moved blocks * refactor to submodules * tidy files and app insights parent_id * pre commit * fix: resolve pr-check issues - unused locals, ip_restriction headers type, nullable, unused var * fix: add parent_id to application_insights var, fix Network api-versions to 2025-03-01 * fix: body schema validation, coalesce failure, for_each apply-time issue - Rename vnetBackupRestoreEnabled/vnetContentShareEnabled/vnetImagePullEnabled to outboundVnetRouting object - Change apiDefinitionUrl to apiDefinition = { url = ... } - Remove healthCheckEvictionTimeInMin (not in ARM schema) - Remove serviceTag from ip_security_restrictions (use ipAddress for service tags) - Fix coalesce failure when app_stack is null and linux_fx_version is null - Fix for_each/count using length(merged_app_settings) which depends on apply-time values * fix: lock_azapi null guard, PE location/parent_id, sensitive output * fix app service plan zones and exclude consumption plan * fix authsettings config * fix variable interfaces to more closely match the API interface. Set secure defaults. * fix bugs * more fixes and refactoring * override tflint rules for modules * remove unused local * fix linting * relax regex for server farm id to be case insensitive * try australia east * bug fix * fix bug * bug fixes * fix sensitive issue * pre commit * remove app insights and bug fixes * fix idempotency * bug fixes * more fixes * more fixes * more fixes * fix zip deploy * add retry for destroy eventual consistency * fix app insights nullness * linting * fix linting
1 parent 5168088 commit f088066

300 files changed

Lines changed: 14918 additions & 12003 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ examples/*/policy
5252
sensitive.variables.tf
5353
*.mptfbackup
5454
.avm
55+
56+
# Generated zip files
57+
examples/zip_deploy_file/resources_for_zip_deploy.zip

README.md

Lines changed: 1517 additions & 1399 deletions
Large diffs are not rendered by default.

_header.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
# terraform-azurerm-avm-res-web-site
1+
# Azure Verified Module for App Service (Web Apps, Function Apps, and Logic Apps)
22

3-
This is the module to deploy function apps in Azure.
3+
This is an Azure Verified Module (AVM) for deploying and managing Azure App Service resources, including Web Apps, Function Apps, and Logic Apps (Standard).
44

5-
NOTES:
6-
7-
- `0.13.0` supports `azurerm` `4.8` and later versions.
8-
- For `azurerm` `4.x` support, please use `0.12.x` and later versions.
9-
- For `azurerm` `3.x` support, please use `0.11.x` and prior versions.
5+
It supports Linux and Windows operating systems, deployment slots, custom domains, managed identities, private endpoints, diagnostic settings, Application Insights integration, IP restrictions, auto heal, storage mounts, and Flex Consumption plans.

avm.tflint.override.hcl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
rule "diagnostic_settings" {
2+
enabled = false
3+
}
4+
5+
rule "private_endpoints" {
6+
enabled = false
7+
}

avm.tflint_module.override.hcl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
rule "required_output_rmfr7" {
2+
enabled = false
3+
}
4+
5+
rule "terraform_required_providers_declaration" {
6+
enabled = false
7+
}
8+
9+
rule "required_module_source_tffr1" {
10+
enabled = false
11+
}
12+
13+
rule "private_endpoints" {
14+
enabled = false
15+
}

data.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

examples/always_ready/.e2eignore

Whitespace-only changes.

examples/always_ready/README.md

Lines changed: 115 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,165 @@
11
<!-- BEGIN_TF_DOCS -->
22
<!-- Code generated by terraform-docs. DO NOT EDIT. -->
3-
# Flex Consumption (FC1) with Always Ready feature example
3+
# Flex Consumption with Always Ready Instances
44

5-
This deploys the module with a Linux Function App utilizing the Flex Consumption Plan, with always-ready instances.
5+
This example deploys a Linux Function App on the Azure Flex Consumption (FC1) plan with always-ready instances configured.
66

7-
```hcl
8-
## Section to provide a random Azure region for the resource group
9-
# This allows us to randomize the region for the resource group.
10-
module "regions" {
11-
source = "Azure/regions/azurerm"
12-
version = "0.8.0"
13-
}
7+
Always-ready instances keep a specified number of pre-warmed workers for designated trigger types (e.g., `http`, `blob`, `durable`), reducing cold-start latency for critical functions. This example demonstrates how to configure the `always_ready` variable to reserve instances for specific triggers.
8+
9+
The example uses `kind = "functionapp"`, `os_type = "Linux"`, and `function_app_uses_fc1 = true`.
1410

15-
# This allows us to randomize the region for the resource group.
11+
```hcl
1612
resource "random_integer" "region_index" {
1713
max = length(local.azure_regions) - 1
1814
min = 0
1915
}
20-
## End of section to provide a random Azure region for the resource group
2116
22-
# This ensures we have unique CAF compliant names for our resources.
2317
module "naming" {
2418
source = "Azure/naming/azurerm"
2519
version = "0.4.2"
2620
}
2721
28-
resource "azurerm_resource_group" "example" {
22+
resource "azapi_resource" "resource_group" {
2923
location = local.azure_regions[random_integer.region_index.result]
3024
name = module.naming.resource_group.name_unique
25+
type = "Microsoft.Resources/resourceGroups@2025-04-01"
26+
body = {}
27+
tags = {
28+
SecurityControl = "Ignore" # Useful for test environments
29+
}
3130
}
3231
33-
resource "azurerm_service_plan" "example" {
34-
location = azurerm_resource_group.example.location
35-
name = module.naming.app_service_plan.name_unique
36-
os_type = "Linux"
37-
resource_group_name = azurerm_resource_group.example.name
38-
sku_name = "FC1"
32+
resource "azapi_resource" "service_plan" {
33+
location = azapi_resource.resource_group.location
34+
name = module.naming.app_service_plan.name_unique
35+
parent_id = azapi_resource.resource_group.id
36+
type = "Microsoft.Web/serverfarms@2025-03-01"
37+
body = {
38+
kind = "functionapp"
39+
sku = {
40+
name = "FC1"
41+
}
42+
properties = {
43+
reserved = true
44+
zoneRedundant = true
45+
}
46+
}
3947
tags = {
4048
app = "${module.naming.function_app.name_unique}-always-ready"
4149
}
4250
}
4351
44-
resource "azurerm_user_assigned_identity" "user" {
45-
location = azurerm_resource_group.example.location
46-
name = module.naming.user_assigned_identity.name_unique
47-
resource_group_name = azurerm_resource_group.example.name
52+
resource "azapi_resource" "user_assigned_identity" {
53+
location = azapi_resource.resource_group.location
54+
name = module.naming.user_assigned_identity.name_unique
55+
parent_id = azapi_resource.resource_group.id
56+
type = "Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30"
57+
body = {}
4858
}
4959
50-
resource "azurerm_storage_account" "example" {
51-
account_replication_type = "ZRS"
52-
account_tier = "Standard"
53-
location = azurerm_resource_group.example.location
54-
name = module.naming.storage_account.name_unique
55-
resource_group_name = azurerm_resource_group.example.name
60+
resource "azapi_resource" "storage_account" {
61+
location = azapi_resource.resource_group.location
62+
name = module.naming.storage_account.name_unique
63+
parent_id = azapi_resource.resource_group.id
64+
type = "Microsoft.Storage/storageAccounts@2025-01-01"
65+
body = {
66+
kind = "StorageV2"
67+
sku = {
68+
name = "Standard_ZRS"
69+
}
70+
properties = {
71+
networkAcls = {
72+
defaultAction = "Allow"
73+
bypass = "AzureServices"
74+
}
75+
}
76+
}
5677
tags = {
5778
SecurityControl = "Ignore"
5879
}
80+
}
5981
60-
network_rules {
61-
default_action = "Allow"
62-
bypass = ["AzureServices"]
82+
resource "azapi_resource" "storage_container" {
83+
name = "example-always-ready-container"
84+
parent_id = "${azapi_resource.storage_account.id}/blobServices/default"
85+
type = "Microsoft.Storage/storageAccounts/blobServices/containers@2025-01-01"
86+
body = {}
87+
}
88+
89+
resource "azapi_resource" "log_analytics_workspace" {
90+
location = azapi_resource.resource_group.location
91+
name = "${module.naming.log_analytics_workspace.name}-always-ready"
92+
parent_id = azapi_resource.resource_group.id
93+
type = "Microsoft.OperationalInsights/workspaces@2025-02-01"
94+
body = {
95+
properties = {
96+
retentionInDays = 30
97+
sku = {
98+
name = "PerGB2018"
99+
}
100+
}
63101
}
64102
}
65103
66-
resource "azurerm_storage_container" "example" {
67-
name = "example-always-ready-container"
68-
storage_account_id = azurerm_storage_account.example.id
104+
resource "azapi_resource" "application_insights" {
105+
location = azapi_resource.resource_group.location
106+
name = "${module.naming.application_insights.name_unique}-always-ready"
107+
parent_id = azapi_resource.resource_group.id
108+
type = "Microsoft.Insights/components@2020-02-02"
109+
body = {
110+
kind = "web"
111+
properties = {
112+
Application_Type = "web"
113+
WorkspaceResourceId = azapi_resource.log_analytics_workspace.id
114+
}
115+
}
116+
response_export_values = ["properties.ConnectionString", "properties.InstrumentationKey"]
69117
}
70118
71119
module "avm_res_web_site" {
72120
source = "../../"
73121
74-
kind = "functionapp"
75-
location = azurerm_resource_group.example.location
76-
name = "${module.naming.function_app.name_unique}-always-ready"
77-
# Uses an existing app service plan
78-
os_type = azurerm_service_plan.example.os_type
79-
resource_group_name = azurerm_resource_group.example.name
80-
service_plan_resource_id = azurerm_service_plan.example.id
122+
location = azapi_resource.resource_group.location
123+
name = "${module.naming.function_app.name_unique}-always-ready"
124+
parent_id = azapi_resource.resource_group.id
125+
service_plan_resource_id = azapi_resource.service_plan.id
81126
always_ready = {
82127
http = {
83128
name = "http"
84129
instance_count = 3
85130
}
86131
blob = {
87132
name = "blob"
88-
instance_count = 0
133+
instance_count = 3
89134
}
90135
durable = {
91136
name = "durable"
92-
instance_count = 0
137+
instance_count = 3
93138
}
94139
}
95-
enable_telemetry = var.enable_telemetry
96-
fc1_runtime_name = "node"
97-
fc1_runtime_version = "20"
98-
function_app_uses_fc1 = true
99-
instance_memory_in_mb = 2048
140+
application_insights_connection_string = azapi_resource.application_insights.output.properties.ConnectionString
141+
application_insights_key = azapi_resource.application_insights.output.properties.InstrumentationKey
142+
enable_telemetry = var.enable_telemetry
143+
fc1_runtime_name = "node"
144+
fc1_runtime_version = "20"
145+
function_app_uses_fc1 = true
146+
instance_memory_in_mb = 2048
147+
kind = "functionapp"
100148
managed_identities = {
101149
# Identities can only be used with the Standard SKU
102150
system_assigned = true
103151
user_assigned_resource_ids = [
104-
azurerm_user_assigned_identity.user.id
152+
azapi_resource.user_assigned_identity.id
105153
]
106154
}
107-
maximum_instance_count = 100
108-
# Uses an existing storage account
109-
storage_account_access_key = azurerm_storage_account.example.primary_access_key
110-
# storage_authentication_type = "StorageAccountConnectionString"
111-
storage_authentication_type = "UserAssignedIdentity"
112-
storage_container_endpoint = azurerm_storage_container.example.id
113-
storage_container_type = "blobContainer"
114-
storage_user_assigned_identity_id = azurerm_user_assigned_identity.user.id
155+
maximum_instance_count = 100
156+
os_type = "Linux"
157+
public_network_access_enabled = true
158+
storage_account_access_key = data.azapi_resource_action.storage_keys.output.keys[0].value
159+
storage_authentication_type = "userassignedidentity"
160+
storage_container_endpoint = azapi_resource.storage_container.id
161+
storage_container_type = "blobcontainer"
162+
storage_user_assigned_identity_id = azapi_resource.user_assigned_identity.id
115163
tags = {
116164
module = "Azure/avm-res-web-site/azurerm"
117165
version = "0.19.3"
@@ -127,20 +175,23 @@ The following requirements are needed by this module:
127175

128176
- <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) (~> 1.9)
129177

130-
- <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) (>= 4.21.1)
178+
- <a name="requirement_azapi"></a> [azapi](#requirement\_azapi) (~> 2.4)
131179

132180
- <a name="requirement_random"></a> [random](#requirement\_random) (>= 3.5.0, < 4.0.0)
133181

134182
## Resources
135183

136184
The following resources are used by this module:
137185

138-
- [azurerm_resource_group.example](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) (resource)
139-
- [azurerm_service_plan.example](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/service_plan) (resource)
140-
- [azurerm_storage_account.example](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) (resource)
141-
- [azurerm_storage_container.example](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) (resource)
142-
- [azurerm_user_assigned_identity.user](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) (resource)
186+
- [azapi_resource.application_insights](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
187+
- [azapi_resource.log_analytics_workspace](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
188+
- [azapi_resource.resource_group](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
189+
- [azapi_resource.service_plan](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
190+
- [azapi_resource.storage_account](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
191+
- [azapi_resource.storage_container](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
192+
- [azapi_resource.user_assigned_identity](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) (resource)
143193
- [random_integer.region_index](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) (resource)
194+
- [azapi_resource_action.storage_keys](https://registry.terraform.io/providers/Azure/azapi/latest/docs/data-sources/resource_action) (data source)
144195

145196
<!-- markdownlint-disable MD013 -->
146197
## Required Inputs
@@ -185,34 +236,14 @@ Description: The ID of the app service
185236

186237
Description: Full output of service plan created
187238

188-
### <a name="output_sku_name"></a> [sku\_name](#output\_sku\_name)
189-
190-
Description: The number of workers
191-
192239
### <a name="output_storage_account_id"></a> [storage\_account\_id](#output\_storage\_account\_id)
193240

194241
Description: The ID of the storage account
195242

196-
### <a name="output_storage_account_kind"></a> [storage\_account\_kind](#output\_storage\_account\_kind)
197-
198-
Description: The kind of storage account
199-
200243
### <a name="output_storage_account_name"></a> [storage\_account\_name](#output\_storage\_account\_name)
201244

202245
Description: Full output of storage account created
203246

204-
### <a name="output_storage_account_replication_type"></a> [storage\_account\_replication\_type](#output\_storage\_account\_replication\_type)
205-
206-
Description: The kind of storage account
207-
208-
### <a name="output_worker_count"></a> [worker\_count](#output\_worker\_count)
209-
210-
Description: The number of workers
211-
212-
### <a name="output_zone_redundant"></a> [zone\_redundant](#output\_zone\_redundant)
213-
214-
Description: The number of workers
215-
216247
## Modules
217248

218249
The following Modules are called:
@@ -229,12 +260,6 @@ Source: Azure/naming/azurerm
229260

230261
Version: 0.4.2
231262

232-
### <a name="module_regions"></a> [regions](#module\_regions)
233-
234-
Source: Azure/regions/azurerm
235-
236-
Version: 0.8.0
237-
238263
<!-- markdownlint-disable-next-line MD041 -->
239264
## Data Collection
240265

examples/always_ready/_header.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
# Flex Consumption (FC1) with Always Ready feature example
1+
# Flex Consumption with Always Ready Instances
22

3-
This deploys the module with a Linux Function App utilizing the Flex Consumption Plan, with always-ready instances.
3+
This example deploys a Linux Function App on the Azure Flex Consumption (FC1) plan with always-ready instances configured.
4+
5+
Always-ready instances keep a specified number of pre-warmed workers for designated trigger types (e.g., `http`, `blob`, `durable`), reducing cold-start latency for critical functions. This example demonstrates how to configure the `always_ready` variable to reserve instances for specific triggers.
6+
7+
The example uses `kind = "functionapp"`, `os_type = "Linux"`, and `function_app_uses_fc1 = true`.

examples/always_ready/data.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
data "azapi_resource_action" "storage_keys" {
2+
action = "listKeys"
3+
method = "POST"
4+
resource_id = azapi_resource.storage_account.id
5+
type = "Microsoft.Storage/storageAccounts@2025-01-01"
6+
response_export_values = ["keys"]
7+
}

0 commit comments

Comments
 (0)