将 Terraform 中创建的参数传递到 CloudFormation 时出现问题

Posted

技术标签:

【中文标题】将 Terraform 中创建的参数传递到 CloudFormation 时出现问题【英文标题】:Problem passing parameters created in Terraform to CloudFormation 【发布时间】:2021-02-17 11:45:55 【问题描述】:

使用之前 SO 帖子中的指导:[https://***.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,但由于我直接将其传入,因此我尝试将其删除。

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

【问题讨论】:

【参考方案1】:

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

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

    删除 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

【讨论】:

以上是关于将 Terraform 中创建的参数传递到 CloudFormation 时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

由 Terraform 在 LocalStack 中创建的 DynamoDB 表在 NoSQL Workbench 中不可见

在 Redux thunk 中创建的数组未正确传递到状态树

terraform - 将 vpc_id 参数从不同的 VPC 传递到多个子网

如何将在我的 Javascript 中创建的字符串数组传递给 C# 代码隐藏文件?

您如何将 main 中创建的实例传递给类?

将一个函数中创建的 PHP 变量传递给另一个函数