如何将 pass/concat 变量放入 `aws_instance` 资源中的 `data.aws_ami` 部分

How to pass/concat variable into the `data.aws_ami` section in the `aws_instance` resource

我在 ami=data.aws_ami.$var.ami_name.id 行中定义变量时遇到困难。

我试过ami= "${data.aws_ami.(var.ami_name).id}"但在这两种情况下我都得到了:

79:   ami = data.aws_ami.(var.ami_name)).id
│ 
│ An attribute name is required after a dot.

它仅适用于字符串值 data.aws_ami.ubuntu-1804.id

我的问题是如何将变量连接到 data.aws_ami?

最终目标是根据不同的 OS ec2 实例(Suse、Ubuntu、RHEL)进行配置,所有这些都取决于部署时提供的变量。

variable "ami_name" {
  default = "ubuntu"
}

data "aws_ami" "amazon" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm*"]
  }
}

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_instance" "linux" {
  key_name = var.ami_key_pair_name
  //ami           = var.ami_id
  //I want this to be dynamic so I can deploy either Amazon or Ubuntu in all regions. 
  ami            = data.aws_ami.$var.ami_name.id 
  //ami           = data.aws_ami.ubuntu.id # this works
  instance_type = "t2.micro"
tags = {
    Name = var.instance_name
  }
  vpc_security_group_ids = [
    aws_security_group.allow-ssh-http.id
  ]
}

我进行了搜索,但找不到任何相关内容。我正在使用 Terraform v0.15.4

您显示的代码:data.aws_ami.$var.ami_name.id 不是有效的 terraform 语法。

你问的可能是这样的:

provider "aws" { region = "us-east-2" }

locals {
    allowed_os = {
        "amazon": {owner: "amazon",       filter: "amzn2-ami-hvm*"},
        "suse":   {owner: "amazon",       filter: "*suse*"},
        "RHEL":   {owner: "amazon",       filter: "*RHEL*"},
        "ubuntu": {owner: "099720109477", filter: "*ubuntu-bionic-18.04-amd64-*"},
    }
}

variable "ami_name" {
  default = "ubuntu"

  validation {
    condition     = can(regex("amazon|suse|RHEL|ubuntu", var.ami_name))
    error_message = "Invalid ami name, allowed_values = [amazon suse RHEL ubuntu]."
  }
}

data "aws_ami" "os" {
  for_each = local.allowed_os

  most_recent = true
  owners      = [each.value.owner]
  filter {
    name   = "name"
    values = [each.value.filter]
  }
}

resource "aws_instance" "linux" {
  ami           = data.aws_ami.os[var.ami_name].id
  instance_type = "t2.micro"
  # ... todo add arguments here
}

我的方法是在 aws_ami 中使用 for_each,这将为我们提供一个数组,稍后我们可以在 aws_instance 资源中使用它:

  • data.aws_ami.os["ubuntu"].id
    在这里,我们使用硬编码值来访问代码中的特定 AMI。

  • data.aws_ami.os[var.ami_name].id
    或者以这种方式使用用户或配置文件提供的变量。

您可以向数组添加更多项以添加其他操作系统,与过滤器相同,您只需更改 allowed_os 局部变量即可满足您的需要。

另外,我向您的 ami_name 变量添加了验证,以匹配我们在 for_each 中使用的允许的不同 OS,这样我们就可以在他们可以之前防止任何问题导致错误。