AWS SAM & Parameter Store: How to select parameter for the deployment into different environments
S

3

6

I have a setup where I am using CodeCommit as my repository to store lambda functions and CodePipeline using AWS SAM to deploy and create lambda functions.

I would like to deploy the lambda functions into different environments such as QA, staging, and Prod. I have used the AWS Parameters store to reference my variables.

Below is my template.yaml file that I have set up that creates a lambda function and it uses AWS parameter store to reference the vairables

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Test    

Parameters:
  BucketName:
    Description: 'Required. Bucket Name'
    Type: 'AWS::SSM::Parameter::Value<String>'
    Default: 'MyBucketname' 

  CSVPath:
    Description: 'Required. Configkey Name'
    Type: 'AWS::SSM::Parameter::Value<String>'
    Default: 'MyCSVPath' 

Resources:
    GetOrdersFunction:
        Type: AWS::Serverless::Function 
        Properties:
            CodeUri: ./LambdaCode
            Handler: app.lambda_handler
            FunctionName: app
            Runtime: python3.6
            Description: 'staging'
            Environment: 
                Variables:
                    BucketName: !Ref BucketName
                    CSVPath: !Ref CSVPath
            Events:
              HelloWorld:
                    Type: Api
                    Properties:
                        Path: /orders
                        Method: get  

I am able to define variables in my template.yaml for deployment but I am not sure how I can define it for different environments (prod or qa).

When the pipeline triggers it should deploy to QA environment using QA variables and deploy to prod using prod variables which will be defined in AWS Parameter store

What changes should I make in my template.yaml file to enable deploying to different environments?

Sendai answered 29/1, 2021 at 21:7 Comment(2)
do you have one code pipeline per environment or at least different stage or action per environment ? you can pass ParameterOverrides from codepipeline to pass right parameter values {"BucketName":"/BUCKETNAME/DEV","CSVPath":"/CSVPATH/DEV"}Sandbag
yes i have one code pipeline per environmentSendai
O
7

As Meir has mentioned, You can use parameters and condition functionality in cloudformation to do that, for example, you will add a parameter section as follow:

Parameters:
  Stage:
    Type: String
    Default: staging
    Description: Parameter for getting the deployment stage

then a mapping section with a map to hold the environment variables for all your stages

Mappings:
  StagesMap:
    staging:
      CONFIG_BUCKET: staging-bucket-name
      CONFIG_KEY: source-data-key-path
    prod:
      CONFIG_BUCKET: prod-bucket-name
      CONFIG_KEY: source-data-key-path

then your function can use the variables based on which environment you are in:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: CD Demo Lambda
Resources:
  CDDemoLambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
      CodeUri: ./LambdaCode
      FunctionName: ApigatewayLambda
      AutoPublishAlias: ApiLambda
      Description: 'Lambda function validation'
      MemorySize: 128
      Timeout: 30
      Events:
        ApiEvent:
          Type: Api
          Properties:
            Path: /getazs
            Method: get
      Environment:
        Variables:
          CONFIG_BUCKET: !FindInMap
            - StagesMap
            - Ref: Stage
            - CONFIG_BUCKET
          CONFIG_KEY: !FindInMap
            - StagesMap
            - Ref: Stage
            - CONFIG_KEY

Now when you are calling your sam to deploy command, you need to define which stage you are deploying to. ex:

sam deploy --parameter-overrides Stage=prod

Your complete cloudformation template should look like this:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: CD Demo Lambda

Parameters:
  Stage:
    Type: String
    Default: staging
    Description: Parameter for getting the deployment stage

Mappings:
  StagesMap:
    staging:
      CONFIG_BUCKET: staging-bucket-name
      CONFIG_KEY: source-data-key-path
    prod:
      CONFIG_BUCKET: prod-bucket-name
      CONFIG_KEY: source-data-key-path


Resources:
  CDDemoLambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
      CodeUri: ./LambdaCode
      FunctionName: ApigatewayLambda
      AutoPublishAlias: ApiLambda
      Description: 'Lambda function validation'
      MemorySize: 128
      Timeout: 30
      Events:
        ApiEvent:
          Type: Api
          Properties:
            Path: /getazs
            Method: get
      Environment:
        Variables:
          CONFIG_BUCKET: !FindInMap
            - StagesMap
            - Ref: Stage
            - CONFIG_BUCKET
          CONFIG_KEY: !FindInMap
            - StagesMap
            - Ref: Stage
            - CONFIG_KEY
Oshinski answered 31/1, 2021 at 7:58 Comment(1)
thank you, this was what i really need for my setup :)Sendai
A
2

You're looking for the mappings and FindInMap functionality. Take a look at the examples and switch between RegionMap to EnvMap, it will fit perfectly for your use case.

The expectation here is that according to a given argument (Parameter) a set of variables will be taken, this is exactly what mapping does.

Arne answered 29/1, 2021 at 21:20 Comment(0)
S
2

CloudFormation template default parameters can be overridden from code pipeline by passing parameterOverrides

From Console:

  • Add/Edit Action

  • Action provider Cloudformation

  • Action Mode

  • Create/Update a stack

  • Advanced -> Parameter Overrides

    {"BucketName":"/BUCKETNAME/DEV","CSVPath":"/CSVPATH/DEV"}
    

If codepipeline is created from a Cloudformation template:

                  - Name: DeployMyStack
                    InputArtifacts:
                        - Name: Artifacts
                    ActionTypeId:
                        Category: Deploy
                        Owner: AWS
                        Version: 1
                        Provider: CloudFormation
                    Configuration:
                        ActionMode: 'CREATE_UPDATE'
                        Capabilities: CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND
                        ParameterOverrides: !Sub
                            - '{"BucketName":"/BUCKETNAME/${Env}","CSVPath":"/CSVPATH/${Env}'
                            - {
                                  Env: !Ref Environment,
                              }
                        RoleArn: !Ref CloudFormationServiceRoleArn
                        StackName: !Sub
                            - Gl${ENV}-My-Stack
                            - { ENV: !Ref Environment }
                        TemplatePath: 'Artifacts::MyTemplate.yaml'
Sandbag answered 29/1, 2021 at 23:12 Comment(6)
Hi thanks for your response, would this also work for AWS SAM as that is what is being used for the deployment of lambda functionsSendai
If I understand it right, you using sam to build and deploy lambdas. But where are you running command sam deploy ?Sandbag
I am creating sam template.yaml which then gets used by CodePipline. it uses codebuild which integrates with cloud formation and code deploy to deploy the lambda functionsSendai
my question remains that I want to use the same template.yaml file for my prod, QA, and test envs. How would I then define the parameterOveride in the .yaml as this will all be set up using the codepipline?Sendai
parameterOveride will not be defined in your current template. But the template used to create codepipeline. If you are creating codepipeline manually, then you need to pass in parameterOveride from console.Sandbag
thank you, i have found it on the console where to define that. many thanks :)Sendai

© 2022 - 2024 — McMap. All rights reserved.