From e6595a9e0a8028b4b711469eabf2b4d21b18b901 Mon Sep 17 00:00:00 2001
From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
Date: Thu, 11 Jul 2024 09:23:09 +0100
Subject: [PATCH 1/5] feat: nee telemetry
---
.github/workflows/module-version.yml | 67 ----------------------------
locals.telemetry.tf | 66 ---------------------------
locals.version.tf.json | 5 ---
main.telemetry.tf | 38 +++++++++-------
terraform.tf | 8 +++-
variables.tf | 1 +
6 files changed, 30 insertions(+), 155 deletions(-)
delete mode 100644 .github/workflows/module-version.yml
delete mode 100644 locals.telemetry.tf
delete mode 100644 locals.version.tf.json
diff --git a/.github/workflows/module-version.yml b/.github/workflows/module-version.yml
deleted file mode 100644
index 1440e809..00000000
--- a/.github/workflows/module-version.yml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-name: module version
-
-on:
- pull_request:
- branches:
- - main
- paths:
- - '**.tf'
- - '**.tf.json'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-jobs:
- checkversion:
- env:
- SEMVER_REGEX: '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
- MODULE_VERSION_FILE: locals.version.tf.json
- MODULE_JSON_QUERY: .locals.module_version
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - run: |
- VER=$(curl --silent -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .name | sed s/^v//)
- if echo "$VER" | grep -P -qv "$SEMVER_REGEX"; then
- echo "Release version $VER is not a valid semantic version"
- exit 1
- fi
- echo LATEST_RELEASE="$VER" >> "$GITHUB_ENV"
- name: Get latest release version
-
- - run: |
- VER=$(jq -r '${{ env.MODULE_JSON_QUERY }}' < ${{ env.MODULE_VERSION_FILE }})
- if echo "$VER" | grep -P -qv "$SEMVER_REGEX"; then
- echo "Module version $VER is not a valid semantic version"
- exit 1
- fi
- echo MODULE_VERSION="$VER" >> "$GITHUB_ENV"
- name: Get module version
-
- - run: |
- MODVERMAJOR=$(echo ${{ env.MODULE_VERSION }} | cut -d. -f1)
- MODVERMINOR=$(echo ${{ env.MODULE_VERSION }} | cut -d. -f2)
- MODVERPATCH=$(echo ${{ env.MODULE_VERSION }} | cut -d. -f3)
-
- RELVERMAJOR=$(echo ${{ env.LATEST_RELEASE }} | cut -d. -f1)
- RELVERMINOR=$(echo ${{ env.LATEST_RELEASE }} | cut -d. -f2)
- RELVERPATCH=$(echo ${{ env.LATEST_RELEASE }} | cut -d. -f3)
-
- if [ "$MODVERMAJOR" -lt "$RELVERMAJOR" ]; then
- echo "Module version ${{ env.MODULE_VERSION }} is less than latest release ${{ env.LATEST_RELEASE }}"
- exit 1
- fi
-
- if [ "$MODVERMAJOR" -eq "$RELVERMAJOR" ] && [ "$MODVERMINOR" -lt "$RELVERMINOR" ]; then
- echo "Module version ${{ env.MODULE_VERSION }} is less than latest release ${{ env.LATEST_RELEASE }}"
- exit 1
- fi
-
- if [ "$MODVERMAJOR" -eq "$RELVERMAJOR" ] && [ "$MODVERMINOR" -eq "$RELVERMINOR" ] && [ "$MODVERPATCH" -lt "$RELVERPATCH" ]; then
- echo "Module version ${{ env.MODULE_VERSION }} is less than latest release ${{ env.LATEST_RELEASE }}"
- exit 1
- fi
- name: Check module version is greater than latest release
diff --git a/locals.telemetry.tf b/locals.telemetry.tf
deleted file mode 100644
index 2f579c7c..00000000
--- a/locals.telemetry.tf
+++ /dev/null
@@ -1,66 +0,0 @@
-# Telemetry is collected by creating an empty ARM deployment with a specific name
-# If you want to disable telemetry, you can set the disable_telemetry variable to true
-locals {
- # root_module_puid is the UUID that identifies the root module in the telemetry ARM deployment.
- telem_root_puid = "50a8a460-d517-4b11-b86c-6de447806b67"
-
- # telem_arm_subscription_template is the ARM template content for the telemetry deployment.
- telem_arm_subscription_template = {
- "$schema" = "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#"
- contentVersion = "1.0.0.0"
- parameters = {}
- variables = {}
- resources = []
- outputs = {
- telemetry = {
- type = "String"
- value = "For more information, see https://aka.ms/lz-vending/tf/telemetry"
- }
- }
- }
-
- # subscription telemetry bit fields
- telem_root_subscription_alias_enabled = var.subscription_alias_enabled ? 1 : 0
- telem_root_subscription_management_group_association_enabled = var.subscription_management_group_association_enabled ? 2 : 0
- telem_root_subscription_tags_enabled = length(var.subscription_tags) > 0 ? 4 : 0
-
- # virtualnetwork telemetry bit fields
- telem_root_virtual_network_enabled = var.virtual_network_enabled ? 256 : 0
- telem_root_virtual_network_peering_enabled = anytrue([for k, v in var.virtual_networks : v.hub_peering_enabled]) ? 512 : 0
- telem_root_virtual_network_vwan_connection_enabled = anytrue([for k, v in var.virtual_networks : v.vwan_connection_enabled]) ? 1024 : 0
- telem_virtual_network_resource_lock_enabled = anytrue([for k, v in var.virtual_networks : v.resource_group_lock_enabled]) ? 2048 : 0
- telem_root_vwan_advanced_routing_enabled = anytrue([for k, v in var.virtual_networks : length(v.vwan_propagated_routetables_labels) > 0 || length(v.vwan_propagated_routetables_resource_ids) > 0 || v.vwan_associated_routetable_resource_id != ""]) ? 4096 : 0
-
- # roleassignment telemetry bit fields
- telem_root_role_assignment_enabled = var.role_assignment_enabled ? 65536 : 0
-
- # Calculate the denary value of the bit fields
- telem_root_bitfield_denary = (
- local.telem_root_subscription_alias_enabled +
- local.telem_root_subscription_management_group_association_enabled +
- local.telem_root_subscription_tags_enabled +
- local.telem_root_virtual_network_enabled +
- local.telem_root_virtual_network_peering_enabled +
- local.telem_root_virtual_network_vwan_connection_enabled +
- local.telem_virtual_network_resource_lock_enabled +
- local.telem_root_vwan_advanced_routing_enabled +
- local.telem_root_role_assignment_enabled
- )
-
- # Convert the denary value to hexadecimal and pad with zeros to the left to a length of 8 characters.
- telem_root_bitfield_hex = format("%08x", local.telem_root_bitfield_denary)
-
- # 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_root_arm_deployment_name = substr(
- format(
- "pid-%s_%s_%s",
- local.telem_root_puid,
- local.module_version,
- local.telem_root_bitfield_hex,
- ),
- 0,
- 64
- )
-}
diff --git a/locals.version.tf.json b/locals.version.tf.json
deleted file mode 100644
index 2716b922..00000000
--- a/locals.version.tf.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "locals": {
- "module_version": "4.1.3"
- }
-}
diff --git a/main.telemetry.tf b/main.telemetry.tf
index 6630dd9e..b8482b25 100644
--- a/main.telemetry.tf
+++ b/main.telemetry.tf
@@ -1,16 +1,24 @@
-# This is the root module telemetry deployment that is only created if telemetry is enabled.
-# It is deployed to the created or supplied subscription
-resource "azapi_resource" "telemetry_root" {
- count = var.disable_telemetry ? 0 : 1
- parent_id = local.subscription_resource_id
- name = local.telem_root_arm_deployment_name
- type = "Microsoft.Resources/deployments@2021-04-01"
- location = var.location
- body = jsonencode({
- properties = {
- mode = "Incremental"
- template = local.telem_arm_subscription_template
- }
- })
- ignore_missing_property = true
+data "azurerm_client_config" "telemetry" {
+ count = var.disable_telemetry ? 0 : 1
+}
+
+data "modtm_module_source" "telemetry" {
+ count = var.disable_telemetry ? 0 : 1
+ module_path = path.module
+}
+
+resource "random_uuid" "telemetry" {
+ count = var.disable_telemetry ? 0 : 1
+}
+
+resource "modtm_telemetry" "telemetry" {
+ count = var.disable_telemetry ? 0 : 1
+
+ tags = {
+ subscription_id = local.subscription_id
+ tenant_id = one(data.azurerm_client_config.telemetry).tenant_id
+ module_source = one(data.modtm_module_source.telemetry).module_source
+ module_version = one(data.modtm_module_source.telemetry).module_version
+ random_id = one(random_uuid.telemetry).result
+ }
}
diff --git a/terraform.tf b/terraform.tf
index d2bdb883..0f45ac2e 100644
--- a/terraform.tf
+++ b/terraform.tf
@@ -1,9 +1,13 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azapi = {
source = "azure/azapi"
- version = ">= 1.4.0"
+ version = "~> 1.4"
+ }
+ modtm = {
+ source = "azure/modtm"
+ version = "~> 0.3"
}
}
}
diff --git a/variables.tf b/variables.tf
index 24eb58d0..da7c6205 100644
--- a/variables.tf
+++ b/variables.tf
@@ -29,4 +29,5 @@ module "lz_vending" {
```
DESCRIPTION
default = false
+ nullable = false
}
From 678d436be2a57e9de633291fd022400ef01e3c8b Mon Sep 17 00:00:00 2001
From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
Date: Thu, 11 Jul 2024 09:27:08 +0100
Subject: [PATCH 2/5] style: use pessimistic version constraint
---
modules/budget/terraform.tf | 4 ++--
modules/resourcegroup/terraform.tf | 4 ++--
modules/resourceprovider/terraform.tf | 4 ++--
modules/roleassignment/terraform.tf | 4 ++--
modules/subscription/terraform.tf | 8 ++++----
modules/usermanagedidentity/terraform.tf | 4 ++--
6 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/modules/budget/terraform.tf b/modules/budget/terraform.tf
index ff5db750..60d17dc7 100644
--- a/modules/budget/terraform.tf
+++ b/modules/budget/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azapi = {
source = "azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.11"
}
}
}
diff --git a/modules/resourcegroup/terraform.tf b/modules/resourcegroup/terraform.tf
index ff5db750..ca1472a5 100644
--- a/modules/resourcegroup/terraform.tf
+++ b/modules/resourcegroup/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azapi = {
source = "azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.13"
}
}
}
diff --git a/modules/resourceprovider/terraform.tf b/modules/resourceprovider/terraform.tf
index f0b843f5..eed9a02c 100644
--- a/modules/resourceprovider/terraform.tf
+++ b/modules/resourceprovider/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azapi = {
source = "Azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.11"
}
}
}
diff --git a/modules/roleassignment/terraform.tf b/modules/roleassignment/terraform.tf
index aad40749..fe670e86 100644
--- a/modules/roleassignment/terraform.tf
+++ b/modules/roleassignment/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
- version = ">= 3.7.0"
+ version = "~> 3.7"
}
}
}
diff --git a/modules/subscription/terraform.tf b/modules/subscription/terraform.tf
index ceb0bccb..3eb3935c 100644
--- a/modules/subscription/terraform.tf
+++ b/modules/subscription/terraform.tf
@@ -1,17 +1,17 @@
terraform {
- required_version = ">= 1.4.0"
+ required_version = "~> 1.4"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
- version = ">= 3.7.0"
+ version = "~> 3.7"
}
azapi = {
source = "Azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.11"
}
time = {
source = "hashicorp/time"
- version = ">= 0.9.1"
+ version = "~> 0.9"
}
}
}
diff --git a/modules/usermanagedidentity/terraform.tf b/modules/usermanagedidentity/terraform.tf
index ff5db750..60d17dc7 100644
--- a/modules/usermanagedidentity/terraform.tf
+++ b/modules/usermanagedidentity/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = ">= 1.3.0"
+ required_version = "~> 1.3"
required_providers {
azapi = {
source = "azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.11"
}
}
}
From 83a8d73e5e7244aaad1b035721ff2a7a5ca44c5a Mon Sep 17 00:00:00 2001
From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
Date: Thu, 11 Jul 2024 09:29:43 +0100
Subject: [PATCH 3/5] docs: make docs
---
README.md | 13 +++++++++----
modules/budget/README.md | 4 ++--
modules/resourcegroup/README.md | 4 ++--
modules/resourceprovider/README.md | 4 ++--
modules/roleassignment/README.md | 4 ++--
modules/subscription/README.md | 8 ++++----
modules/usermanagedidentity/README.md | 4 ++--
7 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/README.md b/README.md
index 10114f7b..6122972c 100644
--- a/README.md
+++ b/README.md
@@ -136,9 +136,11 @@ module "lz_vending" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azapi](#requirement\_azapi) (>= 1.4.0)
+- [azapi](#requirement\_azapi) (~> 1.4)
+
+- [modtm](#requirement\_modtm) (~> 0.3)
## Modules
@@ -1021,7 +1023,10 @@ Default: `{}`
The following resources are used by this module:
-- [azapi_resource.telemetry_root](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
+- [modtm_telemetry.telemetry](https://registry.terraform.io/providers/azure/modtm/latest/docs/resources/telemetry) (resource)
+- [random_uuid.telemetry](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) (resource)
+- [azurerm_client_config.telemetry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) (data source)
+- [modtm_module_source.telemetry](https://registry.terraform.io/providers/azure/modtm/latest/docs/data-sources/module_source) (data source)
## Outputs
@@ -1108,4 +1113,4 @@ Authorized use of Microsoft trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
-
+
\ No newline at end of file
diff --git a/modules/budget/README.md b/modules/budget/README.md
index c89b99ad..0f35f4ed 100644
--- a/modules/budget/README.md
+++ b/modules/budget/README.md
@@ -34,9 +34,9 @@ module "budget" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azapi](#requirement\_azapi) (>= 1.11.0)
+- [azapi](#requirement\_azapi) (~> 1.11)
## Modules
diff --git a/modules/resourcegroup/README.md b/modules/resourcegroup/README.md
index a89fd163..b46dad8d 100644
--- a/modules/resourcegroup/README.md
+++ b/modules/resourcegroup/README.md
@@ -33,9 +33,9 @@ module "resourcegroups" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azapi](#requirement\_azapi) (>= 1.11.0)
+- [azapi](#requirement\_azapi) (~> 1.13)
## Modules
diff --git a/modules/resourceprovider/README.md b/modules/resourceprovider/README.md
index ae89c907..d945951f 100644
--- a/modules/resourceprovider/README.md
+++ b/modules/resourceprovider/README.md
@@ -28,9 +28,9 @@ module "resourceproviders" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azapi](#requirement\_azapi) (>= 1.11.0)
+- [azapi](#requirement\_azapi) (~> 1.11)
## Modules
diff --git a/modules/roleassignment/README.md b/modules/roleassignment/README.md
index 2ea8a52c..501f0441 100644
--- a/modules/roleassignment/README.md
+++ b/modules/roleassignment/README.md
@@ -29,9 +29,9 @@ module "roleassignment" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azurerm](#requirement\_azurerm) (>= 3.7.0)
+- [azurerm](#requirement\_azurerm) (~> 3.7)
## Modules
diff --git a/modules/subscription/README.md b/modules/subscription/README.md
index ef2d5c20..08be940d 100644
--- a/modules/subscription/README.md
+++ b/modules/subscription/README.md
@@ -31,13 +31,13 @@ module "subscription" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.4.0)
+- [terraform](#requirement\_terraform) (~> 1.4)
-- [azapi](#requirement\_azapi) (>= 1.11.0)
+- [azapi](#requirement\_azapi) (~> 1.11)
-- [azurerm](#requirement\_azurerm) (>= 3.7.0)
+- [azurerm](#requirement\_azurerm) (~> 3.7)
-- [time](#requirement\_time) (>= 0.9.1)
+- [time](#requirement\_time) (~> 0.9)
## Modules
diff --git a/modules/usermanagedidentity/README.md b/modules/usermanagedidentity/README.md
index 80781a96..7ef6e4c1 100644
--- a/modules/usermanagedidentity/README.md
+++ b/modules/usermanagedidentity/README.md
@@ -67,9 +67,9 @@ module "umi" {
The following requirements are needed by this module:
-- [terraform](#requirement\_terraform) (>= 1.3.0)
+- [terraform](#requirement\_terraform) (~> 1.3)
-- [azapi](#requirement\_azapi) (>= 1.11.0)
+- [azapi](#requirement\_azapi) (~> 1.11)
## Modules
From 514f44aa9ae4c760dc8fae7f21a1a4370b26edff Mon Sep 17 00:00:00 2001
From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
Date: Thu, 11 Jul 2024 09:33:21 +0100
Subject: [PATCH 4/5] fix: add random provider
---
README.md | 2 ++
terraform.tf | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/README.md b/README.md
index 6122972c..591b398f 100644
--- a/README.md
+++ b/README.md
@@ -142,6 +142,8 @@ The following requirements are needed by this module:
- [modtm](#requirement\_modtm) (~> 0.3)
+- [random](#requirement\_random) (~> 3.6)
+
## Modules
The following Modules are called:
diff --git a/terraform.tf b/terraform.tf
index 0f45ac2e..cd0b4114 100644
--- a/terraform.tf
+++ b/terraform.tf
@@ -9,5 +9,9 @@ terraform {
source = "azure/modtm"
version = "~> 0.3"
}
+ random = {
+ source = "hashicorp/random"
+ version = "~> 3.6"
+ }
}
}
From 117060cab77041507c1689c3985282e27f6adc6e Mon Sep 17 00:00:00 2001
From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
Date: Thu, 11 Jul 2024 10:47:46 +0100
Subject: [PATCH 5/5] feat: begin migration to terraform test
---
.github/workflows/go-test-unit.yml | 21 ++------
Makefile | 3 +-
main.telemetry.tf | 2 +-
modules/budget/main.tf | 6 +--
modules/budget/terraform.tf | 4 +-
modules/resourcegroup/main.tf | 2 +-
modules/resourcegroup/terraform.tf | 4 +-
modules/resourceprovider/terraform.tf | 4 +-
modules/roleassignment/terraform.tf | 4 +-
modules/subscription/main.tf | 4 +-
modules/subscription/terraform.tf | 6 +--
modules/usermanagedidentity/main.tf | 26 +++++-----
modules/usermanagedidentity/terraform.tf | 4 +-
modules/virtualnetwork/main.tf | 52 ++++---------------
modules/virtualnetwork/terraform.tf | 2 +-
modules/virtualnetwork/tests/valid.tftest.hcl | 44 ++++++++++++++++
terraform.tf | 4 +-
tests/go.mod | 2 +-
tests/virtualnetwork/virtualnetwork_test.go | 39 --------------
19 files changed, 96 insertions(+), 137 deletions(-)
create mode 100644 modules/virtualnetwork/tests/valid.tftest.hcl
diff --git a/.github/workflows/go-test-unit.yml b/.github/workflows/go-test-unit.yml
index b735ae6a..3e54a355 100644
--- a/.github/workflows/go-test-unit.yml
+++ b/.github/workflows/go-test-unit.yml
@@ -56,9 +56,9 @@ jobs:
strategy:
fail-fast: false
matrix:
- azapi_version: ['latest', '1.11.0']
- azurerm_version: ['latest', '3.7.0']
- terraform_version: ['latest', '1.4.0']
+ azapi_version: ['latest', '1.14.0']
+ azurerm_version: ['latest', '3.107.0']
+ terraform_version: ['latest', '1.6.0']
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -72,20 +72,7 @@ jobs:
terraform_version: ${{ matrix.terraform_version }}
terraform_wrapper: false
- - name: Setup go
- uses: actions/setup-go@v5
- with:
- go-version-file: tests/go.mod
- cache-dependency-path: tests/go.sum
-
- - name: Set GOMAXPROCS to 2 * number of cores
- run: |
- CORES="$(grep -Pc '^processor\t' /proc/cpuinfo)"
- ((DOUBLE=CORES*2))
- echo "Setting GOMAXPROCS to $DOUBLE"
- echo "GOMAXPROCS=$DOUBLE" >> "$GITHUB_ENV"
-
- - name: Go test
+ - name: Terraform test
run: make TESTARGS='-v' TESTFILTER='${{ github.event.inputs.test_filter }}' test
env:
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
diff --git a/Makefile b/Makefile
index 0f906af3..e969a76e 100644
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,8 @@ lint:
cd tests && golangci-lint run
test: fmtcheck
- cd tests && go test $(TEST) $(TESTARGS) -run ^Test$(TESTFILTER) -timeout=$(TESTTIMEOUT)
+ terraform test
+ if [ -d "modules" ]; then for dir in modules/*; do if [ -d "$$dir" ]; then echo "==> Testing $$dir"; cd $$dir; terraform test; echo; cd - >/dev/null; fi; done; fi
testdeploy: fmtcheck
cd tests && TERRATEST_DEPLOY=1 go test $(TEST) $(TESTARGS) -run ^TestDeploy$(TESTFILTER) -timeout $(TESTTIMEOUT)
diff --git a/main.telemetry.tf b/main.telemetry.tf
index b8482b25..e57bc039 100644
--- a/main.telemetry.tf
+++ b/main.telemetry.tf
@@ -1,4 +1,4 @@
-data "azurerm_client_config" "telemetry" {
+data "azapi_client_config" "telemetry" {
count = var.disable_telemetry ? 0 : 1
}
diff --git a/modules/budget/main.tf b/modules/budget/main.tf
index 864fa335..c75e6717 100644
--- a/modules/budget/main.tf
+++ b/modules/budget/main.tf
@@ -2,7 +2,7 @@ resource "azapi_resource" "budget" {
type = "Microsoft.Consumption/budgets@2021-10-01"
name = var.budget_name
parent_id = var.budget_scope
- body = jsonencode({
+ body = {
properties = {
amount = var.budget_amount
category = "Cost"
@@ -13,7 +13,5 @@ resource "azapi_resource" "budget" {
startDate = var.budget_time_period.start_date
}
}
- })
+ }
}
-
-
diff --git a/modules/budget/terraform.tf b/modules/budget/terraform.tf
index 60d17dc7..39685a89 100644
--- a/modules/budget/terraform.tf
+++ b/modules/budget/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azapi = {
source = "azure/azapi"
- version = "~> 1.11"
+ version = "~> 1.14"
}
}
}
diff --git a/modules/resourcegroup/main.tf b/modules/resourcegroup/main.tf
index 4589b9bd..6ed72798 100644
--- a/modules/resourcegroup/main.tf
+++ b/modules/resourcegroup/main.tf
@@ -3,6 +3,6 @@ resource "azapi_resource" "rg" {
type = "Microsoft.Resources/resourceGroups@2021-04-01"
name = var.resource_group_name
location = var.location
- body = jsonencode({})
+ body = {}
tags = var.tags
}
diff --git a/modules/resourcegroup/terraform.tf b/modules/resourcegroup/terraform.tf
index ca1472a5..39685a89 100644
--- a/modules/resourcegroup/terraform.tf
+++ b/modules/resourcegroup/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azapi = {
source = "azure/azapi"
- version = "~> 1.13"
+ version = "~> 1.14"
}
}
}
diff --git a/modules/resourceprovider/terraform.tf b/modules/resourceprovider/terraform.tf
index eed9a02c..f8023117 100644
--- a/modules/resourceprovider/terraform.tf
+++ b/modules/resourceprovider/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azapi = {
source = "Azure/azapi"
- version = "~> 1.11"
+ version = "~> 1.14"
}
}
}
diff --git a/modules/roleassignment/terraform.tf b/modules/roleassignment/terraform.tf
index fe670e86..01f91545 100644
--- a/modules/roleassignment/terraform.tf
+++ b/modules/roleassignment/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
- version = "~> 3.7"
+ version = "~> 3.107"
}
}
}
diff --git a/modules/subscription/main.tf b/modules/subscription/main.tf
index 27dc4d41..14d60d99 100644
--- a/modules/subscription/main.tf
+++ b/modules/subscription/main.tf
@@ -23,7 +23,7 @@ resource "azapi_resource" "subscription" {
name = var.subscription_alias_name
parent_id = "/"
- body = jsonencode({
+ body = {
properties = {
displayName = var.subscription_display_name
workload = var.subscription_workload
@@ -33,7 +33,7 @@ resource "azapi_resource" "subscription" {
tags = var.subscription_tags
}
}
- })
+ }
response_export_values = ["properties.subscriptionId"]
lifecycle {
ignore_changes = [
diff --git a/modules/subscription/terraform.tf b/modules/subscription/terraform.tf
index 3eb3935c..dc86a07c 100644
--- a/modules/subscription/terraform.tf
+++ b/modules/subscription/terraform.tf
@@ -1,13 +1,13 @@
terraform {
- required_version = "~> 1.4"
+ required_version = "~> 1.6"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
- version = "~> 3.7"
+ version = "~> 3.107"
}
azapi = {
source = "Azure/azapi"
- version = "~> 1.11"
+ version = "~> 1.14"
}
time = {
source = "hashicorp/time"
diff --git a/modules/usermanagedidentity/main.tf b/modules/usermanagedidentity/main.tf
index 13aed69b..f4ad91b4 100644
--- a/modules/usermanagedidentity/main.tf
+++ b/modules/usermanagedidentity/main.tf
@@ -12,11 +12,11 @@ resource "azapi_resource" "rg_lock" {
type = "Microsoft.Authorization/locks@2020-05-01"
parent_id = one(azapi_resource.rg).id
name = coalesce(var.resource_group_lock_name, "lock-${one(azapi_resource.rg).name}")
- body = jsonencode({
+ body = {
properties = {
level = "CanNotDelete"
}
- })
+ }
depends_on = [
azapi_resource.rg,
azapi_resource.umi,
@@ -33,7 +33,7 @@ resource "azapi_resource" "umi" {
type = "Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31"
name = var.name
parent_id = var.resource_group_creation_enabled ? one(azapi_resource.rg).id : "/subscriptions/${var.subscription_id}/resourceGroups/${var.resource_group_name}"
- body = jsonencode({})
+ body = {}
location = var.location
tags = var.tags
response_export_values = [
@@ -49,13 +49,13 @@ resource "azapi_resource" "umi_federated_credential_github_branch" {
name = coalesce(each.value.name, "github-${each.value.organization}-${each.value.repository}-branch-${each.value.value}")
parent_id = azapi_resource.umi.id
locks = [azapi_resource.umi.id] # Concurrent Federated Identity Credentials writes under the same managed identity are not supported
- body = jsonencode({
+ body = {
properties = {
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${each.value.organization}/${each.value.repository}:ref:refs/heads/${each.value.value}"
}
- })
+ }
}
resource "azapi_resource" "umi_federated_credential_github_tag" {
@@ -79,13 +79,13 @@ resource "azapi_resource" "umi_federated_credential_github_environment" {
name = coalesce(each.value.name, "github-${each.value.organization}-${each.value.repository}-environment-${each.value.value}")
parent_id = azapi_resource.umi.id
locks = [azapi_resource.umi.id] # Concurrent Federated Identity Credentials writes under the same managed identity are not supported
- body = jsonencode({
+ body = {
properties = {
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${each.value.organization}/${each.value.repository}:environment:${each.value.value}"
}
- })
+ }
}
resource "azapi_resource" "umi_federated_credential_github_pull_request" {
@@ -94,13 +94,13 @@ resource "azapi_resource" "umi_federated_credential_github_pull_request" {
name = coalesce(each.value.name, "github-${each.value.organization}-${each.value.repository}-pull-request")
parent_id = azapi_resource.umi.id
locks = [azapi_resource.umi.id] # Concurrent Federated Identity Credentials writes under the same managed identity are not supported
- body = jsonencode({
+ body = {
properties = {
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${each.value.organization}/${each.value.repository}:pull_request"
}
- })
+ }
}
resource "azapi_resource" "umi_federated_credential_terraform_cloud" {
@@ -109,13 +109,13 @@ resource "azapi_resource" "umi_federated_credential_terraform_cloud" {
name = coalesce(each.value.name, "terraformcloud-${each.value.organization}-${each.value.project}-${each.value.workspace}-${each.value.run_phase}")
parent_id = azapi_resource.umi.id
locks = [azapi_resource.umi.id] # Concurrent Federated Identity Credentials writes under the same managed identity are not supported
- body = jsonencode({
+ body = {
properties = {
audiences = ["api://AzureADTokenExchange"]
issuer = "https://app.terraform.io"
subject = "organization:${each.value.organization}:project:${each.value.project}:workspace:${each.value.workspace}:run_phase:${each.value.run_phase}"
}
- })
+ }
}
resource "azapi_resource" "umi_federated_credential_advanced" {
@@ -124,11 +124,11 @@ resource "azapi_resource" "umi_federated_credential_advanced" {
name = each.value.name
parent_id = azapi_resource.umi.id
locks = [azapi_resource.umi.id] # Concurrent Federated Identity Credentials writes under the same managed identity are not supported
- body = jsonencode({
+ body = {
properties = {
audiences = each.value.audiences
issuer = each.value.issuer_url
subject = each.value.subject_identifier
}
- })
+ }
}
diff --git a/modules/usermanagedidentity/terraform.tf b/modules/usermanagedidentity/terraform.tf
index 60d17dc7..39685a89 100644
--- a/modules/usermanagedidentity/terraform.tf
+++ b/modules/usermanagedidentity/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azapi = {
source = "azure/azapi"
- version = "~> 1.11"
+ version = "~> 1.14"
}
}
}
diff --git a/modules/virtualnetwork/main.tf b/modules/virtualnetwork/main.tf
index 0c07bfc7..72cf87de 100644
--- a/modules/virtualnetwork/main.tf
+++ b/modules/virtualnetwork/main.tf
@@ -16,14 +16,13 @@ resource "azapi_resource" "rg_lock" {
type = "Microsoft.Authorization/locks@2017-04-01"
parent_id = azapi_resource.rg[each.key].id
name = coalesce(each.value.lock_name, substr("lock-${each.key}", 0, 90))
- body = jsonencode({
+ body = {
properties = {
level = "CanNotDelete"
}
- })
+ }
depends_on = [
azapi_resource.vnet,
- azapi_update_resource.vnet,
azapi_resource.peering_hub_outbound,
azapi_resource.peering_hub_inbound,
azapi_resource.peering_mesh,
@@ -32,15 +31,14 @@ resource "azapi_resource" "rg_lock" {
}
# azapi_resource.vnet are the virtual networks that will be created
-# lifecycle ignore changes to the body to prevent subnets being deleted
-# see #45 for more information
resource "azapi_resource" "vnet" {
for_each = var.virtual_networks
parent_id = "${local.subscription_resource_id}/resourceGroups/${each.value.resource_group_name}"
- type = "Microsoft.Network/virtualNetworks@2021-08-01"
+ type = "Microsoft.Network/virtualNetworks@2024-01-01"
name = each.value.name
location = coalesce(each.value.location, var.location)
- body = jsonencode({
+ tags = each.value.tags
+ body = {
properties = merge(
{
addressSpace = {
@@ -49,6 +47,7 @@ resource "azapi_resource" "vnet" {
dhcpOptions = {
dnsServers = each.value.dns_servers
}
+ subnets = null
},
each.value.ddos_protection_enabled ? {
ddosProtectionPlan = {
@@ -57,44 +56,14 @@ resource "azapi_resource" "vnet" {
enableDdosProtection = true
} : null
)
- })
- tags = each.value.tags
- lifecycle {
- ignore_changes = [body, tags]
}
+ response_export_values = ["*"]
+
depends_on = [
azapi_resource.rg,
]
}
-# azapi_update_resource.vnet are the virtual networks that will be created
-# This is a workaround for #45 to allow updates to the virtual network
-# without deleting the subnets created elsewhere
-resource "azapi_update_resource" "vnet" {
- for_each = var.virtual_networks
- resource_id = azapi_resource.vnet[each.key].id
- type = "Microsoft.Network/virtualNetworks@2021-08-01"
- body = jsonencode({
- properties = merge(
- {
- addressSpace = {
- addressPrefixes = each.value.address_space
- }
- dhcpOptions = {
- dnsServers = each.value.dns_servers
- }
- },
- each.value.ddos_protection_enabled ? {
- ddosProtectionPlan = {
- id = each.value.ddos_protection_plan_id
- }
- enableDdosProtection = true
- } : null
- )
- tags = each.value.tags
- })
-}
-
# azapi_resource.peering_hub_outbound creates one-way peering from the spoke to the supplied hub virtual network.
# They are not created if the hub virtual network is an empty string.
resource "azapi_resource" "peering_hub_outbound" {
@@ -161,7 +130,7 @@ resource "azapi_resource" "vhubconnection" {
type = "Microsoft.Network/virtualHubs/hubVirtualNetworkConnections@2022-07-01"
parent_id = each.value.vwan_hub_resource_id
name = coalesce(each.value.vwan_connection_name, "vhc-${uuidv5("url", azapi_resource.vnet[each.key].id)}")
- body = jsonencode({
+ body = {
properties = merge({
enableInternetSecurity = each.value.vwan_security_configuration.secure_internet_traffic
remoteVirtualNetwork = {
@@ -180,6 +149,5 @@ resource "azapi_resource" "vhubconnection" {
}
}
})
- })
- ignore_body_changes = each.value.vwan_security_configuration.routing_intent_enabled ? ["properties.routingConfiguration"] : []
+ }
}
diff --git a/modules/virtualnetwork/terraform.tf b/modules/virtualnetwork/terraform.tf
index ff5db750..2aac0e59 100644
--- a/modules/virtualnetwork/terraform.tf
+++ b/modules/virtualnetwork/terraform.tf
@@ -3,7 +3,7 @@ terraform {
required_providers {
azapi = {
source = "azure/azapi"
- version = ">= 1.11.0"
+ version = "~> 1.14"
}
}
}
diff --git a/modules/virtualnetwork/tests/valid.tftest.hcl b/modules/virtualnetwork/tests/valid.tftest.hcl
new file mode 100644
index 00000000..08a6d30c
--- /dev/null
+++ b/modules/virtualnetwork/tests/valid.tftest.hcl
@@ -0,0 +1,44 @@
+mock_provider "azapi" {}
+
+variables {
+ subscription_id = "00000000-0000-0000-0000-000000000000"
+ virtual_networks = {
+ primary = {
+ name = "primary-vnet",
+ address_space = ["192.168.0.0/24"],
+ location = "westeurope",
+ resource_group_name = "primary-rg",
+ }
+ secondary = {
+ name = "secondary-vnet",
+ address_space = ["192.168.1.0/24"],
+ location = "northeurope",
+ resource_group_name = "secondary-rg",
+ }
+ }
+}
+
+run "valid" {
+ command = plan
+
+ assert {
+ condition = alltrue([for k, v in var.virtual_networks : azapi_resource.vnet[k].name == v.name])
+ error_message = "Virtual network names do not match input"
+ }
+ assert {
+ condition = alltrue([for k, v in var.virtual_networks : azapi_resource.vnet[k].location == v.location])
+ error_message = "Virtual network locations do not match input"
+ }
+ assert {
+ condition = alltrue([for k, v in var.virtual_networks : azapi_resource.vnet[k].body.properties.addressSpace.addressPrefixes == v.address_space])
+ error_message = "Virtual network locations do not match input"
+ }
+ assert {
+ condition = alltrue([for k, v in var.virtual_networks : azapi_resource.rg["${k}-rg"].name == v.resource_group_name])
+ error_message = "Resource group names do not match input"
+ }
+ assert {
+ condition = alltrue([for k, v in var.virtual_networks : azapi_resource.rg["${k}-rg"].location == v.location])
+ error_message = "Resource group locations do not match input"
+ }
+}
diff --git a/terraform.tf b/terraform.tf
index cd0b4114..bc627772 100644
--- a/terraform.tf
+++ b/terraform.tf
@@ -1,9 +1,9 @@
terraform {
- required_version = "~> 1.3"
+ required_version = "~> 1.6"
required_providers {
azapi = {
source = "azure/azapi"
- version = "~> 1.4"
+ version = "~> 1.14"
}
modtm = {
source = "azure/modtm"
diff --git a/tests/go.mod b/tests/go.mod
index f0e7cccd..ca321f5d 100644
--- a/tests/go.mod
+++ b/tests/go.mod
@@ -1,6 +1,6 @@
module github.com/Azure/terraform-azurerm-lz-vending/tests
-go 1.21.4
+go 1.22.5
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
diff --git a/tests/virtualnetwork/virtualnetwork_test.go b/tests/virtualnetwork/virtualnetwork_test.go
index 1cc89b13..fb844218 100644
--- a/tests/virtualnetwork/virtualnetwork_test.go
+++ b/tests/virtualnetwork/virtualnetwork_test.go
@@ -16,45 +16,6 @@ const (
moduleDir = "../../modules/virtualnetwork"
)
-// TestVirtualNetworkCreateValid tests the creation of a plan that
-// creates two virtual networks in the specified resource groups.
-func TestVirtualNetworkCreateValid(t *testing.T) {
- t.Parallel()
-
- v := getMockInputVariables()
- test, err := setuptest.Dirs(moduleDir, "").WithVars(v).InitPlanShowWithPrepFunc(t, utils.AzureRmAndRequiredProviders)
- require.NoError(t, err)
- defer test.Cleanup()
-
- resources := []string{
- "azapi_resource.rg[\"primary-rg\"]",
- "azapi_resource.rg[\"secondary-rg\"]",
- "azapi_resource.vnet[\"primary\"]",
- "azapi_resource.vnet[\"secondary\"]",
- "azapi_update_resource.vnet[\"primary\"]",
- "azapi_update_resource.vnet[\"secondary\"]",
- "azapi_resource.rg_lock[\"primary-rg\"]",
- "azapi_resource.rg_lock[\"secondary-rg\"]",
- }
- check.InPlan(test.PlanStruct).NumberOfResourcesEquals(len(resources)).ErrorIsNilFatal(t)
-
- for _, r := range resources {
- check.InPlan(test.PlanStruct).That(r).Exists().ErrorIsNil(t)
- }
-
- // Loop through each virtual network and check the values
- vns := v["virtual_networks"].(map[string]map[string]any)
- for k, v := range vns {
- rgres := fmt.Sprintf("azapi_resource.rg[\"%s-rg\"]", k)
- vnetres := fmt.Sprintf("azapi_resource.vnet[\"%s\"]", k)
- check.InPlan(test.PlanStruct).That(rgres).Key("name").HasValue(v["resource_group_name"]).ErrorIsNil(t)
- check.InPlan(test.PlanStruct).That(rgres).Key("location").HasValue(v["location"]).ErrorIsNil(t)
- check.InPlan(test.PlanStruct).That(vnetres).Key("name").HasValue(v["name"]).ErrorIsNil(t)
- check.InPlan(test.PlanStruct).That(vnetres).Key("location").HasValue(v["location"]).ErrorIsNil(t)
- check.InPlan(test.PlanStruct).That(vnetres).Key("body").Query("properties.addressSpace.addressPrefixes").HasValue(v["address_space"]).ErrorIsNil(t)
- }
-}
-
// TestVirtualNetworkCreateValid tests the creation of a plan that
// creates two virtual networks in the specified resource groups with custom DNS servers.
func TestVirtualNetworkCreateValidWithCustomDns(t *testing.T) {