amazon-web-servicesaws-cloudformation

CloudFormation Select ImageId based on Instance Family


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?


Solution

  • As recognized by @Paolo and @Marcin, !Select can't be used inside a !FindInMap. The full instance type (ie: t4g.small) can't be used as keys inside the Mappings section either, since they contain non alpha-numeric characters.

    I feel like this is a better solution, rather than trying to split the instance type (t4g.small) to find the Instance Family, it constructs the InstanceType from an InstanceFamily + InstanceSize. That way, we can use the InstanceFamily inside the Mappings.

    AWSTemplateFormatVersion: 2010-09-09
    Description: My Server
    Parameters:
    
      InstanceFamily:
        Description: "Instance Family ie: t4g, t3a, m5)"
        Type: String
        AllowedValues:
          - t2
          - t3
          - t3a
          - t4g
    
      InstanceSize:
        Description: "Instance Size (micro, small, medium, large)"
        Type: String
        AllowedValues:
          - micro
          - small
          - medium
          - large
    
    Mappings:
      AmiMap:
        ## Last Updated 2022-07-01
        us-east-1:
          ## AMD64 Instances. Ubuntu 22.04 us-east-1
          t2:   ami-0f65ab0fd913bc7be 
          t3:   ami-0f65ab0fd913bc7be
          t3a:  ami-0f65ab0fd913bc7be
    
          ## Graviton (ARM) Instances Ubuntu 22.04 us-east-1
          t4g:   ami-0cf2a935e8b19b29b
    
    Resources:
      LaunchConfig:
        Type: AWS::AutoScaling::LaunchConfiguration
        Properties:
          AssociatePublicIpAddress: true
          BlockDeviceMappings:
             ...
          ImageId: !FindInMap
            - AmiMap
            - "us-east-1"
            - !Ref InstanceFamily
          InstanceType: !Join ['.', [!Ref InstanceFamily, !Ref InstanceSize]]
          InstanceMonitoring: false
          ...