incidents_notifier.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package slack
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "net/http"
  7. "strings"
  8. "time"
  9. "github.com/porter-dev/porter/api/types"
  10. porter_agent "github.com/porter-dev/porter/internal/kubernetes/porter_agent/v2"
  11. "github.com/porter-dev/porter/internal/models/integrations"
  12. )
  13. type IncidentsNotifier struct {
  14. slackInts []*integrations.SlackIntegration
  15. Config *types.NotificationConfig
  16. }
  17. func NewIncidentsNotifier(conf *types.NotificationConfig, slackInts ...*integrations.SlackIntegration) *IncidentsNotifier {
  18. return &IncidentsNotifier{
  19. slackInts: slackInts,
  20. Config: conf,
  21. }
  22. }
  23. func (s *IncidentsNotifier) NotifyNew(incident *porter_agent.Incident, url string) error {
  24. res := []*SlackBlock{}
  25. topSectionMarkdwn := fmt.Sprintf(
  26. ":warning: Your application %s crashed on Porter. <%s|View the incident.>",
  27. "`"+incident.ReleaseName+"`",
  28. url,
  29. )
  30. namespace := strings.Split(incident.ID, ":")[2]
  31. createdAt := time.Unix(incident.CreatedAt, 0).UTC()
  32. res = append(
  33. res,
  34. getMarkdownBlock(topSectionMarkdwn),
  35. getDividerBlock(),
  36. getMarkdownBlock(fmt.Sprintf("*Namespace:* %s", "`"+namespace+"`")),
  37. getMarkdownBlock(fmt.Sprintf("*Name:* %s", "`"+incident.ReleaseName+"`")),
  38. getMarkdownBlock(fmt.Sprintf(
  39. "*Created at:* <!date^%d^ {date_num} {time_secs}| %s>",
  40. createdAt.Unix(),
  41. createdAt.Format("2006-01-02 15:04:05 UTC"),
  42. )),
  43. getMarkdownBlock(fmt.Sprintf("```\n%s\n```", incident.LatestMessage)),
  44. )
  45. slackPayload := &SlackPayload{
  46. Blocks: res,
  47. }
  48. payload, err := json.Marshal(slackPayload)
  49. if err != nil {
  50. return err
  51. }
  52. reqBody := bytes.NewReader(payload)
  53. client := &http.Client{
  54. Timeout: time.Second * 5,
  55. }
  56. for _, slackInt := range s.slackInts {
  57. _, err := client.Post(string(slackInt.Webhook), "application/json", reqBody)
  58. if err != nil {
  59. return err
  60. }
  61. }
  62. return nil
  63. }
  64. func (s *IncidentsNotifier) NotifyResolved(incident *porter_agent.Incident, url string) error {
  65. res := []*SlackBlock{}
  66. namespace := strings.Split(incident.ID, ":")[2]
  67. createdAt := time.Unix(incident.CreatedAt, 0).UTC()
  68. resolvedAt := time.Unix(incident.UpdatedAt, 0).UTC()
  69. topSectionMarkdwn := fmt.Sprintf(
  70. ":white_check_mark: The incident for application %s has been resolved. <%s|View the incident.>",
  71. "`"+incident.ReleaseName+"`",
  72. url,
  73. )
  74. res = append(
  75. res,
  76. getMarkdownBlock(topSectionMarkdwn),
  77. getDividerBlock(),
  78. getMarkdownBlock(fmt.Sprintf("*Namespace:* %s", "`"+namespace+"`")),
  79. getMarkdownBlock(fmt.Sprintf("*Name:* %s", "`"+incident.ReleaseName+"`")),
  80. getMarkdownBlock(fmt.Sprintf(
  81. "*Created at:* <!date^%d^ {date_num} {time_secs}| %s>",
  82. createdAt.Unix(),
  83. createdAt.Format("2006-01-02 15:04:05 UTC"),
  84. )),
  85. getMarkdownBlock(fmt.Sprintf(
  86. "*Resolved at:* <!date^%d^ {date_num} {time_secs}| %s>",
  87. resolvedAt.Unix(),
  88. resolvedAt.Format("2006-01-02 15:04:05 UTC"),
  89. )),
  90. )
  91. slackPayload := &SlackPayload{
  92. Blocks: res,
  93. }
  94. payload, err := json.Marshal(slackPayload)
  95. if err != nil {
  96. return err
  97. }
  98. reqBody := bytes.NewReader(payload)
  99. client := &http.Client{
  100. Timeout: time.Second * 5,
  101. }
  102. for _, slackInt := range s.slackInts {
  103. _, err := client.Post(string(slackInt.Webhook), "application/json", reqBody)
  104. if err != nil {
  105. return err
  106. }
  107. }
  108. return nil
  109. }