How do I program a conditional when creating a resource in terraform?

36 views Asked by At

So I'm currently new to terraform and I'm using CSVs as inputs to generate different types of resources. Some of these resources have conditions meaning that they should only be created if these conditions are met. Below is the piece of code that I wrote. This code works, but not exactly the way is required.

locals {
  csv_data1 = <<-CSV
    short_hostname,tunnel,fqdn,access_app_type,service_url,no_tls_verify
    fralinuxhost1,fratest-tunnel01,fralinuxhost1.example.com,ssh,ssh://fralinuxhost1.example.com,false
    fralinuxhost2,fratest-tunnel01,fralinuxhost1.example.com,ssh,ssh://fralinuxhost2.example.com,false
    sjclinuxhost2,sjctest-tunnel01,sjclinuxhost2.example.com,ssh,ssh://sjclinuxhost2.example.com,false
  CSV

  csv_data2 = <<-CSV
    tunnelnameref,secret
    fratest-tunnel01,secretblahblah1
    sjctest-tunnel01,secretblahblah2
  CSV

  publichost = csvdecode(local.csv_data1)
  tunnelnameref = csvdecode(local.csv_data2)

}

resource "cloudflare_zone" "example_com" {
    account_id = var.account_id
    paused              = false
    plan                = "free"
    type                = "full"
    zone                = "example.com"
}

resource "cloudflare_access_group" "test_users_and_require_warp" {
    account_id = var.account_id
    name       = "test_users_and_require_warp"

    include {
        any_valid_service_token = false
        certificate             = false
        device_posture          = []
        email                   = [
            "[email protected]",
            "[email protected]",
        ]
        email_domain            = []
        everyone                = false
        geo                     = []
        group                   = []
        ip                      = []
        ip_list                 = []
        login_method            = []
        service_token           = []
    }

    require {
        any_valid_service_token = false
        certificate             = false
        device_posture          = [
            "1234567890-102001203-3194aaa",
        ]
        email                   = []
        email_domain            = []
        everyone                = false
        geo                     = []
        group                   = []
        ip                      = []
        ip_list                 = []
        login_method            = []
        service_token           = []
    }
}

resource "cloudflare_tunnel" "example" {
  for_each = { for host in local.tunnelnameref : host.tunnelnameref => host }
 
  account_id   = var.account_id
  name         = each.value.tunnelnameref
  secret       = each.value.secret
}

resource "cloudflare_access_application" "example" {
  for_each = { for host in local.publichost : host.short_hostname => host }

  account_id                 = var.account_id
  allowed_idps               = []
  app_launcher_visible       = true
  auto_redirect_to_identity  = false
  custom_pages               = []
  domain                     = each.value["fqdn"]
  enable_binding_cookie      = false
  http_only_cookie_attribute = true
  name                       = each.value.short_hostname
  service_auth_401_redirect  = false
  session_duration           = "24h"
  skip_interstitial          = true
  tags                       = []
  type                       = each.value["access_app_type"]
}

resource "cloudflare_record" "example" {
  for_each = { for host in local.publichost : host.short_hostname => host }

  zone_id = cloudflare_zone.example_com.id
  name    = each.value["short_hostname"]
  value   = "${cloudflare_tunnel.example[each.value.tunnel].id}.cfargotunnel.com"
  type    = "CNAME"
  proxied = true
}

resource "cloudflare_access_policy" "example" {
  for_each       = { for host in local.publichost : host.short_hostname => host }
  application_id = cloudflare_access_application.example[each.value.short_hostname].id
  zone_id        = cloudflare_zone.example_com.id
  name           = each.value["fqdn"]
  precedence     = "1"
  decision       = "allow"

  include {
    group = [
      cloudflare_access_group.test_users_and_require_warp.id
    ]
  }
}

resource "cloudflare_tunnel_config" "example" {
  for_each = { for host in local.tunnelnameref : host.tunnelnameref => host }
  account_id = var.account_id
  tunnel_id  = cloudflare_tunnel.example[each.value.tunnelnameref].id

  config {
    dynamic "ingress_rule" {
      for_each = local.publichost

      content {
        hostname = ingress_rule.value["fqdn"]
        service  = ingress_rule.value["service_url"]

        origin_request {
          bastion_mode             = false
          disable_chunked_encoding = false
          http2_origin             = false
          keep_alive_connections   = 0
          no_happy_eyeballs        = false
          no_tls_verify            = ingress_rule.value["no_tls_verify"]
          proxy_port               = 0
        }
      }
    }
    ingress_rule {
      service = "http_status:404"
    }

    warp_routing {
      enabled = true
    }
  }
}

I tried depends_on, but since I'm using a for_each that isn't possible. for_each has some syntax for conditionals, but I can't seem to figure out how to make it work in this scenario using CSV data to generate resources.

The output looks correct, but the last resource or the cloudflare_tunnel_config resource gets generated for the csv_data1 times the csv_data2. In other words the output for that section looks like below

  # cloudflare_tunnel_config.example["fratest-tunnel01"] will be created
  + resource "cloudflare_tunnel_config" "example" {
      + account_id = "blah"
      + id         = (known after apply)
      + tunnel_id  = (known after apply)

      + config {
          + ingress_rule {
              + hostname = "fralinuxhost1.example.com"
              + service  = "ssh://fralinuxhost1.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + hostname = "fralinuxhost2.example.com"
              + service  = "ssh://fralinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + hostname = "sjclinuxhost2.example.com"
              + service  = "ssh://sjclinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + service = "http_status:404"
            }
          + warp_routing {
              + enabled = true
            }
        }
    }

  # cloudflare_tunnel_config.example["sjctest-tunnel01"] will be created
  + resource "cloudflare_tunnel_config" "example" {
      + account_id = "blah"
      + id         = (known after apply)
      + tunnel_id  = (known after apply)

      + config {
          + ingress_rule {
              + hostname = "fralinuxhost1.example.com"
              + service  = "ssh://fralinuxhost1.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + hostname = "fralinuxhost2.example.com"
              + service  = "ssh://fralinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + hostname = "sjclinuxhost2.example.com"
              + service  = "ssh://sjclinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + service = "http_status:404"
            }
          + warp_routing {
              + enabled = true
            }
        }
    }

But the output should look like the one below:

  # cloudflare_tunnel_config.example["fratest-tunnel01"] will be created
  + resource "cloudflare_tunnel_config" "example" {
      + account_id = "blah"
      + id         = (known after apply)
      + tunnel_id  = (known after apply)

      + config {
          + ingress_rule {
              + hostname = "fralinuxhost1.example.com"
              + service  = "ssh://fralinuxhost1.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + hostname = "fralinuxhost2.example.com"
              + service  = "ssh://fralinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + service = "http_status:404"
            }
          + warp_routing {
              + enabled = true
            }
        }
    }

  # cloudflare_tunnel_config.example["sjctest-tunnel01"] will be created
  + resource "cloudflare_tunnel_config" "example" {
      + account_id = "blah"
      + id         = (known after apply)
      + tunnel_id  = (known after apply)

      + config {
          + ingress_rule {
              + hostname = "sjclinuxhost2.example.com"
              + service  = "ssh://sjclinuxhost2.example.com"

              + origin_request {
                  + bastion_mode             = false
                  + connect_timeout          = "30s"
                  + disable_chunked_encoding = false
                  + http2_origin             = false
                  + keep_alive_connections   = 0
                  + keep_alive_timeout       = "1m30s"
                  + no_happy_eyeballs        = false
                  + no_tls_verify            = false
                  + proxy_address            = "127.0.0.1"
                  + proxy_port               = 0
                  + tcp_keep_alive           = "30s"
                  + tls_timeout              = "10s"
                }
            }
          + ingress_rule {
              + service = "http_status:404"
            }
          + warp_routing {
              + enabled = true
            }
        }
    }

How would I be able to accomplish this?

1

There are 1 answers

0
Lorenzo Felletti On

You can specify conditions to perform some filtering while in a for. You should do something like this:

resource "cloudflare_tunnel_config" "example" {
  for_each = { for host in local.tunnelnameref : host.tunnelnameref => host if  <your_condition> }

  # ...
}