Lost in AWS CDK? Here's Your Map for Debugging Like a Pro

dixitjain

Dixit R Jain

Posted on July 2, 2023

Lost in AWS CDK? Here's Your Map for Debugging Like a Pro

Greetings, fellow AWS adventurers! We all know that embarking on a journey through the vast landscape of the Amazon Web Services (AWS) can sometimes feel like navigating through a dense jungle. The AWS Cloud Development Kit (CDK), a powerful Infrastructure as Code tool, is like our trusty machete, slashing through the undergrowth and making the path clearer. But what happens when our machete hits a snag? That's right, we debug!

Today, we'll be exploring the thrilling world of debugging AWS CDK. Fasten your seatbelts, because we're about to dive into some real-life examples!

Debugging Flow

1. Addressing Synth Errors

Let's start with an all-too-common scenario: you're trying to synth your CDK stack, but it's throwing errors that you just can't make sense of. Fear not, this is a familiar path for many of us.

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
const s3 = cdk.s3;
const app = new cdk.app(); // should be new cdk.App();
new s3.bucket(app, "MyBucket", { versioned: true }); // should be new s3.Bucket(app, "MyBucket", { versioned: true });
cfn.synth();
Enter fullscreen mode Exit fullscreen mode

A common mistake here is forgetting to capitalize the App and Bucket constructs. Remember, in Javascript, class names should start with an uppercase letter.

2. Stack Trace Debugging

The stack trace is like your trusty compass, guiding you to the exact location of the error. Let's take a look at a typical stack trace error:

Error: 'bucketName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z0-9.\-_]{1,255}
Enter fullscreen mode Exit fullscreen mode

The stack trace points you to the problematic parameter, in this case, 'bucketName'. Make sure the name adheres to the stated pattern.

3. Missing Permissions

When AWS gives you an AccessDenied error, it's like a giant 'Keep Out' sign. In this case, your AWS CDK might be trying to access resources it doesn't have permission for.

const myBucket = new s3.Bucket(this, 'MyBucket');
new s3deploy.BucketDeployment(this, 'DeployWebsite', {
  sources: [s3deploy.Source.asset('./website-dist')],
  destinationBucket: myBucket,
});
Enter fullscreen mode Exit fullscreen mode

You need to ensure that the AWS profile used has the necessary permissions to create and manage S3 buckets. Check your IAM roles and policies in the AWS Console.

Also, consider this common scenario:

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class MyCdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'MyBucket');

    const myFunction = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'index.handler',
    });

    // Oops! We forgot to give the Lambda function the necessary permissions to read from the S3 bucket.
  }
}
Enter fullscreen mode Exit fullscreen mode

In this case, your Lambda function won't be able to access the S3 bucket until you've granted the necessary permissions.

4. Logical Errors

Sometimes the path seems clear, but you still end up at the wrong destination. That's often the case with logical errors.

const table = new dynamodb.Table(this, 'MyTable', {
  partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
});
table.addGlobalSecondaryIndex({
  indexName: 'MyIndex',
  partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
});
Enter fullscreen mode Exit fullscreen mode

Here, we're trying to add a global secondary index (GSI) with the same partition key as the base table. DynamoDB doesn't allow this, so we need to choose a different attribute for the GSI partition key.

Likewise, consider below code

import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';

export class MyCdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const myFunction = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'index.handler',
    });

    const api = new apigateway.RestApi(this, 'MyApi');
    const resource = api.root.addResource('mypath');

    const integration = new apigateway.LambdaIntegration(myFunction);

    // Incorrect: The Lambda function is not correctly set as the handler.
    resource.addMethod('GET'); // It should have been resource.addMethod('GET', integration);
  }
}

Enter fullscreen mode Exit fullscreen mode

In this case, the code compiles and the stack deploys, but the API Gateway doesn't trigger the Lambda function as expected due to a logical error.

5. The Unknown

The last category is for those moments when you're lost in the dark, and even Google can't help you. At these times, your best bet is to turn on the AWS CDK debug logging.

export DEBUG=*
cdk deploy
Enter fullscreen mode Exit fullscreen mode

This command will output a wealth of information about what AWS CDK is doing behind the scenes, which can help you navigate even the murkiest swamps of confusion.

You can also debug AWS CDK applications by running them in the language they're written in, such as TypeScript or Python. For TypeScript, you'd execute the JavaScript file in debug mode. Here's a simple way to do it in VSCode:

First, make sure you have a .vscode/launch.json file in your project's root folder. If not, create it:

mkdir .vscode/
touch .vscode/launch.json
Enter fullscreen mode Exit fullscreen mode

Then, modify launch.json as follows:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-node",
      "request": "launch",
      "name": "Launch Program",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "runtimeArgs": [
        "-r", "./node_modules/ts-node/register/transpile-only"
      ],
      "args": [
        "${workspaceFolder}/bin/cdk.ts"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Make sure the ${workspaceFolder}/bin/cdk.ts matches the entry point for your application in the bin folder. Then, simply put in your breakpoints and debug as usual​.

However, remember that when debugging your code, CDK tokens will still be represented as "tokens" and not their actual values. Tokens represent values that can only be resolved at a later time in the lifecycle of an app. For example, the name of an Amazon S3 bucket that you define in your AWS CDK app is only allocated by AWS CloudFormation when you deploy your app​​.

And that's a wrap, folks! Next time you're lost in the AWS jungle, remember: the AWS CDK is your trusty machete, and these debugging tips are your survival guide. So, go ahead and explore with confidence! Happy debugging!

💖 💪 🙅 🚩
dixitjain
Dixit R Jain

Posted on July 2, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related