title: Passing a list of KeyValuePairs to AWS Cloudformation template
body: <p>I am building a cloudformation template for a bunch (~75) of microservices running in ECS. There is a top-level template that includes all the microservices as nested stacks. Instead of creating dozens of different template files for each of the services I would like all of the microservices to use the same <code>microservice.yaml</code> template and use parameters to define which microservice to run.</p>
  
  <pre><code>AWSTemplateFormatVersion: '2010-09-09'
  Description: Deploy a service into an ECS cluster
  Parameters:
    ServiceName:
      Type: String
    ImageUrl:
      Type: String
    LogLevel:
      Type: String
      Default: debug
    NodeEnv:
      Type: String
      Default: integration
  
  Resources:
    TaskDefinition:
      Type: AWS::ECS::TaskDefinition
      Properties:
        RequiresCompatibilities: 
          - EC2
        ContainerDefinitions:
          - Name: !Ref 'ServiceName'
            Image: !Ref 'ImageUrl'
            Environment:
              - Name: LOG_LEVEL
                Value: !Ref 'LogLevel'
              - Name: NODE_ENV
                Value: !Ref 'NodeEnv'
  
    Service:
      Type: AWS::ECS::Service
      Properties:
        ServiceName: !Ref 'ServiceName'
        Cluster: !ImportValue production-infrastructure:ECSClusterName
        DesiredCount: 1
        TaskDefinition: !Ref 'TaskDefinition'
  </code></pre>
  
  <p>In <code>master.yaml</code> I will list all of the services like so:</p>
  
  <pre><code>FooBarMicroservice:
    Type: AWS::CloudFormation::Stack
    Properties:
      Parameters:
        ServiceName: fooBarMicroservice
        ImageUrl: !Join ['' , [ !Ref 'ECRHost', '/fooBarMicroservice']]
      TemplateURL: "https://mybucket.s3.amazonaws.com/cloudformation-templates/microservice.yaml"
  </code></pre>
  
  <p>The problem is that many of the microservices require additional unique environment variables. What I've done until now is add all the possible variables to the one template with default values of <code>''</code>. But now the <code>TaskDefinition</code> is beginning to look like this:</p>
  
  <pre><code>TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      RequiresCompatibilities: 
        - EC2
      ContainerDefinitions:
        - Name: !Ref 'ServiceName'
          Image: !Ref 'ImageUrl'
          Environment:
            - Name: LOG_LEVEL
              Value: !Ref 'LogLevel'
            - Name: NODE_ENV
              Value: !Ref 'NodeEnv'
            - Name: SMTP
              Value: !Ref 'SMTP'
            - Name: ACME_CLIENT_ID
              Value: !Ref 'AcmeClientId'
            - Name: ACME_SECRET
              Value: !Ref 'AcmeSecret'
            - Name: ACME_TIMEOUT
              Value: !Ref 'AcmeTimeout'
            - Name: FOO_WEBHOOK_ROUTE
              Value: !Ref 'FooWebhookRoute'
            - Name: EXPIRES_IN
              Value: !Ref 'expiresIn'
            ...
            ...
  </code></pre>
  
  <p>For any given microservice, most of those are just empty environment variables. This is becoming very unwieldy and confusing.</p>
  
  <p>Ideally, I'd like to be able to pass a list of KeyValuesPairs to the <code>microservice.yaml</code> with all of the unique environment variables. Something like this (that does not work):</p>
  
  <pre><code>FooBarMicroservice:
    Type: AWS::CloudFormation::Stack
    Properties:
      Parameters:
        ServiceName: fooBarMicroservice
        ImageUrl: !Join ['' , [ !Ref 'ECRHost', '/fooBarMicroservice']]
        Env:
          - Name: ACME_CLIENT_ID
            Value: 'AE4051DE41'
          - Name: ACME_SECRET
            Value: 'TdUGm6GR&gt;nQp|q&lt;'
      TemplateURL: "https://mybucket.s3.amazonaws.com/cloudformation-templates/microservice.yaml"
  </code></pre>
  
  <p>and then join the <code>!Ref Env</code> list with the existing list of common env variables.</p>
  
  <p>I have searched high and low but have been unable to find a viable solution. The closest reference is from <a href="https://stackoverflow.com/questions/47821408/cloudformation-keyvaluepair-list-as-a-parameter">this question</a> almost two years ago with no relevant answer.</p>