Skip to main content

CDK Organizer Python Library

This library contains the core features to handle CDK projects including:

  • Logging
  • Configuration Resolver
  • Stack Groups Loader
  • Naming Utils

Full documentation: https://cdk-organizer.github.io/

Installation

pip install cdk-organizer[terraform,aws]

Extras

  • terraform: Include cdktf as a dependency.
  • aws: Include aws-cdk-lib as a dependency.

CDK Start Script

The content of the app.py file should be as follows:

AWS CDK

import aws_cdk as cdk
from cdk_organizer.miscellaneous.logging import setup_logging
from cdk_organizer.stack_group import StackGroupLoader

app = cdk.App()
logger = setup_logging(__name__, app.node.try_get_context("loglevel") or "INFO")
loader = StackGroupLoader(app)

loader.synth()
app.synth()

CDK for Terraform

from cdk_organizer.miscellaneous.logging import setup_logging
from cdk_organizer.stack_group import StackGroupLoader
from cdktf import App

app = App()
logger = setup_logging(__name__, app.node.try_get_context("loglevel") or "INFO")
loader = StackGroupLoader(app)

loader.synth()
app.synth()

Context Variables

The following context variables are required to the CDK Organizer to work properly:

  • env
  • region

The variables can be set in the cdk.json file:

{
  ...
  "context": {
    ...
    "env": "dev",
    "region": "us-east-1"
    ...
  }
  ...
}

Or passed as arguments to the CDK CLI:

cdk synth --context env=dev --context region=us-east-1

In the cdktf CLI the context variables cannot be passed as arguments, so they need to be set in the cdk.json file. https://github.com/hashicorp/terraform-cdk/issues/2019 The env variable can also be set as an environment variable CDK_ENV.

Project Structure

To apply the pattern purposed in this library for CDK projects, the following structure is required:

.
+-- cdk.json
+-- app.py

Stack Structure

the stack class needs to inherit from class cdk_organizer.aws.stack.Stack for AWS CDK and cdk_organizer.terraform.stack.Stack for Terraform CDK.

AWS CDK

from constructs import Construct
from cdk_organizer.aws.stack import Stack
from cdk_organizer.aws.stack_group import StackGroup


class MyStack(Stack):
    def __init__(
        self,
        scope: Construct,
        id: str,
        stack_group: StackGroup,
        **kwargs
    ) -> None:
        super().__init__(scope, id, stack_group, **kwargs)

Terraform CDK

from constructs import Construct
from cdk_organizer.terraform.stack import Stack
from cdk_organizer.terraform.stack_group import StackGroup


class MyStack(Stack):
    def __init__(
        self,
        scope: Construct,
        id: str,
        stack_group: StackGroup,
        **kwargs
    ) -> None:
        super().__init__(scope, id, stack_group, **kwargs)

Using S3 Backend

To use S3 terraform backend, the following resources are required:

  • S3 Bucket
  • DynamoDB Table

Add the following object to the environment configuration file:

s3_backend:
  bucket: "<bucket-name>"
  region: "<aws-region>"
  dynamodb_table: "<dynamodb-table-name>"

Stack Group Structure

Create a stacks folder in the root of the project and structure it as follows:

.
+-- cdk.json
+-- app.py
+-- stacks/
| +-- <groupName>/
|   +-- stacks.py

The stack groups files follow this pattern:

AWS CDK

import aws_cdk as cdk
from dataclasses import dataclass
from cdk_organizer.aws.stack_group import StackGroup

@dataclass
class MyStackGroupConfig:
    domain: str
    ipv6: bool = True


class MyStackGroup(StackGroup[MyStackGroupConfig]):
    def _load_stacks(self) -> None:
        MyStack(
            self.app,
            self.get_stack_name('my-stack'),
            stack_group=self,
            parameters=MyStackParameters(
                domain=self.data.domain,
                ipv6=self.data.ipv6
            )
        )

Terraform

import cdktf
from dataclasses import dataclass
from cdk_organizer.terraform.stack_group import StackGroup

@dataclass
class MyStackGroupConfig:
    domain: str
    ipv6: bool = True


class MyStackGroup(StackGroup[MyStackGroupConfig]):
    def _load_stacks(self) -> None:
        MyStack(
            self.app,
            self.get_stack_name('my-stack'),
            stack_group=self,
            parameters=MyStackParameters(
                domain=self.data.domain,
                ipv6=self.data.ipv6
            )
        )

Using Stack Attributes from Other Stack Groups

In some cases, you may want to use the attributes of another stack group. For example, refer the DNS Hosted Zone created by a shared stack group.

To resolve the group use the self.resolve_group function in the stack group class, like the example below:

import aws_cdk as cdk
from dataclasses import dataclass
from cdk_organizer.aws.stack_group import StackGroup
from stacks.dns import DNSStackGroup

@dataclass
class MyStackGroupConfig:
    domain: str
    ipv6: bool = True


class MyStackGroup(StackGroup[MyStackGroupConfig]):
    def _load_stacks(self) -> None:
        MyStack(
            self.app,
            self.get_stack_name('my-stack'),
            stack_group=self,
            parameters=MyStackParameters(
                domain=self.data.domain,
                zone=self.resolve_group(DNSStackGroup).zone
                ipv6=self.data.ipv6
            )
        )

The function get_stack_name generates the stack name based on following pattern.

Pattern: {module_path}-{name}-{region}-{env}

Consider the following example:

module_path: myproject.myapp.www name: spa region: us-east-1 env: dev

Stack name will be:

  • myproject-myapp-www-spa-us-east-1-dev.

Config Structure

Create a config folder in the root of the project and structure it as follows:

.
+-- cdk.json
+-- app.py
+-- config/
| +-- <env>/
|   +-- config.yaml
|   +-- <region>/
|     +-- config.yaml
|     +-- <groupName>/
|         +-- config.yaml

The first two levels are reserved to the environment name and the region name, the next levels needs to match the stack group structure.

Example:

.
+-- cdk.json
+-- app.py
+-- config/
| +-- config.yaml
| +-- dev/
|   +-- config.yaml
|   +-- us-east-1/
|     +-- config.yaml
|     +-- app1/
|       +-- config.yaml
+-- stacks/
| +-- app1/
|   +-- stacks.py
+-- templates/
|   +-- stacks/

Examples

Release files for cdk-organizer 1.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cdk-organizer 1.11.0
File Size Uploaded
cdk_organizer-1.11.0.tar.gz 13.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cdk-organizer 1.11.0
File Interpreter ABI Platform
cdk_organizer-1.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.4 kB

Release files / cdk_organizer-1.11.0.tar.gz

Download URL cdk_organizer-1.11.0.tar.gz
Size 13.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ae8fae353b2195170b68089343d0a7608354cdee47a07db6020ca1f66884d2c0
BLAKE2b-256 checksum
How to use checksums
14c27fd91a96eaccae74907d095fad77c0b9b6395f41d7de097f67424933cf0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.5.1 CPython/3.9.5 Darwin/23.0.0

Release files / cdk_organizer-1.11.0-py3-none-any.whl

Download URL cdk_organizer-1.11.0-py3-none-any.whl
Size 17.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d2732356e480781e4fe48e1a79dda5207db3a3bc561a0ad118b227b371001176
BLAKE2b-256 checksum
How to use checksums
8659d3e6e4f3c6e4aa1d0f6c6c7e1c35380a3e19c5c5bd7c42a9437311a48088
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.5.1 CPython/3.9.5 Darwin/23.0.0
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page