Output is not published by a root module

Hello,
it appears that in order to obtain an “output” value from the root module, I have to define it (output) twice. Once in the root and then in the calling module.

Is this an expected behavior and why? I’d think that publishing in the root level should be sufficient…

main.tf:

module  "vm_key" {
  source = "../../../modules/AWS/comp/keys"
...
}
output "vm_key" {
  value = module.vm_key.key_name
}

root module ( …/…/…/modules/AWS/comp/keys/keys.tf) :

resource "aws_key_pair" "vm_key" {
...
}
output "key_name" {
  value = aws_key_pair.vm_key.key_name
}

Log:

terraform apply  -var-file=common.tfvars 
module.vm_key.aws_key_pair.vm_key: Refreshing state... [id=id_XX]

Changes to Outputs:
  + vm_key = "id_XX"

To have an output from your root module (which can be seen using the remote state data source or via terraform output) you need to include an output block within your root module. The associated “value” attribute of the block can reference anything the root module knows about, for example a local, an attribute from a resource defined within the root module or an output from a module called by the root module.

If you have a value that you do want to include in the root module output that comes from a module, that module needs to define an output block itself that exposes whatever value you want. A module is a way of encapsulating code, very similar in concept to a library or class in other programming languages. The only way to transfer data into or out of a module is by that module allowing it, using variable and output blocks within the module code.

Also I’d double check your nomenclature. The root module is the directory containing the Terraform state settings and where you run the Terraform command itself from. I’m not sure from what you posted if that matches with your understanding?

@stuart-c ,
you are right, my nomenclature was incorrect. Thank you for the explanation - I think I understand now.

But something else is missing…
I’m attempting to get the output value from a different workspace in the same org ( TerraformCloud) as per The terraform_remote_state Data Source | Terraform | HashiCorp Developer and Terraform Registry

I do see the “key_name” output in the TFC workspace.
The code :

data tfe_outputs key {
  organization = "XXX"
  workspace = "TheOtherWorkspace"
}


module "vm" {
...
  key_name =  data.tfe_outputs.values.key.values.key_name
...
}

Log:

terraform plan -var-file=../D9.tfvars
data.tfe_outputs.key: Reading...
data.tfe_outputs.key: Read complete after 0s [id=XXXXXXX]
module.vm.data.aws_ami.AM2: Reading...
module.vm.data.aws_ami.AM2: Read complete after 0s [id=QQQQQQQQ]
╷
│ Error: Unsupported attribute
│ 
│   on ec2.tf line 21, in module "vm":
│   21:   key_name =  data.tfe_outputs.key.values.key_name
│ 
│ This object does not have an attribute named "key_name".

Do you mind to point my error, please?

This error suggests that either the root module of TheOtherWorkspace doesn’t have an output "key_name" block, or that you’ve not yet applied the change to add that block to the other workspace and so the value hasn’t been committed in the workspace’s latest state snapshot. (tfe_outputs reads output values from the most recent state snapshot of the workspace).

If you have access to TheOtherWorkspace in the Terraform Cloud UI then you can find a table of all of that workspace’s output values on the main page representing that workspace. Can you see an output value named key_name in the table there?

It tends to be hard to answer questions about interactions between specific Terraform Cloud workspaces in this forum because the contributors here cannot see how you have all of your workspaces set up. This might be a better question for HashiCorp Support, since they can (with your permission) look directly at how you’ve set up your workspaces, whereas in this forum we can only make general guesses about what the problem might be.

yes, it was there.
I just realized that by default the workspace is not sharing outputs. Changing that option solved my little problem.

@apparentlymart and @stuart-c : Thank you for helping me out with this problem! Truly appreciate your time and effort.

A quick question:
is there a way to examine what the return object/value has? As of right now, i’m guessing what the attributes object might have… I’m thinking something like python’s inspect (https://www.codingem.com/inspect-a-python-object/)

Take a look at the terraform output and terraform state show commands. Also terraform console can be useful.

2 Likes

If you’ve already applied at least one plan that included reading that tfe_outputs data source then one way to directly see the effective type (as seen by your downstream configuration) is to run terraform console and use its special type command which is specific to the console only:

type(data.tfe_outputs.key.values)

You can also see the types at the source workspace using commands like what @stuart-c mentioned. But the console technique I’ve described here is something you can do from the workspace that is consuming these outputs, rather than from the workspace that produces them.