deployment_notifier.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package slack
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "net/http"
  6. "time"
  7. "github.com/porter-dev/porter/api/types"
  8. "github.com/porter-dev/porter/internal/models/integrations"
  9. "github.com/porter-dev/porter/internal/notifier"
  10. )
  11. type DeploymentNotifier struct {
  12. slackInts []*integrations.SlackIntegration
  13. Config *types.NotificationConfig
  14. }
  15. func NewDeploymentNotifier(conf *types.NotificationConfig, slackInts ...*integrations.SlackIntegration) *DeploymentNotifier {
  16. return &DeploymentNotifier{
  17. slackInts: slackInts,
  18. Config: conf,
  19. }
  20. }
  21. type SlackPayload struct {
  22. Blocks []*SlackBlock `json:"blocks"`
  23. }
  24. type SlackBlock struct {
  25. Type string `json:"type"`
  26. Text *SlackText `json:"text,omitempty"`
  27. }
  28. type SlackText struct {
  29. Type string `json:"type"`
  30. Text string `json:"text"`
  31. }
  32. func (s *DeploymentNotifier) Notify(opts *notifier.NotifyOpts) error {
  33. if s.Config != nil {
  34. if !s.Config.Enabled {
  35. return nil
  36. }
  37. if opts.Status == notifier.StatusHelmDeployed && !s.Config.Success {
  38. return nil
  39. }
  40. if opts.Status == notifier.StatusPodCrashed && !s.Config.Failure {
  41. return nil
  42. }
  43. if opts.Status == notifier.StatusHelmFailed && !s.Config.Failure {
  44. return nil
  45. }
  46. }
  47. // we create a basic payload as a fallback if the detailed payload with "info" fails, due to
  48. // marshaling errors on the Slack API side.
  49. blocks, basicBlocks := getSlackBlocks(opts)
  50. slackPayload := &SlackPayload{
  51. Blocks: blocks,
  52. }
  53. basicSlackPayload := &SlackPayload{
  54. Blocks: basicBlocks,
  55. }
  56. basicPayload, err := json.Marshal(basicSlackPayload)
  57. if err != nil {
  58. return err
  59. }
  60. payload, err := json.Marshal(slackPayload)
  61. if err != nil {
  62. return err
  63. }
  64. basicReqBody := bytes.NewReader(basicPayload)
  65. reqBody := bytes.NewReader(payload)
  66. client := &http.Client{
  67. Timeout: time.Second * 5,
  68. }
  69. for _, slackInt := range s.slackInts {
  70. resp, err := client.Post(string(slackInt.Webhook), "application/json", reqBody)
  71. if err != nil || resp.StatusCode != 200 {
  72. client.Post(string(slackInt.Webhook), "application/json", basicReqBody)
  73. }
  74. }
  75. return nil
  76. }