0

I'm playing around with the AWS CDK (Typescript) for some self-learning. Specifically, I'd like to have a lambda function execute daily at a specific time or say at every N minutes. Especially since I think I'd like to have many such functions, it probably wouldn't be a bad idea to use a construct that encapsulates a lambda function, an EventBridge rule for it, and perhaps some logging etc. utilities that go with it.

Instead of writing my own construct, I realized there's aws-eventbridge-lambda so I gave it a try. In my project, I have a lambda folder in the root, which contains hello.py which has an extremely simple lambda_handler definition. Then, my stack is the following:

import { Stack, StackProps, Duration } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { EventbridgeToLambdaProps, EventbridgeToLambda } from '@aws-solutions-constructs/aws-eventbridge-lambda';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as events from 'aws-cdk-lib/aws-events';

export class TimedLambdaStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const constructProps: EventbridgeToLambdaProps = {
      lambdaFunctionProps: {
        code: lambda.Code.fromAsset('lambda'),
        runtime: lambda.Runtime.PYTHON_3_9,
        handler: 'hello.lambda_handler'
      },
      eventRuleProps: {
        schedule: events.Schedule.rate(Duration.minutes(5))
      }
    };
    
    new EventbridgeToLambda(this, 'test-eventbridge-lambda', constructProps);
  }
}

My cdk deploys fine. I'm doing it via a pipeline which is essentially copied from the CDK Workshop:

import * as cdk from 'aws-cdk-lib';
import * as codecommit from 'aws-cdk-lib/aws-codecommit';
import { Construct } from 'constructs';
import {CodeBuildStep, CodePipeline, CodePipelineSource} from "aws-cdk-lib/pipelines";

export class TimedPipelineStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const repo = new codecommit.Repository(this, 'TimedRepo', {
            repositoryName: "TimedRepo"
        });

        const pipeline = new CodePipeline(this, 'Pipeline', {
            pipelineName: 'TimedLambdaPipeline',
            synth: new CodeBuildStep('SynthStep', {
                input: CodePipelineSource.codeCommit(repo, 'master'),
                installCommands: [
                    'npm install -g aws-cdk'
                    #'npm install -s @aws-solutions-constructs/aws-eventbridge-lambda'
                ],
                commands: [
                    'npm ci',
                    'npm run build',
                    'npx cdk synth'
                ]
            }
        )
    });
    }
}

Looking into the resulting CloudFormation stack, I'm confused. I see there's an EventBridge rule but I see no Lambda function provisioned.

Am I misunderstanding what the construct is for, or doing something silly?

1
  • It looks correct to me. I would try running cdk synth locally and inspect the cloudformation template that is generated. Maybe the issue is related to the pipeline instead of the construct. Commented Jun 15, 2022 at 1:15

1 Answer 1

1

Your Pipeline is not deploying anything. To have your pipeline deploy your stacks, you need to add stages to it.

In the CDK Workshop you linked, it explains this about the code you copied:

At this point, you have a fully operating CDK pipeline that will automatically update itself on every commit, BUT at the moment, that is all it does. We need to add a stage to the pipeline that will deploy our application.

Here's a simple stage code from the workshop, with the only thing changed is the name of the stack it deploys. You'll need to modify the import to reflect the location of your stack definition.

import { TimedLambdaStack } from './timed-lambda-stack';
import { Stage, StageProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class WorkshopPipelineStage extends Stage {
    constructor(scope: Construct, id: string, props?: StageProps) {
        super(scope, id, props);

        new TimedLambdaStack(this, 'TimedLambdaStack');
    }
}

Then you need to add the stage to the pipeline as shown in the workshop:

import * as cdk from 'aws-cdk-lib';
import * as codecommit from 'aws-cdk-lib/aws-codecommit';
import { Construct } from 'constructs';
import {WorkshopPipelineStage} from './pipeline-stage';
import {CodeBuildStep, CodePipeline, CodePipelineSource} from "aws-cdk-lib/pipelines";

export class TimedPipelineStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        // This creates a new CodeCommit repository called 'TimedRepo'
        const repo = new codecommit.Repository(this, 'TimedRepo', {
            repositoryName: "TimedRepo"
        });

       // The basic pipeline declaration. This sets the initial structure
        // of our pipeline
       const pipeline = new CodePipeline(this, 'Pipeline', {
            pipelineName: 'TimedLambdaPipeline',
            synth: new CodeBuildStep('SynthStep', {
                    input: CodePipelineSource.codeCommit(repo, 'master'),
                    installCommands: [
                        'npm install -g aws-cdk'
                    ],
                    commands: [
                        'npm ci',
                        'npm run build',
                        'npx cdk synth'
                    ]
                }
            )
        });

        const deploy = new WorkshopPipelineStage(this, 'Deploy');
        const deployStage = pipeline.addStage(deploy);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.