I'm trying to select an AMI dynamically based on the Instance Family. The instance family being determined from the first few letters (before the period) from the InstanceType.
I would think that the following CloudFormation snippet would work. It uses !Select and !Split to find the first few characters of the InstanceType. The Instance Family should be passed as the third argument to FindInMap. However, it fails with the error:
An error occurred (ValidationError) when calling the CreateStack operation: Template error: every Fn::FindInMap object requires three parameters, the map name, map key and the attribute for return value
AWSTemplateFormatVersion: 2010-09-09
Description: my new server
Parameters:
InstanceType:
Description: Instance Type
Type: String
AllowedValues:
- t2.micro
- t3a.small
- t3a.medium
- t4g.micro
- t4g.small
- t4g.medium
Mappings:
AmiMap:
us-east-1:
## AMD64 Instances
t2: ami-0f65ab0fd913bc7be
t3a: ami-0f65ab0fd913bc7be
## Graviton (ARM) Instances
t4g: ami-0cf2a935e8b19b29b
Resources:
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
...
ImageId: !FindInMap
- AmiMap
- "us-east-1"
- !Select [0, !Split [".", !Ref InstanceType ]]
Why isn't the !Select ... !Split
line returning a string for FindInMap
to recognize?
CodePudding user response:
This is because you can't use Select in FindInMap. You can only use Ref
and FindInMap
. From docs:
You can use the following functions in a Fn::FindInMap function:
Fn::FindInMap
Ref
CodePudding user response:
As Marcin mentioned, you can't use !Select
within a !FindInMap
statement.
I suspect the reason you tried to do it this way is because it's not possible to have the mapping keys with a non alphanumeric character (e.g. t2.micro
).
You can, however, achieve the desired behavior by:
- Modifying the allowed values for the parameters to have only alphanumeric characters
- Modifying the mapping keys accordingly
AWSTemplateFormatVersion: 2010-09-09
Description: my new server
Parameters:
InstanceType:
Description: Instance Type
Type: String
AllowedValues:
- t2micro
- t3asmall
- t3amedium
- t4gmicro
- t4gsmall
- t4gmedium
Mappings:
AmiMap:
us-east-1:
## AMD64 Instances
t2micro: ami-0f65ab0fd913bc7be
t3asmall: ami-0f65ab0fd913bc7be
## Graviton (ARM) Instances
t4gmicro: ami-0cf2a935e8b19b29b
Resources:
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
...
ImageId: !FindInMap
- AmiMap
- "us-east-1"
- !Ref InstanceType
now obviously, this implies that your parameter is no longer "properly" formatted for usage, therefore anytime you need to refer to the instance type you'll need to use a combination of !Split
and !Join
statements to re-introduce the .
:
InstanceType: !Join ['.', !Split ["micro", !Join ['.', !Split ["small", !Join ['.', !Split ["medium",!Ref InstanceType]]]]]]