Rick
Rick

Reputation: 111

Terraform find latest ami via data

I'm trying to implement some sort of mechanism where someone can fill in a variable which defines if it's going to deploy an Amazon Linux machine or a self-created packer machine. But for some reason it's not picking up the AWS AMI while it does find my own. Here's the code:

Main.tf of the module:

    data "aws_ami" "latest" {
  most_recent = true
  owners      = [var.owner]

  filter {
    name   = "name"
    values = [lookup(var.default_ami, var.ami)]
  }
}

resource "aws_instance" "test-ec2deployment" {
  ami                         = data.aws_ami.latest.id

variables.tf:

variable "default_ami" {
  type        = map
  description = "Choose windows 2016 or 2019"
  default = {
    "2016"  = "WIN2016-CUSTOM*"
    "2019"  = "WIN2019-CUSTOM*"
    "linux" = "ami-0fb02dcdd38048fb9"
  }
}

#Above are the options, here you need to make a decision.
variable "ami" {
  description = "You can either choose the 2019 or the 2016 image or the linux image."
  default     = "2019"
}

And finally the main.tf which calls on the module:

module "aws_instance" {
  shared_credentials_file = ""
  source                  = ""
  env_name                = ""
  volume_size             = "60"
  ami                     = "linux"
}

Like i said, it does find the correct image when i'm entering either 2019 or 2016. The error message is as follows:

module.aws_instance.data.aws_ami.latest: Refreshing state...

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

Any idea's?

Thanks for the help!

PS: I've emptied some fields on purpose.

Upvotes: 7

Views: 23568

Answers (3)

Daniel Viglione
Daniel Viglione

Reputation: 9427

If you are searching by name, you may want to use wildcards. For example, there is an ecs-optimized ami named amzn2-ami-ecs-hvm-2.0.20220318-x86_64-ebs. However, terraform couldn't find it. When I used wildcards, it worked: amzn2-ami-ecs-hvm-2.0.202*-x86_64-ebs

The actual code looks as so:

data "aws_ami" "ecs_optimized_ami" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-ecs-hvm-2.0.202*-x86_64-ebs"]
  }
}

Upvotes: 2

neelneelpurk
neelneelpurk

Reputation: 81

Marcin's answer is spot on. AMI name and AMI id are two different things, you cannot use AMI id to search AMI based on its name. For using AMI id, you need to use "image-id" filter. To get a complete list of filters that we can use for searching AMI, check this.

Now, coming to your problem. You can use "name" and "image-id" filter together to get the required AMI. If you don't have value for any of them use "*". I solved it in the following way -

variable "ami" {
  description = "You can either choose the 2019 or the 2016 image or the linux image."
  default     = "2019"
}

variable "default_ami" {
  type = map(any)
  default = {
    "linux" = {
      name = "*"
      ami_id = "ami-0fb02dcdd38048fb9"
    },
    "2016" = {
      name = "WIN2016-CUSTOM*"
      ami_id = "*"
    },
    "2019" = {
      name = "WIN2019-CUSTOM*"
      ami_id = "*"
    }
  }
}

data "aws_ami" "latest" {
  most_recent = true
  owners      = [var.owner]

  filter {
    name   = "name"
    values = ["${var.default_ami[var.ami]["name"]}"]
  }
  filter {
    name   = "image-id"
    values = ["${var.default_ami[var.ami]["ami_id"]}"]
  }
}

resource "aws_instance" "test-ec2deployment" {
  ami = data.aws_ami.latest.id
  instance_type = var.instance_type
}

Upvotes: 4

Marcin
Marcin

Reputation: 238309

AMI name and AMI id are two different things. You are using AMI id (ami-0fb02dcdd38048fb9) to search AMI based on its name. This will not work obviously. You have to replace ami-0fb02dcdd38048fb9 with AMI name.

You haven't specified how you named your linux AMI, maybe Linux2019-CUSTOM*? Whatever the name you've used, you have to use that, not AMI id.

Upvotes: 1

Related Questions