#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"
}
}
}