首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Terraform:如何循环遍历元素列表并根据每个元素创建资源?

Terraform:如何循环遍历元素列表并根据每个元素创建资源?
EN

Stack Overflow用户
提问于 2022-08-13 00:01:25
回答 2查看 314关注 0票数 1

我需要为在s3变量中传递的每个data_uri设置aws data_uri访问点;这是为了提供一个跨帐户uri(s)。我只需要从这些data_uri中的每一个解析桶名,然后为每个桶创建资源。我该怎么做?

以下是我到目前为止所拥有的:

代码语言:javascript
复制
resource "aws_s3_access_point" "s3_access_point" {
  count    = var.create ? 1 : 0
  for_each = var.inference

  bucket = split("/", replace(each.value.image_uri, "s3://", ""))[0]
  name   = format("%s-%s", split("/", replace(each.value.image_uri, "s3://", ""))[0], "-access-point")
}

变量如下所示:

代码语言:javascript
复制
{
"inference": [
  {
  "data_uri": "s3://my_bucket/model.tar.gz"
  },
  {
  "data_uri": "s3://my_bucket_2/model.tar.gz"
  },
  {
  "data_uri": "s3://my_bucket_3/model.tar.gz"
  }
]
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-13 00:39:12

如果命名是一致的,我建议使用拆分。另外,您不能将计数每一个混合使用;根据情况需要使用其中的一种。

注:这个答案是根据下面的评论重新修改的。

代码语言:javascript
复制
locals {
  inference = [
    { "data_uri" : "s3://my_bucket/model.tar.gz" },
    { "data_uri" : "s3://my_bucket_2/model.tar.gz" },
    { "data_uri" : "s3://my_bucket_3/model.tar.gz" }
  ]

  uri_bucket_map = {
    for x in local.inference : x.data_uri =>
    split("/", split("//", x.data_uri)[1])[0]
  }
}

resource "aws_s3_access_point" "s3_access_point" {
  for_each = local.uri_bucket_map

  bucket = each.value
  name   = var.s3_access_point_name
}

output "s3_access_point" {
  value = { for uri, ap in aws_s3_access_point.s3_access_point : uri => ap.arn }
}

在这个迭代中,我们生成一个从data_uribucket_name的映射,以便您可以在需要时访问这两个映射。当然,您仍然可以使用uri的toset版本并在资源中计算桶,但是由于您更喜欢这个方法,所以您可以访问其他地方的桶名,所以我使用了映射。

在创建资源之后,我们生成一个输出,即从data_uri到访问点arn的映射。

票数 3
EN

Stack Overflow用户

发布于 2022-08-15 17:31:14

函数文档包括一个包含用于匹配URL的方案和权限部分的模式的示例,这是对RFC 3986附录B中给出的模式的简化。

regex(“^(?:(?P^:/?#+))”?(?://(?P^/?#*))?“,”https://terraform.io/docs/"“{ "terraform.io”方案“= "https”}

这些S3 URL似乎遵循通常的URL生成,因此解析这些URL的一种方法是通过相同的regex模式运行它们:

代码语言:javascript
复制
> regex("^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?", "s3://my_bucket/model.tar.gz")
{
  "authority" = "my_bucket"
  "scheme" = "s3"
}

为此,我首先从local.inference获得一个新值,该值扩展了这些URL:

代码语言:javascript
复制
locals {
  data_uris = [
    for o in local.inference : merge(
      {uri = o.data_uri},
      regex("^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?", o.data_uri),
    )
  ]
}

上面的merge是将regex结果与原始输入URI组合起来,为每个输入获得一个简单的对象:

代码语言:javascript
复制
[
  {
    uri       = "s3://my_bucket/model.tar.gz",
    scheme    = "s3"
    authority = "my_bucket"
  },
  {
    uri       = "s3://my_bucket_2/model.tar.gz",
    scheme    = "s3"
    authority = "my_bucket_2"
  },
  {
    uri       = "s3://my_bucket_3/model.tar.gz",
    scheme    = "s3"
    authority = "my_bucket_3"
  },
]

然后,我们可以在for_each中进行更多的过滤/投影,将其转换为一组桶名,如果没有设置var.create,则将它们全部过滤掉,并跳过任何不是S3 URL的内容:

代码语言:javascript
复制
resource "aws_s3_access_point" "s3_access_point" {
  for_each = toset([
    for ap in local.data_uris : ap.authority
    if var.enabled && ap.scheme == "s3"
  ])

  bucket = each.key
  name   = "${each.key}-access-point"
}

在这里使用regex显然并不理想,因为很不清楚regex模式正在做什么。如果您继续这样做,那么我建议包括源代码注释,注意这个regex正在解析URI,并可能链接到RFC 3986附录B来解释该模式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73340731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档