Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standalone variable validations that can address multiple variables #32792

Closed
DonBower opened this issue Mar 7, 2023 · 3 comments
Closed

Standalone variable validations that can address multiple variables #32792

DonBower opened this issue Mar 7, 2023 · 3 comments
Labels
enhancement new new issue not yet triaged

Comments

@DonBower
Copy link

DonBower commented Mar 7, 2023

Terraform Version

% terraform --version
Terraform v1.0.8
on darwin_amd64

Use Cases

Some input validations are based on multiple variables for example when two separate variables are mutually exclusive or inclusive. Other circumstanes might require an input for one variable if a different value has a specific value.
For a mutually exclusive example, let's look at the AWS resource aws_flow_log. In the Argument Reference, it states:
Note:
One of eni_id, subnet_id, transit_gateway_id, transit_gateway_attachment_id, or vpc_id must be specified.

Currently, we cannot test for this condition with the current validation rule set.

Providing a standalone validation resource, that is checked when all the variables are available to the called module (see apparentlymart's comment), would allow the user to program for such mutually exclusive conditions.

Attempted Solutions

I didn't really try this, because I know it does not work:

variable "vpc_id" {
type = string
default = null
validation { 
    condition       = var.vpc_id != null  && var.subnet_id != null ? false : true
    error_message   = "You can specify vpc_id or subnet_id, but not both."
  }
}

variable "subnet_id" {
type = string
default = null
validation { 
    condition       = var.vpc_id != null  && var.subnet_id != null ? false : true
    error_message   = "You can specify vpc_id or subnet_id, but not both."
  }
}

Proposal

Provide for an standalone validation stanza:

variable "vpc_id" {
  type    = string
  default = null
}

variable "subnet_id" {
  type    = string
  default = null
}

validation { 
  condition       = var.vpc_id != null  && var.subnet_id != null ? false : true
  error_message   = "You can specify vpc_id or subnet_id, but not both."
}

References

@DonBower DonBower added enhancement new new issue not yet triaged labels Mar 7, 2023
@apparentlymart
Copy link
Member

Thanks for this feature request, @DonBower!

It seems like it's describing essentially the same use-case as #25609, albeit with a different proposed solution. Would you agree? If so, I'd prefer to merge this into the other issue just because otherwise it will split the ideas about how to address this and the voting on how many people have the problem over two different issues, making it harder to infer prioritization.

In your particular case I think you could get an effect similar to what you described by using a precondition associated with your aws_flow_log resource:

locals {
  flow_log_mutex_args = tomap({
    eni_id                        = var.eni_id
    subnet_id                     = var.subnet_id
    transit_gateway_id            = var.transit_gateway_id
    transit_gateway_attachment_id = var.transit_gateway_attachment_id 
  })
  flow_log_mutex_args_set = toset([
    for k, v in local.flow_log_mutex_args : k
    if v != null
  ])
}

resource "aws_flow_log" "example" {
  eni_id                        = var.eni_id
  subnet_id                     = var.subnet_id
  transit_gateway_id            = var.transit_gateway_id
  transit_gateway_attachment_id = var.transit_gateway_attachment_id
  # ...
  
  lifecycle {
    precondition {
      condition     = length(var.flow_log_mutex_args) == 1
      error_message = "Must set exactly one of ${join(", ", keys(local.flow_log_mutex_args))}"
    }
  }
}

(This example would be easier to write if there were a helper function for answering questions about how many null values there are in a map, etc, but of course that's a separate question from where to write the rule.)

One notable difference between input variable validation and resource preconditions is that input variable validation is handled during the validate phase (terraform validate) whereas preconditions and postconditions are handled only during the planning phase. But it's being evaluated during the planning phase that gives preconditions their increased flexibility, since they can then rely on other values in the module having already been evaluated upstream as a natural consequence of the plan-building process.

@DonBower
Copy link
Author

DonBower commented Mar 7, 2023

I absolutely agree, same issue, different proposed solution. Feel free to merge.
And thanks for the lifecycle precondition example. I will attempt to merge that into our existing private module.

@apparentlymart
Copy link
Member

I apparently previously forgot to merge this into #25609, so I'm belatedly doing it now.

At the time I'm writing this there's an active language experiment for the other issue, so testing and feedback from that experiment would be very welcome!

@apparentlymart apparentlymart closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement new new issue not yet triaged
Projects
None yet
Development

No branches or pull requests

2 participants