OpsLevel / terraform-provider-opslevel

Terraform provider for OpsLevel.com
https://registry.terraform.io/providers/OpsLevel/opslevel/latest/docs
MIT License
8 stars 5 forks source link

fix filter predicate validation when created with for_each loop #379

Closed davidbloss closed 1 month ago

davidbloss commented 1 month ago

Issues

Multiple filter blocks created with a for_each loop fail on validation. If a predicate's value field is set via each.key, the value would be unknown at validation time. This should not be counted as invalid configuration.

Changelog

Tophatting

With this Terraform config:

resource "opslevel_filter" "first_party_services" {
  for_each = toset(local.envs)
  name     = "Test application (${each.key})"
  predicate {
    key            = "tags"
    key_data       = "third-party"
    type           = "does_not_equal"
    value          = "true"
    case_sensitive = true
  }
  predicate {
    key            = "tags"
    key_data       = "environment"
    type           = "equals"
    value          = each.key
    case_sensitive = true
  }
  connective = "and"
}

locals {
  envs = [
    "development",
    "sandbox",
    "production",
  ]
}

Before this fix, terraform plan

│ Error: Invalid Attribute Configuration
│ 
│   with opslevel_filter.first_party_services,
│   on main.tf line 1, in resource "opslevel_filter" "first_party_services":
│    1: resource "opslevel_filter" "first_party_services" {
│ 
│ Predicate type 'equals' requires a value

After this fix, terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # opslevel_filter.first_party_services["development"] will be created
  + resource "opslevel_filter" "first_party_services" {
      + connective = "and"
      + id         = (known after apply)
      + name       = "First-party application (development)"

      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "third-party"
          + type             = "does_not_equal"
          + value            = "true"
        }
      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "environment"
          + type             = "equals"
          + value            = "development"
        }
    }

  # opslevel_filter.first_party_services["production"] will be created
  + resource "opslevel_filter" "first_party_services" {
      + connective = "and"
      + id         = (known after apply)
      + name       = "First-party application (production)"

      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "third-party"
          + type             = "does_not_equal"
          + value            = "true"
        }
      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "environment"
          + type             = "equals"
          + value            = "production"
        }
    }

  # opslevel_filter.first_party_services["sandbox"] will be created
  + resource "opslevel_filter" "first_party_services" {
      + connective = "and"
      + id         = (known after apply)
      + name       = "First-party application (sandbox)"

      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "third-party"
          + type             = "does_not_equal"
          + value            = "true"
        }
      + predicate {
          + case_insensitive = (known after apply)
          + case_sensitive   = true
          + key              = "tags"
          + key_data         = "environment"
          + type             = "equals"
          + value            = "sandbox"
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.