Reputation: 2210
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
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