diff --git a/README.md b/README.md
index a42a0cd..1a1f525 100644
--- a/README.md
+++ b/README.md
@@ -12,35 +12,42 @@ Things to do:
1. Configure federated identity credentials on the user assigned managed identity. Use the GitHub environment.
1. Search and update TODOs within the code and remove the TODO comments once complete.
-Major version Zero (0.y.z) is for initial development. Anything MAY change at any time. A module SHOULD NOT be considered stable till at least it is major version one (1.0.0) or greater. Changes will always be via new versions being published and no changes will be made to existing published versions. For more details please go to
+> [!IMPORTANT]
+> As the overall AVM framework is not GA (generally available) yet - the CI framework and test automation is not fully functional and implemented across all supported languages yet - breaking changes are expected, and additional customer feedback is yet to be gathered and incorporated. Hence, modules **MUST NOT** be published at version `1.0.0` or higher at this time.
+>
+> All module **MUST** be published as a pre-release version (e.g., `0.1.0`, `0.1.1`, `0.2.0`, etc.) until the AVM framework becomes GA.
+>
+> However, it is important to note that this **DOES NOT** mean that the modules cannot be consumed and utilized. They **CAN** be leveraged in all types of environments (dev, test, prod etc.). Consumers can treat them just like any other IaC module and raise issues or feature requests against them as they learn from the usage of the module. Consumers should also read the release notes for each version, if considering updating to a more recent version of a module to see if there are any considerations or breaking changes etc.
## Requirements
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (>= 1.5.0)
-- [azurerm](#requirement\_azurerm) (>= 3.71.0)
+- [azapi](#requirement\_azapi) (>= 1.9.0, < 2.0)
-- [random](#requirement\_random) (>= 3.5.0)
+- [azurerm](#requirement\_azurerm) (>= 3.71.0, < 4.0)
+
+- [random](#requirement\_random) (>= 3.5.0, < 4.0)
## Providers
The following providers are used by this module:
-- [azurerm](#provider\_azurerm) (>= 3.71.0)
+- [azurerm](#provider\_azurerm) (>= 3.71.0, < 4.0)
-- [random](#provider\_random) (>= 3.5.0)
+- [random](#provider\_random) (>= 3.5.0, < 4.0)
## Resources
The following resources are used by this module:
-- [azurerm_TODO_the_resource_for_this_module.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/TODO_the_resource_for_this_module) (resource)
- [azurerm_management_lock.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/management_lock) (resource)
- [azurerm_private_endpoint.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) (resource)
- [azurerm_private_endpoint_application_security_group_association.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint_application_security_group_association) (resource)
+- [azurerm_resource_group.TODO](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) (resource)
- [azurerm_resource_group_template_deployment.telemetry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group_template_deployment) (resource)
- [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)
- [random_id.telem](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) (resource)
@@ -279,4 +286,4 @@ No modules.
## Data Collection
The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.
-
+
\ No newline at end of file
diff --git a/examples/default/README.md b/examples/default/README.md
index 9bfe247..b9d9ff5 100644
--- a/examples/default/README.md
+++ b/examples/default/README.md
@@ -11,6 +11,10 @@ terraform {
source = "hashicorp/azurerm"
version = ">= 3.7.0, < 4.0.0"
}
+ random = {
+ source = "hashicorp/random"
+ version = ">= 3.5.0, < 4.0.0"
+ }
}
}
@@ -18,35 +22,43 @@ provider "azurerm" {
features {}
}
-variable "enable_telemetry" {
- type = bool
- default = true
- description = <.
-If it is set to false, then no telemetry will be collected.
-DESCRIPTION
+
+## Section to provide a random Azure region for the resource group
+# This allows us to randomize the region for the resource group.
+module "regions" {
+ source = "Azure/regions/azurerm"
+ version = ">= 0.3.0"
+}
+
+# This allows us to randomize the region for the resource group.
+resource "random_integer" "region_index" {
+ max = length(module.regions.regions) - 1
+ min = 0
}
+## End of section to provide a random Azure region for the resource group
# This ensures we have unique CAF compliant names for our resources.
module "naming" {
source = "Azure/naming/azurerm"
- version = "0.4.0"
+ version = ">= 0.3.0"
}
# This is required for resource modules
resource "azurerm_resource_group" "this" {
+ location = module.regions.regions[random_integer.region_index.result].name
name = module.naming.resource_group.name_unique
- location = "MYLOCATION" # TODO update with a real location, e.g. EastUS
}
# This is the module call
-module "MYMODULE" {
+# Do not specify location here due to the randomization above.
+# Leaving location as `null` will cause the module to use the resource group location
+# with a data source.
+module "test" {
source = "../../"
# source = "Azure/avm--/azurerm"
# ...
- enable_telemetry = var.enable_telemetry
- name = "" # TODO update with module.naming..name_unique
+ enable_telemetry = var.enable_telemetry # see variables.tf
+ name = "TODO" # TODO update with module.naming..name_unique
resource_group_name = azurerm_resource_group.this.name
}
```
@@ -60,17 +72,22 @@ The following requirements are needed by this module:
- [azurerm](#requirement\_azurerm) (>= 3.7.0, < 4.0.0)
+- [random](#requirement\_random) (>= 3.5.0, < 4.0.0)
+
## Providers
The following providers are used by this module:
- [azurerm](#provider\_azurerm) (>= 3.7.0, < 4.0.0)
+- [random](#provider\_random) (>= 3.5.0, < 4.0.0)
+
## Resources
The following resources are used by this module:
- [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) (resource)
+- [random_integer.region_index](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) (resource)
## Required Inputs
@@ -99,17 +116,23 @@ No outputs.
The following Modules are called:
-### [MYMODULE](#module\_MYMODULE)
+### [naming](#module\_naming)
-Source: ../../
+Source: Azure/naming/azurerm
-Version:
+Version: >= 0.3.0
-### [naming](#module\_naming)
+### [regions](#module\_regions)
-Source: Azure/naming/azurerm
+Source: Azure/regions/azurerm
+
+Version: >= 0.3.0
-Version: 0.4.0
+### [test](#module\_test)
+
+Source: ../../
+
+Version:
## Data Collection
diff --git a/examples/default/main.tf b/examples/default/main.tf
index 33dfb89..7347f9c 100644
--- a/examples/default/main.tf
+++ b/examples/default/main.tf
@@ -26,8 +26,8 @@ module "regions" {
# This allows us to randomize the region for the resource group.
resource "random_integer" "region_index" {
- min = 0
max = length(module.regions.regions) - 1
+ min = 0
}
## End of section to provide a random Azure region for the resource group
@@ -39,8 +39,8 @@ module "naming" {
# This is required for resource modules
resource "azurerm_resource_group" "this" {
- name = module.naming.resource_group.name_unique
location = module.regions.regions[random_integer.region_index.result].name
+ name = module.naming.resource_group.name_unique
}
# This is the module call
@@ -52,6 +52,6 @@ module "test" {
# source = "Azure/avm--/azurerm"
# ...
enable_telemetry = var.enable_telemetry # see variables.tf
- name = "TODO" # TODO update with module.naming..name_unique
+ name = "TODO" # TODO update with module.naming..name_unique
resource_group_name = azurerm_resource_group.this.name
}
diff --git a/locals.telemetry.tf b/locals.telemetry.tf
index 52abdb4..ff0467b 100644
--- a/locals.telemetry.tf
+++ b/locals.telemetry.tf
@@ -1,17 +1,8 @@
locals {
- # This is the unique id AVM Terraform modules that is supplied by the AVM team.
- # See https://azure.github.io/Azure-Verified-Modules/specs/shared/#id-sfr3---category-telemetry---deploymentusage-telemetry
- telem_puid = "46d3xgtf"
-
# TODO: change this to the name of the module. See https://azure.github.io/Azure-Verified-Modules/specs/shared/#id-sfr3---category-telemetry---deploymentusage-telemetry
module_name = "CHANGEME"
-
# TODO: Change this. Should be either `res` or `ptn`
module_type = "res"
-
- # This ensures we don't get errors if telemetry is disabled.
- telem_random_hex = can(random_id.telem[0].hex) ? random_id.telem[0].hex : ""
-
# This constructs the ARM deployment name that is used for the telemetry.
# We shouldn't ever hit the 64 character limit but use substr just in case.
telem_arm_deployment_name = substr(
@@ -26,7 +17,6 @@ locals {
0,
64
)
-
# This is an empty ARM deployment template.
telem_arm_template_content = jsonencode(
{
@@ -43,4 +33,9 @@ locals {
}
}
)
+ # This is the unique id AVM Terraform modules that is supplied by the AVM team.
+ # See https://azure.github.io/Azure-Verified-Modules/specs/shared/#id-sfr3---category-telemetry---deploymentusage-telemetry
+ telem_puid = "46d3xgtf"
+ # This ensures we don't get errors if telemetry is disabled.
+ telem_random_hex = can(random_id.telem[0].hex) ? random_id.telem[0].hex : ""
}
diff --git a/main.privateendpoint.tf b/main.privateendpoint.tf
index e5c036b..0a23b06 100644
--- a/main.privateendpoint.tf
+++ b/main.privateendpoint.tf
@@ -1,20 +1,30 @@
# TODO remove this code & var.private_endpoints if private link is not support. Note it must be included in this module if it is supported.
resource "azurerm_private_endpoint" "this" {
- for_each = var.private_endpoints
- name = each.value.name != null ? each.value.name : "pe-${var.name}"
+ for_each = var.private_endpoints
+
location = coalesce(each.value.location, var.location, local.resource_group_location)
+ name = each.value.name != null ? each.value.name : "pe-${var.name}"
resource_group_name = each.value.resource_group_name != null ? each.value.resource_group_name : var.resource_group_name
subnet_id = each.value.subnet_resource_id
custom_network_interface_name = each.value.network_interface_name
tags = each.value.tags
private_service_connection {
+ is_manual_connection = false
name = each.value.private_service_connection_name != null ? each.value.private_service_connection_name : "pse-${var.name}"
private_connection_resource_id = azurerm_resource_group.TODO.id # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
- is_manual_connection = false
subresource_names = ["TODO subresource name, see https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-overview#private-link-resource"]
}
+ dynamic "ip_configuration" {
+ for_each = each.value.ip_configurations
+ content {
+ name = ip_configuration.value.name
+ private_ip_address = ip_configuration.value.private_ip_address
+ member_name = "TODO subresource name"
+ subresource_name = "TODO subresource name"
+ }
+ }
dynamic "private_dns_zone_group" {
for_each = length(each.value.private_dns_zone_resource_ids) > 0 ? ["this"] : []
@@ -23,21 +33,11 @@ resource "azurerm_private_endpoint" "this" {
private_dns_zone_ids = each.value.private_dns_zone_resource_ids
}
}
-
- dynamic "ip_configuration" {
- for_each = each.value.ip_configurations
-
- content {
- name = ip_configuration.value.name
- subresource_name = "TODO subresource name"
- member_name = "TODO subresource name"
- private_ip_address = ip_configuration.value.private_ip_address
- }
- }
}
resource "azurerm_private_endpoint_application_security_group_association" "this" {
- for_each = local.private_endpoint_application_security_group_associations
- private_endpoint_id = azurerm_private_endpoint.this[each.value.pe_key].id
+ for_each = local.private_endpoint_application_security_group_associations
+
application_security_group_id = each.value.asg_resource_id
+ private_endpoint_id = azurerm_private_endpoint.this[each.value.pe_key].id
}
diff --git a/main.telemetry.tf b/main.telemetry.tf
index 88e56f0..f15b62e 100644
--- a/main.telemetry.tf
+++ b/main.telemetry.tf
@@ -1,14 +1,16 @@
resource "random_id" "telem" {
- count = var.enable_telemetry ? 1 : 0
+ count = var.enable_telemetry ? 1 : 0
+
byte_length = 4
}
# This is the module telemetry deployment that is only created if telemetry is enabled.
# It is deployed to the resource's resource group.
resource "azurerm_resource_group_template_deployment" "telemetry" {
- count = var.enable_telemetry ? 1 : 0
+ count = var.enable_telemetry ? 1 : 0
+
+ deployment_mode = "Incremental"
name = local.telem_arm_deployment_name
resource_group_name = var.resource_group_name
- deployment_mode = "Incremental"
template_content = local.telem_arm_template_content
}
diff --git a/main.tf b/main.tf
index 1c94190..64cb628 100644
--- a/main.tf
+++ b/main.tf
@@ -1,32 +1,34 @@
# TODO: insert resources here.
data "azurerm_resource_group" "parent" {
count = var.location == null ? 1 : 0
- name = var.resource_group_name
+
+ name = var.resource_group_name
}
# TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
resource "azurerm_resource_group" "TODO" {
- name = var.name # calling code must supply the name
- location = coalesce(var.location, local.resource_group_location)
- # etc
+ location = coalesce(var.location, local.resource_group_location)
+ name = var.name # calling code must supply the name
}
# required AVM resources interfaces
resource "azurerm_management_lock" "this" {
- count = var.lock.kind != "None" ? 1 : 0
+ count = var.lock.kind != "None" ? 1 : 0
+
+ lock_level = var.lock.kind
name = coalesce(var.lock.name, "lock-${var.name}")
scope = azurerm_resource_group.TODO.id # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
- lock_level = var.lock.kind
}
resource "azurerm_role_assignment" "this" {
- for_each = var.role_assignments
- scope = azurerm_resource_group.TODO.id # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
- role_definition_id = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? each.value.role_definition_id_or_name : null
- role_definition_name = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? null : each.value.role_definition_id_or_name
+ for_each = var.role_assignments
+
principal_id = each.value.principal_id
+ scope = azurerm_resource_group.TODO.id # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
condition = each.value.condition
condition_version = each.value.condition_version
- skip_service_principal_aad_check = each.value.skip_service_principal_aad_check
delegated_managed_identity_resource_id = each.value.delegated_managed_identity_resource_id
+ role_definition_id = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? each.value.role_definition_id_or_name : null
+ role_definition_name = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? null : each.value.role_definition_id_or_name
+ skip_service_principal_aad_check = each.value.skip_service_principal_aad_check
}
diff --git a/outputs.tf b/outputs.tf
index bfdc2ee..7831e76 100644
--- a/outputs.tf
+++ b/outputs.tf
@@ -1,13 +1,11 @@
-# TODO: insert outputs here.
+output "private_endpoints" {
+ description = "A map of private endpoints. The map key is the supplied input to var.private_endpoints. The map value is the entire azurerm_private_endpoint resource."
+ value = azurerm_private_endpoint.this
+}
# Module owners should include the full resource via a 'resource' output
# https://azure.github.io/Azure-Verified-Modules/specs/terraform/#id-tffr2---category-outputs---additional-terraform-outputs
output "resource" {
- value = azurerm_resource_group.TODO # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
description = "This is the full output for the resource."
-}
-
-output "private_endpoints" {
- value = azurerm_private_endpoint.this
- description = "A map of private endpoints. The map key is the supplied input to var.private_endpoints. The map value is the entire azurerm_private_endpoint resource."
+ value = azurerm_resource_group.TODO # TODO: Replace this dummy resource azurerm_resource_group.TODO with your module resource
}
diff --git a/terraform.tf b/terraform.tf
index 07fdb67..b47db18 100644
--- a/terraform.tf
+++ b/terraform.tf
@@ -1,14 +1,18 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = ">= 1.5.0"
required_providers {
- # TODO: Ensure all required providers are listed here.
+ # TODO: Ensure all required providers are listed here and the version property includes a constraint on the maximum major version.
+ azapi = {
+ source = "Azure/azapi"
+ version = ">= 1.9.0, < 2.0"
+ }
azurerm = {
source = "hashicorp/azurerm"
- version = ">= 3.71.0"
+ version = ">= 3.71.0, < 4.0"
}
random = {
source = "hashicorp/random"
- version = ">= 3.5.0"
+ version = ">= 3.5.0, < 4.0"
}
}
}
diff --git a/variables.tf b/variables.tf
index 1d99e79..f5b519c 100644
--- a/variables.tf
+++ b/variables.tf
@@ -1,28 +1,7 @@
-variable "enable_telemetry" {
- type = bool
- default = true
- description = <.
-If it is set to false, then no telemetry will be collected.
-DESCRIPTION
-}
-
-# This is required for most resource modules
-variable "resource_group_name" {
- type = string
- description = "The resource group where the resources will be deployed."
-}
-
-variable "location" {
- type = string
- description = "Azure region where the resource should be deployed. If null, the location will be inferred from the resource group location."
- default = null
-}
-
variable "name" {
type = string
description = "The name of the this resource."
+
validation {
condition = can(regex("TODO", var.name))
error_message = "The name must be TODO." # TODO remove the example below once complete:
@@ -31,6 +10,12 @@ variable "name" {
}
}
+# This is required for most resource modules
+variable "resource_group_name" {
+ type = string
+ description = "The resource group where the resources will be deployed."
+}
+
# required AVM interfaces
# remove only if not supported by the resource
# tflint-ignore: terraform_unused_declarations
@@ -41,8 +26,8 @@ variable "customer_managed_key" {
key_version = optional(string, null)
user_assigned_identity_resource_id = optional(string, null)
})
- description = "Customer managed keys that should be associated with the resource."
default = {}
+ description = "Customer managed keys that should be associated with the resource."
}
variable "diagnostic_settings" {
@@ -58,8 +43,22 @@ variable "diagnostic_settings" {
event_hub_name = optional(string, null)
marketplace_partner_resource_id = optional(string, null)
}))
- default = {}
- nullable = false
+ default = {}
+ description = <.
+If it is set to false, then no telemetry will be collected.
DESCRIPTION
}
+variable "location" {
+ type = string
+ default = null
+ description = "Azure region where the resource should be deployed. If null, the location will be inferred from the resource group location."
+}
+
variable "lock" {
type = object({
name = optional(string, null)
kind = optional(string, "None")
})
- description = "The lock level to apply. Default is `None`. Possible values are `None`, `CanNotDelete`, and `ReadOnly`."
default = {}
+ description = "The lock level to apply. Default is `None`. Possible values are `None`, `CanNotDelete`, and `ReadOnly`."
nullable = false
+
validation {
condition = contains(["CanNotDelete", "ReadOnly", "None"], var.lock.kind)
error_message = "The lock level must be one of: 'None', 'CanNotDelete', or 'ReadOnly'."
@@ -110,8 +112,8 @@ variable "managed_identities" {
system_assigned = optional(bool, false)
user_assigned_resource_ids = optional(set(string), [])
})
- description = "Managed identities to be created for the resource."
default = {}
+ description = "Managed identities to be created for the resource."
}
variable "private_endpoints" {
@@ -194,7 +196,6 @@ DESCRIPTION
# tflint-ignore: terraform_unused_declarations
variable "tags" {
type = map(any)
- description = "The map of tags to be applied to the resource"
default = {}
+ description = "The map of tags to be applied to the resource"
}
-