Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define CloudWatch Alarm Payload structure #296

Merged
merged 11 commits into from Jul 21, 2020
56 changes: 56 additions & 0 deletions events/sns.go
Expand Up @@ -30,3 +30,59 @@ type SNSEntity struct {
UnsubscribeURL string `json:"UnsubscribeUrl"`
Subject string `json:"Subject"`
}

type CloudWatchAlarmSNSPayload struct {
AlarmName string `json:"AlarmName"`
AlarmDescription string `json:"AlarmDescription"`
AWSAccountID string `json:"AWSAccountId"`
NewStateValue string `json:"NewStateValue"`
NewStateReason string `json:"NewStateReason"`
StateChangeTime string `json:"StateChangeTime"`
Region string `json:"Region"`
AlarmARN string `json:"AlarmArn"`
OldStateValue string `json:"OldStateValue"`
Trigger CloudWatchAlarmTrigger `json:"Trigger"`
}

type CloudWatchAlarmTrigger struct {
Period int64 `json:"Period"`
EvaluationPeriods int64 `json:"EvaluationPeriods"`
ComparisonOperator string `json:"ComparisonOperator"`
Threshold float64 `json:"Threshold"`
TreatMissingData string `json:"TreatMissingData"`
EvaluateLowSampleCountPercentile string `json:"EvaluateLowSampleCountPercentile"`
Metrics []CloudWatchMetricDataQuery `json:"Metrics,omitempty"`
MetricName string `json:"MetricName,omitempty"`
Namespace string `json:"Namespace,omitempty"`
StatisticType string `json:"StatisticType,omitempty"`
Statistic string `json:"Statistic,omitempty"`
Unit string `json:"Unit,omitempty"`
Dimensions []CloudWatchDimension `json:"Dimensions,omitempty"`
}

type CloudWatchMetricDataQuery struct {
Expression string `json:"Expression,omitempty"`
ID string `json:"Id"`
Label string `json:"Label,omitempty"`
MetricStat CloudWatchMetricStat `json:"MetricStat,omitempty"`
Period int64 `json:"Period,omitempty"`
ReturnData bool `json:"ReturnData,omitempty"`
}

type CloudWatchMetricStat struct {
Metric CloudWatchMetric `json:"Metric"`
Period int64 `json:"Period"`
Stat string `json:"Stat"`
Unit string `json:"Unit,omitempty"`
}

type CloudWatchMetric struct {
Dimensions []CloudWatchDimension `json:"Dimensions,omitempty"`
MetricName string `json:"MetricName,omitempty"`
Namespace string `json:"Namespace,omitempty"`
}

type CloudWatchDimension struct {
Name string `json:"name"`
Value string `json:"value"`
}
29 changes: 29 additions & 0 deletions events/sns_test.go
Expand Up @@ -33,3 +33,32 @@ func TestSnsEventMarshaling(t *testing.T) {
func TestSnsMarshalingMalformedJson(t *testing.T) {
test.TestMalformedJson(t, SNSEvent{})
}

func TestCloudWatchAlarmSNSPayloadMarshaling(t *testing.T) {
// 1. read JSON from file
inputJson := test.ReadJSONFromFile(t, "./testdata/cloudwatch-alarm-sns-payload-single-metric.json")

// 2. de-serialize into Go object
var inputEvent SNSEvent
if err := json.Unmarshal(inputJson, &inputEvent); err != nil {
t.Errorf("could not unmarshal event. details: %v", err)
}

// 3.retrieve message from the Go object
var message = inputEvent.Records[0].SNS.Message

// 4. de-serialize message into Go object
var inputCloudWatchPayload CloudWatchAlarmSNSPayload
if err := json.Unmarshal([]byte(message), &inputCloudWatchPayload); err != nil {
t.Errorf("could not unmarshal event. details: %v", err)
}

// 5. serialize message to JSON
outputJson, err := json.Marshal(inputCloudWatchPayload)
if err != nil {
t.Errorf("could not marshal event. details: %v", err)
}

// 4. check result
assert.JSONEq(t, string(message), string(outputJson))
}
22 changes: 22 additions & 0 deletions events/testdata/cloudwatch-alarm-sns-payload-multiple-metrics.json
@@ -0,0 +1,22 @@
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:EXAMPLE",
"Sns": {
"Type": "Notification",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"TopicArn": "arn:aws:sns:EXAMPLE",
"Subject": "TestInvoke",
"Message": "{\"AlarmName\":\"EXAMPLE\",\"AlarmDescription\":\"EXAMPLE\",\"AWSAccountId\":\"EXAMPLE\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 out of the last 1 datapoints [1234.0 (06/03/15 17:43:27)] was greater than the threshold (0.0) (minimum 1 datapoint for OK -> ALARM transition).\",\"StateChangeTime\":\"2015-06-03T17:43:27.123+0000\",\"Region\":\"EXAMPLE\",\"AlarmArn\":\"arn:aws:cloudwatch:REGION:ACCOUNT_NUMBER:alarm:EXAMPLE\",\"OldStateValue\":\"INSUFFICIENT_DATA\",\"Trigger\":{\"Period\":60,\"EvaluationPeriods\":1,\"ComparisonOperator\":\"GreaterThanThreshold\",\"Threshold\":0.0,\"TreatMissingData\":\"- TreatMissingData: missing\",\"EvaluateLowSampleCountPercentile\":\"\",\"Metrics\":[{\"Expression\":\"m1*1\",\"Id\":\"e1\",\"Label\":\"Expression1\",\"ReturnData\":true},{\"Id\":\"m1\",\"MetricStat\":{\"Metric\":{\"Dimensions\":[{\"value\":\"TestInstance\",\"name\":\"InstanceId\"}],\"MetricName\":\"NetworkOut\",\"Namespace\":\"AWS/EC2\"},\"Period\":60,\"Stat\":\"Average\"},\"ReturnData\":false}]}}",
"Timestamp": "2015-06-03T17:43:27.123Z",
"SignatureVersion": "1",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"UnsubscribeUrl": "EXAMPLE",
"MessageAttributes": {}
}
}
]
}
22 changes: 22 additions & 0 deletions events/testdata/cloudwatch-alarm-sns-payload-single-metric.json
@@ -0,0 +1,22 @@
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:EXAMPLE",
"Sns": {
"Type": "Notification",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"TopicArn": "arn:aws:sns:EXAMPLE",
"Subject": "TestInvoke",
"Message": "{\"AlarmName\": \"EXAMPLE\",\"AlarmDescription\": \"EXAMPLE\",\"AWSAccountId\": \"123456789012\",\"NewStateValue\": \"ALARM\",\"NewStateReason\": \"Threshold Crossed: 1 out of the last 1 datapoints [1234.0 (06/03/15 17:43:27)] was greater than the threshold (0.0) (minimum 1 datapoint for OK -> ALARM transition).\",\"StateChangeTime\": \"2015-06-03T17:43:27.123+0000\",\"Region\": \"EXAMPLE\",\"AlarmArn\": \"arn:aws:cloudwatch:REGION:ACCOUNT_NUMBER:alarm:EXAMPLE\",\"OldStateValue\": \"INSUFFICIENT_DATA\",\"Trigger\": {\"MetricName\": \"NetworkOut\",\"Namespace\": \"AWS/EC2\",\"StatisticType\": \"Statistic\",\"Statistic\": \"AVERAGE\",\"Unit\": \"Bytes\",\"Dimensions\": [{\"value\": \"TestInstance\",\"name\": \"InstanceId\"}],\"Period\": 60,\"EvaluationPeriods\": 1,\"ComparisonOperator\": \"GreaterThanThreshold\",\"Threshold\": 0.0,\"TreatMissingData\": \"- TreatMissingData: missing\",\"EvaluateLowSampleCountPercentile\": \"\"}}",
"Timestamp": "2015-06-03T17:43:27.123Z",
"SignatureVersion": "1",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"UnsubscribeUrl": "EXAMPLE",
"MessageAttributes": {}
}
}
]
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -3,6 +3,6 @@ module github.com/aws/aws-lambda-go
go 1.12

require (
github.com/stretchr/testify v1.4.0
github.com/stretchr/testify v1.5.1
github.com/urfave/cli/v2 v2.1.1
)
12 changes: 12 additions & 0 deletions go.sum
@@ -1,8 +1,14 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go v1.31.12 h1:SxRRGyhlCagI0DYkhOg+FgdXGXzRTE3vEX/gsgFaiKQ=
github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
Expand All @@ -13,8 +19,14 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
Expand Down