Skip to content

[lambda] Cannot avoid circular dependency when lambda and cloudwatch-events resources are in different stacks #10942

@tmokmss

Description

@tmokmss

From v1.68.0, it became impossible to avoid circular dependencies in certain cases.

The cases are for example:

  • when lambda function and cloudwatch events which invoke the lambda function are defined in different stacks.

I assume this PR #10622 introduced this behavior, but not sure.

Reproduction Steps

Define two stacks as below.
One is a stack which defines a lambda function.
Another is a stack which defines CloudWatch event to invoke the lambda repeatedly.

import cdk = require('@aws-cdk/core');
import lambda = require('@aws-cdk/aws-lambda');
import events = require('@aws-cdk/aws-events');
import eventsTarget = require('@aws-cdk/aws-events-targets');

class LambdaStack extends cdk.Stack {
    readonly handler: lambda.IFunction;

    constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        const handler = new lambda.Function(this, 'handler', {
            runtime: lambda.Runtime.NODEJS_12_X,
            handler: 'main.handler',
            code: lambda.Code.fromInline('hoge'),
            
        });

        this.handler = handler;
        // Uncomment this line to avoid circular dependency. It worked before v1.68.0
        // this.handler = lambda.Function.fromFunctionArn(this, `handler-ref`, handler.functionArn);
    }
}

class CwStack extends cdk.Stack {
    constructor(scope: cdk.App, id: string, handler: lambda.IFunction, props?: cdk.StackProps) {
        super(scope, id, props);
        const target = new eventsTarget.LambdaFunction(handler);

        new events.Rule(this, `rule`, {
            schedule: events.Schedule.rate(cdk.Duration.minutes(10)),
            targets: [target],
        });
    }
}

const lambdaStack = new LambdaStack(app, 'LambdaStack');
new CwStack(app, 'CwStack', lambdaStack.handler);

And run cdk synth

What did you expect to happen?

Before v1.68.0, the error below happens.

Error: 'LambdaStack' depends on 'CwStack' (LambdaStack -> CwStack/rule/Resource.Arn). 
Adding this dependency (CwStack -> LambdaStack/handler/Resource.Arn) would create a cyclic reference.

To avoid this error, as it was an only work-around I know, you can pass the reference of the lambda function retrieved by fromFunctionArn.
So uncommenting the line in the above code resolved this problem and cdk synth passes successfully.

What actually happened?

From v1.68.0, unfortunately, the reference of the lambda also creates circular dependencies.
So whether we use the actual lambda function or the reference of it, the same error below happens.

Error: 'LambdaStack' depends on 'CwStack' (LambdaStack -> CwStack/rule/Resource.Arn). 
Adding this dependency (CwStack -> LambdaStack/handler/Resource.Arn) would create a cyclic reference.

There's no possible work-around I found so far.

Environment

  • CLI Version : v1.68.0
  • Framework Version: v1.68.0
  • Node.js Version: v14.13.0
  • OS : macOS
  • Language (Version): TypeScript

Other

This composition of stacks are commonly used in our production environment, because there're many cases that several stacks share the same lambda function.
Rather than defining a lambda function in several stacks duplicately, we'd like to define it in a single stack and referring to it from other stacks.

It'll be great if you provide us with a option which enables the previous behavior of lambda reference. (maybe specifying canCreatePermissions from outside?)

public addPermission(id: string, permission: Permission) {
if (!this.canCreatePermissions) {
// FIXME: @deprecated(v2) - throw an error if calling `addPermission` on a resource that doesn't support it.
return;
}


This is 🐛 Bug Report

Metadata

Metadata

Assignees

Labels

@aws-cdk/aws-lambdaRelated to AWS LambdabugThis issue is a bug.effort/smallSmall work item – less than a day of effortp1

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions