I have two use-cases
- I am trying to create a local variable from Datasource output. During terraform plan the local variable is failing with null data.
data "google_compute_subnetwork" "gke_subnet" {
for_each = { for x in var.cloudamqp_vpc_peerings : "${x.subnet_name}" => x }
region = lookup(each.value,"subnet_region",var.cloudamqp_provider_region)
name = each.value.subnet_name
}
locals {
subnet_values = data.google_compute_subnetwork.gke_subnet
primary_range_firewall_rules = distinct(flatten([
for x,y in local.subnet_values
: { name = x, cidr_range = y.ip_cidr_range, protocols = ["AMQP", "AMQPS"], ports = [15672] }
]))
secondary_range_firewall_rules = distinct(flatten([
for x in var.cloudamqp_vpc_peerings
: [
for y in local.subnet_values[x.subnet_name].secondary_ip_range
: { name = y.range_name, cidr_range = y.ip_cidr_range, protocols = ["AMQP", "AMQPS"], ports = [15672] }
]
]))
}
local.subnet_values is object with 2 attributes
| x.subnet_name is "scanfarm-infra-subnet1"
A null value cannot be used as the collection in a 'for' expression.
- I have an output dependent on a datasource. After the first tf apply the output will be null. Once the data source is computed and added to tf statefile, Output will be added on the second run.
output "username" {
value = data.cloudamqp_credentials.credentials.username
}
output "password" {
value = data.cloudamqp_credentials.credentials.password
sensitive = true
}
Hi @gdineshkumar627,
That appears to be a problem with the cloudamqp_credentials
data source. It sounds like the provider is not consistently returning values for the fields you are accessing, and I would file and issue with the provider.
@jbardin Thanks for the quick response.
I do have an issue with google Datasource.
data "google_compute_subnetwork" "gke_subnet" {
for_each = { for x in var.cloudamqp_vpc_peerings : "${x.subnet_name}" => x }
region = lookup(each.value,"subnet_region",var.cloudamqp_provider_region)
name = each.value.subnet_name
}
OK, you seem to have 2 unrelated problems here. I’m not sure what is incorrect with the google_compute_subnetwork
configuration from the little shown here. It would help to have a more complete reproduction, showing the variables and types of values expected, and the complete context of the error to show exactly which expression is failing.
I am trying to create a loca variable (type: list of maps) from the google_compute_subnetwork
data source output.
datasource block
data "google_compute_subnetwork" "gke_subnet" {
for_each = { for x in var.cloudamqp_vpc_peerings : "${x.subnet_name}" => x }
region = lookup(each.value,"subnet_region",var.cloudamqp_provider_region)
name = each.value.subnet_name
}
Local variables block
locals {
subnet_values = data.google_compute_subnetwork.gke_subnet
primary_range_firewall_rules = distinct(flatten([
for x,y in local.subnet_values
: { name = x, cidr_range = y.ip_cidr_range, protocols = ["AMQP", "AMQPS"], ports = [15672] }
]))
secondary_range_firewall_rules = distinct(flatten([
for x in var.cloudamqp_vpc_peerings
: [
for y in local.subnet_values[x.subnet_name].secondary_ip_range
: { name = y.range_name, cidr_range = y.ip_cidr_range, protocols = ["AMQP", "AMQPS"], ports = [15672] }
]
]))
}
Issue:
Datasource is returning null data, the local variables are trying to iterate over that and failing
Failed expression : for y in local.subnet_values[x.subnet_name].secondary_ip_range
local.subnet_values is object with 2 attributes
| x.subnet_name is "scanfarm-infra-subnet1"
A null value cannot be used as the collection in a 'for' expression.
The error indicates that local.subnet_values[x.subnet_name].secondary_ip_range
is null
, which is not valid in a for
expression. If this is something which is expected to never be null, that may be an issue with the provider. If null
is a possible value in this case, you will need to make the it conditional at some point. Either using something like
local.subnet_values[x.subnet_name].secondary_ip_range == null ? [] : ...
Or wrapping it in try, and returning an empty collection if it fails.
try([ for y in local.subnet_values[x.subnet_name].secondary_ip_range
: { name = y.range_name, cidr_range = y.ip_cidr_range, protocols = ["AMQP", "AMQPS"], ports = [15672] }
], [])