Terraform 使用数据源输出动态生成字符串

Posted

技术标签:

【中文标题】Terraform 使用数据源输出动态生成字符串【英文标题】:Terraform dynamically generate strings using data sources output 【发布时间】:2022-01-04 19:32:00 【问题描述】:

有什么方法可以将 Terraform 数据源输出作为输入提供给另一个 Terraform 文件

场景是,我有一个 terraform 代码来使用数据源获取特定标签(此处为 jenkins)的私有 IP 地址(此处为 3 个 IP 10.1.1.1,10.1.1.2,10.1.1.3)

data "aws_instances" "mytag" 
    filter 
        name = "tag:Application"
        values = ["jenkins"]
    


output "output from aws" 
    value = data.aws_instances.mytag_private_ips

每当我应用 terraform 时,在 下面的 metric-filter 代码应该能够从上面的代码中获取结果 IP,并使其在实时状态下可用(aws 控制台)

resource "aws_cloudwatch_log_metric_filter" "test" 
    name = "test-metric-filter"
    pattern = "[w1,w2,w3,w4!=\"*<IP1>*\"&&w4!=\"*<IP2>*\"&&w4!=\"*<IP3>*\",w5=\"*admin*\"]"
    log_group_name = var.test_log_group_name

    metric_transformation 
      name ="test-metric-filter"
      namespace = "General"
    

因此,aws 控制台中 metric 模式的最终结果应该如下所示

[w1,w2,w3,w4!="*10.1.1.1*"&&w4!="*10.1.1.2*"&&w4!="*10.1.1.3*",w5="*admin*"]

最终目标是每当生成新 IP 时,它将被填充为模式(在 aws-console 中),而无需更改指标过滤器代码。

感谢任何帮助,因为我在 terraform 上找不到任何精确的文档,允许我们使用数据源动态生成字符串

【问题讨论】:

这么少的代码为什么要两个文件? 【参考方案1】:

您正在寻找的是 Terraform 中的 string interpolation。

我相信你会想要做以下事情:

pattern = "[w1,w2,w3,w4!=\"*$data.aws_instances.mytag.private_ips[0]*\"&&w4!=\"*$data.aws_instances.mytag.private_ips[1]*\"&&w4!=\"*$data.aws_instances.mytag.private_ips[2]*\",w5=\"*admin*\"]"

我建议谨慎使用此语句,因为如果您没有至少 3 个实例,它将失败。你会想要一些动态的东西。

【讨论】:

【参考方案2】:

不知道为什么这么简单的事情需要两个文件... 这是我会做的:

provider "aws" 
  region = "us-east-1"


data "aws_instances" "test" 
  filter 
    name   = "architecture"
    values = ["x86_64"]
  


resource "aws_cloudwatch_log_metric_filter" "test" 
  name    = "test-metric-filter"
  pattern = "[w1,w2,w3,w4!=\"*$data.aws_instances.test.private_ips[0]*\",w5=\"*admin*\"]"
  log_group_name = "test_log_group_name"

  metric_transformation 
    name      = "test-metric-filter"
    namespace = "General"
    value     = 1
  

然后会显示一个 terraform 计划

Terraform will perform the following actions:

  # aws_cloudwatch_log_metric_filter.test will be created
  + resource "aws_cloudwatch_log_metric_filter" "test" 
      + id             = (known after apply)
      + log_group_name = "test_log_group_name"
      + name           = "test-metric-filter"
      + pattern        = "[w1,w2,w3,w4!=\"*172.31.70.170*\",w5=\"*admin*\"]"

      + metric_transformation 
          + name      = "test-metric-filter"
          + namespace = "General"
          + unit      = "None"
          + value     = "1"
        
    

Plan: 1 to add, 0 to change, 0 to destroy.

连接字符串很简单:"foo $var.bar 123" 在这种情况下,我们的 private_ips 是一个数组,所以我们需要 [x]

对于更复杂的连接,请查看格式函数:https://www.terraform.io/docs/language/functions/format.html

我确实更改了过滤器以便能够在我的环境中进行测试,并且还使用了比您的更短的模式,但这是您需要的基础,只需添加更多的 make changes 以满足您的需求。

【讨论】:

以上是关于Terraform 使用数据源输出动态生成字符串的主要内容,如果未能解决你的问题,请参考以下文章

您如何在应用程序代码中引用动态 terraform 输出?

Terraform - 如何将列表转换为地图(如何使用 terraform 获取 AMI 标签)

动静态链接库

如何从 Terraform 输出中传递值而不将其放入 tfvars 文件中

如何使用 terraform 生成 yml 配置文件

Terraform 查找函数 - 错误:应为数字,实际类型为字符串