如果数据源未找到任何结果,如何继续执行 Terraform?

How can I continue Terraform's execution if a data source does not find any results?

提问人:cien 提问时间:11/11/2023 最后编辑:Paolocien 更新时间:11/16/2023 访问量:99

问:

这个命令通过终端对我来说效果很好:

aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text

输出:

subnet-whatIwouldExpect

但是在 Terraform 中将其设置为变量完全是另一回事。

(我一直很高兴地使用 Terraform 计划/应用/销毁等)

data "external" "ssm_parameter_value" {
  program = ["bash", "-c", <<-EOF
    result=$(aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text)
    echo "{\"result\": \"$result\"}"
  EOF
  ]
}

output "ssm_parameter_result" {
  value = data.external.ssm_parameter_value.result
}

当我尝试 terraform refresh 时,我得到:

ssm_parameter_result = tomap({
  "result" = ""
})

这是非常令人沮丧的,我不知道我做错了什么。

这是我的整个文件:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.34.0"
    }
  }
  
  required_version = ">= 0.14.9"
}

provider "aws" {
  region = "eu-west-2"
  default_tags {
    tags = local.common_tags
  }
}

data "aws_caller_identity" "current" {}

data "aws_region" "current" {}

# Execute AWS CLI command to get SSM parameter value
data "external" "ssm_parameter_value" {
  program = ["bash", "-c", <<-EOF
    result=$(aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text)
    echo "{\"result\": \"$result\"}"
  EOF
  ]
}

output "ssm_parameter_result" {
  value = data.external.ssm_parameter_value.result
}

编辑:

我知道data "aws_ssm_parameter" "example" { name = "/A/B/C" }

但是,如果 AWS 上不存在 ParameterNotFound,则此操作将失败。

这似乎不是surpsa

我希望能够利用

data.external.ssm_parameter_value.result

以后要推动其他资源的创建/不创建,请执行以下操作:

例如

resource "aws_security_group_rule" "example" {  
  count = data.external.ssm_parameter_value.result != "" ? 1 : 0
  type              = "ingress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  security_group_id = data.external.ssm_parameter_value.result["result"]
  source_security_group_id = aws_security_group.another-sg.id
  
  description = "All Traffic from Lambda"
}
amazon-web-services terraform aws-cli

评论


答:

1赞 Paolo 11/11/2023 #1

正如 Mark 在他的回答中所解释的那样,如果可能,您应该使用特定于资源的数据源。但是,如果资源不存在,数据源将始终出错。几年前曾提出增强请求,请求更改此行为,但被拒绝。

因此,在这种情况下,外部源是一个有效的替代方案。data

外部数据源要求程序输出必须是 JSON 对象。在此示例中,您可以执行以下操作:

# Execute AWS CLI command to get SSM parameter value
data "external" "ssm_parameter_value" {
  program = ["bash", "-c", <<-EOF
    param=$(aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text 2>/dev/null);
    if [ "$?" -eq 0 ]; then 
      jq -r -n --arg param "$param" '{"param":$param}'
    else
      jq -r -n '{"param":""}'
    fi
  EOF
  ]
}

output "ssm_parameter_result" {
  value = data.external.ssm_parameter_value.result.param
}

如果密钥存在,则输出将为:

$ terraform apply
...
ssm_parameter_result = "foo"

如果密钥不存在,则输出将为:

$ terraform apply
...
ssm_parameter_result = ""

请注意,此方法需要创建 JSON 对象。jq

评论

0赞 cien 11/13/2023
这是一个比马克的评论好得多的评论,我很欣赏你所做的考虑