Reputation: 431
After i create a cloud-watch event rule i am trying to add a target to it but i am unable to add a input transformation. Previously the add target had the props allowed for input transformation but it does not anymore.
codeBuildRule.addTarget(new SnsTopic(props.topic));
The aws cdk page provides this solution but i dont exactly understand what it says
You can add additional targets, with optional input transformer using eventRule.addTarget(target[, input]). For example, we can add a SNS topic target which formats a human-readable message for the commit.
Upvotes: 13
Views: 12706
Reputation: 854
I ran into the same issue, trying to figure out where to define inputPath
and inputTemplate
. There's only some CDK abstraction available with one input field (message
, event
, or input
based on the target object). Turns out, the abstraction already contains everything that's required to create inputPath
and inputTemplate
, it's just a matter of insufficient documentation.
This abstraction is pretty neat because it automatically creates the inputPath
and inputTemplate
for you when you specify the message
(or input
, event
, ... ) in the CDK target object. For each unique EventField.fromPath()
that you use, it creates an inputPath
key-value pair for you and uses that key in the inputTemplate
.
For myself, I've made it clearer by mimicking the input transformer in the code:
import * as events from 'aws-cdk-lib/aws-events'
import * as targets from 'aws-cdk-lib/aws-events-targets'
...
const eventInputMapping = {
account: events.EventField.account,
region: events.EventField.region,
alarmName: events.EventField.fromPath('$.detail.alarmName'),
description: events.EventField.fromPath('$.detail.configuration.description'),
startTime: events.EventField.fromPath('$.detail.state.timestamp'),
state: events.EventField.fromPath('$.detail.state.value'),
metric: events.EventField.fromPath('$.detail.configuration.metrics[0].metricStat.metric.name'),
clusterName: events.EventField.fromPath('$.detail.configuration.metrics[0].metricStat.metric.dimensions.ClusterName'),
serviceName: events.EventField.fromPath('$.detail.configuration.metrics[0].metricStat.metric.dimensions.ServiceName'),
}
const eventInputTemplate = {
title: `Service ${eventInputMapping.serviceName} went into ${eventInputMapping.state} state for ${eventInputMapping.metric} ${eventInputMapping.description}.`,
text: `The ECS scaling alarm ${eventInputMapping.alarmName} got triggered at ${eventInputMapping.startTime}` +
` This impacts the scaling of ECS service ${eventInputMapping.serviceName} in ECS cluster ${eventInputMapping.clusterName}. `,
source_type_name: 'amazon ecs',
tags: [
`account-id:${eventInputMapping.account}`,
`region:${eventInputMapping.region}`,
`servicename:${eventInputMapping.serviceName}`,
`clustername:${eventInputMapping.clusterName}`,
],
}
new events.Rule(this, 'DefaultEcsMetricsScalingAlarms', {
...
targets: [new targets.ApiDestination(eventsDestination, {
event: events.RuleTargetInput.fromObject(eventInputTemplate)
}),
],
})
This will result in the following inputPath
:
{
"account": "$.account",
"detail-alarmName": "$.detail.alarmName",
"detail-configuration-description": "$.detail.configuration.description",
"detail-configuration-metrics-0--metricStat-metric-dimensions-ClusterName": "$.detail.configuration.metrics[0].metricStat.metric.dimensions.ClusterName",
"detail-configuration-metrics-0--metricStat-metric-dimensions-ServiceName": "$.detail.configuration.metrics[0].metricStat.metric.dimensions.ServiceName",
"detail-configuration-metrics-0--metricStat-metric-name": "$.detail.configuration.metrics[0].metricStat.metric.name",
"detail-state-timestamp": "$.detail.state.timestamp",
"detail-state-value": "$.detail.state.value",
"region": "$.region"
}
and inputTemplate
{
"title": "Service <detail-configuration-metrics-0--metricStat-metric-dimensions-ServiceName> went into <detail-state-value> state for <detail-configuration-metrics-0--metricStat-metric-name> <detail-configuration-description>.",
"text": "The ECS scaling alarm <detail-alarmName> got triggered at <detail-state-timestamp> This impacts the scaling of ECS service <detail-configuration-metrics-0--metricStat-metric-dimensions-ServiceName> in ECS cluster <detail-configuration-metrics-0--metricStat-metric-dimensions-ClusterName>. ",
"source_type_name": "amazon ecs",
"tags": [
"account-id:<account>",
"region:<region>",
"service:<detail-configuration-metrics-0--metricStat-metric-dimensions-ServiceName>",
"cluster:<detail-configuration-metrics-0--metricStat-metric-dimensions-ClusterName>"
]
}
Upvotes: 0
Reputation: 983
This would work for CDK Python. CodeBuild to SNS notifications.
sns_topic = sns.Topic(...)
codebuild_project = codebuild.Project(...)
sns_topic.grant_publish(codebuild_project)
codebuild_project.on_build_failed(
f'rule-on-failed',
target=events_targets.SnsTopic(
sns_topic,
message=events.RuleTargetInput.from_multiline_text(
f"""
Name: {events.EventField.from_path('$.detail.project-name')}
State: {events.EventField.from_path('$.detail.build-status')}
Build: {events.EventField.from_path('$.detail.build-id')}
Account: {events.EventField.from_path('$.account')}
"""
)
)
)
Credits to @pruthvi-raj comment on an answer above
Upvotes: 1
Reputation: 377
I had the same question trying to implement this tutorial in CDK: Tutorial: Set up a CloudWatch Events rule to receive email notifications for pipeline state changes
I found this helpful as well: Detect and react to changes in pipeline state with Amazon CloudWatch Events
NOTE: I could not get it to work using the Pipeline's class method onStateChange().
I ended up writing a Rule:
const topic = new Topic(this, 'topic', {topicName: 'codepipeline-notes-failure',
});
const description = `Generated by the CDK for stack: ${this.stackName}`;
new Rule(this, 'failed', {
description: description,
eventPattern: {
detail: {state: ['FAILED'], pipeline: ['notes']},
detailType: ['CodePipeline Pipeline Execution State Change'],
source: ['aws.codepipeline'],
},
targets: [
new SnsTopic(topic, {
message: RuleTargetInput.fromText(
`The Pipeline '${EventField.fromPath('$.detail.pipeline')}' has ${EventField.fromPath(
'$.detail.state',
)}`,
),
}),
],
});
After implementing, if you navigate to Amazon EventBridge -> Rules, then select the rule, then select the Target(s) and then click View Details you will see the Target Details with the Input transformer & InputTemplate.
Input transformer: {"InputPathsMap":{"detail-pipeline":"$.detail.pipeline","detail-state":"$.detail.state"},"InputTemplate":"\"The Pipeline '<detail-pipeline>' has <detail-state>\""}
Upvotes: 8
Reputation: 7397
You should specify the message
prop and use RuleTargetInput
static methods. Some of these methods can use strings returned by EventField.fromPath()
:
// From a path
codeBuildRule.addTarget(new SnsTopic(props.topic, {
message: events.RuleTargetInput.fromEventPath('$.detail')
}));
// Custom object
codeBuildRule.addTarget(new SnsTopic(props.topic, {
message: RuleTargetInput.fromObject({
foo: EventField.fromPath('$.detail.bar')
})
}));
Upvotes: 19