Javier Mr
Javier Mr

Reputation: 2210

Cloud formation configuration depending on the region being created

Which is the best approach for having a cloud formation template (CFT) use different values for configuration in the mappings depending on the region it's being created?

For example, let's assume I have a service deployed in 2 different regions (Europe and America). Each instance of the service writes to its own DynamoDB (DDB) table, lets call it Data. In order to create the DDB I use a CFT. Since the traffic is not the same in both regions I would like to set different capacity units for the table.

For the above, I could add a parameter to the CFT to state if the template is for Europe or America, create a mapping with the desired valued keyed by the parameter value, and depending on it get one or the other.

Like:

AWSTemplateFormatVersion: 2010-09-09
Resources:
  DdbData:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      TableName: 'Data'
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: !FindInMap
          - DdbDataCapacityUnits
          - 'Read'
          - !Ref Continent
        WriteCapacityUnits: !FindInMap
          - DdbDataCapacityUnits
          - 'Write'
          - !Ref Continent
Mappings:
  DdbDataCapacityUnits:
    Read:
        Europe: '10'
        America: '5'
    Write:
        Europe: '5'
        America: '10'
Parameters:
  Continent:
    Description: The continent in which the stack is being created, either Europe or America
    Type: String
    AllowedValues:
      - Europe
      - America
    Default: Europe

However, since I'm managing multiple regions with the same CFT I would like to use StacksSets to update both of them as one. The stacks for the stack set all have the same parameters, is just that the creation its done in multiple regions.

My approach was to use the pseudoparameter AWS::Region as the key in the configuration mapping like:

AWSTemplateFormatVersion: 2010-09-09
Resources:
  DdbData:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      TableName: 'Data'
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: !FindInMap
          - DdbDataCapacityUnits
          - 'Read'
          - !Ref AWS::Region
        WriteCapacityUnits: !FindInMap
          - DdbDataCapacityUnits
          - 'Write'
          - !Ref AWS::Region
Mappings:
  DdbDataCapacityUnits:
    Read:
      'eu-west-1': '10'
      'us-east-1': '5'
    Write:
      'eu-west-1': '5'
      'us-east-1': '10'

But this approach doesn't work as I get on error when creating the stack: Template validation error: Template format error: Mappings attribute name 'eu-west-1' must contain only alphanumeric characters.

Is there any approach in which I can achieve this?

Upvotes: 1

Views: 605

Answers (1)

John Rotenstein
John Rotenstein

Reputation: 269881

You can swap the region and the Read/Write attribute.

For example, here is a mapping for finding AMIs:

Mappings:
  AmazonLinuxEcsAMI:
    us-east-1:
      AMI: ami-07eb698ce660402d2
    us-east-2:
      AMI: ami-0a0c6574ce16ce87a
    us-west-1:
      AMI: ami-04c22ba97a0c063c4
    us-west-2:
      AMI: ami-09568291a9d6c804c

It can then be used with:

ImageId: !FindInMap [AmazonLinuxEcsAMI, !Ref 'AWS::Region', AMI]

So, try putting the region as the first level instead of Read, then putting Read and Write as the next level.

Upvotes: 4

Related Questions