Search code examples
yamlterraformterraform-provider-awsterraform0.12+terraform-template-file

Terraform yaml config


I have the following YAML config file:

AWSConfig:
  conformance_pack_templates:
    - Operational_Best_Practices_test1:
       - excluded_accounts:
           -  "closed"
           -  "staging"
    - Operational_Best_Practices_test2:
        - excluded_accounts:
            -  "opened"

I want to get all the "excluded" accounts id existing in my AWS organization that include the names specified in the lists.
I am using data.aws_organizations_organization.org.accounts to get all the accounts details under the AWS organization.
the data source output is :

  ([{
    "arn" = "arn:aws:organizations::example1:account/f-432145321/example"
    "email" = "test@example.com"
    "id" = "543632464532"
    "name" = "closed"
    "status" = "SUSPENDED"
  },
  {
    "arn" = "arn:aws:organizations::example2:account/f-43214431/example"
    "email" = "test1@example.com"
    "id" = "45321534214"
    "name" = "closed"
    "status" = "SUSPENDED"
  },
])

I need to filter all the accounts with the names specified in the lists, and to get the following list of objects format output:

[ 
  { template = Operational_Best_Practices_test1, 
    excluded_accounts = [ 543632464532, 45321534214, 54325413421 ]},
  { template = Operational_Best_Practices_test2, 
    excluded_accounts = [ 65465554365, 654365436543 ]}
]

Solution

  • You can use a for with a condition and the contains function in order to achieve this.

    Given:

    variable "accounts" {
      default = [{
          "arn" = "arn:aws:organizations::example1:account/f-432145321/example"
          "email" = "test@example.com"
          "id" = "543632464532"
          "name" = "closed"
          "status" = "SUSPENDED"
        },
        {
          "arn" = "arn:aws:organizations::example2:account/f-43214431/example"
          "email" = "test1@example.com"
          "id" = "45321534214"
          "name" = "closed"
          "status" = "SUSPENDED"
        },
        {
          "arn" = "arn:aws:organizations::example3:account/f-43214431/example"
          "email" = "test1@example.com"
          "id" = "45321534215"
          "name" = "opened"
          "status" = "OPENED"
        },
      ]
    }
    
    output "test" {
      value = {
        for rules in "${yamldecode(file("aws_config.yml")).AWSConfig.conformance_pack_templates}" :
          keys(rules).0 => [
            for account in var.accounts : 
              account.id
            if contains(rules[keys(rules).0].0.excluded_accounts, account.name)
          ]
      }
    }
    

    This yields:

    test = {
      "Operational_Best_Practices_test1" = [
        "543632464532",
        "45321534214",
      ]
      "Operational_Best_Practices_test2" = [
        "45321534215",
      ]
    }
    

    This said, if you are the owner of the YAML and you are allowed to change the structure of it a bit, converting some of your lists into dictionaries, like this:

    AWSConfig:
      conformance_pack_templates:
        Operational_Best_Practices_test1:
          excluded_accounts:
            -  "closed"
            -  "staging"
        Operational_Best_Practices_test2:
          excluded_accounts:
            -  "opened"
    

    You can simplify the terraform code by removing the need of the keys function:

    output "test" {
      value = {
        for label, rule in "${yamldecode(file("aws_config.yml")).AWSConfig.conformance_pack_templates}" :
          label => [
            for account in var.accounts : 
              account.id
            if contains(rule.excluded_accounts, account.name)
          ]
      }
    }