DEV Community

Ran Isenberg for AWS Heroes

Posted on • Originally published at ranthebuilder.cloud

1

Deploy AWS AppConfig Configuration with the New L2 CDK Constructs

Photo by Shashank Kumawat: [https://www.pexels.com/photo/assorted-color-banners-on-mountain-893975/](https://www.pexels.com/photo/assorted-color-banners-on-mountain-893975/)

In this post, I’ll guide you through deploying AWS AppConfig configurations using the AWS Cloud Development Kit (CDK) and the new AppConfig L2 constructs (higher abstraction).

We will deploy a JSON configuration for feature flags’ usage for serverless and non-serverless applications alike with Python CDK code.

[https://www.ranthebuilder.cloud/](https://www.ranthebuilder.cloud/)

[https://www.buymeacoffee.com/ranthebuilder](https://www.buymeacoffee.com/ranthebuilder)

This blog post was originally published on my website, “Ran The Builder.”

Quick AppConfig Introduction

AWS AppConfig is a self-managed service that stores plain TEXT/YAML/JSON configuration to be consumed by multiple clients.

Let’s look at AppConfig’s advantages:

  1. FedRAMP High certified

  2. Fully Serverless

  3. Out-of-the-box support for schema validations that run before a configuration update.

  4. Out-of-the-box integration with AWS CloudWatch alarms triggers an automatic configuration revert if a configuration update fails your AWS Lambda functions. Read more about it here.

  5. You can define configuration deployment strategies. Deployment strategies define how and when to change a configuration. Read more about it here.

  6. It provides a single API that fetches configuration.

If you’ve read my previous AppConfig posts, you know that I use AWS Lambda Powertools feature flags utility to fetch and evaluate AppConfig configurations.

Our Goal

We aim to deploy a JSON freeform configuration that we can use with the AWS Lambda Powertools feature flags utility.

The construct I present here will deploy a JSON configuration to AppConfig as a freeform configuration with a zero wait time deployment strategy.

For production accounts, you should use a canary deployment profile and configure JSON validations and a CloudWatch alarm to trigger an automatic rollback in case of service errors during configuration deployment.

If you want to learn about best practices for feature flags and how to use, build, and test feature flags, check out my two posts about them:

Let’s go ahead and write some code.

Python Dependencies

To consume the new L2 construct, which contains better abstractions, add the following statements to your poetry file:

[tool.poetry.dev-dependencies]
# CDK
aws-cdk-lib = ">=2.93.0"
constructs = ">=10.0.0"
"aws-cdk.aws-appconfig-alpha" = "^2.93.0-alpha.0"
view raw pyproject.toml hosted with ❤ by GitHub

Be aware that we are using an alpha construct, which might break or contain bugs. Use it at your discretion. However, after testing it, I can confirm it works as expected at the time of writing, and it’s already part of the AWS Lambda Handler Cookbook project.

Configuration Construct

Let’s go over my new construct, which uses L2 higher abstractions constructs, thus reducing the overall effort to define AppConfig configurations:

import aws_cdk.aws_appconfig_alpha as appconfig
from aws_cdk import Duration, RemovalPolicy
from constructs import Construct
class ConfigurationStore(Construct):
def __init__(
self,
scope: Construct,
id_: str,
environment: str,
service_name: str,
configuration_name: str,
configuration_str: str,
) -> None:
"""
This construct should be deployed in a different repo and have its own
pipeline so updates can be decoupled from
running the service pipeline and without redeploying the service lambdas.
Args:
scope (Construct): The scope in which to define this construct.
id_ (str): The scoped construct ID. Must be unique.
environment (str): AppConfig environment name to create.
service_name (str): AppConfig application name to create.
configuration_name (str): AppConfig configuration name to create.
configuration_str (str): AppConfig configuration content to create.
"""
super().__init__(scope, id_)
self.app_name = f'{id_}{service_name}'
self.config_app = appconfig.Application(
self,
id=self.app_name,
name=self.app_name,
)
self.config_app.apply_removal_policy(RemovalPolicy.DESTROY)
self.config_env = appconfig.Environment(
self,
id=f'{id_}env',
application=self.config_app,
name=environment,
)
self.config_env.apply_removal_policy(RemovalPolicy.DESTROY)
# zero minutes, zero bake, 100 growth all at once
self.config_dep_strategy = appconfig.DeploymentStrategy(
self,
f'{id_}zero',
rollout_strategy=appconfig.RolloutStrategy.linear(
growth_factor=100,
deployment_duration=Duration.minutes(0),
final_bake_time=Duration.minutes(0),
),
)
self.config_dep_strategy.apply_removal_policy(RemovalPolicy.DESTROY)
self.config = appconfig.HostedConfiguration(
self,
f'{id_}version',
application=self.config_app,
name=configuration_name,
content=appconfig.ConfigurationContent.from_inline(configuration_str),
type=appconfig.ConfigurationType.FREEFORM,
deployment_strategy=self.config_dep_strategy,
deploy_to=[self.config_env],
)
# workaround until https://github.com/aws/aws-cdk/issues/26804 is resolved
self.config.node.default_child.apply_removal_policy(RemovalPolicy.DESTROY) # type: ignore
view raw appconfig.py hosted with ❤ by GitHub

Our construct requires several input parameters:
  1. id_ (str): The scoped construct ID. It must be unique.

  2. Environment (str): AppConfig environment name to create.

  3. service_name (str): AppConfig application name to create.

  4. configuration_name (str): AppConfig configuration name to create.

  5. configuration_str (str): AppConfig configuration content to create

In lines 33–40, we create the AppConfig application; in line 40, we set the removal policy to destroy. You will have a similar approach applied to all resources.

In lines 41–48, we define the AWS AppConfig environment.

In lines 51–61, we define the AppConfig deployment strategy. I chose an immediate deployment (zero minutes for bake and deployment times), but you should use the canary deployment options or define your own for production workloads. Read the docs here.

In lines 63–75, we define the configuration to deploy and connect all the resources.

Notice how I chose line 69, the freeform type. You must use freeform for usage with the Powertools feature flags utility.

In line 68, we provide the configuration string we got as a construct input parameter.

Line 75 is a workaround until the removal policy is set and exposed correctly (see the link to the CDK issue).

Bottom line:

The new L2 constructs are a welcome edition as they reduce the total amount of code and the overall complexity, but I suggest that you create your own construct that wraps these L2 constructs into one or use the example I provided here.

For other information and connecting advanced features such as JSON validators, extensions, and CloudWatch alarm, refer to the official documentation below:

https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_appconfig_alpha.html

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

Imagine monitoring that's actually built for developers

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay