Search code examples
pythonamazon-web-servicesaws-lambdaaws-cdkaws-codepipeline

How to refer an queue object from one stack to another stack in AWS CDK Python?


I am trying to send an EC2 termination event in one account (Acct. 1) to an SQS queue in a different account (Acct. 2), whenever there is an EC2 termination in Acct. 1.

I am using AWS CDK to implement this functionality.

  • Stack A is for building the event bridge rule to publish the termination event to the SQS queue in Acct. 1.
  • Stack B is for building the SQS queue in Acct. 2.

The issue I am facing is to get the SQS queue object from Stack B to Stack A so I can add it as the target for the event bridge rule.

Following is the code I tried:

Stack B

# This is the Queue
    TerminationQueue = sqs.Queue(
        self,
        'Queue',
        queue_name = 'TerminationQueue',
        delivery_delay = cdk.Duration.seconds(300),
        visibility_timeout = cdk.Duration.seconds(300),
        retention_period=cdk.Duration.seconds(7200)

    )
    
# Output
  cdk.CfnOutput(self, 'TerminationQueueOutput', value = TerminationQueue)

Stack A

# This is Termination Event
    TerminationEventRule = events.Rule(
        self,
        'EventRule',
        event_pattern = events.EventPattern(
            detail_type=["Termination Event Notification"],
            source=["aws.ec2"],
            detail = {
                "state": ["terminated"]
                 }
        ),
        enabled=True,
    )
 
# Import
  EventsQueue = cdk.Fn.import_value('TerminationQueueOutput')

When I am trying the above I am getting the error "Expected a string, got {"$jsii.byref":"@aws-cdk/aws-sqs.Queue@10026"}"

Then I tried to send queue name by TerminationQueue.queue_name but that gives the following error "jsii.errors.JSIIError: Expected object reference, got "${Token[TOKEN.437]}"


Solution

  • CfnOutput always outputs a string. You can output the ARN of the queue ( available at TerminationQueue.queueArn), and then create the queue in another stack with Queue.fromQueueArn

    The idiomatic way to do this, though, is expose the queue as an instance variable and just pass it to the Stack A's constructor. CDK will do the above under the hood, abstracting it away. Here's an example from the docs:

    prod = cdk.Environment(account="123456789012", region="us-east-1")
    
    stack1 = StackThatProvidesABucket(app, "Stack1", env=prod)
    
    # stack2 will take a property "bucket"
    stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod)
    

    You can pass your queue the same way.