Skip to content

Commit

Permalink
feat: evb extract-sam-event
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacobsson committed Oct 11, 2020
1 parent 1742603 commit e515658
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 15 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ Options:

This is an experimental feature. Grouping by tag is possible for the following target types: Lambda, StepFunctions, SNS, SQS, Kinesis. More will follow.

## Extract `AWS::Serverless::Function` Event to `AWS::Events::Rule`
Sometimes you start off with a simple [EventBridgeRule](https://github.com/aws/serverless-application-model/blob/master/versions/2016-10-31.md#eventbridgerule) transform on you `AWS::Serverless::Function` resource. Later on you might want to evolve it and start using an [InputTransformer](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-rule-inputtransformer.html) or retry/DLQ configurations which is only supported by `AWS::Events::Rule`

Use `evb extract-sam-event` to unfold the SAM event to full CloudFormation syntax.

## Local debugging
Local debugging makes use to API Gateway V2 websockets to forward actual events in the cloud to your developer machine. The requires a [Serverless Application Repository app](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/751354400372/evb-local) to be installed in your account. Note that depending on your traffic, there will be some small effect on your billing in the form of Lambda invocations, API Gateway invocations, CloudWatch Logs and DynamoDB R/W.
Expand Down
26 changes: 18 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ program
await patternBuilder.browseEvents(cmd.format, schemaApi, evbApi);
});

program
program
.command("diagram")
.alias("d")
.option(
Expand All @@ -71,15 +71,25 @@ program
await diagramBuilder.build(cmd.eventbus);
});

program
.command("extract-sam-event")
.alias("e")
.option("-t, --template [template]", "Path to template file", "template.yml")
.description("Exctracts an EventBusRule event from an AWS::Serverless::Function resource to an AWS::Events::Rule for more advanced use cases")
.action(async (cmd) => {
templateParser.load(cmd.template);
await templateParser.extractSamDefinition();
});

const ruleDefault = "choose from template";
program
.command("local")
.alias("l")
.option(
"-s, --stack-name [stackName]",
"Establishes local consumption of all rules in a stack"
)
.option("--arn [arn]", "Establishes local consumption of a rule ARN")
.command("local")
.alias("l")
.option(
"-s, --stack-name [stackName]",
"Establishes local consumption of all rules in a stack"
)
.option("--arn [arn]", "Establishes local consumption of a rule ARN")
.option(
"-r, --rule [rule]",
"Establishes local consumption of a rule in a local CloudFormation template",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mhlabs/evb-cli",
"version": "1.1.13",
"version": "1.1.14",
"description": "A package for building EventBridge/CloudWatch Events patterns",
"main": "index.js",
"scripts": {
Expand Down
89 changes: 83 additions & 6 deletions src/template-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,95 @@ async function injectPattern(pattern) {
resource.value.Properties.EventPattern = pattern;
resource.value.Properties.EventBusName = eventBus;
template.Resources[resource.name] = resource.value;
fs.writeFileSync(
templatePath,
format === "json"
? JSON.stringify(template, null, 2)
: YAML.stringify(template)
);
saveTemplate();
}
}

function saveTemplate() {
fs.writeFileSync(
templatePath,
format === "json"
? JSON.stringify(template, null, 2)
: YAML.stringify(template)
);
}

async function extractSamDefinition() {
const events = [];
Object.keys(template.Resources).filter(
(f) =>
template.Resources[f].Type === "AWS::Serverless::Function" &&
template.Resources[f].Properties.Events &&
Object.keys(template.Resources[f].Properties.Events).forEach((e) => {
if (
template.Resources[f].Properties.Events[e].Type ===
"EventBridgeRule" ||
template.Resources[f].Properties.Events[e].Type === "CloudWatchEvent"
) {
events.push({
name: `${e} -> ${f}`,
value: {
function: f,
event: e,
config: template.Resources[f].Properties.Events[e].Properties,
},
});
}
})
);

const extractEvent = await inputUtil.selectFrom(
events,
"Select SAM event to extract"
);

delete template.Resources[extractEvent.function].Properties.Events[extractEvent.event];


let suggestion = `${extractEvent.event}Rule`;
if (template.Resources[suggestion]) {
suggestion = `${extractEvent.event}To${extractEvent.function}Rule`;
}
const resourceName = await inputUtil.text("Resource name", suggestion);

template.Resources[resourceName] = {
Type: "AWS::Events::Rule",
Properties: {
EventBusName: extractEvent.config.EventBusName || "default",
EventPattern: extractEvent.config.Pattern,
State: "ENABLED",
Targets: [{
Arn: { "Fn::GetAtt": [extractEvent.function, "Arn"] },
Id: suggestion,
Input: extractEvent.config.Input,
InputPath: extractEvent.config.InputPath
}],
},
};
template.Resources[`${resourceName}Permission`] = {
Type: "AWS::Lambda::Permission",
Properties: {
FunctionName: {
Ref: extractEvent.function
},
Action: "lambda:InvokeFunction",
Principal: "events.amazonaws.com",
SourceArn: {
"Fn::GetAtt": [
suggestion,
"Arn"
]
}
}
};

saveTemplate();
}

module.exports = {
getFormattedResourceList,
getLambdaFunctions,
load,
injectPattern,
extractSamDefinition,
};

0 comments on commit e515658

Please sign in to comment.