skip to Main Content

I am new to AWS CDK and have a issue implementing what I was able to implement on the AWS console successfully

this is the event rule that I have setup {

"$or": [{
      "detail.distance": [{
        "numeric": [">=", 0]
      }]
    }, {
      "detail.duration": [{
        "numeric": [">=", 0]
      }]
    }],
    "replay-name": [{
      "exists": true
    }]
    
  }

When I am trying to implement this in CDK
I could see the limitation it has with setting up event pattern

https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.aws_events/EventPattern.html

what i am trying:

cfn_rule = aws_events.CfnRule(
    self,
    id=f"{stack_id}-rule-to-invoke-lambda",
    name="rule-to-invoke-lambda",
    event_bus_name=event_bus.event_bus_name,
    event_pattern=aws_events.EventPattern(
        source=["mts-simulation"], #toDo Have to add the pattern but unable to design it 
    ),
    targets=[
        aws_events.CfnRule.TargetProperty(
            arn=lambda_function.function_arn, #coming in from function parameter
            id=f"{stack_id}-target-to-lambda-function",
            input_transformer=aws_events.CfnRule.InputTransformerProperty(
                input_template='{"uptime":"<detail-uptime>",'
                ' "distance": "<detail-distance>",'
                '"duration": "<detail-duration>","timestamp": "<timestamp>"}',
                input_paths_map={
                    "timestamp": "$.time",
                    "detail-uptime": "$.detail.system_uptime",
                    "detail-distance": "$.detail.distance",
                    "detail-duration": "$.detail.duration",
                    
                },
            ),
        )
    ],
)

This could be elementary but currently stuck with it.
Could anyone have bit of patient and help me out of it?

Edited after implementing the answer from Scott Hsieh:

Missing out on 2 things:

  1. associating it to an exiting event bus
{
  "detail": {
    "replay-name": [{
      "exists": true
    }],
    "$or": [{
      "distance": [{
        "numeric": [">=", 0]
      }]
    }, {
      "duration": [{
        "numeric": [">=", 0]
      }]
    }]
  },
  "source": ["mts-simulation"]
}

this rule is failing because "replay-name" is flowing into a event outside detail part of the a json event.

for example:
event =

{ "field1":"value",
    "field2":"value",
    detail:{ "distance":"value",
    "duration":"value"
    }    
    }

2

Answers


  1. Chosen as BEST ANSWER

    The above answer is great. But didn't seem to figure that out for my requirement. Here is what worked out for me:

    cfn_rule = aws_events.CfnRule(
                self,
                id=f"{stack_id}-invoke-lambda-read-file",
                name="rule-to-invoke-lambda-read-file",
                event_bus_name=event_bus.event_bus_name,
                event_pattern={"$or":[{"detail.distance":[{"numeric":[">=",0]}]},{"detail.duration":[{"numeric":[">=",0]}]}],"replay-name":[{"exists":True}]},
                targets=[
                    aws_events.CfnRule.TargetProperty(
                        arn=lambda_function.function_arn,
                        id=f"{stack_id}-invoke-lambda-read-file",
    

    as you could see I am passing event_patter as an dictionary explicitly.

    hope it helps.


  2. Brief to AWS CDK Constructs

    CfnRule is a L1 construct a.k.a CFN resources. In most cases you choose L2 constructs for your CDK application since built-in L2 constructs are usually crafted with intention for most general scenarios. You can also realize that using L1 constrcuts usually takes more effort regarding setting attributes than L2 constructs. For now, as a beginner, I would suggest you neglect L3 constructs at first, you come to meet up L3 when you are more advanced with CDK. For detail, you can read through this documentation.

    Implementing an Event Rule with AWS CDK in Python

    Back to your question, it looks like a case where an event will trigger a Lambda function and you want to manage this flow with CDK based on Python. As you can see from the documentation of EventPattern:

    Important: this class can only be used with a Rule class. In particular, do not use it with CfnRule class: your pattern will not be rendered correctly. In a CfnRule class, write the pattern as you normally would when directly writing CloudFormation.

    With your intention, I believe the following snippet can fit your needs:

    .
    .
    import aws_cdk.aws_events as events
    import aws_cdk.aws_events_targets as targets
    .
    .
    .
    """
    Python version: Python 3.11.2
    CDK version: 2.73.0 (build 43e681e)
    """
    rule = events.Rule(self, "rule",
        rule_name="rule-to-invoke-lambda",
        event_pattern=events.EventPattern(
            source=["mts-simulation"],
            detail={
                "$or": [
                    {"distance": [{"numeric": [">=", 0]}]},
                    {"duration": [{"numeric": [">=", 0]}]}
                ],
                "replay-name": [{"exists": True}]
            }
        )
    )
    rule.add_target(targets.LambdaFunction(lambda_function,
        event=events.RuleTargetInput.from_object({
                "uptime": events.EventField.from_path("$.detail.system_uptime"),
                "distance": events.EventField.from_path("$.detail.distance"),
                "duration": events.EventField.from_path("$.detail.duration"),
                "timestamp": events.EventField.from_path("$.detail.time")
            })
    ))
    

    CloudFormation JSON Output

    After synthesizing, your CFN JSON output will be similar as the following:

    "ruleF2C1DCDC": {
       "Type": "AWS::Events::Rule",
       "Properties": {
        "EventPattern": {
         "detail": {
          "$or": [
           {
            "distance": [
             {
              "numeric": [
               ">=",
               0
              ]
             }
            ]
           },
           {
            "duration": [
             {
              "numeric": [
               ">=",
               0
              ]
             }
            ]
           }
          ],
          "replay-name": [
           {
            "exists": true
           }
          ]
         },
         "source": [
          "mts-simulation"
         ]
        },
        "Name": "rule-to-invoke-lambda",
        "State": "ENABLED",
        "Targets": [
         {
          "Arn": {
           "Fn::GetAtt": [
            "LambdaFunctionBF21E41F",
            "Arn"
           ]
          },
          "Id": "Target0",
          "InputTransformer": {
           "InputPathsMap": {
            "detail-system_uptime": "$.detail.system_uptime",
            "detail-distance": "$.detail.distance",
            "detail-duration": "$.detail.duration",
            "detail-time": "$.detail.time"
           },
           "InputTemplate": "{"uptime":<detail-system_uptime>,"distance":<detail-distance>,"duration":<detail-duration>,"timestamp":<detail-time>}"
          }
         }
        ]
       },
       "Metadata": {
        "aws:cdk:path": "EventLambdaStack/rule/Resource"
       }
      }
    

    Feedback

    In the future when managing AWS infrastructure with CDK, examples in CDK documentation would be valuable since in some cases, configuration in CloudFormation and setting via CDK APIs can differ a bit much. You can use the minimal snippet to check the difference of the L2 APIs and CFN configuration. In the end, try to figure out what L2 components are crafted for Amazon EventBridge and its available targets in CDK. Good luck on your CDK journey.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search