We have created some terraform stacks for different domains, like network stack for vpc, rds stack for rds stuff, etc.
And, for instance, the rds stack depends on the network stack to get values from the outputs:
Output from network stack:
output "public_subnets" {
value = aws_subnet.public.*.id
}
output "private_subnets" {
value = aws_subnet.private.*.id
}
output "data_subnets" {
value = aws_subnet.data.*.id
}
... an so on
And the rds stack will tap on the outputs
data "tfe_outputs" "networking" {
organization = "my-tf-cloud-org"
workspace = "network-production-eucentral1"
}
But when I try to use the output:
│
│ on main.tf line 20, in module "db":
│ 20: base_domain = data.tfe_outputs.dns.values.fqdn
│ ├────────────────
│ │ data.tfe_outputs.dns.values has a sensitive value
│
│ This object does not have an attribute named "fqdn".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 22, in module "db":
│ 22: subnets = data.tfe_outputs.networking.values.data_subnets
│ ├────────────────
│ │ data.tfe_outputs.networking.values has a sensitive value
│
│ This object does not have an attribute named "data_subnets".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 23, in module "db":
│ 23: vpc_id = data.tfe_outputs.networking.values.vpc_id
│ ├────────────────
│ │ data.tfe_outputs.networking.values has a sensitive value
│
│ This object does not have an attribute named "vpc_id".
This was working before; it started all of a sudden.
I tried adding the nonsensitive cast, but it does not work.
Any idea?
Update:
I manage to fix the issue. I'm using terraform cloud with a remote state. If you go to your workspace_with_the_output general settings in tf cloud you will find an option called "Remote state sharing".
I added my workspace_which_consume_state on that list and now it's working. Hopefully, this helps
Related
Using resource azurerm_windows_function_app, I am trying to use the ip_restriction block in site_config however upon plan/apply it errors as apparently optional values are required.
All i want to achieve is to Deny all traffic unless from a network/subnet.
The documentation (https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/windows_function_app) states this is possible.
I am using the latest provider version and the latest Terraform version.
Terraform v1.3.7 on windows_amd64 + provider registry.terraform.io/hashicorp/azurerm v3.38.0 + provider registry.terraform.io/hashicorp/template v2.2.0
Code block uploaded to here https://codebeautify.org/cs/c433a9
Doing an apply on the above I get
Error: Incorrect attribute value type │ │ on main.tf line 181, in resource "azurerm_windows_function_app" "windows_function_app": │ 181: ip_restriction = [ { │ 182: action = "Deny" │ 183: virtual_network_subnet_id = data.terraform_remote_state.netsec_outputs.outputs.vnet_subnets_info["APIM"].id │ 184: name = "APIM Access" │ 185: priority = 1 │ 186: } ] │ ├──────────────── │ │ data.terraform_remote_state.netsec_outputs.outputs.vnet_subnets_info["APIM"].id is "/subscriptions/0000000--00000000--00000000/resourceGroups/prt-sit-2-netsec- 01/providers/Microsoft.Network/virtualNetworks/prt-sit-2-vnet/subnets/apim" │ │ Inappropriate value for attribute "ip_restriction": element 0: attributes "headers", "ip_address", and "service_tag" are required
What i expect to happen is it completes a plan and wishes to add the ip_restriction block.
Worked around my issue. If you use a dynamic block with only the elements you wish to use it passes and validates
I have the following locals file. I need to get the child and parent names separately in for each in terraform.
locals:
{
l3_crm:
[
{ parent: "crm", child: ["crm-sap", "crm-sf"] },
{ parent: "fin", child: ["fin-mon"] },
]
}
For the following ou creation code in aws, parent_id needs the parent name from the locals and ou_name needs the corresponding child name iterated.
module "l3_crm" {
source = "./modules/ou"
for_each = { for idx, val in local.l3_crm : idx => val }
ou_name = [each.value.child]
parent_id = module.l2[each.key.parent].ou_ids[0]
depends_on = [module.l2]
ou_tags = var.l2_ou_tags
}
I get the following error:
│ Error: Unsupported attribute
│
│ on main.tf line 30, in module "l3_rnd":
│ 30: parent_id = module.l2[each.key.parent].ou_ids[0]
│ ├────────────────
│ │ each.key is a string, known only after apply
│
│ This value does not have any attributes.
╵
Let me know what I am doing wrong in for loop.
I tried this as well:
module "l3_rnd" {
source = "./modules/ou"
for_each = { for parent, child in local.l3_crm : parent => child }
ou_name = [each.value]
parent_id = module.l2[each.key].ou_ids[0]
depends_on = [module.l2]
ou_tags = var.l2_ou_tags
}
with the local.tf:
locals {
l3_crm = [
{ "rnd" : ["crm-sap", "crm-sf"] },
{ "trade" : ["fin-mon"] }
]
}
I get these errors:
╷
│ Error: Invalid value for module argument
│
│ on main.tf line 28, in module "l3_crm":
│ 28: ou_name = [each.value]
│
│ The given value is not suitable for child module variable "ou_name" defined
│ at modules\ou\variables.tf:1,1-19: element 0: string required.
╵
╷
│ Error: Invalid value for module argument
│
│ on main.tf line 28, in module "l3_crm":
│ 28: ou_name = [each.value]
│
│ The given value is not suitable for child module variable "ou_name" defined
│ at modules\ou\variables.tf:1,1-19: element 0: string required.
╵
╷
│ Error: Invalid index
│
│ on main.tf line 29, in module "l3_crm":
│ 29: parent_id = module.l2[each.key].ou_ids[0]
│ ├────────────────
│ │ each.key is "1"
│ │ module.l2 is object with 2 attributes
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on main.tf line 29, in module "l3_crm":
│ 29: parent_id = module.l2[each.key].ou_ids[0]
│ ├────────────────
│ │ each.key is "0"
│ │ module.l2 is object with 2 attributes
│
│ The given key does not identify an element in this collection value.
╵
time=2022-11-11T13:24:15Z level=error msg=Hit multiple errors:
Hit multiple errors:
exit status 1
With your current structure you can reconstruct the map in your meta-argument like:
for_each = { for l3_crm in local.l3_crm : l3_crm.parent => l3_crm.child }
to access the values of each key in the list element and reconstruct to a map of parent keys and child values.
You can also optimize the structure like:
l3_crm:
[
{ "crm" = ["crm-sap", "crm-sf"] },
{ "fin" = ["fin-mon"] },
]
and then:
for_each = { for parent, child in local.l3_crm : parent => child }
where you cannot simply convert to a set type with toset because set(map) is not allowed as an argument value type.
Either way the references are updated fully accordingly:
ou_name = [each.key]
parent_id = module.l2[each.value].ou_ids[0]
I have been testing out something using the terraform for_each loop method and ran into this error with the local_file resource.
$ cat main.tf
resource "local_file" "pet" {
filename = each.value
for_each = var.filename
}
$ cat variables.tf
variable "filename" {
type = set(string)
default = [
"/home/user/pets.txt",
"/home/user/dogs.txt",
"/home/user/cats.txt"
]
}
when I run terraform plan after init, I see the following errors:
$ terraform plan
╷
│ Error: Invalid combination of arguments
│
│ with local_file.pet,
│ on main.tf line 1, in resource "local_file" "pet":
│ 1: resource "local_file" "pet" {
│
│ "content_base64": one of `content,content_base64,sensitive_content,source` must be specified
╵
╷
│ Error: Invalid combination of arguments
│
│ with local_file.pet,
│ on main.tf line 1, in resource "local_file" "pet":
│ 1: resource "local_file" "pet" {
│
│ "source": one of `content,content_base64,sensitive_content,source` must be specified
╵
╷
│ Error: Invalid combination of arguments
│
│ with local_file.pet,
│ on main.tf line 1, in resource "local_file" "pet":
│ 1: resource "local_file" "pet" {
│
│ "content": one of `content,content_base64,sensitive_content,source` must be specified
╵
╷
│ Error: Invalid combination of arguments
│
│ with local_file.pet,
│ on main.tf line 1, in resource "local_file" "pet":
│ 1: resource "local_file" "pet" {
│
│ "sensitive_content": one of `content,content_base64,sensitive_content,source` must be specified
╵
From the documentation, I can see argument content is optional:
so I am confused with the above error.
Having encountered the same issue while using the count and for_each meta arguments, I resorted to creating a "content" variable with some dummy text and the errors disappeared afterwards.
But why does hashicorp say they (content, sensitive_content etc) are optional, if without them, the config won't run successfully?
I hope this helps!
As the error message says:
one of content,content_base64,sensitive_content,source must be specified
The documentation states for each of content, content_base64, sensitive_content, and source, that they are optional but also that they do conflict with the other three of them, and it also does not specify a default value.
In consequence, you need to specify exactly one of these four arguments.
Also it makes much sense, as you need to define the content of the file you want to be created.
I am trying to read the yaml file and assign value to local variable, below code giving `Invalid index' error. how to fix this error message?
YAML file server.yaml
vm:
- name: vmingd25
- system_cores: 4
Code block
locals {
vm_raw = yamldecode(file("server.yaml"))["vm"]
vm_name= local.vm_raw["name"]
vm_cpu = local.vm_raw["system_cores"]
}
Error message
╷
│ Error: Invalid index
│
│ on main.tf line 16, in locals:
│ 16: vm_name= local.vm_raw["name"]
│ ├────────────────
│ │ local.vm_raw is tuple with 10 elements
│
│ The given key does not identify an element in this collection value: a number is required.
╵
╷
│ Error: Invalid index
│
│ on main.tf line 17, in locals:
│ 17: vm_cpu = local.vm_raw["system_cores"]
│ ├────────────────
│ │ local.vm_raw is tuple with 10 elements
│
│ The given key does not identify an element in this collection value: a number is required.
Your YAML is equivalent to the following JSON:
{
"vm": [
{
"name": "vmingd25"
},
{
"system_cores": 4
}
]
}
As you can see the vm element is a list of objects because you are using the - character. This means you need to either:
Change you YAML to remove the - list definition. e.g.
vm:
name: vmingd25
system_cores: 4
This would turn the list into a dictionary so you could index with the keys as you have done in your question. OR
If you cannot change the YAML then you will need to index with an integer. This might work if your YAML never changes but is definitely not recommended.
I've seen a good amount of posts that talk about passing a module's output into another module. For some reason I can't get this to work.
I can get the output of the module without any issues
$ terraform output
this_sg_id = sg-xxxxxxxxxxxxxxxxx
However, when I call the module in the resource or into another module, it asks me for the Security group ID.
$ terraform plan
var.vpc_security_group_ids
Security Group ID
Enter a value:
Here's my file structure:
── dev
│ └── service
│ └── dev_instance
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
├── modules
│ ├── ec2
│ │ ├── build_ec2.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── sg
│ ├── build_sg.tf
│ ├── outputs.tf
│ └── variables.tf
Not sure if this is correct but in dev/service/dev_instance/main.tf:
module "build_sg" {
source = "../../../modules/sg/"
vpc_id = var.vpc_id
sg_name = var.sg_name
sg_description = var.sg_description
sg_tag = var.sg_tag
sg_tcp_ports = var.sg_tcp_ports
sg_tcp_cidrs = var.sg_tcp_cidrs
sg_udp_ports = var.sg_udp_ports
sg_udp_cidrs = var.sg_udp_cidrs
sg_all_ports = var.sg_all_ports
sg_all_cidrs = var.sg_all_cidrs
}
module "build_ec2" {
source = "../../../modules/ec2/"
vpc_security_group_ids = ["${module.build_sg.this_sg_id}"]
}
In dev/service/dev_instance/output.tf:
output "this_sg_id" {
description = "The security group ID"
value = "${module.build_sg.this_sg_id}"
}
My ec2 module build_ec2.tf file has the following:
resource "aws_instance" "ec2" {
vpc_security_group_ids = ["${module.build_sg.this_sg_id}"]
}
You have a var "vpc_security_group_ids" defined somewhere, I assume in one of your variables.tf files. Terraform doesn't automatically know to fill that in with the output from a module. You need to remove the var definition and just use the module output reference in your template.
Variables are used to pass in values from the command line. They are not tied to module outputs in any way. If you expect values to come from a module you are using then you should not be also defining that value as a variable.
I also think, you need to remove var definition from your variable tf file and use only module output reference.