mulitple json file as inputs throws error for building dashboard - terraform

My main.tf looks like this, Im trying to pass mulitple json files as input into the dashboard resource but running into an error
locals{
json_file = fileset(path.module, "dash/*.json")
json_data = {
for files in local.json_file : files => jsondecode(file(files))
}
}
resource "google_monitoring_dashboard" "dashboards" {
for_each = local.json_data
project = var.monitoring_project
dashboard_json = local.json_data
}
I get the following error
│ Error: Incorrect attribute value type
│
│ on dashboard.tf line 12, in resource "google_monitoring_dashboard" "usecase_dashboards":
│ 12: dashboard_json = local.json_data
│ ├────────────────
│ │ local.json_data is object with 1 attribute "dash/airflow-dashboard.json"
│
│ Inappropriate value for attribute "dashboard_json": string required.

Finally figured it out
locals{
json_file = fileset(path.module, "dash/*.json")
}
resource "google_monitoring_dashboard" "usecase_dashboards" {
for_each = local.json_file
project = var.monitoring_project
dashboard_json =file(each.key)
}
Thanks #marko-e, Your comments provided the hint...

Related

Handling list of maps in for loop in terraform

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]

module. is a object, known only after apply

I'm trying to create a ssm parameter in aws for dyanamo db table with name and arn so it can be referenced by another application. I've tried a few different things but can't figure out what I'm doing wrong here. Can anyone tell me what is wrong here?
Thank you
Here's my main file with the module.
main.tf
locals {
prefix = "/this/is/a/test"
}
module "test_table" {
source = "git#github.com:test/terraform-modules.git//dynamodb"
name = "dynamo-${local.environment}"
ssm_parameter_prefix = local.prefix
tags = {
Environment = local.environment
}
}
resource "aws_ssm_parameter" "table_name" {
provider = aws.east
name = "${local.prefix}/new/table-name"
type = "String"
value = module.test_table.name
}
resource "aws_ssm_parameter" "table_arn" {
provider = aws.east
name = "${local.prefix}/new/table-arn"
type = "String"
value = module.test_table.arn
}
Here is the output
outputs.tf
output "test_table" {
value = module.test_table
}
output "table_arn" {
value = module.test_table.arn
}
output "table_name" {
value = module.test_table.name
}
Terraform Error
│ Error: Unsupported attribute
│
│ on dynamo.tf line, in resource "aws_ssm_parameter" "table_name":
│ 118: value = module.test_table.name
│ ├────────────────
│ │ module.test_table is a object, known only after apply
│
│ This object does not have an attribute named "name".
╵
╷
│ Error: Unsupported attribute
│
│ on dynamo.tf line, in resource "aws_ssm_parameter" "table_arn":
│ 125: value = module.test_table.arn
│ ├────────────────
│ │ module.test_table is a object, known only after apply
│
│ This object does not have an attribute named "arn".
╵
The output blocks you showed declare output values named table_arn and table_name, but your references are to module.test_table.name and module_test.table.arn.
You'll need to either change the output value names to match the references, or change the references to match the output value names. Specifically, you'll need to either remove the table_ prefix from each of your output value names, or add table_ to the front of the references like module.test_table.table_name and module.test_table.table_arn.

terraform Invalid value for "seqs" parameter: all arguments must be lists or tuples; got string

Why i'm not using the ID directly:
I have multiple datalake's where the filesystem is deployed. It throws error "resource not found" during the deployment.
What i'm trying to achieve now:
i am trying to use concat function and create the ID's. which is throwing an error.
module.adlsfs["adlsfilesystem1"].time_sleep.wait_few_mins_fs: Refreshing state... [id=2022-07-23T21:45:55Z]
╷
│ Error: Invalid function argument
│
│ on ../../../tf-core-module/adls/fs/filesystem.tf line 20, in resource "azurerm_storage_data_lake_gen2_filesystem" "storagedlsgen2fs":
│ 20: storage_account_id = concat("/subscriptions/",data.azurerm_subscription.current.id,"/resourceGroups/rsg-test/providers/Microsoft.Storage/storageAccounts/",each.value.staname)
│
│ Invalid value for "seqs" parameter: all arguments must be lists or tuples; got string.
╵
╷
│ Error: Invalid function argument
│
│ on ../../../tf-core-module/adls/fs/filesystem.tf line 20, in resource "azurerm_storage_data_lake_gen2_filesystem" "storagedlsgen2fs":
│ 20: storage_account_id = concat("/subscriptions/",data.azurerm_subscription.current.id,"/resourceGroups/rsg-test/providers/Microsoft.Storage/storageAccounts/",each.value.staname)
│
│ Invalid value for "seqs" parameter: all arguments must be lists or tuples; got string.
data "azurerm_subscription" "current" {
}
locals {
staname = toset([
for pair in sort(var.sta_name) : {
staname = pair
}
])
}
//**********************************************************
// Create File System in Datalake
//**********************************************************
resource "azurerm_storage_data_lake_gen2_filesystem" "storagedlsgen2fs" {
for_each = { for p in local.staname : jsonencode(p) => p }
name = var.adlsfilesystems
storage_account_id = concat("/subscriptions/",data.azurerm_subscription.current.id,"/resourceGroups/resourcegroup/providers/Microsoft.Storage/storageAccounts/",each.value.staname)
}
Is it even possible to use the function here? and how can i solve this.
thank you
I think that instead of concat, you want join:
storage_account_id = join("",["/subscriptions/",data.azurerm_subscription.current.id,"/resourceGroups/resourcegroup/providers/Microsoft.Storage/storageAccounts/",each.value.staname])

Dynamic block of lifecycle_rule not working in terraform 1.0.6

The following block within a google_cloud_storage resource
dynamic "lifecycle_rule" {
for_each = var.bucket_lifecycle_rule
content {
condition {
age = lifecycle_rule.age
with_state = lifecycle_rule.with_state
}
action {
type = lifecycle_rule.type
storage_class = lifecycle_rule.storage_class
}
}
}
with the following variable declaration
variable "bucket_lifecycle_rule" {
description = "Lifecycle rules"
type = list(object({
age = string
with_state = string
type = string
storage_class = string
}))
default = [
{
age = 30
with_state = "ANY"
type = "SetStorageClass"
storage_class = "COLDLINE"
},
{
age = 120
with_state = "ANY"
type = "Delete"
storage_class = ""
},
]
}
errors out as follows:
│ Error: Unsupported attribute
│
│ on main.tf line 18, in resource "google_storage_bucket" "my_bucket":
│ 18: age = lifecycle_rule.age
│
│ This object does not have an attribute named "age".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 19, in resource "google_storage_bucket" "my_bucket":
│ 19: with_state = lifecycle_rule.with_state
│
│ This object does not have an attribute named "with_state".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 22, in resource "google_storage_bucket" "my_bucket":
│ 22: type = lifecycle_rule.type
│
│ This object does not have an attribute named "type".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 23, in resource "google_storage_bucket" "my_bucket":
│ 23: storage_class = lifecycle_rule.storage_class
│
│ This object does not have an attribute named "storage_class".
why is that?
You have to reference the properties from your objects with value:
dynamic "lifecycle_rule" {
for_each = var.bucket_lifecycle_rule
content {
condition {
age = lifecycle_rule.value.age
with_state = lifecycle_rule.value.with_state
}
action {
type = lifecycle_rule.value.type
storage_class = lifecycle_rule.value.storage_class
}
}
}
In the Terraform docs there is a note about this:
The iterator object has two attributes:
key is the map key or list element index for the current element. If
the for_each expression produces a set value then key is identical to value and should not be used.
value is the value of the current element.

Separate structure for variables.tf gets "Object, known only after apply"

I have recently separated terraform files from it's variable file as per below structure
(root)
| main.tf
| users.tf
| roles.tf
├── Configuration (folder)
├──── azure-pipelines.yml
├──── .gitignore
├──── variables.tf
and since then I am getting bellow error messages
│ Error: Unsupported attribute
│
│ on main.tf line 77, in resource "azurerm_key_vault_secret" "primary_account_storage_access_key":
│ 77: name = "${module.variables.storage-account_name}-access-key"
│ ├────────────────
│ │ module.variables is a object, known only after apply
│
│ This object does not have an attribute named "storage-account_name".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 78, in resource "azurerm_key_vault_secret" "primary_account_storage_access_key":
│ 78: value = module.variables.storage-access_key
│ ├────────────────
│ │ module.variables is a object, known only after apply
│
│ This object does not have an attribute named "storage-access_key".
╵
This is how problematic resource "primary_account_storage_access_key" is defined
resource "azurerm_key_vault_secret" "primary_account_storage_access_key" {
depends_on = [azurerm_key_vault_access_policy.terraform_sp_access]
key_vault_id = data.azurerm_key_vault.azvault.id
name = "${module.variables.storage-account_name}-access-key"
value = module.variables.storage-access_key
}
Module is defined as below:
module "variables" {
source = "./Configuration"
}
I have no issue with utilizing the same module in other resources placed in the same file (main.tf)
terraform {
backend "azurerm" {
resource_group_name = module.variables.storage-resource_group_name
storage_account_name = module.variables.storage-storage_account_name
container_name = module.variables.storage-container_name
key = module.variables.storage-key
}
}
Found articles here on the site focusing on the error suggesting
"splat" operator with "toset" / "one" function, however that did not help:
name = "${toset(module.variables[*].storage-account_name)}-access-key"
value = toset(module.variables[*].storage-access_key)
name = "${one(module.variables[*].storage-account_name)}-access-key"
value = one(module.variables[*].storage-access_key)
Content of variables.tf what child module variables uses:
variable "storage-resource_group_name" {
type = string
default = "Reporting-HFM-integration-rg"
}
variable "storage-account_name" {
type = string
default = "reportinghfmintegration"
}
variable "storage-container_name" {
type = string
default = "tfstate-blob"
}
variable "storage-key" {
type = string
default = "terraform.tfstate"
}
variable "storage-access_key" {
type = string
default = "u3K..."
}
variable "keyVault-name" {
type = string
default = "se-dataplat-dwvault-prod"
}
variable "keyVault-resource_group_name" {
type = string
default = "AzureDataPlatform-dwtools-prod-rg"
}
variable "keyVault-id" {
type = string
default = "/subscriptions/23a89ca1-9743-4b3b-b5ff-41cea9985deb/resourceGroups/..."
}

Resources