简体   繁体   中英

How can I leverage for_each to shorten my Terraform code?

I would like to create a set of Azure policies and add them to an initiative using Terraform.

The way I have set up my architecture/structure however feels wrong, as I have to repeat myself over and over again. There are going to be a lot more instances (like module "resource-group-policy" {} ) of my policy-module . Currently, I also have to add a policy_definition_reference for each of the policy resources.

My first approach was to come up with an additional module that bundles similar instances of my policy-module together. This way my main.tf become a lot shorter and readable, however, it almost doubled my code, as I had to introduce an output var for each of my submodules to output the policies id.

Is there a way I can leverage for example the for_each statement to significantly shorten my terraform code?

./policy-module/main.tf

terraform {
   # ...
}

resource "azurerm_policy_definition" "policy" {
    # ...
}

./policy-module/output.tf

output "id" {
    value = azurerm_policy_definition.policy.id
}

./policy-module/variables.tf

variable "pattern" {
    type = string
}

# ...

./main.tf

terraform {
  # ...
}

provider "azurerm" {
  # ...
}

resource "azurerm_policy_set_definition" "initiative" {    
    # ...

    policy_definition_reference {
      policy_definition_id = module.management-group-policy.id
    }

    policy_definition_reference {
      policy_definition_id = module.resource-group-policy.id
    }

    # ...    
}
    
module "management-group-policy" {
    source = "./policy-module"

    pattern = "mg-*"
    type = "Microsoft.Management/managementGroups"
    display_name = "Management Groups"
}

module "resource-group-policy" {
    source = "./policy-module"

    pattern = "rg-*"
    type = "Microsoft.Resources/resourceGroups"
    display_name = "Resource Groups"
}

# many more variations of modul

Start with something like this:

module "policies" {
    source = "./policy-module"

    for_each = {
        rg = {
            pattern = "rg-*",
            type = "Microsoft.Resources/resourceGroups",
            display_name = "Resource Groups"
        },
        mg = {
            pattern = "mg-*",
            type = "Microsoft.Management/managementGroups",
            display_name = "Management Groups"
        }
    }

    pattern = each.value.pattern
    type = each.value.type
    display_name = each.value.display_name
}

Your azurerm_policy_set_definition is actually the trickier one:

resource "azurerm_policy_set_definition" "initiative" {    
    # ...

    policy_definition_reference {
        for_each = module.policies

        policy_definition_id = each.key.id
    }
}

I'm not 100% sure about this, have a play around but the essence being that you need to iterate again over the policies which you created above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM