Resources based CDK.
Project description
CDK Resources
Motivation
Architecture
Regular aws-cdk has a stack-based architecture where resources are defined in each stack and then resources are shared between stacks (import from stacks). This project is proposing a resource-based architecture as this would enable a more natural organization of resources based on AWS services.
Typical CDK Structure
└── custom_construct/
| └── constructs1.py
| └── ...
| └── constructs1.py
|
└── stacks/
| └── stack1.py
| └── stack2.py
| ...
| └── stackN.py
└── app.py
└── cdk.json
CDK Resources Approach
└── custom_construct/
| └── constructs1.py
| └── ...
| └── constructs1.py
|
└── resources/
| └── apigateway.py
| └── ec2.py
| └── ecs.py
| └── eks.py
| └── elasticsearch.py
| └── ...
| └── vpc.py
|
└── stacks/
| └── stack1.py
| └── stack2.py
| ...
| └── stackN.py
└── app.py
└── cdk.json
Environment Parameters
One of the most broadly used approach to parameterize a cdk stack based on
environments also knows as stages (dev
, ..., prod
) is to pass them as
configurations in thecdk.json
file.
In a big multi stack project, this approach become a issue as cdk.json
starts
growing is difficult to manage
Parameterization based on context
{
"app": "python3 app.py",
"context": {
"configurations": {
"stack1": {
"dev": {
"aurora_cluster_instances": 1,
...
"ecs_service_desired_container_count": 1
},
"prod": {
"aurora_cluster_instances": 3,
...
"ecs_service_desired_container_count": 5
}
},
...
}
}
}
CDK Resources Parameterization
class PostgreSqlRdsDatabase(Resource[aws_rds.DatabaseCluster]):
construct_class = aws_rds.DatabaseCluster
construct_props = dict(
default=dict(
...
instances=1,
...
),
prod=dict(
instances=2,
)
)
Installation
To install use pip
$ pip install cdk-resources
Components
Resource
Resources are the most important component as it contains mostly all the logic
of the project. A resource is a natural representation of an AWS element, and in
terms of cdk is the equivalent of a Construct Manager. Components must
inherit from cdk_resources.Resource
.
There are two types of resources: resource managed by the stack and imported resources.
Resource Attributes:
-
construct_class (Required): The aws_cdk.construct class this resource represent.
-
construct_props: Required only if it is a managed resource. The cdk construct class properties.
-
construct_lookup_method: Method of the aws_cdk.construct construct to be used to import the object.
-
construct_lookup_props: Required if the object is an imported resource. Kwargs used by
construct_lookup_method
to lookup for the object.
Resource Methods:
-
get(): Class method of the resource that returns the aws_cdk.construct. Either by lookup or because was previously created.
-
post_create(): Extra configurations to apply to the construct after construct was init.
Resource Examples:
As it can seen in the example below for the PostgreSqlRdsDatabase
construct_class is aws_rds.DatabaseCluster
, desired configurations for all
the environments are being specified in the construct_props attr. And other
resources are imported.
from aws_cdk import aws_rds, core, aws_ec2
from cdk_resources import Resource
from resources.ec2 import PostgreSqlRdsDatabaseSg
from resources.vpc import (
DefaultVpc,
DefaultPrivateDbASubnet,
DefaultPrivateDbBSubnet,
DefaultPrivateDbCSubnet,
)
class PostgreSqlRdsDatabase(Resource[aws_rds.DatabaseCluster]):
construct_class = aws_rds.DatabaseCluster
construct_props = dict(
default=dict(
engine=aws_rds.DatabaseClusterEngine.aurora_postgres(
version=aws_rds.AuroraPostgresEngineVersion.VER_13_4
),
backup=aws_rds.BackupProps(retention=core.Duration.days(3)),
deletion_protection=True,
instance_props=lambda: aws_rds.InstanceProps(
instance_type=aws_ec2.InstanceType.of(
aws_ec2.InstanceClass.BURSTABLE3,
aws_ec2.InstanceSize.MEDIUM,
),
security_groups=[PostgreSqlRdsDatabaseSg.get()],
vpc=DefaultVpc.get(),
vpc_subnets=aws_ec2.SubnetSelection(
subnets=[
DefaultPrivateDbASubnet.get(),
DefaultPrivateDbBSubnet.get(),
DefaultPrivateDbCSubnet.get(),
]
),
parameter_group=PostgreSqlParameterGroup().construct,
),
instances=1,
port=5432,
removal_policy=core.RemovalPolicy.RETAIN,
storage_encrypted=True,
),
prod=dict(
backup=aws_rds.BackupProps(retention=core.Duration.days(30)),
instances=2,
vpc_subnets=lambda: aws_ec2.SubnetSelection(
subnets=[
DefaultPrivateDbASubnet.get(),
DefaultPrivateDbCSubnet.get(),
DefaultPrivateDbCSubnet.get()
]
),
),
)
Stacks
A stack is the natural representation of a CFN Stack
. All stacks must inherit
from cdk_resources.ResourceStack
.
Resource Attributes:
-
EXISTING_RESOURCES (list): The list of existing resources that must be inited in aws_cdk.scope. These are resources that are used by the Stack resources.
-
RESOURCES (list): The resources own for this stack.
Resource Examples:
As it can be seen in the example below for the SampleStack
. The stack
creates a DynamoTable, Security Group, RDS Aurora Parameter Group, and
RDS Cluster.
Also, some resources must be imported. Those are specified in EXISTING_RESOURCE list as the VPC resources.
from cdk_resources import ResourceStack
from resources.dynamodb import DynamoTable
from resources.ec2 import PostgreSqlRdsDatabaseSg
from resources.rds import PostgreSqlRdsDatabase, PostgreSqlParameterGroup
from resources.sns import SnsTopic
from resources.vpc import (
DefaultVpc,
DefaultPrivateDbASubnet,
DefaultPrivateDbBSubnet,
DefaultPrivateDbCSubnet,
)
class SampleStack(ResourceStack):
EXISTING_RESOURCES = [
("vpc", DefaultVpc),
("subnet_db_a", DefaultPrivateDbASubnet),
("subnet_db_b", DefaultPrivateDbBSubnet),
("subnet_db_c", DefaultPrivateDbCSubnet),
]
RESOURCES = [
# DynamoDB
("dynamodb", DynamoTable),
# RDS
("postgresql-sg", PostgreSqlRdsDatabaseSg),
("postgresql-parameter-group", PostgreSqlParameterGroup),
("postgresqlDb", PostgreSqlRdsDatabase),
# SNS
("sns-topic", SnsTopic),
]
Parameterization
to do
Examples
Here are some availables examples.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.