Computed attributes cannot be set : org_id - terraform

I am learning how to use Terraform. My aim is to deploy an architecture on GCP so here's my main.tf so far :
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.85.0"
}
}
}
provider "google" {
credentials = file(var.credentials_file)
region = var.region
zone = var.zone
}
data "google_organization" "org" {
domain = var.organization.display_name
org_id = var.organization.id
directory_customer_id = var.organization.directory_customer_id
}
resource "google_folder" "shared" {
display_name = "Shared"
parent = google_organization.org_id
}
resource "google_folder" "ddm" {
display_name = "Data and Digital Marketing"
parent = google_folder.shared.name
}
resource "google_folder" "dtl" {
display_name = "DTL"
parent = google_folder.ddm.name
}
According to the documentation, org_id is within the Attributes Reference
But I get the following errors:
╷
│ Error: Computed attributes cannot be set
│
│ with data.google_organization.org,
│ on main.tf line 17, in data "google_organization" "org":
│ 17: org_id = var.organization.id
│
│ Computed attributes cannot be set, but a value was set for "org_id".
╵
╷
│ Error: Computed attributes cannot be set
│
│ with data.google_organization.org,
│ on main.tf line 18, in data "google_organization" "org":
│ 18: directory_customer_id = var.organization.directory_customer_id
│
│ Computed attributes cannot be set, but a value was set for "directory_customer_id".
╵
╷
│ Error: Reference to undeclared resource
│
│ on main.tf line 22, in resource "google_folder" "shared":
│ 22: parent = google_organization.org_id
│
│ A managed resource "google_organization" "org_id" has not been declared in the root module.
What am I doing wrong?

The organization is set as a data source, but in the previous code, it is used like a resource block.
What needs to be done to reference the organization is this :
data "google_organization" "org" {
organization = var.organization.id
}
org_id is an output, not an input. The only acceptable inputs are organization ordomain; they are mutually exclusive.
And use its outputs like this :
resource "google_folder" "shared" {
display_name = "Shared"
parent = data.google_organization.org.org_id
}
EDIT : This, although syntactically correct, it might not work because the account used must be organization administrator on the organization level. I do not recomment using the google_organization data sourcejust to fetch the ID and other info, I ended up writing those in a variable and just calling it this way :
resource "google_folder" "shared" {
display_name = "Shared"
parent = "organizations/${var.organization.id}"
}

Related

Migrating Azure Key Vault secrets from one Azure subscription to another

I have multiple Azure subscriptions, and I'm working on getting the key vault from one to another. I've written a terraform program to do this. Here I'm calling the data blocks and using for each loop condition from one subscription and using the output value of those as input values in another subscription. But I'm getting the error please help. Below is the code
data "azurerm_key_vault" "ewo1" {
provider = azurerm.demo-eworx-terraform-automation
name = "demo-eworx-keyvault"
resource_group_name = "demo-eworx-rg"
}
output "vault_uri_ewo1" {
value = data.azurerm_key_vault.ewo1.vault_uri
}
data "azurerm_key_vault_secret" "ewo1" {
provider = azurerm.demo-eworx-terraform-automation
for_each = toset(["demo-eworx-terraform-automation-client-secret", "demo-eworx-terraform-automation-client-id", "demo-eworx-terraform-automation-tenant-id", "demo-eworx-terraform-automation-subscription-id"])
name = each.key
key_vault_id = data.azurerm_key_vault.ewo1.id
}
output "secret_value" {
value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
}
data "azurerm_key_vault" "ewo11" {
provider = azurerm.terraform-automation
name = "demo-bteb-keyvault"
resource_group_name = "bteb-demo-work"
}
output "vault_uri_ewo11" {
value = data.azurerm_key_vault.ewo11.vault_uri
}
resource "azurerm_key_vault_secret" "ewo11" {
provider = azurerm.terraform-automation
for_each = toset(["demo-eworx-terraform-automation-client-secret", "demo-eworx-terraform-automation-client-id", "demo-eworx-terraform-automation-tenant-id", "demo-eworx-terraform-automation-subscription-id"])
name = each.key
value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
key_vault_id = data.azurerm_key_vault.ewo11.id
}
I need to migrate azure key vaults secrets from one subscription to another subscription. I have written the above terraform code, I'm passing the data "azurerm_key_vault" "ewo1" output value as resource "azurerm_key_vault_secret" "ewo11" value input. But getting below error.
Can some check and help me in solving the issue
error message:
Error: Incorrect attribute value type
│
│ on demo-keyvault-migration.tf line 38, in resource "azurerm_key_vault_secret" "ewo11":
│ 38: value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
│ ├────────────────
│ │ data.azurerm_key_vault_secret.ewo1 is object with 4 attributes
│
│ Inappropriate value for attribute "value": string required.
╵
╷
│ Error: Incorrect attribute value type
│
│ on demo-keyvault-migration.tf line 38, in resource "azurerm_key_vault_secret" "ewo11":
│ 38: value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
│ ├────────────────
│ │ data.azurerm_key_vault_secret.ewo1 is object with 4 attributes
│
│ Inappropriate value for attribute "value": string required.
╵
╷
│ Error: Incorrect attribute value type
│
│ on demo-keyvault-migration.tf line 38, in resource "azurerm_key_vault_secret" "ewo11":
│ 38: value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
│ ├────────────────
│ │ data.azurerm_key_vault_secret.ewo1 is object with 4 attributes
│
│ Inappropriate value for attribute "value": string required.
╵
╷
│ Error: Incorrect attribute value type
│
│ on demo-keyvault-migration.tf line 38, in resource "azurerm_key_vault_secret" "ewo11":
│ 38: value = [ for secret in data.azurerm_key_vault_secret.ewo1 : secret.name]
│ ├────────────────
│ │ data.azurerm_key_vault_secret.ewo1 is object with 4 attributes
│
╵
There are a couple of issues here, but the primary one is related to the azurerm_key_vault_secret data source. You are querying the data source while using for_each. That means that the result will be an object with key value pairs. That is why you are getting this in the output:
data.azurerm_key_vault_secret.ewo1 is object with 4 attributes
as in for_each you will use four keys:
for_each = toset(["demo-eworx-terraform-automation-client-secret", "demo-eworx-terraform-automation-client-id", "demo-eworx-terraform-automation-tenant-id", "demo-eworx-terraform-automation-subscription-id"])
The easiest and probably the cleanest way to fix the error is as follows:
resource "azurerm_key_vault_secret" "ewo11" {
provider = azurerm.terraform-automation
for_each = data.azurerm_key_vault_secret.ewo1
name = each.key
value = each.value.value
key_vault_id = data.azurerm_key_vault.ewo11.id
}
Here it is a bit unfortunate that each.value.value [1] has to be used due to the attribute naming, but there is not another way. Also, please make sure you understand how the for_each meta-argument [2] works.
[1] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret#value
[2] https://developer.hashicorp.com/terraform/language/meta-arguments/for_each

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.

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/..."
}

Terraform aks module - get cluster name and resource group name via remote state

Hi I am trying to follow this offical guide to manage aks resources. There terraform_remote_state is used to get the resource_group_name and kubernetes_cluster_name.
data "terraform_remote_state" "aks" {
backend = "local"
config = {
path = "/path/to/base/project/terraform.tfstate"
}
}
# Retrieve AKS cluster information
provider "azurerm" {
features {}
}
data "azurerm_kubernetes_cluster" "cluster" {
name = data.terraform_remote_state.aks.outputs.kubernetes_cluster_name
resource_group_name = data.terraform_remote_state.aks.outputs.resource_group_name
}
I have created the inital aks cluster with the aks module. Looking at its output in the documentation, it doesnt export the resource group name or cluster name.
Now I wonder how I can get the information. I have tried the below in the base project.
module "aks" {
...
}
output "resource_group_name" {
value = module.aks.resource_group_name
}
output "kubernetes_cluster_name" {
value = module.aks.cluster_name
}
But I get erros when trying terraform plan
Error: Unsupported attribute
│
│ on main.tf line 59, in output "resource_group_name":
│ 59: value = module.aks.resource_group_name
│ ├────────────────
│ │ module.aks is a object, known only after apply
│
│ This object does not have an attribute named "resource_group_name".
╵
╷
│ Error: Unsupported attribute
│
│ on main.tf line 63, in output "kubernetes_cluster_name":
│ 63: value = module.aks.cluster_name
│ ├────────────────
│ │ module.aks is a object, known only after apply
│
│ This object does not have an attribute named "cluster_name".
Those are listed under inputs for that module though. Now I dont have an idea know how to get those values from the terraform_remote_state.
As the module itself doesn’t have name and resource group as output , we have to declare outputs there first and then call it while deploying or in remote state as well.
So we have to add 2 outputs in output.tf for aks module after doing terraform init.
output "kubernetes_cluster_name" {
value = azurerm_kubernetes_cluster.main.name
}
output "resource_group_name" {
value = azurerm_kubernetes_cluster.main.resource_group_name
}
Then call outputs in main.tf after defining the modules i.e. network and aks , you can see your Kubernetes cluster name in plan as well and after applying it.
output "kuberneteclustername" {
value = module.aks.kubernetes_cluster_name
}
output "resourcegroupname" {
value = module.aks.resource_group_name
}
Now lets test it from the remote state :
data "terraform_remote_state" "aks" {
backend = "local"
config = {
path = "path/to/terraform/aksmodule/terraform.tfstate"
}
}
# Retrieve AKS cluster information
provider "azurerm" {
features {}
}
data "azurerm_kubernetes_cluster" "cluster" {
name = data.terraform_remote_state.aks.outputs.kuberneteclustername
resource_group_name = data.terraform_remote_state.aks.outputs.resourcegroupname
}
output "aks" {
value = data.azurerm_kubernetes_cluster.cluster.name
}
output "rg" {
value = data.azurerm_kubernetes_cluster.cluster.resource_group_name
}

Output CSV file using terraform

I'm trying to use terraform variable data (CSV file) to create a resource group and the name of the resource group are added into the CSV file.
I'm currently experiencing the below error.
provider "azurerm" {
features{}
}
locals {
resource_groupname = csvdecode(file("./test.csv"))
}
resource "azurerm_resource_group" "Main" {
count = length(locals.resource_groupname)
name = locals.resource_groupname[count.index].groupname
location = "North europe"
}
Error Message
Error: Reference to undeclared resource
│
│ on testvariable.tf line 10, in resource "azurerm_resource_group" "Customer11":
│ 10: count = length(locals.groupname)
│
│ A managed resource "locals" "groupname" has not been declared in the root module.
╵
╷
│ Error: Reference to undeclared resource
│
│ on testvariable.tf line 11, in resource "azurerm_resource_group" "Customer11":
│ 11: name = data.locals.groupname[count.index].groupname
│
│ A data resource "locals" "groupname" has not been declared in the root module.
╵
Updated Error Messgae
╷
│ Error: Reference to undeclared resource
│
│ on testtf.tf line 10, in resource "azurerm_resource_group" "Main":
│ 10: count = length(locals.resource_groupname)
│
│ A managed resource "locals" "resource_groupname" has not been declared in the root module.
╵
╷
│ Error: Reference to undeclared resource
│
│ on testtf.tf line 11, in resource "azurerm_resource_group" "Main":
│ 11: name = locals.resource_groupname[count.index].groupname
│
│ A managed resource "locals" "resource_groupname" has not been declared in the root module.
Your code should be (assuming this time you posted correct code):
resource "azurerm_resource_group" "Main" {
count = length(local.resource_groupname)
name = local.resource_groupname[count.index].groupname
location = "North europe"
}
Since ./test.csv is not shown its difficult to speculate on its content and the use in your code.
Suppose your CSV file has headers like
name, location, ABC, XXY, CDF, your
then you use for_each as well here
locals {
resource_groupname = csvdecode(file("./test.csv"))
}
resource "azurerm_resource_group" "Main" {
for_each = { for inst in locals.resource_groupname) : inst.location=> inst
}
name = each.value.name
location = each.value.location
}

Resources