So I created a module for creating a subnet in terraform:
# modules/azure/subnet.main.tf
resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = var.resource_group_name
virtual_network_name = var.virtual_network_name
address_prefixes = var.subnet_address_prefixes
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies
delegation {
name = var.subnet_delegation_name
service_delegation {
name = var.subnet_service_delegation_name
}
}
}
And then I referenced it in another file to create a 2 subnets:
# ../../../modules/azure/subnet/main.tf
locals {
subnet_suffix = "dev-subnet"
subnet_delegation_name = {
public_1 = "app-service-delegation"
}
subnet_service_delegation_name = {
public_1 = "Microsoft.Web/serverFarms"
}
}
module "subnet_public_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-public-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.dev_resource_group.name
virtual_network_name = data.azurerm_virtual_network.dev_virtual_network.name
subnet_address_prefixes = var.subnet_address_prefixes.public_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.public_1
subnet_delegation_name = local.subnet_delegation_name.public_1
subnet_service_delegation_name = local.subnet_service_delegation_name.public_1
tag_environment = var.tag_environment
}
module "subnet_private_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-private-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.dev_resource_group.name
virtual_network_name = data.azurerm_virtual_network.dev_virtual_network.name
subnet_address_prefixes = var.subnet_address_prefixes.private_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.private_1
tag_environment = var.tag_environment
}
However I do not want the subnet_private_1
module to have the subnet_delegation_name
and subnet_service_delegation_name
variables. So I omitted them in the module block, but when I run terraform plan
I get the error:
│ Error: Missing required argument
│
│ with module.subnet_private_1.azurerm_subnet.subnet,
│ on ../../../modules/azure/subnet/main.tf line 9, in resource "azurerm_subnet" "subnet":
│ 9: name = var.subnet_delegation_name
│
│ The argument "delegation.0.name" is required, but no definition was found.
╵
╷
│ Error: Missing required argument
│
│ with module.subnet_private_1.azurerm_subnet.subnet,
│ on ../../../modules/azure/subnet/main.tf line 12, in resource "azurerm_subnet" "subnet":
│ 12: name = var.subnet_service_delegation_name
│
│ The argument "delegation.0.service_delegation.0.name" is required, but no definition was found.
I have also tried to add the variables and set them to null
but it still didn't work fine:
# ../../../modules/azure/subnet/main.tf
locals {
subnet_suffix = "dev-subnet"
}
module "subnet_public_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-public-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.dev_resource_group.name
virtual_network_name = data.azurerm_virtual_network.dev_virtual_network.name
subnet_address_prefixes = var.subnet_address_prefixes.public_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.public_1
subnet_delegation_name = local.subnet_delegation_name.public_1
subnet_service_delegation_name = local.subnet_service_delegation_name.public_1
tag_environment = var.tag_environment
}
module "subnet_private_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-private-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.dev_resource_group.name
virtual_network_name = data.azurerm_virtual_network.dev_virtual_network.name
subnet_address_prefixes = var.subnet_address_prefixes.private_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.private_1
subnet_delegation_name = var.subnet_delegation_name.private_1
subnet_service_delegation_name = var.subnet_service_delegation_name.private_1
tag_environment = var.tag_environment
}
This is my variables.tf file:
variable "subnet_name" {
type = string
description = "The name of the subnet"
default = "mysubnet"
}
variable "resource_group_name" {
type = string
description = "The name which should be used for this Resource Group."
default = "MyDevRG"
}
variable "virtual_network_name" {
type = string
description = "The name of the virtual network"
default = "my-dev-vnet"
}
variable "subnet_address_prefixes" {
type = map(list(string))
description = "The address prefixes to use for the subnet."
default = {
public_1 = ["10.1.1.0/24"],
private_1 = ["10.1.2.0/24"]
}
}
variable "enforce_private_link_endpoint_network_policies" {
type = map(bool)
description = "Enable or Disable network policies for the private link endpoint on the subnet. Setting this to true will Disable the policy and setting this to false will Enable the policy. Default value is false"
default = {
public_1 = false,
private_1 = true
}
}
variable "subnet_delegation_name" {
type = map(string)
description = "A name for this delegation"
default = {
public_1 = "app-service-delegation",
private_1 = null
}
}
variable "subnet_service_delegation_name" {
type = map(string)
description = "The name of service to delegate to."
default = {
public_1 = "Microsoft.Web/serverFarms",
private_1 = null
}
}
variable "tag_environment" {
type = string
description = "A mapping of tags which should be assigned to the resource."
default = "dev"
}
I got this error:
╷
│ Error: Missing required argument
│
│ with module.subnet_private_1.azurerm_subnet.subnet,
│ on ../../../modules/azure/subnet/main.tf line 9, in resource "azurerm_subnet" "subnet":
│ 9: name = var.subnet_delegation_name
│
│ The argument "delegation.0.name" is required, but no definition was found.
╵
╷
│ Error: Missing required argument
│
│ with module.subnet_private_1.azurerm_subnet.subnet,
│ on ../../../modules/azure/subnet/main.tf line 12, in resource "azurerm_subnet" "subnet":
│ 12: name = var.subnet_service_delegation_name
│
│ The argument "delegation.0.service_delegation.0.name" is required, but no definition was found.
There is also an ongoing conversation here - null value is not treated per docs when passed to modules #24142 as to why null isn't working as per the documentation.
Any help as to how I can go about solving this will be highly appreciated.
CodePudding user response:
In your subnet
module you have delegation
settings block that is not optional, that's why you have to specify subnet_delegation_name
and subnet_service_delegation_name
variables when you call subnet
module in subnet_private_1
and subnet_public_1
.
To make delegation
settings block optional you should use Terraform dynamic Blocks.
Here is an example:
subnet
module with dynamic blocks:
# modules/azure/subnet.main.tf
resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = var.resource_group_name
virtual_network_name = var.virtual_network_name
address_prefixes = var.subnet_address_prefixes
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies
dynamic "delegation" {
for_each = var.delegation_settings
content {
name = delegation.value["subnet_delegation_name"]
service_delegation {
name = delegation.value["subnet_service_delegation_name"]
}
}
}
}
subnet
module variables.tf:
variable "delegation_settings" {
type = list(map(string))
default = []
}
main.tf example:
terraform {
required_version = "~> 1.0.8"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.81.0"
}
}
}
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "main" {
name = var.resource_group_name
}
data "azurerm_virtual_network" "main" {
name = var.virtual_network_name
resource_group_name = data.azurerm_resource_group.main.name
}
locals {
subnet_suffix = "dev-subnet"
delegation_settings = [{
subnet_delegation_name = "app-service-delegation"
subnet_service_delegation_name = "Microsoft.Web/serverFarms"
}]
}
module "subnet_public_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-public-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.main.name
virtual_network_name = data.azurerm_virtual_network.main.name
subnet_address_prefixes = var.subnet_address_prefixes.public_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.public_1
delegation_settings = [
{
subnet_delegation_name = local.delegation_settings[0].subnet_delegation_name
subnet_service_delegation_name = local.delegation_settings[0].subnet_service_delegation_name
}
]
tag_environment = var.tag_environment
}
module "subnet_private_1" {
source = "../../../modules/azure/subnet"
subnet_name = "${var.subnet_name}-private-1-${local.subnet_suffix}"
resource_group_name = data.azurerm_resource_group.main.name
virtual_network_name = data.azurerm_virtual_network.main.name
subnet_address_prefixes = var.subnet_address_prefixes.private_1
enforce_private_link_endpoint_network_policies = var.enforce_private_link_endpoint_network_policies.private_1
tag_environment = var.tag_environment
}
Note: I did not add the subnet_delegation_name
and subnet_service_delegation_name
variables to the variables.tf
example file so that Terraform does not complain about omitting it in the subnet_private_1
module block. I only added them in my variables.tf
module file.