Yaml file for CloudFormation - select which subnet ids to put lambdas in

25 Views Asked by At

I'm trying to put my lambdas in the appropriate VPC given the environment. How can that be achieved given I'm building the VPCs in a separate nested stack given the environment?

Using Github actions and sam deploy if that matters.

Parameters:
  environment:
    Type: String
  devLambdaSubnetIds:
    Type: String
    Default: !Join [',', subnet-[devVpcA], subnet-[devVpcB]]
  prodLambdaSubnetIds:
    Type: String
    Default: !Join [',', subnet-[prodVpcA], subnet-[prodVpcB]]
...
Resources:
 HealthCheckFunction:
    Type: AWS::Serverless::Function
    Properties:
        ...
        VpcConfig:
        Ipv6AllowedForDualStack: false
        SecurityGroupIds: 
          - !Ref genericSecurityGroup
        SubnetIds: HERE THIS NEEDS TO BE !Ref devLambdaSubnetIds or !Ref prodLambdaSubnetIds depending on the environment (which is either 'dev' or 'prod')
1

There are 1 best solutions below

0
ddtraveller On BEST ANSWER

You could use a mapping and keep config for each env in the mapping.

In the example below the subnet ids would need to be changed for real subnet ids.

Parameters:
  env:
    Type: String
    Description: Specify an account/environment
    AllowedValues:
      - dev
      - prod

Mappings:
  environments:
    dev:
      sb1: subnet-a
      sb2: subnet-b
    prod:
      sb1: subnet-c
      sb2: subnet-d

Resources:
  HealthCheckFunction:
    Type: AWS::Serverless::Function
    Properties:
      ...
      VpcConfig:
        Ipv6AllowedForDualStack: false
        SecurityGroupIds:
          - !Ref genericSecurityGroup
        SubnetIds:
          - !FindInMap [environments, !Ref env, sb1]
          - !FindInMap [environments, !Ref env, sb2]

You could alternately store the subnet ids in param store at paths like;

/myapp/dev/subnet1
/myapp/dev/subnet2
/myapp/prod/subnet1
/myapp/prod/subnet2

Then, reference them in your template like this;

          - !Sub '{{resolve:ssm:/myapp/${env}/subnet1}}'
          - !Sub '{{resolve:ssm:/myapp/${env}/subnet2}}'

You could use conditions as well.

Conditions:
  IsDevEnvironment: !Equals [!Ref env, 'dev']

Then add in the condition to the resource. You would need two distinct resources, one for dev and one for prod then, though.

  HealthCheckFunctionDevelopment:
    Type: AWS::Serverless::Function
    Condition: IsDevEnvironment
    Properties:
      ...
      VpcConfig:
        Ipv6AllowedForDualStack: false
        SecurityGroupIds:
          - !Ref genericSecurityGroup
        SubnetIds:
          - subnet1-harcoded
          - subnet2-harcoded