skip to Main Content

I am working with a test Terraform Stacks build, creating a resource group and then placing some resources in it. Each resource is created with a separate module, so one for the resource group, another for vnet, subnet, etc. When I reference another component during build, eg the name of the resource group to place a vnet, I’m receiving the error "unsupported attribute – this object does not have an attribute named "resource_group_name"".

# input vars:
location = {
    dev = ["eastus2",]
    stage = ["eastus2",]
    prod = ["centralus","westus"]
}
environment = "dev"
app_name = "app1"

# components.tfstack.hcl:
component "rg" {
  for_each = var.location

  source = "./modules/rg"
  inputs = {
    name      = "${each.value}-${var.environment}-${var.app_name}-rg"
    location  = each.value
    tags      = var.tags
  }

  providers = {
    azurerm = provider.azurerm.this
  }
}

component "vnet" {
  for_each = var.location

  source = "./modules/vnet"
  inputs = {
    name                = "${each.value}-${var.environment}-${var.app_name}-vnet"
    location            = each.value
    resource_group_name = component.rg.resource_group_name
    address_space       = var.vnet_address_space
    tags                = var.tags
  }

  providers = {
    azurerm = provider.azurerm.this
  }
}

# resource group module:
resource "azurerm_resource_group" "rg" {
    name = var.name
    location = var.location

    tags = var.tags
}

output "resource_group_name" {
  value = azurerm_resource_group.rg.name
}

The plan shows the correct resource group name being created and Hashicorp code examples seem to support my syntax. Outputting the "name" property string from the resource group creation module should be referenced with "component.other component name.output string name", am I missing something or doing it wrong?

2

Answers


  1. Terraform stacks component reference to module output error: "unsupported attribute"

    Issue seems to be with the way you declaring the name property in resource group module.

    You should used in such a way that the output is refered properly as mentioned module.rg[each.key].resource_group_name in your vnet module configuration.

    Demo configuration:

    variable "location" {
      type = map(list(string))
      default = {
        dev   = ["eastus2"]
        stage = ["eastus2"]
        prod  = ["centralus", "westus"]
      }
    }
    
    variable "environment" {
      type    = string
      default = "dev"
    }
    
    .
    .
    module "rg" {
      source = "./modules/rg"
    
      for_each = { for k, v in var.location : k => v }
    
      name      = "${each.value[0]}-${var.environment}-${var.app_name}-rg"
      location  = each.value[0]
      tags      = var.tags
    }
    
    
    module "vnet" {
      source = "./modules/vnet"
    
      for_each = { for k, v in var.location : k => v }
    
      name                = "${each.value[0]}-${var.environment}-${var.app_name}-vnet"
      location            = each.value[0]
      resource_group_name = module.rg[each.key].resource_group_name
      address_space       = ["10.0.0.0/16"]
      tags                = var.tags
    }
    

    module/rg:

    resource "azurerm_resource_group" "rg" {
      name     = var.name
      location = var.location
      tags     = var.tags
    }
    
    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    

    module/vnet:

    resource "azurerm_virtual_network" "vnet" {
      name                = var.name
      location            = var.location
      resource_group_name = var.resource_group_name
      address_space       = var.address_space
      tags                = var.tags
    }
    

    Deployment:

    enter image description here

    enter image description here

    Refer:

    https://developer.hashicorp.com/terraform/language/modules/develop

    The for_each Meta-Argument – Configuration Language | Terraform | HashiCorp Developer

    Output Values – Configuration Language | Terraform | HashiCorp Developer

    Terraform referencing output from another module with for_each – Stack Overflow answered by charles-xu

    Login or Signup to reply.
  2. Your component "rg" block includes the for_each argument, which means that component.rg appears in expressions elsewhere as a map of objects whose keys match the keys in var.location. To refer to a specific instance of that component you need to select a specific object from that map using the index syntax, with [ ] brackets.

    Since you are using the same for_each in component "vnet" I assume your intention is to have the vnet instances matched to the rg instances where the keys match, in which case you can use each.key to refer to the key of the current instance of component "vnet", and thus find the matching instance of component "rg":

      resource_group_name = component.rg[each.key].resource_group_name
    

    Because Stacks is relatively new the documentation on these features is not yet as comprehensive as for the traditional Terraform modules language, but for for_each with components in particular the language design is very similar to how for_each behaves for module block in the traditional Terraform language, and so the documentation on referring to instances is also largely relevant to components except that you’d use the prefix component. instead of the prefix module..

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search