terraformhashicorp

Error: Iteration over non-iterable value - terraform


I pretty new to terraform and dont understand what am I doing wrong. My goal is to filter the list based on the specific word each value can have.

So my module looks like this where I define the pipeline_list

    module "pipelines" {
  source = "./pipelines"

  for_each = var.pipelines

  project_id    = data.azuredevops_project.dataanalytics.id
  repo_id       = module.repositories[each.key].repo_id
  pipeline_list = each.value
  group_ids = local.group_ids
}

pipelines tfvars file itself looks like this

    pipelines = {
  Infrastructure = [
    "pipelines/BI-Infrastructure-IaC-CI.yml",
    "pipelines/BI-Infrastructure-IaC-Deploy.yml"
  ],
  Applications = [
    "datafactory/pipelines/DataAnalytics-Datafactory-Test.yml",
    "datafactory/pipelines/DataAnalytics-Datafactory-CI.yml",
    "datafactory/pipelines/DataAnalytics-Datafactory-Deploy.yml",
    "databricks/pipelines/BI-Applications-Databricks-CI.yml",
    "databricks/pipelines/BI-Applications-Databricks-Deploy.yml"
  ]
}

And I woud like to filter this list and only pick the values that contain "Deploy" in it.

My attempt looks like this:

locals {
  deploy_pipelines = flatten([
    for project, pipelines in var.pipeline_list : [
      for pipeline in pipelines : 
        contains(pipeline, "Deploy") ? pipeline : null
    ]
  ])
}

But I get the error saying that

enter image description here

Could please help to idnetify where do I make the mistkae?

EDIT: I have changed locals this way, I think i was doing extra looping since project is not in there. but I get new error now saying Call to function "contains" failed: argument must be list, tuple, or set.

locals {
  deploy_pipelines = flatten([
    for pipeline in var.pipeline_list : 
        contains(pipeline, "Deploy") ? pipeline : null
    ]
  )
    }

Solution

  • The contains function is not a string to substring, see the documentation...
    https://developer.hashicorp.com/terraform/language/functions/contains

    contains determines whether a given list or set contains a given single value as one of its elements.

    what you are looking for is strcontains, Terraform introduced that in version (v1.5.0) https://developer.hashicorp.com/terraform/language/functions/strcontains

    strcontains function checks whether a substring is within another string.


    if you are using an old version of terraform you might have to use regex or a string compare after a replace as a condition, but I would strongly recommend to upgrade to latest.



    Something else I want to point out, this would be your code ...

    variable "pipeline_list" {
      default = [
        "pipelines/BI-Infrastructure-IaC-CI.yml",
        "pipelines/BI-Infrastructure-IaC-Deploy.yml"
      ]
    }
    
    locals {
      deploy_pipelines = flatten([
        for pipeline in var.pipeline_list :
            strcontains(pipeline, "Deploy") ? pipeline : null
        ]
      )
    }
    
    output "test" {
      value = local.deploy_pipelines
    }
    

    that will produce a plan with nulls:

    Changes to Outputs:
      + test = [
          + null,
          + "pipelines/BI-Infrastructure-IaC-Deploy.yml",
        ]
    

    if you don't want the null there (I assume you don't) we can use an if instead

    variable "pipeline_list" {
      default = [
        "pipelines/BI-Infrastructure-IaC-CI.yml",
        "pipelines/BI-Infrastructure-IaC-Deploy.yml"
      ]
    }
    
    locals {
      deploy_pipelines = [
        for pipeline in var.pipeline_list : pipeline
        if strcontains(pipeline, "Deploy")
      ]
    }
    
    output "test" {
      value = local.deploy_pipelines
    }