Ejemplos de Fn::ForEach en la sección Resources - AWS CloudFormation

Ejemplos de Fn::ForEach en la sección Resources

Estos ejemplos son una demostración del uso de la función intrínseca Fn::ForEach en la sección Sintaxis de Resources de la plantilla de CloudFormation.

Replicación de un recurso de Amazon SNS

Este fragmento de ejemplo muestra una lista de cuatro temas de Amazon SNS, con el ID lógico correspondiente a los elementos de la colección (Success, Failure, Timeout, Unknown), con un valor de TopicName coincidente y FifoTopic establecido en true.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Parameters": { "pRepoARNs": { "Description": "ARN of SSO instance", "Type": "CommaDelimitedList" } }, "Resources": { "Fn::ForEach::Topics": [ "TopicName", { "Ref": "pRepoARNs" }, { "SnsTopic${TopicName}": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": { "Fn::Join": [ ".", [ { "Ref": "TopicName" }, "fifo" ] ] }, "FifoTopic": true } } } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Parameters: pRepoARNs: Description: ARN of SSO instance Type: CommaDelimitedList Resources: 'Fn::ForEach::Topics': - TopicName - !Ref pRepoARNs - 'SnsTopic${TopicName}': Type: 'AWS::SNS::Topic' Properties: TopicName: 'Fn::Join': - '.' - - !Ref TopicName - fifo FifoTopic: true

La plantilla transformada será equivalente a la plantilla siguiente:

{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "SnsTopicSuccess": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": "Success.fifo", "FifoTopic": true } }, "SnsTopicFailure": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": "Failure.fifo", "FifoTopic": true } }, "SnsTopicTimeout": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": "Timeout.fifo", "FifoTopic": true } }, "SnsTopicUnknown": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": "Unknown.fifo", "FifoTopic": true } } } }

Replicación de un recurso de Amazon DynamoDB

En este fragmento de ejemplo se crean cuatro recursos AWS::DynamoDB::Table con nombres como Points, Score, etc.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Resources": { "Fn::ForEach::Tables": [ "TableName", ["Points", "Score", "Name", "Leaderboard"], { "DynamoDB${TableName}": { "Type": "AWS::DynamoDB::Table", "Properties": { "TableName": { "Ref": "TableName" }, "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" } ], "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "ProvisionedThroughput": { "ReadCapacityUnits": "5", "WriteCapacityUnits": "5" } } } } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: 'Fn::ForEach::Tables': - TableName - [Points, Score, Name, Leaderboard] - 'DynamoDB${TableName}': Type: 'AWS::DynamoDB::Table' Properties: TableName: !Ref TableName AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: '5' WriteCapacityUnits: '5'

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: DynamoDBPoints: Type: 'AWS::DynamoDB::Table' Properties: TableName: Points AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: '5' WriteCapacityUnits: '5' DynamoDBScore: Type: 'AWS::DynamoDB::Table' Properties: TableName: Score AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: '5' WriteCapacityUnits: '5' DynamoDBName: Type: 'AWS::DynamoDB::Table' Properties: TableName: Name AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: '5' WriteCapacityUnits: '5' DynamoDBLeaderboard: Type: 'AWS::DynamoDB::Table' Properties: TableName: Leaderboard AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: '5' WriteCapacityUnits: '5'

Replicación de varios recursos

En este ejemplo se crean varias instancias de AWS::EC2::NatGateway y AWS::EC2::EIP con la convención de nomenclatura “{ResourceType}${Identifier}”. Puede declarar varios tipos de recursos en un bucle Fn::ForEach para utilizar un único identificador.

nota

En el ejemplo siguiente se supone que existen las condiciones TwoNatGateways y ThreeNatGateways y que están definidos los recursos PublicSubnetA, PublicSubnetB y PublicSubnetC.

nota

Los valores únicos de cada elemento de la colección se definen en la sección de asignaciones, donde se usa la función intrínseca Fn::FindInMap para hacer referencia al valor correspondiente. Si Fn::FindInMap no puede encontrar el identificador correspondiente, la propiedad Condition no se establecerá y se resolverá en !Ref ‘AWS:::NoValue.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Mappings": { "NatGateway": { "Condition": { "B": "TwoNatGateways", "C": "ThreeNatGateways" } } }, "Resources": { "Fn::ForEach::NatGatewayAndEIP": [ "Identifier", [ "A", "B", "C" ], { "NatGateway${Identifier}": { "Type": "AWS::EC2::NatGateway", "Properties": { "AllocationId": { "Fn::GetAtt": [ { "Fn::Sub": "NatGatewayAttachment${Identifier}" }, "AllocationId" ] }, "SubnetId": { "Ref": { "Fn::Sub": "PublicSubnet${Identifier}" } } }, "Condition": { "Fn::FindInMap": [ "NatGateway", "Condition", { "Ref": "Identifier" }, { "DefaultValue": { "Ref": "AWS::NoValue" } } ] } }, "NatGatewayAttachment${Identifier}": { "Type": "AWS::EC2::EIP", "Properties": { "Domain": "vpc" }, "Condition": { "Fn::FindInMap": [ "NatGateway", "Condition", { "Ref": "Identifier" }, { "DefaultValue": { "Ref": "AWS::NoValue" } } ] } } } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::LanguageExtensions Mappings: NatGateway: Condition: B: TwoNatGateways C: ThreeNatGateways Resources: Fn::ForEach::NatGatewayAndEIP: - Identifier - - A - B - C - NatGateway${Identifier}: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt - !Sub NatGatewayAttachment${Identifier} - AllocationId SubnetId: !Ref Fn::Sub: PublicSubnet${Identifier} Condition: !FindInMap - NatGateway - Condition - !Ref Identifier - DefaultValue: !Ref AWS::NoValue NatGatewayAttachment${Identifier}: Type: AWS::EC2::EIP Properties: Domain: vpc Condition: !FindInMap - NatGateway - Condition - !Ref Identifier - DefaultValue: !Ref AWS::NoValue

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::LanguageExtensions Resources: NatGatewayA: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt - NatGatewayAttachmentA - AllocationId SubnetId: !Ref PublicSubnetA NatGatewayB: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt - NatGatewayAttachmentB - AllocationId SubnetId: !Ref PublicSubnetB Condition: TwoNatGateways NatGatewayC: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt - NatGatewayAttachmentC - AllocationId SubnetId: !Ref PublicSubnetC Condition: ThreeNatGateways NatGatewayAttachmentA: Type: AWS::EC2::EIP Properties: Domain: vpc NatGatewayAttachmentB: Type: AWS::EC2::EIP Properties: Domain: vpc Condition: TwoNatGateways NatGatewayAttachmentC: Type: AWS::EC2::EIP Properties: Domain: vpc Condition: ThreeNatGateways

Replicación de varios recursos mediante bucles Fn::ForEach anidados

En este ejemplo se usan bucles Fn::ForEach anidados para asignar tres recursos (AWS::EC2::NetworkAcl, AWS::EC2::Subnet y AWS::EC2::SubnetNetworkAclAssociation) entre sí.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": "10.0.0.0/16", "EnableDnsSupport": "true", "EnableDnsHostnames": "true" } }, "Fn::ForEach::SubnetResources": [ "Prefix", [ "Transit", "Public" ], { "Nacl${Prefix}Subnet": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" } } }, "Fn::ForEach::LoopInner": [ "Suffix", [ "A", "B", "C" ], { "${Prefix}Subnet${Suffix}": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" } } }, "Nacl${Prefix}Subnet${Suffix}Association": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": { "Fn::Sub": "${Prefix}Subnet${Suffix}" } }, "NetworkAclId": { "Ref": { "Fn::Sub": "Nacl${Prefix}Subnet" } } } } } ] } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: 'true' EnableDnsHostnames: 'true' 'Fn::ForEach::SubnetResources': - Prefix - [Transit, Public] - 'Nacl${Prefix}Subnet': Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref 'VPC' 'Fn::ForEach::LoopInner': - Suffix - [A, B, C] - '${Prefix}Subnet${Suffix}': Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref 'VPC' 'Nacl${Prefix}Subnet${Suffix}Association': Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref 'Fn::Sub': '${Prefix}Subnet${Suffix}' NetworkAclId: !Ref 'Fn::Sub': 'Nacl${Prefix}Subnet'

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: 'true' EnableDnsHostnames: 'true' NaclTransitSubnet: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC TransitSubnetA: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclTransitSubnetAAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref TransitSubnetA NetworkAclId: !Ref NaclTransitSubnet TransitSubnetB: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclTransitSubnetBAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref TransitSubnetB NetworkAclId: !Ref NaclTransitSubnet TransitSubnetC: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclTransitSubnetCAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref TransitSubnetC NetworkAclId: !Ref NaclTransitSubnet NaclPublicSubnet: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC PublicSubnetA: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclPublicSubnetAAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref PublicSubnetA NetworkAclId: !Ref NaclPublicSubnet PublicSubnetB: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclPublicSubnetBAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref PublicSubnetB NetworkAclId: !Ref NaclPublicSubnet PublicSubnetC: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC NaclPublicSubnetCAssociation: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref PublicSubnetC NetworkAclId: !Ref NaclPublicSubnet

Referencia a propiedades replicadas para un recurso de Amazon EC2

En este ejemplo se usa la función intrínseca Fn::ForEach para hacer referencia a recursos AWS::EC2::Instance replicados.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Mappings": { "Instances": { "InstanceType": { "B": "m5.4xlarge", "C": "c5.2xlarge" }, "ImageId": {"A": "ami-id1"} } }, "Resources": { "Fn::ForEach::Instances": [ "Identifier", [ "A", "B", "C" ], { "Instance${Identifier}": { "Type": "AWS::EC2::Instance", "Properties": { "InstanceType": { "Fn::FindInMap": [ "Instances", "InstanceType", {"Ref": "Identifier"}, {"DefaultValue": "m5.xlarge"} ] }, "ImageId": { "Fn::FindInMap": [ "Instances", "ImageId", {"Ref": "Identifier"}, {"DefaultValue": "ami-id-default"} ] } } } } ] }, "Outputs": { "SecondInstanceId": { "Description": "Instance Id for InstanceB", "Value": {"Ref": "InstanceB"} }, "SecondPrivateIp": { "Description": "Private IP for InstanceB", "Value": { "Fn::GetAtt": [ "InstanceB", "PrivateIp" ] } } } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Mappings: Instances: InstanceType: B: m5.4xlarge C: c5.2xlarge ImageId: A: ami-id1 Resources: 'Fn::ForEach::Instances': - Identifier - [A, B, C] - 'Instance${Identifier}': Type: 'AWS::EC2::Instance' Properties: InstanceType: !FindInMap [Instances, InstanceType, !Ref 'Identifier', {DefaultValue: m5.xlarge}] ImageId: !FindInMap [Instances, ImageId, !Ref 'Identifier', {DefaultValue: ami-id-default}] Outputs: SecondInstanceId: Description: Instance Id for InstanceB Value: !Ref 'InstanceB' SecondPrivateIp: Description: Private IP for InstanceB Value: !GetAtt [InstanceB, PrivateIp]

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: InstanceA: Type: 'AWS::EC2::Instance' Properties: InstanceType: m5.xlarge ImageId: ami-id1 InstanceB: Type: 'AWS::EC2::Instance' Properties: InstanceType: m5.4xlarge ImageId: ami-id-default InstanceC: Type: 'AWS::EC2::Instance' Properties: InstanceType: c5.2xlarge ImageId: ami-id-default Outputs: SecondInstanceId: Description: Instance Id for InstanceB Value: !Ref InstanceB SecondPrivateIp: Description: Private IP for InstanceB Value: !GetAtt [InstanceB, PrivateIp]

Replicación de propiedades de un recurso de Amazon EC2

En este ejemplo se usa la función intrínseca Fn::ForEach para repetir algunas propiedades como ImageId, InstanceType y AvailabilityZone en un recurso AWS::EC2::Instance.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Mappings": { "InstanceA": { "Properties": { "ImageId": "ami-id1", "InstanceType": "m5.xlarge" } }, "InstanceB": { "Properties": { "ImageId": "ami-id2" } }, "InstanceC": { "Properties": { "ImageId": "ami-id3", "InstanceType": "m5.2xlarge", "AvailabilityZone": "us-east-1a" } } }, "Resources": { "Fn::ForEach::Instances": [ "InstanceLogicalId", [ "InstanceA", "InstanceB", "InstanceC" ], { "${InstanceLogicalId}": { "Type": "AWS::EC2::Instance", "Properties": { "DisableApiTermination": true, "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash\n", "yum update -y\n", "yum install -y httpd.x86_64\n", "systemctl start httpd.service\n", "systemctl enable httpd.service\n", "echo \"Hello World from $(hostname -f)\" > /var/www/html/index.html\n" ] ] } }, "Fn::ForEach::Properties": [ "PropertyName", [ "ImageId", "InstanceType", "AvailabilityZone" ], { "${PropertyName}": { "Fn::FindInMap": [ { "Ref": "InstanceLogicalId" }, "Properties", { "Ref": "PropertyName"}, { "DefaultValue": { "Ref": "AWS::NoValue" } } ] } } ] } } } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Mappings: InstanceA: Properties: ImageId: ami-id1 InstanceType: m5.xlarge InstanceB: Properties: ImageId: ami-id2 InstanceC: Properties: ImageId: ami-id3 InstanceType: m5.2xlarge AvailabilityZone: us-east-1a Resources: 'Fn::ForEach::Instances': - InstanceLogicalId - [InstanceA, InstanceB, InstanceC] - '${InstanceLogicalId}': Type: 'AWS::EC2::Instance' Properties: DisableApiTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd.x86_64 systemctl start httpd.service systemctl enable httpd.service echo "Hello World from $(hostname -f)" > /var/www/html/index.html 'Fn::ForEach::Properties': - PropertyName - [ImageId, InstanceType, AvailabilityZone] - '${PropertyName}': 'Fn::FindInMap': - Ref: 'InstanceLogicalId' - Properties - Ref: 'PropertyName' - {DefaultValue: !Ref 'AWS::NoValue'}

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Resources: InstanceA: Type: 'AWS::EC2::Instance' Properties: DisableApiTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd.x86_64 systemctl start httpd.service systemctl enable httpd.service echo "Hello World from $(hostname -f)" > /var/www/html/index.html ImageId: ami-id1 InstanceType: m5.xlarge InstanceB: Type: 'AWS::EC2::Instance' Properties: DisableApiTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd.x86_64 systemctl start httpd.service systemctl enable httpd.service echo "Hello World from $(hostname -f)" > /var/www/html/index.html ImageId: ami-id2 InstanceC: Type: 'AWS::EC2::Instance' Properties: DisableApiTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd.x86_64 systemctl start httpd.service systemctl enable httpd.service echo "Hello World from $(hostname -f)" > /var/www/html/index.html ImageId: ami-id3 InstanceType: m5.2xlarge AvailabilityZone: us-east-1a

Transferencia de caracteres no alfanuméricos en Collection para Fn::ForEach

En este ejemplo, se utiliza la sintaxis &{}, que permite que los caracteres no alfanuméricos (. y /) de las direcciones IP se pasen dentro de la Collection.

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::LanguageExtensions", "Parameters": { "IpAddresses": { "Type": "CommaDelimitedList", "Default": "10.0.2.0/24,10.0.3.0/24,10.0.4.0/24" } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": "10.0.0.0/16", "EnableDnsSupport": "true", "EnableDnsHostnames": "true" } }, "Fn::ForEach::Subnets": [ "CIDR", { "Ref": "IpAddresses" }, { "Subnet&{CIDR}": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "CidrBlock": { "Ref": "CIDR" } } } } ] } }

YAML

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Parameters: IpAddresses: Type: CommaDelimitedList Default: '10.0.2.0/24,10.0.3.0/24,10.0.4.0/24' Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: 'true' EnableDnsHostnames: 'true' 'Fn::ForEach::Subnets': - CIDR - !Ref IpAddresses - 'Subnet&{CIDR}': Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: !Ref CIDR

La plantilla transformada será equivalente a la plantilla siguiente:

AWSTemplateFormatVersion: 2010-09-09 Transform: 'AWS::LanguageExtensions' Parameters: IpAddresses: Type: CommaDelimitedList Default: '10.0.2.0/24,10.0.3.0/24,10.0.4.0/24' Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: 'true' EnableDnsHostnames: 'true' Subnet1002024: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: 10.0.2.0/24 Subnet1003024: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: 10.0.3.0/24 Subnet1004024: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: 10.0.4.0/24