Using AWS CDK to bring infra code closer to application developers
Tags: aws, cdk
Published: 2022-05-15 09:56:56

AWS Summit Berlin 2022 took place on May11-12 there I attended a great talk by **Gregor Hohpe** and **Luis Morales** from AWS titled `Infrastructure as actual code`. In it they presented AWS CDK. I thought of giving it a try and this post is about my initial impression about AWS CDK. 

Before we go to what AWS CDK does , let's look at why infrastructure as code is important. In current cloud native application architecture ability to deploy infra in an automated, repeatable and consistent way is a must have. Many tools provides a way to achieve that for example CloudFormation by AWS, terraform for Hashicorp to name a few. 

However primarily these tools have it's own DSL to achieve that. Cloudformation uses YAML/Json files, while terraform uses HCL (HashiCorp Configuration Language). 

What if developers  can use their favourite programming language that they are using to write their application and in which they have expertise ? Well this is where AWS CDK shines. 

AWS CDK enables us to use known programming language like Typescript, JavaScript, Java, Python, Java, C#/.Net and Go. 

Below is how a simple Lambda function with Api Gateway integration may look like - 


```java
public class MovieLambdaInfraStack extends Stack{
    public MovieLambdaInfraStack(final Construct scope, final String id){
        this(scope, id, null);
    }

    public MovieLambdaInfraStack(final Construct scope, final String id, final StackProps props){
        super(scope, id, props);
        // Parameters
        CfnParameter version = CfnParameter.Builder
                .create(this, "lambda-version")
                .description("Version of lambda app jar")
                .type("String")
                .build();
        // Bucket storing lambda code
        IBucket lambdaCodeBucket = createBucket();

        // Lambda Definition
        String lambdaSource = "movie-lambda-app-" + version.getValueAsString() + ".jar";
        IFunction lambda = Function.Builder.create(this, "sab-lambda-artifact")
                .code(Code.fromBucket(lambdaCodeBucket, lambdaSource))
                .runtime(Runtime.JAVA_11)
                .functionName("sab-lambda-artifact")
                .handler("com.sab.LambdaHandler")
                .tracing(Tracing.ACTIVE)
                .timeout(Duration.minutes(5))
                .memorySize(512)
                .build();

        // Api Gateway

        LambdaIntegration lambdaIntegration = LambdaIntegration.Builder
                .create(lambda)
                .proxy(true)
                .build();

        RestApi api = RestApi.Builder.create(this, "movies")
                .defaultIntegration(lambdaIntegration)
                .apiKeySourceType(ApiKeySourceType.HEADER)
                .build();

        Resource movies = api.getRoot().addResource("movies");
        movies.addMethod("POST");

    }

    @NotNull
    private IBucket createBucket(){
        return Bucket.fromBucketName(this, "lambda-code-bucket", "sab-lambda-artifact");
    }
}
```

and a simple main method that will be run by AWS CDK to deploy this stack

```java
 public static void main(final String[] args) {
        App app = new App();

        new MovieLambdaInfraStack(app, "MovieLambdaInfraStack", StackProps.builder()
                .env(Environment.builder()
                        .account("xxxxxx")
                        .region("xxxx")
                        .build())
                .build());

        app.synth();
    }
```

AWS CDK comes with cmd line cli which will deploy this app on AWS. Underneath it generates a cloudformation template.

## AWS CDK Basic Components 

**App** - An `App` is an component which will be deployed by cdk and will contain one or more than `Stacks`.

**Stack** - A `Stack` is what defines our infra. This will contain one or more `Constructs`

**Constructs** - These are real AWS services . We can also create our custom constructs.

See more components at https://docs.aws.amazon.com/cdk/v2/guide/core_concepts.html.

## Things that I like

I have used cloudformation, which personally I do not prefer mostly because for complex infra it can become real tangled up and hard to read. 

In recent times I have used mostly terraform, and I liked it. It supports multiple cloud. We can create our own modules and components in terraform. HCL language is pretty expressive. It has it's own way to define functions, types, loop of variables which sometimes become a little unintuitive for us developers. 

my first impression With AWS CDK  is that I see below advantages - 

* As developer I feel much at ease to be able to use my favourite and known programming constructs to infra.

* We can even write Unit tests using good old Junit . Below is an example 

```java
 @Test
    void itShouldGenerateLambda(){
        App app = new App();
        Stack lambda = new MovieLambdaInfraStack(app, "MovieLambdaInfraStack");
        Template template = Template.fromStack(lambda);
        template.resourceCountIs("AWS::Lambda::Function",1);
        template.hasResourceProperties("AWS::Lambda::Function", Map.of(
                "Handler", "com.sab.LambdaHandler"
        ));
    }
```

* We can make full use of abstraction in case of using object oriented programming languages. 

* This ability of creating abstraction will help us to impart same domain driven design thinking that we can apply on application code level.

* More over I see if we use good abstraction level while writing our infra code it will serve as a blue print how different components are interacting to each other. In other word, we can discover the infrastructural architecture of an application . We will have both software level architecture and infra level architecture side by side in a single place . I believe this will give us great insight. 

* Developers get a broader picture how infra components are working together to achieve what their application code try to express. 

## On the down side

However on the down side - 

* Strong tie up with cloudformation means this is AWS cloud specific. Though there are libraries like cdk-tf (https://github.com/hashicorp/terraform-cdk) for terraform and cdk8s for Kubernetes is available. 

* Relatively new so I am yet to judge it's efficiency in large production infrastructure. 

But overall I liked the CDK approach and I hope it's adoption will bring infra code closer to application code and break the silos in terms of tools and languages between infra and application code.