|
| 1 | +package events |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "fmt" |
| 6 | + "slices" |
| 7 | + |
| 8 | + "github.com/aws/aws-sdk-go-v2/aws/arn" |
| 9 | + "github.com/slack-go/slack" |
| 10 | +) |
| 11 | + |
| 12 | +type RecoveryPointStateChange struct { |
| 13 | + StateChangeEvent |
| 14 | + BackupVaultArn string `json:"backupVaultArn"` |
| 15 | + BackupVaultName string `json:"backupVaultName"` |
| 16 | + ResourceArn string `json:"resourceArn"` |
| 17 | + ResourceType string `json:"resourceType"` |
| 18 | + State string `json:"state"` |
| 19 | + Status string `json:"status"` |
| 20 | + StatusMessage string `json:"statusMessage"` |
| 21 | + DeletedBy string `json:"deletedBy"` |
| 22 | + Raw string `json:"-"` |
| 23 | +} |
| 24 | + |
| 25 | +func (sce *RecoveryPointStateChange) SlackMessage() (slack.MsgOption, slack.MsgOption) { |
| 26 | + var blocks []slack.Block |
| 27 | + |
| 28 | + header := slack.NewHeaderBlock(slack.NewTextBlockObject("plain_text", "Recovery Point Changed", false, false)) |
| 29 | + blocks = append(blocks, header) |
| 30 | + |
| 31 | + var detailFields []*slack.TextBlockObject |
| 32 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*State*\n%s", sce.State), false, false)) |
| 33 | + |
| 34 | + if sce.BackupVaultName != "" { |
| 35 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Vault*\n%s", sce.BackupVaultName), false, false)) |
| 36 | + } |
| 37 | + if sce.ResourceArn != "" { |
| 38 | + rArn, rArnErr := arn.Parse(sce.ResourceArn) |
| 39 | + if rArnErr == nil { |
| 40 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Account*\n%s", rArn.AccountID), false, false)) |
| 41 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Type*\n%s", sce.ResourceType), false, false)) |
| 42 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Region*\n%s", rArn.Region), false, false)) |
| 43 | + detailFields = append(detailFields, slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Resource*\n%s", rArn.Resource), false, false)) |
| 44 | + } |
| 45 | + } |
| 46 | + details := slack.NewSectionBlock(nil, detailFields, nil) |
| 47 | + blocks = append(blocks, details) |
| 48 | + |
| 49 | + if sce.StatusMessage != "" { |
| 50 | + desc := slack.NewSectionBlock( |
| 51 | + slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("```\n%s\n```", sce.StatusMessage), false, false), |
| 52 | + nil, nil, |
| 53 | + ) |
| 54 | + blocks = append(blocks, desc) |
| 55 | + } |
| 56 | + |
| 57 | + return slack.MsgOptionText(sce.StatusMessage, false), slack.MsgOptionBlocks(blocks...) |
| 58 | +} |
| 59 | + |
| 60 | +func (sce *RecoveryPointStateChange) IsAlertable() bool { |
| 61 | + failedStates := []string{"DELETED"} |
| 62 | + return slices.Contains(failedStates, sce.State) && sce.DeletedBy == "MANUAL_DELETE" |
| 63 | +} |
| 64 | + |
| 65 | +func NewRecoveryPointStateChange(raw json.RawMessage) (*RecoveryPointStateChange, error) { |
| 66 | + var sce RecoveryPointStateChange |
| 67 | + if err := json.Unmarshal(raw, &sce); err != nil { |
| 68 | + return &RecoveryPointStateChange{}, err |
| 69 | + } |
| 70 | + if sce.State == "" { |
| 71 | + sce.State = sce.Status |
| 72 | + } |
| 73 | + sce.StatusMessage = "Recovery point (aka backup) changed within the AWS Backup service. Please confirm it was intended." |
| 74 | + return &sce, nil |
| 75 | +} |
0 commit comments