jsonterraformavro

Terraform 1.9.8: Variable Validation Condition Always Evaluates True When Referencing Another Variable


I am setting up variable validation for Kafka topic schemas for a Terraform module I am creating.

The schemas can be one of two types: AVRO or JSON. As both schema types are defined in a .json file, I use a variable called scheama_format to determine what type the incoming schema is. The schema itself is provided by a variable called schema_path, pointing to a .json file.

When evaluating if the file given by schema_path is valid, I have to know what type of file it is to know what keys I must check. I have tried many variations, but my current validation condition looks like this:

variable "schema_path" {
  type             = string
  description      = "Relative path to the schema file to upload to the Schema Registry."

  ...

  ###################
  # THIS IS THE VALIDATION THAT IS NOT WORKING
  ###################
  validation {
    conditions     = (var.schema_format != "AVRO") || (jsondecode(file(var.schema_path)).type == "record")
    error_message  = "If schema_format is 'AVRO', the schema file must have a type of 'record'."
  }
}

variable "schema_format" {
  type             = string
  description      = "The type of schema. Must be either 'JSON' or 'AVRO'."
  
  ...
}

No matter what I do, whenever a validation condition includes the value of a different variable, the condition will evaluate as true (and thus the validation will never trigger an error).

Is this a bug in Terraform, or is there something I am missing here?

I have tried en exhaustive number of conditions using a different variable and they all evaluate as true.

Even simple conditions such as:

variable "schema_path" {
  ...

  validation {
    conditions     = (length(var.schema_format) < 0) || (length(var.schema_path) < 0)
    error_message  = "TEST"
  }
}

variable "schema_format" {
  ...
}

To my mind, this condition should evaluate as false no matter what, but it evaluates as true.

If I try:

variable "schema_path" {
  ...

  validation {
    conditions     = false || (length(var.schema_path) < 0)
    error_message  = "TEST"
  }
}

variable "schema_format" {
  ...
}

the condition evaluates as false, but as soon as I use a different variable as part of the condition, it evaluates as true.

If this is the intended behaviour, I do not understand the point of Terraform version 1.9.0 allowing the use of different variables as part of a variable's validation. What am I missing?

EDIT:

For context, this is what a generic version of the schema file:

{
  "type": "record",
  "namespace": "com.mycorp.mynamespace",
  "name": "sampleRecord",
  "doc": "Sample schema to help you get started.",
  "fields": [
    ...
  ]
}

Solution

  • After digging around some more, I ended up adding a lifecycle precondition to my schema resource.

    locals {
      schema     = file(var.schema_path)
      schemaJson = jsondecode(local.schema)
    }
    resource "confluent_schema" "schema" {
      depends_on   = [confluent_kafka_topic.topic]
      subject_name = "${confluent_kafka_topic.topic.topic_name}-value"
      format       = var.schema_format
      schema       = local.schema
    
    
      lifecycle {
        precondition {
          condition     = var.schema_format != "AVRO" || jsondecode(local.schema).type == "record"
          error_message = "Schema must be a valid AVRO schema. Key 'Type' must have value 'record'"
        }
      }
    }
    

    Using a precondition means that an error will be thrown if the condition is not met. Unfortunatley, this block will only run during terraform plan and terraform apply, meaning that terraform validate will no longer run all the validation logic.


    This is a workaround that will be fine for my use case, but the central question still stands:

    Why does using other variables in a variable's validate block cause the condition to always evaluate to true?

    I feel like I am still missing something. Either this is a bug in Terraform or I am missing something with how this functionality is intended to be used.