AWS - Decouple configuration from code
Tags: aws, javascript, configdata, appconfig
Published: 2022-05-08 17:23:22

**Requirement**
- Separate configuration from application code.
- Application code has to pickup any changes to configuration data immediately.

**AWS AppConfig**
- Feature of AWS Systems Manager service.
- AppConfig allows to quickly deploy configurations.
- Allows configuration formats like text / json / file from s3 etc.
- Applications that was using Tridion and migrating to AWS can make use of AWS AppConfig which is powerful than Tridion. 
- AWS AppConfig can be used with applications hosted on Amazon EC2 instances, AWS Lambda, containers etc.

**Creating configuration data in AWS AppConfig** 
This [link](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-working.html) walks through step by step creation and deployment of Configuration using AWS AppConfig.
To follow along this blog - use below settings while setup.
- Use Freeform Configuration profile type
- Application Name: BlogConfig
- Environment Name: prod
- Configuration Name: productRollout

**Configuration data**
Follow above link to deploy below JSON configuration data to AppConfig.
```
{
  "newProductRolloutFlag": true,  
  "newProductRolloutStates": ["IL","CA"]
}
```

**How to access configuration data from  AppConfig**
Two ways - API from AWS SDK and Lambda Extension

**AWS SDK**
It's a two step process:
Without diving into extensive details, on a high level...
1. Establish configuration session using _StartConfigurationSession_ API - this returns _InitialConfigurationToken_ to be passed to the below API for first time.
2. _GetLatestConfiguration_ API - this returns the latest configuration data from AppConfig along with _NextPollConfigurationToken_ to be passed in subsequent call.

My personal choice is using **AppConfig Lambda Extension** - this is a performant and developer friendly way.

**AppConfig Lambda extension**
AWS has built a lambda extension for AppConfig - Below are the steps to add AppConfig Lambda Extension as a lambda layer in AWS console UI.
Goto AWS Lambda Service -> Add Lambda layer -> Choose a Layer -> AWS layers -> AWS-AppConfig-Extension -> Add the latest version shown.

**Sample Code**
```
//index.js (NodeJS runtime)
const http = require('http');
const params = process.env.APPCONFIG_PROFILE.split('/')
//Sample APPCONFIG_PROFILE value: "BlogConfig/prod/productRollout"
const AppConfigApplication = params [0]; //BlogConfig
const AppConfigEnvironment = params [1]; //prod
const AppConfigConfiguration = params [2] //productRollout

function getConfiguration(application, environment, configuration) {
    return new Promise((resolve, reject) => {
        const req = http.get(`http://localhost:2772/applications/${application}/environments/${environment}/configurations/${configuration}`, (res) => {
            if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error('statusCode=' + res.statusCode));
            }
            var body = [];
            res.on('data', function(chunk) {
                body.push(chunk);
            });
            res.on('end', function() {
                resolve(Buffer.concat(body).toString());
            });
        });
        req.on('error', (e) => {
            reject(e.message);
        });
        req.end();
    });
}

exports.handler = async (event) => {
  try {
    const configData = await getConfiguration(AppConfigApplication, AppConfigEnvironment, AppConfigConfiguration);    
    const parsedConfigData = JSON.parse(configData);
    console.log(parsedConfigData);
    
    if(parsedConfigData.newProductRolloutFlag && parsedConfigData.newProductRolloutStates.includes("IL")) {
        console.log("Running newProduct feature");
        /*
        NEW PRODUCT ROLLOUT IMPLEMENTATION
        */
    }
  } catch (err) {
      console.error(err);
      return err;
  } 
}; 
```
Above example show cased the Seperation of Configuration data from source code as well as how Lambda immediately picks up changes to configuration data from AWS AppConfig.

Image by <a href="https://pixabay.com/users/absolutvision-6158753/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2692247">Gino Crescoli</a> from <a href="https://pixabay.com//?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2692247">Pixabay</a>