Terraform: empty list comparison does not work if the list contains an object

Created on 4 Dec 2019  路  4Comments  路  Source: hashicorp/terraform

Terraform Version

Terraform v0.12.17

Terraform Configuration Files

Thanks @dpiddockcmp for a simpler example. https://github.com/hashicorp/terraform/issues/23562#issuecomment-562669467

variable "object" {
  type    = list(object({ a = string }))
  default = [] 
}

output "equal" {
  value = var.object == [] ? "empty" : "not empty"
} 

output "not_equal" {
  value = var.object != [] ? "not empty" : "empty"
}

Expected Behavior

Outputs:
equal = empty
not_equal = empty

Actual Behavior

Outputs:
equal = not empty
not_equal = not empty

Steps to Reproduce

terraform init
terraform apply -auto-approve

Solution

variable "object" {
  type    = list(object({ a = string }))
  default = []
}

output "equal" {
  value = length(var.object) == 0 ? "empty" : "not empty"
}

output "not_equal" {
  value = length(var.object) != 0 ? "not empty" : "empty"
}

References


https://github.com/terraform-aws-modules/terraform-aws-eks/pull/606#issuecomment-561795104

config enhancement v0.12

Most helpful comment

Hi @shanmugakarna,

Thanks for filing the issue. The comparison here is failing because the equality operator first compares types.

The type of var.object here (using the internal representation) is cty.List(cty.Object(map[string]cty.Type{"a":cty.String})), while the [] literal is of type cty.EmptyTuple, which do not compare as equal.

The preferred way to check for an empty set or series of any type would be to check its length, rather than compare it against a literal value

value = length(var.object) == 0 ? "empty" : "not empty"

There are however some cases where comparison against a literal value may be quite useful. In these cases we will need to decide on and implement a limited set of automatic type conversion rules for comparing equality.

Related: #21978

All 4 comments

Hi, this is more generic that the reporter implies. Empty list comparison does not work if the list contains an object:

variable "object" {
  type    = list(object({ a = string }))
  default = [] 
}

output "equal" {
  value = var.object == [] ? "empty" : "not empty"
} 

output "not_equal" {
  value = var.object != [] ? "not empty" : "empty"
}
Outputs:
equal = not empty
not_equal = not empty

ok, i was testing only yamlencode, let me change the title. Updating my example with @dpiddockcmp as the his generic example is simple and clear

Hi @shanmugakarna,

Thanks for filing the issue. The comparison here is failing because the equality operator first compares types.

The type of var.object here (using the internal representation) is cty.List(cty.Object(map[string]cty.Type{"a":cty.String})), while the [] literal is of type cty.EmptyTuple, which do not compare as equal.

The preferred way to check for an empty set or series of any type would be to check its length, rather than compare it against a literal value

value = length(var.object) == 0 ? "empty" : "not empty"

There are however some cases where comparison against a literal value may be quite useful. In these cases we will need to decide on and implement a limited set of automatic type conversion rules for comparing equality.

Related: #21978

Hi @jbardin

Thank you. I already have the length solution as part of the issue description. So, if this behaviour is expected, then we can close the issue.

Was this page helpful?
0 / 5 - 0 ratings