Module Terraform:从模块中提取标记值

Module Terraform:从模块中提取标记值,module,terraform,lookup,Module,Terraform,Lookup,我有一个标签模块,我想从中查找terraform 0.13.2中资源的值 tags.tf module "tags" { source = "git::ssh://git@blah.git?ref=v0.2.3" product = var.product tag3 = var.tag3 tag4 =

我有一个标签模块,我想从中查找terraform 0.13.2中资源的值

tags.tf

    module "tags" {
      source             = "git::ssh://git@blah.git?ref=v0.2.3"
      product            = var.product
      tag3               = var.tag3
      tag4               = var.tag4
      tag5               = var.tag5
      tag6               = var.tag6
      tag7               = "tag7"
      tag8               = "tag8"
      tag9               = "tag9"
      tag10              = "tag10"
      componentInfo      = "componentinfo"
    }
app.tf

  tags = {
      source        = lookup(module.tags.tags,"source")
      componentInfo = lookup(module.tags.tags,"componentInfo") 
  }
但是,当我运行此命令时,我得到:

    10:39:06        Error: Invalid function argument
    10:39:06        
    10:39:06        
    10:39:06        Warning: Value for undeclared variable
    10:39:06        
    10:39:06        The root module does not declare a variable named "aws_env" but a value was
    10:39:06        found in file "vars/egdp-dev-us-east-1.tfvars". To use this value, add a
    10:39:06        "variable" block to the configuration.
    10:39:06        
    10:39:06        Using a variables file to set an undeclared variable is deprecated and will
    10:39:06        become an error in a future release. If you wish to provide certain "global"
    10:39:06        settings to all configurations in your organization, use TF_VAR_...
    10:39:06        environment variables to set these instead.
    10:39:06        
    10:39:06        
    10:39:06        Warning: Deprecated Resource
    10:39:06        
    10:39:06        The null_data_source was historically used to construct intermediate values to
    10:39:06        re-use elsewhere in configuration, the same can now be achieved using locals
    10:39:06        
    10:39:06          on avro-gen-layer.tf line 30, in resource "aws_s3_bucket_object" "avro-gen-bucket":
    10:39:06          30:       source        = lookup(module.tags.tags,"source")
    10:39:06            |----------------
    10:39:06            | module.tags.tags is object with 16 attributes
    10:39:06        
    10:39:06        Invalid value for "inputMap" parameter: the given object has no attribute
    10:39:06        "source".
我在运行terraform版本0.12.3的github的其他地方也看到过同样的代码模式。为了简洁起见,我删去了这个例子

以下工作;但是,为我试图配置的s3 bucket定义了太多的标记,因此我只想将其筛选为最重要的标记:

  tags = merge(
    module.tags.tags,
    {
        "Name" = "datahub_producer_td"
    }
  )
任何帮助都将不胜感激

更新

我忽略了源是一个有自己输出的地形模块。源不是这些输出中的一个,因此第一次查找不会工作,因为它不是一个输出,但似乎componentInfo应该有,但得到了相同的错误

这是该模块的output.tf

output.tf

    data "null_data_source" "tags" {
      count = length(keys(local.all_tags))
    
      inputs = {
        key                 = element(keys(local.all_tags), count.index)
        value               = element(values(local.all_tags), count.index)
        propagate_at_launch = "true"
      }
    }
    
    output "tags" {
      value = local.all_tags
    }
    
    output "asg_tags" {
      value = data.null_data_source.asg_tags.*.outputs
    }

您将标记模块视为一个映射,因此应使用
局部变量
来处理映射对象,如下所示:

locals {
  tags = {
    source  = "source"
    product = "product"
  }
}


# Example usages:

resource "a_resource" "my_resource" {
  lookup_tags = {
      source  = lookup(local.tags,"source")
      product = lookup(local.tags,"product") 
  }

  local_tags = local.tags

  merge_tags = merge(
    local.tags,
    {
        "Name" = "datahub_producer_td"
    }
  )
}

如果您确实需要使用模块,那么您应该有一个返回映射的输出

output "tags" {
  value = {
    source  = "source"
    product = "product"
  }
}
好的,那么“source”在标签模块中是而不是,就是这样,而且宾果是这样的,日志上说的:facepalm:。另外,
“组件信息”
的索引是
“组件信息”

如果我将这些属性移动到局部变量,然后使用命令行控制台
terraform控制台
来探索变量,那么就更容易看到发生了什么,果然module.tags.tags是一个具有17个属性的对象,就像它所说的那样

为了使它更简洁,我寻找了一种python称之为“字典理解”的方法,我发现

我无法找到如何将if子句用于属性过滤器;但是,我能够过滤列表,然后过滤属性:

tags = merge(
    module.tags.tags,
    {
        "Name" = local.artifact
    }
)
s3_keys = [for k in keys(local.tags):k if contains([
    "ComponentInfo"],k)]
s3_tags = {for k in local.s3_keys: k => local.tags[k]}
通过这种方式,可以搜索并仅选择特定对象所需的标记,因为并非所有对象都具有相同的标记要求

当然,这项工作可能更适合标记模块


另外,
lookup(module.tags.tags,“ComponentInfo”)
也可以工作

如何定义
标记
模块?您是否在其中输出任何标记?如上所示-未定义任何输出。我认为我不需要它,因为它不是子模块或根模块。我刚刚检查了示例,查找代码就在那里——与13.2版相同。我一定是遗漏了什么……我补充了我试图纠正的原始问题;s3 bucket的标签太多了。我不明白你怎么没有输出,但是你可以引用
module.tags.tags
,得到一个有16个属性的对象。您必须在tags模块内声明名为
tags
的输出才能实现这一点。我觉得你没有展示所有的代码。同样,这句话:“它不是子模块或根模块”对我来说毫无意义,一个模块除了根的子模块或另一个模块的子模块之外还能是什么?还不清楚您包含的任何代码实际上是如何解决“bucket有太多标记”的根本问题的。你确定这就是全部代码吗?我现在看到我的module tags.tf只定义了11个属性。哪里有16个?另外,如果需要输出,为什么消息会说有一个具有16个属性的tags对象。还有,为什么合并工作正常?我确实需要弄清11和16之间的差异。虽然我缩短了我的标记示例,但日志显示有16个属性(虽然我只定义了11个),并且这些属性合并得很好,正如我所说的。问题是-如果这些属性存在,那么为什么它们不可用于插值。今晚晚些时候我将尝试这一方法,看看它是否有效。我看到了问题,模块的结构似乎只是属性;然而,来源:“git::ssh://git@blah.git?ref=v0.2.3“定义输出。稍后,当我开始工作时……我通过使用更新版本的git::ssh://git@blah.git定义的输出较少,并使用merge。然而;我仍然无法筛选已定义的标记。如日志所示,有一个具有16个属性的模块(定义为输出,我当时不知道);有没有办法使用插值来选择其中一个?