5

Can anyone provide or point at an AWS-CDK/typescript example provisioning an AWS AppConfig app/env/config consumed by a lambda please? Could not find anything meaningful online.

Maxim Suponya
  • 1,419
  • 2
  • 20
  • 43

2 Answers2

5

A little late to this party, If anyone is coming to this question, looking for a quick answer, here you go:

AppConfig Does Not Have Any Official L2 Constructs

  • This means that one has to work with L1 constructs currently vended here
  • This is ripe for someone authoring an L2/L3 construct (I am working on vending this custom construct soon - so keep an eye out on updates here).
  • This does not mean its hard to use AppConfig in CDK, its just that unlike L2/L3 constructs, we have to dig deeper into setting AppConfig up reading their documentation.

A Very Simple Example (YMMV)

Here is a custom construct I have to setup AppConfig:

import {
  CfnApplication,
  CfnConfigurationProfile,
  CfnDeployment,
  CfnDeploymentStrategy,
  CfnEnvironment,
  CfnHostedConfigurationVersion,
} from "aws-cdk-lib/aws-appconfig";
import { Construct } from "constructs";

// 1. https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appconfig-readme.html - there are no L2 constructs for AppConfig.
// 2. https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-working.html- this the CDK code from this console setup guide.
export class AppConfig extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    // create a new app config application.
    const testAppConfigApp: CfnApplication = new CfnApplication(
      this,
      "TestAppConfigApp",
      {
        name: "TestAppConfigApp",
      }
    );

    // you can customize this as per your needs.
    const immediateDeploymentStrategy = new CfnDeploymentStrategy(
      this,
      "DeployStrategy",
      {
        name: "ImmediateDeployment",
        deploymentDurationInMinutes: 0,
        growthFactor: 100,
        replicateTo: "NONE",
        finalBakeTimeInMinutes: 0,
      }
    );

    // setup an app config env
    const appConfigEnv: CfnEnvironment = new CfnEnvironment(
      this,
      "AppConfigEnv",
      {
        applicationId: testAppConfigApp.ref,
        // can be anything that makes sense for your use case.
        name: "Production",
      }
    );

    // setup config profile
    const appConfigProfile: CfnConfigurationProfile = new CfnConfigurationProfile(
      this,
      "ConfigurationProfile",
      {
        name: "TestAppConfigProfile",
        applicationId: testAppConfigApp.ref,
        // we want AppConfig to manage the configuration profile, unless we need from SSM or S3.
        locationUri: "hosted",
        // This can also be "AWS.AppConfig.FeatureFlags"
        type: "AWS.Freeform",
      }
    );

    // Update AppConfig
    const configVersion: CfnHostedConfigurationVersion = new CfnHostedConfigurationVersion(
      this,
      "HostedConfigurationVersion",
      {
        applicationId: testAppConfigApp.ref,
        configurationProfileId: appConfigProfile.ref,
        content: JSON.stringify({
          someAppConfigResource: "SomeAppConfigResourceValue",
          //... add more as needed.
        }),
        // https://www.rfc-editor.org/rfc/rfc9110.html#name-content-type
        contentType: "application/json",
      }
    );

    // Perform deployment.
    new CfnDeployment(this, "Deployment", {
      applicationId: testAppConfigApp.ref,
      configurationProfileId: appConfigProfile.ref,
      configurationVersion: configVersion.ref,
      deploymentStrategyId: immediateDeploymentStrategy.ref,
      environmentId: appConfigEnv.ref,
    });
  }
}

Here is what goes inside my lambda handler (please note that you should have lambda layers enabled for AppConfig extension, see more information here):

const http = require('http');

exports.handler = async (event) => {
  
  const res = await new Promise((resolve, reject) => {
    http.get(
      "http://localhost:2772/applications/TestAppConfigApp/environments/Production/configurations/TestAppConfigProfile", 
      resolve
    );
  });
  let configData = await new Promise((resolve, reject) => {
    let data = '';
    res.on('data', chunk => data += chunk);
    res.on('error', err => reject(err));
    res.on('end', () => resolve(data));
  });
  const parsedConfigData = JSON.parse(configData);    
  return parsedConfigData;
};

EDIT: As promised, I released a new npm library : https://www.npmjs.com/package/cdk-appconfig, as of this update, this is still pre-release, but time permitting I will release a 1.x soon. But this will allow people to check out/fork if need be. Please share feedback/or open PRs if you'd like to collaborate.

uLYsseus
  • 995
  • 6
  • 16
  • 37
  • https://www.npmjs.com/package/cdk-appconfig – uLYsseus Feb 19 '23 at 10:54
  • Is it possible to add 2 config files to the same AppConfig construct? – Tirth Rami Apr 11 '23 at 15:43
  • @TirthRami sorry just seeing this after a while, yeah you can absolutely do so. For each AppConfig Application, you can add multiple configuration profiles. See the following: 1. https://github.com/JoeNonExotic/appconfig/blob/main/src/utils.ts#L84 (utilities from the library) 2. https://github.com/JoeNonExotic/appconfig/blob/main/src/simple-appconfig.ts (usage example) . Once you have an application you can add multiple config profiles. – uLYsseus May 26 '23 at 18:39
0

I have no experience with AWS AppConfig. But I would start here and here

nsquires
  • 899
  • 2
  • 8
  • 20
  • 1
    sidenote: as of 2023 you really do not want to use CDKv1. Just in case anyone looks at this link and doesn't see it. – thoroc Aug 11 '23 at 14:12