From db845c0b26fb9c69dbc43b15c5a3d08b513d72c5 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Wed, 21 Feb 2024 12:16:10 +1000 Subject: [PATCH] updated readme --- README.md | 23 +++++++---- examples/default/README.md | 61 +++++++++++++++++++--------- examples/default/main.tf | 6 +-- locals.telemetry.tf | 15 +++---- main.privateendpoint.tf | 32 +++++++-------- main.telemetry.tf | 8 ++-- main.tf | 24 ++++++----- outputs.tf | 12 +++--- variables.tf | 83 +++++++++++++++++++------------------- 9 files changed, 146 insertions(+), 118 deletions(-) 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/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" } -