Filter AWS AMI based on a map of tag names and values

I’m trying to create an aws_ami data source that fetches the latest AMI based on a few tags. The catch is that I want to do it with a map of tags and their values, not by defining filters for each specific tag in the data source

Example:

module-vars.tf

variable "filter-tags" {
  type = "map"
  default = {
    "java_vendor" = "oracle"
  }
}

module.tf

data "aws_ami" "aws-ami" {
  most_recent = true
  owners = ["self"]

  // Filter code here
  // e.g. FICTIONAL CODE, DON'T USE
  filter {
    name = "tags:${var.filter-tags}"
  }
}

So obviously this filter-tags variable should be able to change and the filtered AMI should have all the tags matching.

Any ideas?

Found a way

data "aws_ami" "aws-ami" {
  most_recent = true
  owners = ["self"]

  dynamic "filter" {
    for_each = var.filter-tags
    iterator = tag
    content {
      name = "tag:${tag.key}"
      values = ["${tag.value}"]
    }
  }
}
1 Like

I’m running into the same issue with doing a dynamic filter for aws_ami. i’m using version 0.14.8. any idea on how to get this to dynamically filter with a list or map?

data “aws_ami” “db_ami” {
most_recent = true
owners = [“self”]

dynamic “filter” {
for_each = var.filter-tags

content {
  name = tag.key
  values = tag.value
}

}

terraform plan

Error: Invalid value for module argument

on main.tf line 38, in module “ec2_cluster”:
38: filter-tags = {
39: “tag:os” = [“ubuntu”]
40: “tag:release” = [“bionic”]
41: “tag:Team” = [“dba”]
42: “tag:purpose” = [“goodpurpose”]
43: }

The given value is not suitable for child module variable “filter-tags”
defined at …/…/…/modules/services/elastic-cluster/variables.tf:142,1-23:
element “tag:release”: string required.

Can you share the value you use for var.filter-tags?

here is my latest @grantorchard1 … if i uncomment my hard coded filters, it works fine. i just can’t get the dynamic filter to work.

terraform plan

Error: Your query returned no results. Please change your search criteria and try again.

  on ../../../modules/services/elastic-cluster/main.tf line 6, in data "aws_ami" "db_ami":
   6: data "aws_ami" "db_ami" {

***

dynamic "filter" {

    for_each = var.filter_tags
    iterator = tag
    content {
      name = "tag:${tag.key}"
      values = ["tag.value"]
    }
  }


  #filter {
  #  name   = "tag:os"
  #  values = ["ubuntu"]
  #}

  #filter {
  #  name   = "tag:release"
  #  values = ["bionic"]
  #}

  #filter {
  #  name   = "tag:Team"
  #  values = ["dba"]
  #}

  #filter {
  #  name   = "tag:purpose"
  #  values = ["GoodPurpose"]
  #}
}


variable "filter_tags" {
  description = "Custom tags to set on the Instances in the ASG"
  type        = map(string)
  default     = {
    "os" = "ubuntu"
    "release" = "bionic"
    "Team" = "dba"
    "purpose" = "GoodPurpose"
  }
}

it works with 1 key/value pair in my map but need to get it to work for more than 1.

  dynamic "filter" {
    for_each = var.filter_tags
    iterator = tag
    content {
      name = "tag:${tag.key}"
      values = [tag.value]
    }
  }

variable "filter_tags" {
  description = "Custom tags to set on the Instances in the ASG"
  type        = map(string)
  default     = {
    "os" = "ubuntu"
  }
}

never mind, case closed. it was actually valid. the image tags was off one.

1 Like