Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloudformation & Parameter Store: How to select parameter for the environment

I want to read the URL of my database from parameter store in my CloudFormation template. This is easy enough for a single URL, but I can't figure out how to change the URL with different environments.

I have four environments (development, integration, pre-production and production) and their details are stored on four different paths in Parameter Store:

/database/dev/url
/database/int/url
/database/ppe/url
/database/prod/url

I now want to pick the correct Database URL when deploying via CloudFormation. How can I do this?

Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - int
      - ppe
      - prod
  DatabaseUrl:
    Type: 'AWS::SSM::Parameter::Value<String>'
    # Obviously the '+' operator here won't work - so what do I do?
    Default: '/database/' + Environment + '/url'
like image 685
Frederik Avatar asked Feb 09 '18 11:02

Frederik


2 Answers

This feature isn't as neat as one would wish. You have to actually pass name/path of each parameter that you want to look up from the parameter store.

Template:

AWSTemplateFormatVersion: 2010-09-09

Description: Example

Parameters:

  BucketNameSuffix:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /example/dev/BucketNameSuffix

Resources:

  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub parameter-store-example-${BucketNameSuffix}

If you don't pass any parameters to the template, BucketNameSuffix will be populated with the value stored at /example/dev/BucketNameSuffix. If you want to use, say, a prod value (pointed to by /example/prod/BucketNameSuffix), then you should specify value for parameter BucketNameSuffix, but instead of passing the actual value you should pass the alternative name of the parameter to use, so you'd pass /example/prod/BucketNameSuffix.

aws cloudformation update-stack --stack-name example-dev \
--template-body file://./example-stack.yml

aws cloudformation update-stack --stack-name example-prod \
--template-body file://./example-stack.yml \
--parameters ParameterKey=BucketNameSuffix,ParameterValue=/example/prod/BucketNameSuffix

A not so great AWS blog post on this: https://aws.amazon.com/blogs/mt/integrating-aws-cloudformation-with-aws-systems-manager-parameter-store/

Because passing million meaningless parameters seems stupid, I might actually generate an environment-specific template and set the right Default: in the generated template so for prod environment Default would be /example/prod/BucketNameSuffix and then I can update the prod stack without passing any parameters.

like image 52
jbasko Avatar answered Nov 03 '22 17:11

jbasko


You can populate CloudFormation templates with parameters stored in AWS Systems Manager Parameter Store using Dynamic References

In this contrived example we make two lookups using resolve:ssm and replace the environment using !Join and !Sub

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Environment:
    Type: String
    Default: prod
    AllowedValues:
      - prod
      - staging
Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ContainerDefinitions:
        Image: !Join
          - ''
          -   - 'docker.io/bitnami/redis@'
              - !Sub '{{resolve:ssm:/app/${Environment}/digest-sha/redis}}'
        Environment:
          - Name: DB_HOST
            Value: !Sub '{{resolve:ssm:/app/${Environment}/db-host}}'
like image 1
Tim Avatar answered Nov 03 '22 18:11

Tim