Skip to content

Commit

Permalink
Merge pull request #1 from raykrishardi/main
Browse files Browse the repository at this point in the history
feat: hl-component-eventbridge-rule
  • Loading branch information
tarunmenon95 authored Sep 20, 2024
2 parents aa98f6f + 282bdab commit 576d534
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/rspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: cftest

on: [push, pull_request]

jobs:
rspec:
uses: theonestack/shared-workflows/.github/workflows/rspec.yaml@main
secrets: inherit
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
out/
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,43 @@
# eventbridge-rule CfHighlander component
## Parameters

| Name | Use | Default | Global | Type | Allowed Values |
| ---- | --- | ------- | ------ | ---- | -------------- |
| EnvironmentName | Tagging | dev | true | string
| EnvironmentType | Tagging | development | true | string | ['development', 'production']
| EventsRuleState | Enable/Disable the EB rules | ENABLED | false | string | ['ENABLED', 'DISABLED']

## Outputs/Exports

| Name | Value | Exported |
| ---- | ----- | -------- |

## Included Components

## Example Configuration
### Highlander
```
Component name: 'eventbridge-rule', template: 'eventbridge-rule'
```

## Cfhighlander Setup

install cfhighlander [gem](https://github.com/theonestack/cfhighlander)

```bash
gem install cfhighlander
```

or via docker

```bash
docker pull theonestack/cfhighlander
```
## Testing Components

1. [optional] Create new test files
- You could copy existing test file. When you do so, please change the file name and `test_metadata.name` according to the test file name
2. Run `cfhighlander cftest`
3. Run `kurgan test <test_file_name> --type spec` for each of the test files to re-generate the spec files
- Example `<test_file_name>`: hello-world for tests/hello-world.test.yaml
4. Run `rspec`
12 changes: 12 additions & 0 deletions eventbridge-rule.cfhighlander.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CfhighlanderTemplate do
Name 'eventbridge-rule'
ComponentVersion component_version
Description "#{component_name} - #{component_version}"

Parameters do
ComponentParam 'EnvironmentName', 'dev', isGlobal: true
ComponentParam 'EnvironmentType', 'development', allowedValues: ['development','production'], isGlobal: true
ComponentParam 'EventsRuleState', 'ENABLED', allowedValues: ['ENABLED', 'DISABLED']
end

end
60 changes: 60 additions & 0 deletions eventbridge-rule.cfndsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
CloudFormation do
events = external_parameters.fetch(:events, {})
events.each do |name, properties|
event_pattern = {}
schedule_pattern = ""

# rule with event pattern or schedule
case properties["type"]
when "event_pattern"
event_pattern = {
source: properties["source"],
"detail-type": properties["detail_type"],
"detail": properties["detail"]
}
when "schedule"
schedule_pattern = properties["schedule_pattern"]
end

# event targets
targets = []
properties['targets'].each do |target|
event_target = {}

event_target["Arn"] = FnSub(target["arn"])
event_target["Id"] = FnSub("${EnvironmentName}-#{target["id"]}")
event_target["Input"] = FnSub(target["input"].to_json) if target.has_key?('input')

if target.has_key?('dlq_arn')
event_target["DeadLetterConfig"] = {
"Arn": FnSub(target["dlq_arn"])
}
end

targets.append(event_target)
end

Events_Rule(name) do
Description FnSub("${EnvironmentName}-#{name}")
State Ref(:EventsRuleState)
EventPattern FnSub(event_pattern.to_json) if properties["type"] == "event_pattern"
ScheduleExpression schedule_pattern if properties["type"] == "schedule"
Targets targets
end

# eventbridge permission resource depending on the target type
properties['targets'].each do |target|
case target["type"]
when "lambda"
Lambda_Permission("#{name}#{target["id"]}Permission") do
FunctionName FnSub(target["arn"])
Action 'lambda:InvokeFunction'
Principal 'events.amazonaws.com'
SourceArn FnGetAtt(name, "Arn")
end
end
end

end
end

1 change: 1 addition & 0 deletions eventbridge-rule.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
component_version: 1.0.0
68 changes: 68 additions & 0 deletions spec/ecs_service_event_lambda_target_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'yaml'

describe 'compiled component eventbridge-rule' do

context 'cftest' do
it 'compiles test' do
expect(system("cfhighlander cftest #{@validate} --tests tests/ecs_service_event_lambda_target.test.yaml")).to be_truthy
end
end

let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ecs_service_event_lambda_target/eventbridge-rule.compiled.yaml") }

context "Resource" do


context "TestEvent" do
let(:resource) { template["Resources"]["TestEvent"] }

it "is of type AWS::Events::Rule" do
expect(resource["Type"]).to eq("AWS::Events::Rule")
end

it "to have property Description" do
expect(resource["Properties"]["Description"]).to eq({"Fn::Sub"=>"${EnvironmentName}-TestEvent"})
end

it "to have property State" do
expect(resource["Properties"]["State"]).to eq({"Ref"=>"EventsRuleState"})
end

it "to have property EventPattern" do
expect(resource["Properties"]["EventPattern"]).to eq({"Fn::Sub"=>"{\"source\":[\"aws.ecs\"],\"detail-type\":[\"ECS Task State Change\"],\"detail\":{\"lastStatus\":[\"RUNNING\"],\"desiredStatus\":[\"RUNNING\"],\"clusterArn\":[\"arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1\"],\"group\":[\"service:nginx\"]}}"})
end

it "to have property Targets" do
expect(resource["Properties"]["Targets"]).to eq([{"Arn"=>{"Fn::Sub"=>"arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world"}, "Id"=>{"Fn::Sub"=>"${EnvironmentName}-HelloWorldLambda"}, "Input"=>{"Fn::Sub"=>"{\"target_recycle_cluster_arn\":\"arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1\",\"target_recycle_service_name\":\"nginx\",\"target_recycle_service_warmup_period_second\":0}"}, "DeadLetterConfig"=>{"Arn"=>{"Fn::Sub"=>"arn:aws:sqs:ap-southeast-2:123456789012:dlq"}}}])
end

end

context "TestEventHelloWorldLambdaPermission" do
let(:resource) { template["Resources"]["TestEventHelloWorldLambdaPermission"] }

it "is of type AWS::Lambda::Permission" do
expect(resource["Type"]).to eq("AWS::Lambda::Permission")
end

it "to have property FunctionName" do
expect(resource["Properties"]["FunctionName"]).to eq({"Fn::Sub"=>"arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world"})
end

it "to have property Action" do
expect(resource["Properties"]["Action"]).to eq("lambda:InvokeFunction")
end

it "to have property Principal" do
expect(resource["Properties"]["Principal"]).to eq("events.amazonaws.com")
end

it "to have property SourceArn" do
expect(resource["Properties"]["SourceArn"]).to eq({"Fn::GetAtt"=>["TestEvent", "Arn"]})
end

end

end

end
68 changes: 68 additions & 0 deletions spec/ecs_service_schedule_lambda_target_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'yaml'

describe 'compiled component eventbridge-rule' do

context 'cftest' do
it 'compiles test' do
expect(system("cfhighlander cftest #{@validate} --tests tests/ecs_service_schedule_lambda_target.test.yaml")).to be_truthy
end
end

let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ecs_service_schedule_lambda_target/eventbridge-rule.compiled.yaml") }

context "Resource" do


context "TestEvent" do
let(:resource) { template["Resources"]["TestEvent"] }

it "is of type AWS::Events::Rule" do
expect(resource["Type"]).to eq("AWS::Events::Rule")
end

it "to have property Description" do
expect(resource["Properties"]["Description"]).to eq({"Fn::Sub"=>"${EnvironmentName}-TestEvent"})
end

it "to have property State" do
expect(resource["Properties"]["State"]).to eq({"Ref"=>"EventsRuleState"})
end

it "to have property ScheduleExpression" do
expect(resource["Properties"]["ScheduleExpression"]).to eq("cron(0/5 * * * ? *)")
end

it "to have property Targets" do
expect(resource["Properties"]["Targets"]).to eq([{"Arn"=>{"Fn::Sub"=>"arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world"}, "Id"=>{"Fn::Sub"=>"${EnvironmentName}-HelloWorldLambda"}, "Input"=>{"Fn::Sub"=>"{\"target_recycle_cluster_arn\":\"arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1\",\"target_recycle_service_name\":\"nginx\",\"target_recycle_service_warmup_period_second\":0}"}, "DeadLetterConfig"=>{"Arn"=>{"Fn::Sub"=>"arn:aws:sqs:ap-southeast-2:123456789012:dlq"}}}])
end

end

context "TestEventHelloWorldLambdaPermission" do
let(:resource) { template["Resources"]["TestEventHelloWorldLambdaPermission"] }

it "is of type AWS::Lambda::Permission" do
expect(resource["Type"]).to eq("AWS::Lambda::Permission")
end

it "to have property FunctionName" do
expect(resource["Properties"]["FunctionName"]).to eq({"Fn::Sub"=>"arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world"})
end

it "to have property Action" do
expect(resource["Properties"]["Action"]).to eq("lambda:InvokeFunction")
end

it "to have property Principal" do
expect(resource["Properties"]["Principal"]).to eq("events.amazonaws.com")
end

it "to have property SourceArn" do
expect(resource["Properties"]["SourceArn"]).to eq({"Fn::GetAtt"=>["TestEvent", "Arn"]})
end

end

end

end
23 changes: 23 additions & 0 deletions tests/ecs_service_event_lambda_target.test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
test_metadata:
type: config
name: ecs_service_event_lambda_target

events:
TestEvent:
type: event_pattern
source: ["aws.ecs"]
detail_type: ["ECS Task State Change"]
detail:
lastStatus: ["RUNNING"]
desiredStatus: ["RUNNING"]
clusterArn: ["arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1"]
group: ["service:nginx"]
targets:
- arn: arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world
id: HelloWorldLambda
input:
target_recycle_cluster_arn: "arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1"
target_recycle_service_name: "nginx"
target_recycle_service_warmup_period_second: 0
dlq_arn: arn:aws:sqs:ap-southeast-2:123456789012:dlq
type: lambda
17 changes: 17 additions & 0 deletions tests/ecs_service_schedule_lambda_target.test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
test_metadata:
type: config
name: ecs_service_schedule_lambda_target

events:
TestEvent:
type: schedule
schedule_pattern: cron(0/5 * * * ? *)
targets:
- arn: arn:aws:lambda:ap-southeast-2:123456789012:function:hello-world
id: HelloWorldLambda
input:
target_recycle_cluster_arn: "arn:aws:ecs:ap-southeast-2:123456789012:cluster/cluster1"
target_recycle_service_name: "nginx"
target_recycle_service_warmup_period_second: 0
dlq_arn: arn:aws:sqs:ap-southeast-2:123456789012:dlq
type: lambda

0 comments on commit 576d534

Please sign in to comment.