Answers: <p>When validating an input variable of a collection type, we typically want to write a validation rule that tests if something is true for each value within the collection, rather than true of the collection as a whole.</p>
  <p>You can write a &quot;for each&quot; sort of condition using Terraform's <a href="https://www.terraform.io/docs/configuration/expressions/for.html" rel="nofollow noreferrer"><code>for</code> expressions</a>. If you are using Terraform v0.14 or later then you can write it concisely using <a href="https://www.terraform.io/docs/configuration/functions/alltrue.html" rel="nofollow noreferrer">the <code>alltrue</code> function</a> along with a <code>for</code> expression that produces a true or false result for each of the items, like this:</p>
  <pre><code>  validation {
      condition = alltrue([
        for id in var.security_groups : can(regex(&quot;^sg-&quot;, id))
      ])
      error_message = &quot;All security group ids must start with \&quot;sg-\&quot;.&quot;
    }
  </code></pre>
  <hr />
  <p>If you are using Terraform v0.13 then you won't have the <code>alltrue</code> function available to you yet, but you can get a similar result in a clunkier way by using the optional <code>if</code> clause of a <code>for</code> expression to filter out all of the valid ids and then checking whether the resulting list is empty -- that is, whether there are any remaining items that were <em>not</em> valid:</p>
  <pre><code>  validation {
      condition = length([
        for id in var.security_groups : id
        if !can(regex(&quot;^sg-&quot;, id))
      ]) == 0
      error_message = &quot;All security group ids must start with \&quot;sg-\&quot;.&quot;
    }
  </code></pre>
  <p>This second example is a bit more cryptic to understand because it's using some language features in an atypical way, so I'll break it down into smaller parts to explain:</p>
  <ul>
  <li><code>[for id in var.security_groups : id if !can(regex(&quot;^sg-&quot;, id))]</code> filters the elements of <code>var.security_groups</code> to keep only the ones where the expression is true.</li>
  <li><code>!can(regex(&quot;^sg-&quot;, id))</code> uses the <code>!</code> operator to turn your original expression that decides if the value is <em>valid</em> into an expression which decides if the value is <em>invalid</em>. Consequently the result of the <code>for</code> expression will be empty unless there's at least one invalid value.</li>
  <li>Finally, the <code>length( ... ) == 0</code> around the <code>for</code> expression says that the value is only valid if filtering out all of the valid values produces an empty list, which conversely means that the list didn't contain any invalid values.</li>
  </ul>
  
Answers: CC BY-SA 4.0
Answers: 2021-01-06T13:57:33.237Z
Answers: thanks for help.
Answers: Vader
Answers: CC BY-SA 4.0
Answers: 2021-01-06T00:55:15.363Z
Answers: 2021-01-06T17:27:23.473Z
Answers: 2021-01-06T17:27:23.473Z
Answers: Martin Atkins
Body: <p>is it possible to use validation of a variable type equals list(string)?</p>
  <p>My example:</p>
  <p><strong>main.tf</strong></p>
  <pre><code>  name            = &quot;tf-prd-sg-foo&quot;
    image_id        = &quot;ami-00e788542ee66c64f&quot;
    instance_type   = &quot;m5.xlarge&quot;
    security_groups = [&quot;sg-000000&quot;, &quot;sg-00000000&quot;] # Example of SG only to contextualize
  }
  </code></pre>
  <p><strong>vars.tf</strong></p>
  <pre><code>variable &quot;security_groups&quot;  {
      type        = list(string)
      default     = [] 
      description = &quot;(Optional) A list of associated security group IDS.&quot;
  
      validation {
        condition = can(regex(&quot;^sg-&quot;, var.security_groups))
        error_message = &quot;The Security Groups need starts to \&quot;sg-\&quot;.&quot;
      }
  }
  </code></pre>
  <p>When I try execute returns the following error:</p>
  <pre><code>[terragrunt] 2021/01/05 17:12:10 Running command: terraform plan
  
  Error: Invalid value for variable
  
    on vars.tf line 21:
    21: variable &quot;security_groups&quot;  {
  
  The Security Groups need starts to &quot;sg-&quot;.
  
  This was checked by the validation rule at vars.tf:26,5-15.
  
  [terragrunt] 2021/01/05 17:12:12 Hit multiple errors:
  exit status 1
  
  
  </code></pre>
  
Tags: <terraform><terragrunt><aws-security-group>
Title: Terraform variable Validation
UserDisplayName: Vader
ThreadText: # Terraform variable Validation
  
  (Asked by: username_0 on 2021-01-05)
  
  is it possible to use validation of a variable type equals list(string)?
  
  My example:
  
  **main.tf**
  
  ```
    name            = "tf-prd-sg-foo"
    image_id        = "ami-00e788542ee66c64f"
    instance_type   = "m5.xlarge"
    security_groups = ["sg-000000", "sg-00000000"] # Example of SG only to contextualize
  }
  
  ```
  
  **vars.tf**
  
  ```
  variable "security_groups"  {
      type        = list(string)
      default     = [] 
      description = "(Optional) A list of associated security group IDS."
  
      validation {
        condition = can(regex("^sg-", var.security_groups))
        error_message = "The Security Groups need starts to \"sg-\"."
      }
  }
  
  ```
  
  When I try execute returns the following error:
  
  ```
  [terragrunt] 2021/01/05 17:12:10 Running command: terraform plan
  
  Error: Invalid value for variable
  
    on vars.tf line 21:
    21: variable "security_groups"  {
  
  The Security Groups need starts to "sg-".
  
  This was checked by the validation rule at vars.tf:26,5-15.
  
  [terragrunt] 2021/01/05 17:12:12 Hit multiple errors:
  exit status 1
  
  ```
  
  **Tags:** terraform, terragrunt, aws-security-group
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-01-06. Score: 4 | Accepted answer
  
  When validating an input variable of a collection type, we typically want to write a validation rule that tests if something is true for each value within the collection, rather than true of the collection as a whole.
  
  You can write a "for each" sort of condition using Terraform's [`for` expressions](https://www.terraform.io/docs/configuration/expressions/for.html). If you are using Terraform v0.14 or later then you can write it concisely using [the `alltrue` function](https://www.terraform.io/docs/configuration/functions/alltrue.html) along with a `for` expression that produces a true or false result for each of the items, like this:
  
  ```
    validation {
      condition = alltrue([
        for id in var.security_groups : can(regex("^sg-", id))
      ])
      error_message = "All security group ids must start with \"sg-\"."
    }
  
  ```
  
  ---
  
  If you are using Terraform v0.13 then you won't have the `alltrue` function available to you yet, but you can get a similar result in a clunkier way by using the optional `if` clause of a `for` expression to filter out all of the valid ids and then checking whether the resulting list is empty -- that is, whether there are any remaining items that were *not* valid:
  
  ```
    validation {
      condition = length([
        for id in var.security_groups : id
        if !can(regex("^sg-", id))
      ]) == 0
      error_message = "All security group ids must start with \"sg-\"."
    }
  
  ```
  
  This second example is a bit more cryptic to understand because it's using some language features in an atypical way, so I'll break it down into smaller parts to explain:
  
  * `[for id in var.security_groups : id if !can(regex("^sg-", id))]` filters the elements of `var.security_groups` to keep only the ones where the expression is true.
  * `!can(regex("^sg-", id))` uses the `!` operator to turn your original expression that decides if the value is *valid* into an expression which decides if the value is *invalid*. Consequently the result of the `for` expression will be empty unless there's at least one invalid value.
  * Finally, the `length( ... ) == 0` around the `for` expression says that the value is only valid if filtering out all of the valid values produces an empty list, which conversely means that the list didn't contain any invalid values.
  
  > **Comments:**
  > **username_0**: thanks for help.  
  
  ---
  
  