首页 > 解决方案 > 将 Terraform 中创建的参数传递到 CloudFormation 时出现问题

问题描述

使用之前 SO 帖子中的指导:[https://stackoverflow.com/questions/43266506/is-it-possible-to-execute-a-cloudformation-file-in-terraform]:

我正在尝试将在 Terraform 模板中创建的两个参数作为参数传递到 Cloudformation 模板中:

我的 terraform (v.0.13.5) 代码:

    resource "aws_cloudformation_stack" "cloudwatch-synthetics-canary" {
      provider = aws.primary
      name          = "cloudwatch-synthetics"
      parameters = {
        CloudWatchSyntheticsRole = aws_iam_role.cloudwatch_synthetics_role.arn,
        ResultsBucket = aws_s3_bucket.results_bucket.arn
      }
      template_body = file("${path.module}/cloudwatch_canary.yml")
    }

resource "aws_iam_role" "cloudwatch_synthetics_role" {
  provider           = aws.primary
  name               = "CloudWatchSyntheticsRole"
  description        = "Allows Cloudwatch Lambda to operate in this account."
  assume_role_policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
    {
      "Sid": "AllowLambdaAssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_policy" "cloudwatch_synthetics_role_policy" {
  provider    = aws.primary
  name        = "CloudWatchSyntheticsRolePolicy"
  path        = "/"
  description = "Addtional allowances for the synthetics role"

  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [

    # --- SNIPPED FOR BREVITY ---

  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "cloudwatch_synthetics_role_policy_attachment" {
  provider = aws.primary
  role       = aws_iam_role.cloudwatch_synthetics_role.name
  policy_arn = aws_iam_policy.cloudwatch_synthetics_role_policy.arn
}

我的 Cloudformation 代码:

Parameters:
  CanaryName:
    Type: String
    Default: my-canary
    MaxLength: 21
  HostName:
    Type: String
    Default: api.myhost.net
    MaxLength: 128
  Path:
    Type: String
    Default: /v1/status
    MaxLength: 256
  Port:
    Type: Number
    Default: 443
  CloudWatchSyntheticsRole:
    Type: AWS::IAM::Role
  ResultsBucket:
    Type: AWS::S3::Bucket
...

Resources:
   ExecutionRoleArn:
      Fn::GetAtt:
         - CloudWatchSyntheticsRole
         - Arn             # <-- TRIED WITH AND WITHOUT THIS

在 Terraform.io 中,错误如下:

Error: Creating CloudFormation stack failed: ValidationError: Template error: instance of Fn::GetAtt references undefined resource CloudWatchSyntheticsRole
    status code: 400, request id: 694c...

我尝试将 CFT 中的类型设为字符串,但这似乎也不起作用。Fn::GetAtt: 在 CloudwatchSyntheticsRole 下方也有 '- Arn' 来指代 Arn,但由于我直接将其传递,因此我尝试将其删除。

我觉得我很接近,但缺少一些东西,只需要一些新鲜的眼睛的帮助。

标签: parameter-passingterraformamazon-cloudformationterraform-provider-aws

解决方案


看起来我的一位同事找到的解决方案非常简单:

  1. 确保所有 CFT 变量都在 Terraform 中,并通过 Terraform 将任何默认值作为文字传递给 Cloudformation

  2. 从 CloudFormation 中删除所有默认参数,但仍将变量的名称和类型保持在最低限度。像“MaxLength”这样的其他约束也可以。

例子:

Terraform.tf:

resource "aws_cloudformation_stack" "cloudwatch-synthetics-canary" {
  provider = aws.primary
  name          = "cloudwatch-synthetics"
  parameters = {
    CanaryName = "my-canary",
    HostName = "api.server.net",
    Path = "/v1/status",
    Port = 443,
    RoleArn = aws_iam_role.cloudwatch_synthetics_role.arn,
    S3Location = "s3://${aws_s3_bucket.results_bucket.id}"
  }
  template_body = file("${path.module}/cloudwatch_canary.yml")
}

Cloudformation.yml:

Parameters:
  CanaryName:
    Type: String
    MaxLength: 21
  HostName:
    Type: String
    MaxLength: 128
  Path:
    Type: String
    MaxLength: 256
  Port:
    Type: Number
  RoleArn:
    Type: String
  S3Location:
    Type: String
    MaxLength: 1024

推荐阅读