Home > Software engineering >  CloudFormation Select ImageId based on Instance Family
CloudFormation Select ImageId based on Instance Family

Time:07-07

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:

  1. Modifying the allowed values for the parameters to have only alphanumeric characters
  2. 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]]]]]]
  • Related