如何将变量传递/连接到`aws_instance`资源中的`data.aws_ami`部分

Posted

技术标签:

【中文标题】如何将变量传递/连接到`aws_instance`资源中的`data.aws_ami`部分【英文标题】:How to pass/concat variable into the `data.aws_ami` section in the `aws_instance` resource 【发布时间】:2021-12-22 11:11:38 【问题描述】:

我在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

最终目标是基于不同的操作系统 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添加到问题中并说明它们之间的区别。 【参考方案1】:

您显示的代码: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 中使用的允许的不同操作系统,这样我们就可以防止任何问题在它们导致错误之前发生。

【讨论】:

感谢您的帮助。不幸的是,这对我不起作用。如果所有者是“亚马逊”,我仍然试图弄清楚这将如何适用于不同的操作系统。我如何将您的代码与默认的data "aws_ami" "ubuntu" 相关联,其值指向最新的图像? @greenszpila 你的问题一开始就不是很详细......你没有aws_ami 的代码也许可以澄清所有这些,我们可以重新审视这个......你对数组有任何经验吗在地形?你用我的例子制定了计划吗? 感谢您回复我。我想要一个部署并取决于ami 行中resource 部分中指定的变量。这将部署基于 ubuntu、amazon、rhel 的 ec2 实例。我使用的命令是 terraform apply -var-file=ubuntu.tf for ubuntu image 等等。我已经在上面的代码中添加了aws_ami 部分。不,我没有使用 tf 中的数组的经验,当我使用您的示例运行计划时,我遇到了与 UEFI 相关的奇怪错误。谢谢。 @greenszpila 我更新了我的代码以遵循您在 aws_ami 上所做的事情 感谢@HelderSepulveda,这很有效,非常感谢。非常感谢!

以上是关于如何将变量传递/连接到`aws_instance`资源中的`data.aws_ami`部分的主要内容,如果未能解决你的问题,请参考以下文章

需要将文件名连接到变量

如何将变量连接到特定行

【Axure笔记】8.如何使用url及变量链接页面并实现跳转

如何将变量连接到 Entry 小部件?

如何将滑块连接到 MFC 中的变量

如何将 $_SESSION 变量传递给 websocket 服务器?