Как передать список AZ из Terraform в шаблон CloudFormation?

#amazon-web-services #terraform #amazon-cloudformation

Вопрос:

У меня есть шаблон CloudFormation, который определяет этот параметр:

         "AvailabilityZones" : {
            "Description" : "List of Availability Zones used ... ",
            "Type" : "List<AWS::EC2::AvailabilityZone::Name>"
        },

 

Я вызываю шаблон CF следующим образом:

 resource "aws_cloudformation_stack" "xxx" {

  name = "xxx-stack"

  template_body = file("../cloudformation/xxx_CloudFormation_template_2.1.1.json")

  parameters = {
    VpcId                = aws_vpc.xxxvpc.id
    SubnetCidrBlock      = var.aws_vpc_cidr 
    AvailabilityZones    = var.aws_azs
    InstanceType         = "m5.4xlarge"
    ExternalNet          = "0.0.0.0/0"
    ....
  }

  on_failure = "DELETE"
}
 

Где:

 variable "aws_azs" {
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
 

Я получаю сообщение об ошибке:

 Inappropriate value for attribute "parameters": element "AvailabilityZones": string required.
 

Я перепробовал много вариантов этой темы, но я не вижу, как передать список AZS в шаблон CF из TF.

Я также более чем немного озадачен утверждением о том, что в сообщении об ошибке требуется строка, поскольку тип параметра в шаблоне CF определяется как список.

Пожалуйста, есть идеи?

Ответ №1:

Я бы предпочел использовать templatefile функцию вместо той file , которую вы используете в template_body полевых условиях. Вы можете передавать туда переменные и заполнять шаблон переданными переменными с помощью nice template engine. Там можно использовать переменные, функции, операторы и циклы.

Пример здесь https://www.terraform.io/docs/language/functions/templatefile.html

Ваш пример

 resource "aws_cloudformation_stack" "xxx" {

  ....

  template_body = templatefile("../cloudformation/xxx_CloudFormation_template_2.1.1.json", {
 aws_azs = var. aws_azs
})

  ....
}

 

и ваш файл cf:

  "AvailabilityZones" : {
            "Description" : "List of Availability Zones used ${join(',', aws_azs)} ",
            "Type" : "List<AWS::EC2::AvailabilityZone::Name>"
        },
 

Комментарии:

1. Спасибо. Я понимаю идею. Недостатком является то, что мне приходится редактировать шаблон CF, который поступает от третьей стороны. В идеале я мог бы достичь того, что мне нужно, без редактирования самого шаблона CF.

Ответ №2:

Чтобы передать список значений из Terraform в CloudFormation, вам нужно будет объединить их в виде списка, разделенного запятыми.

TL; DR

 resource "aws_cloudformation_stack" "this" {
  ...
  parameters = {
    AvailabilityZones = join(",", ["us-east-1a", "us-east-1b", "us-east-1c"])
  }

}
 

Объяснение

Чтобы передать списки объектов в шаблон CloudFormation, вам нужно будет либо передать собственную конструкцию, либо список значений, разделенных запятыми.

https://aws.amazon.com/premiumsupport/knowledge-center/multiple-values-list-parameter-cli/

Рассмотрим, что у нас есть шаблон CloudFormation cfn-template.yml , который требует, чтобы мы передавали список AZ в качестве параметра:

 AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  AvailabilityZones:
    Description: List of Availability Zones used ...
    Type: "List<AWS::EC2::AvailabilityZone::Name>"
Resources:
  NullResource: # CF needs at least 1 resource, so we hand it a dummy
    Type: "AWS::CloudFormation::WaitConditionHandle"
Outputs:
  PassedAvailabilityZones:
    Description: The AZs passed into the cfn template from Terraform.
    Value: !Join [ ",", !Ref AvailabilityZones ]
 

В вашей terraform нам нужно будет создать разделенную запятыми строку этих значений и передать их в блоке параметров.

 variable "aws_azs" {
  type    = list(string)
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

resource "aws_cloudformation_stack" "this" {
  name = "test-pass-azs"

  parameters = {
    AvailabilityZones = join(",", var.aws_azs)
  }

  template_body = file("./cfn-template.yml")
}

terraform {
  required_version = "~> 1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}