terraform-如何在属性中使用变量

terraform-如何在属性中使用变量,terraform,terraform-provider-aws,Terraform,Terraform Provider Aws,我不确定这是否是正确的方法,但我想使用一个变量作为属性 例如,我有一个根据用户输入而改变的变量:os\u name=ubuntu 我想使用这个变量名,如下所示 resource "aws_instance" "workerNode" { .................. ami = data.aws_ami.${var.os_name}.image_id .................. } "architecture&

我不确定这是否是正确的方法,但我想使用一个变量作为属性

例如,我有一个根据用户输入而改变的变量:
os\u name=ubuntu

我想使用这个变量名,如下所示

resource "aws_instance" "workerNode" {
  ..................
  ami = data.aws_ami.${var.os_name}.image_id
  ..................
}
  "architecture" = "x86_64"
  "hypervisor" = "xen"
  "id" = "ami-0d3905203a039e3b0"
  "image_id" = "ami-0d3905203a039e3b0"
以下是数据块的示例

data "aws_ami" "suse" {
    count  = "${var.os_name == "suse" ? 1 : 0}"
    owners = ["amazon"]
    most_recent = true
    filter {
        name = "name"
        values = ["suse-sles-${var.os_version}-sp*-v????????-hvm-ssd-x86_64"]
    }
}    
其结果如下:

resource "aws_instance" "workerNode" {
  ..................
  ami = data.aws_ami.${var.os_name}.image_id
  ..................
}
  "architecture" = "x86_64"
  "hypervisor" = "xen"
  "id" = "ami-0d3905203a039e3b0"
  "image_id" = "ami-0d3905203a039e3b0"

但terraform不允许我这么做。有什么方法可以做到这一点,或者我必须改变工作流程吗?

您可以通过为每个
指定一个
的AMI,从而获得一个
地图
,您可以通过按键访问它

我的
data.aws\u ami.myamis
如下所示:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"
出于测试目的,我定义了一个变量
foo
,如下所示:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"
现在我可以像这样访问AMI:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"

您可以根据自己对
os\u名称
os\u版本
的需要对其进行调整。您可以使用
为每个
指定AMI,从而获得一个可以通过键访问的
映射

我的
data.aws\u ami.myamis
如下所示:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"
出于测试目的,我定义了一个变量
foo
,如下所示:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"
现在我可以像这样访问AMI:

data "aws_ami" "myamis" {
  for_each = toset(["suse", "ubuntu"])

  most_recent = true
  owners      = ["amazon"]

  filter {
    name = "name"
    values = ["${each.value}*"]
  }
}
variable "foo" {
  type    = string
  default = "suse"
}
$ tf console
> data.aws_ami.myamis[var.foo].image_id
"ami-0ea50c090ba6e85c5"

您可以根据自己对
os\u name
os\u version
的需要对其进行调整我已经通过使用条件表达式解决了这个问题

output "name" {
    value = "${ var.os_name == "ubuntu" ? data.aws_ami.ubuntu[0].image_id : (var.os_name == "redhat" ? data.aws_ami.redhat[0].image_id : (var.os_name == "centos" ? data.aws_ami.suse[0].image_id : data.aws_ami.suse[0].image_id ))}"
}
我不确定这是否是一种标准的做事方式,但它对我很有效

我尝试用嵌套的条件表达式模拟if/elif/else

output "name" {
    value = "${ var.os_name == "ubuntu" ? data.aws_ami.ubuntu[0].image_id : (var.os_name == "redhat" ? data.aws_ami.redhat[0].image_id : (var.os_name == "centos" ? data.aws_ami.suse[0].image_id : data.aws_ami.suse[0].image_id ))}"
}

我已经通过使用条件表达式解决了这个问题

output "name" {
    value = "${ var.os_name == "ubuntu" ? data.aws_ami.ubuntu[0].image_id : (var.os_name == "redhat" ? data.aws_ami.redhat[0].image_id : (var.os_name == "centos" ? data.aws_ami.suse[0].image_id : data.aws_ami.suse[0].image_id ))}"
}
我不确定这是否是一种标准的做事方式,但它对我很有效

我尝试用嵌套的条件表达式模拟if/elif/else

output "name" {
    value = "${ var.os_name == "ubuntu" ? data.aws_ami.ubuntu[0].image_id : (var.os_name == "redhat" ? data.aws_ami.redhat[0].image_id : (var.os_name == "centos" ? data.aws_ami.suse[0].image_id : data.aws_ami.suse[0].image_id ))}"
}

在不适合使用
for_each
将所有实例收集到单个资源下的情况下(这会隐式地使该资源显示为对象的映射),您可以通过编写表达式来构造等效映射来显式获得类似的结果:

locals {
  amis = {
    suse   = data.aws_ami.suse
    ubuntu = data.aws_ami.ubuntu
  }
}
然后您可以参考
local.amis[“ubuntu”]
local.amis[“suse”]
(如果需要,可以用变量替换元素键)


尽管如此,您的案例似乎有一种可能的不同方法,只需一个
数据块即可实现:

locals {
  os_ami_queries = {
    suse = {
      owners = ["amazon"]
      filters = {
        name = ["suse-sles-${var.os_version}-sp*-v????????-hvm-ssd-x86_64"]
      }
    }
    ubuntu = {
      owners = ["amazon"]
      filters = {
        name = ["ubuntu-${var.os_version}-something-something"]
      }
    }
  }
  ami_query = local.os_ami_queries[var.os_name]
}

data "aws_ami" "selected" {
  owners = local.ami_query.owners

  dynamic "filter" {
    for_each = local.ami_query.filters
    content {
      name   = filter.key
      values = filter.value
    }
  }
}
这种不同的排列在
数据“aws\u ami”
查找之前进行OS选择,因此它可以使用与调用者选择的任何OS相关的设置。然后,ami id将位于
数据.aws\u ami.selected.id


尽管如此,这种方法的缺点是非常间接,并且使用了
动态
块,因此我会将其与备选方案的可读性进行权衡,以选择一种对于不熟悉此配置的人来说主观上似乎最容易遵循的方法这是一个品味的问题,因此,如果你在团队环境中工作,这可能是与同事讨论的问题,以确定哪种方法最适合权衡,比如你希望添加和删除受支持的操作系统的频率,还是更改使用结果的详细信息。

在不适合使用的情况下使用
将所有实例收集到单个资源下,并对每个资源使用
(这会隐式地使该资源显示为对象的映射),通过编写表达式来构造等效映射,可以显式地获得类似的结果:

locals {
  amis = {
    suse   = data.aws_ami.suse
    ubuntu = data.aws_ami.ubuntu
  }
}
然后您可以参考
local.amis[“ubuntu”]
local.amis[“suse”]
(如果需要,可以用变量替换元素键)


尽管如此,您的案例似乎有一种可能的不同方法,只需一个
数据块即可实现:

locals {
  os_ami_queries = {
    suse = {
      owners = ["amazon"]
      filters = {
        name = ["suse-sles-${var.os_version}-sp*-v????????-hvm-ssd-x86_64"]
      }
    }
    ubuntu = {
      owners = ["amazon"]
      filters = {
        name = ["ubuntu-${var.os_version}-something-something"]
      }
    }
  }
  ami_query = local.os_ami_queries[var.os_name]
}

data "aws_ami" "selected" {
  owners = local.ami_query.owners

  dynamic "filter" {
    for_each = local.ami_query.filters
    content {
      name   = filter.key
      values = filter.value
    }
  }
}
这种不同的排列在
数据“aws\u ami”
查找之前进行OS选择,因此它可以使用与调用者选择的任何OS相关的设置。然后,ami id将位于
数据.aws\u ami.selected.id


尽管如此,这种方法的缺点是非常间接,并且使用了
动态
块,因此我会将其与备选方案的可读性进行权衡,以选择一种对于不熟悉此配置的人来说主观上似乎最容易遵循的方法这是一个品味的问题,因此,如果你在团队中工作,这可能是一个与同事讨论的问题,看看哪种方法最适合权衡,比如你希望添加和删除受支持的操作系统的频率与更改使用结果的细节的频率。

数据也是如此。aws_ami
地图?你可以吗请添加它的结构方式?@yvesonline是的。为了方便起见,我添加了一些示例。仅适用于字符串,而不适用于变量/数据访问。您需要在排序映射中构造AMI,以便按键访问它们。问题不在于我如何访问键。问题在于如何使查询动态。
data.aws也是如此_ami
a map?你能添加它的结构吗?@yvesonline是的。为了方便起见,我又添加了几个示例。它只适用于字符串,而不适用于变量/数据访问。你需要在一个排序的映射中构造你的ami,以便按键访问它们。问题不在于我如何访问键。问题在于我如何才能进行查询动态。问题是每个操作系统类型的过滤器都不同。对于某些操作系统,我有3个过滤器,对于某些操作系统,我有5个。如果我只有两个操作系统,那么我可以使用条件,但在我的情况下,我有5个操作系统,每个操作系统有1个数据块。这个答案的要点应该是,您需要在
映射中构造AMI,以便可以访问