Skip to content

Commit 4cccdb4

Browse files
avas27JTGioandim
andauthored
Cloudformation events support (#79)
Co-authored-by: ioandim <[email protected]>
1 parent dce0e7e commit 4cccdb4

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

server/plugin.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ func (p *Plugin) handleNotification(body io.Reader, channel *TeamChannel) {
250250
return
251251
}
252252

253+
if isCloudformationEvent, messageNotification := p.isCloudformationEvent(notification.Message); isCloudformationEvent {
254+
p.API.LogDebug("Processing Cloudformation Event")
255+
p.sendPostNotification(p.createSNSCloudformationEventAttachment(notification.Subject, messageNotification), channel)
256+
return
257+
}
258+
253259
if isRdsEvent, messageNotification := p.isRDSEvent(notification.Message); isRdsEvent {
254260
p.API.LogDebug("Processing RDS Event")
255261
p.sendPostNotification(p.createSNSRdsEventAttachment(notification.Subject, messageNotification), channel)
@@ -299,9 +305,38 @@ func (p *Plugin) isRDSEvent(message string) (bool, SNSRdsEventNotification) {
299305
return len(messageNotification.EventID) > 0, messageNotification
300306
}
301307

308+
func (p *Plugin) isCloudformationEvent(message string) (bool, SNSCloudformationEventNotification) {
309+
var messageNotification SNSCloudformationEventNotification
310+
311+
// alter message in order to decode it in json format
312+
messagejson, err := messageToJSON(message)
313+
314+
if err != nil {
315+
p.API.LogError(
316+
"AWSSNS HandleNotification Decode Error on Cloudformation-Event message notification",
317+
"err", err.Error(),
318+
"message", message)
319+
return false, messageNotification
320+
}
321+
322+
if messagejson != nil {
323+
if err := json.Unmarshal(messagejson, &messageNotification); err != nil {
324+
p.API.LogError(
325+
"AWSSNS HandleNotification Decode Error on Cloudformation-Event message notification",
326+
"err", err.Error(),
327+
"message", message)
328+
return false, messageNotification
329+
}
330+
return len(messageNotification.EventID) > 0, messageNotification
331+
}
332+
return false, messageNotification
333+
}
334+
302335
func (p *Plugin) createSNSRdsEventAttachment(subject string, messageNotification SNSRdsEventNotification) model.SlackAttachment {
303336
p.API.LogDebug("AWSSNS HandleNotification RDS Event", "MESSAGE", subject)
337+
304338
var fields []*model.SlackAttachmentField
339+
305340
fields = addFields(fields, "Event Source", messageNotification.EventSource, true)
306341
fields = addFields(fields, "Event Time", messageNotification.EventTime, true)
307342
fields = addFields(fields, "Identifier Link", messageNotification.IdentifierLink, true)
@@ -317,9 +352,30 @@ func (p *Plugin) createSNSRdsEventAttachment(subject string, messageNotification
317352
return attachment
318353
}
319354

355+
func (p *Plugin) createSNSCloudformationEventAttachment(subject string, messageNotification SNSCloudformationEventNotification) model.SlackAttachment {
356+
p.API.LogDebug("AWSSNS HandleNotification Cloudformation Event", "SUBJECT", subject)
357+
var fields []*model.SlackAttachmentField
358+
359+
fields = addFields(fields, "StackId", messageNotification.StackID, true)
360+
fields = addFields(fields, "StackName", messageNotification.StackName, true)
361+
fields = addFields(fields, "LogicalResourceId", messageNotification.LogicalResourceID, true)
362+
fields = addFields(fields, "PhysicalResourceId", messageNotification.PhysicalResourceID, true)
363+
fields = addFields(fields, "ResourceType", messageNotification.ResourceType, true)
364+
fields = addFields(fields, "Timestamp", messageNotification.Timestamp, true)
365+
fields = addFields(fields, "ResourceStatus", messageNotification.ResourceStatus, true)
366+
367+
attachment := model.SlackAttachment{
368+
Title: subject,
369+
Fields: fields,
370+
}
371+
372+
return attachment
373+
}
374+
320375
func (p *Plugin) createSNSMessageNotificationAttachment(subject string, messageNotification SNSMessageNotification) model.SlackAttachment {
321376
p.API.LogDebug("AWSSNS HandleNotification", "MESSAGE", subject)
322377
var fields []*model.SlackAttachmentField
378+
323379
fields = addFields(fields, "AlarmName", messageNotification.AlarmName, true)
324380
fields = addFields(fields, "AlarmDescription", messageNotification.AlarmDescription, true)
325381
fields = addFields(fields, "AWS Account", messageNotification.AWSAccountID, true)
@@ -583,3 +639,46 @@ func addFields(fields []*model.SlackAttachmentField, title, msg string, short bo
583639
Short: model.SlackCompatibleBool(short),
584640
})
585641
}
642+
643+
func messageToJSON(message string) ([]byte, error) {
644+
messagefields := strings.Split(message, "\n")
645+
if len(messagefields) == 0 {
646+
return nil, errors.New("no message fields present in message string")
647+
}
648+
// examine if the message refers to a cloudformation event by checking if a valid StackId field is included in the first line
649+
stackIDParts := strings.Split(messagefields[0], "=")
650+
if len(stackIDParts) == 2 && stackIDParts[0] == "StackId" {
651+
containsCloudformationArn := strings.Contains(stackIDParts[1], "arn:aws:cloudformation")
652+
if !containsCloudformationArn {
653+
return nil, errors.New("invalid value of StackId field")
654+
}
655+
} else {
656+
return nil, nil
657+
}
658+
659+
var numOfFields int
660+
661+
// if "\n" existed at the end of the message, do not parse the last field
662+
if messagefields[len(messagefields)-1] == "" {
663+
numOfFields = len(messagefields) - 1
664+
} else {
665+
numOfFields = len(messagefields)
666+
}
667+
668+
//split each line of the cloudformation event message to field and value
669+
var fields = make(map[string]string)
670+
for _, field := range messagefields[:numOfFields] {
671+
parts := strings.Split(field, "=")
672+
if len(parts) == 2 && parts[1] != "" {
673+
fields[parts[0]] = parts[1]
674+
} else {
675+
return nil, errors.New("format of Cloudformation event message is incorrect")
676+
}
677+
}
678+
679+
jsonmessage, err := json.Marshal(fields)
680+
if err != nil {
681+
return nil, errors.Wrap(err, "Error marshaling in messageToJSON")
682+
}
683+
return jsonmessage, nil
684+
}

server/sns.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,19 @@ type SNSRdsEventNotification struct {
7070
EventID string `json:"Event ID"`
7171
EventMessage string `json:"Event Message"`
7272
}
73+
74+
type SNSCloudformationEventNotification struct {
75+
StackID string `json:"StackId"`
76+
Timestamp string `json:"Timestamp"`
77+
EventID string `json:"EventId"`
78+
LogicalResourceID string `json:"LogicalResourceId"`
79+
Namespace string `json:"Namespace"`
80+
PhysicalResourceID string `json:"PhysicalResourceId"`
81+
PrincipalID string `json:"PrincipalId"`
82+
ResourceProperties string `json:"ResourceProperties"`
83+
ResourceStatus string `json:"ResourceStatus"`
84+
ResourceStatusReason string `json:"ResourceStatusReason"`
85+
ResourceType string `json:"ResourceType"`
86+
StackName string `json:"StackName"`
87+
ClientRequestToken string `json:"ClientRequestToken"`
88+
}

0 commit comments

Comments
 (0)