164 lines
5.5 KiB
Go
164 lines
5.5 KiB
Go
package action
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/slack-go/slack"
|
|
"github.com/slack-go/slack/socketmode"
|
|
"go.uber.org/zap"
|
|
"houston/appcontext"
|
|
"houston/common/util"
|
|
"houston/internal"
|
|
"houston/logger"
|
|
"houston/model/incident"
|
|
"houston/pkg/slackbot"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const setStatusActionLogTag = "[set_status_command_action]"
|
|
|
|
type SetStatusCommandAction struct {
|
|
socketModeClient *socketmode.Client
|
|
slackBot *slackbot.Client
|
|
}
|
|
|
|
func NewSetStatusCommandAction(
|
|
socketModeClient *socketmode.Client,
|
|
slackBot *slackbot.Client,
|
|
) *SetStatusCommandAction {
|
|
return &SetStatusCommandAction{
|
|
socketModeClient: socketModeClient,
|
|
slackBot: slackBot,
|
|
}
|
|
}
|
|
|
|
func (action *SetStatusCommandAction) PerformAction(evt *socketmode.Event) {
|
|
cmd, ok := evt.Data.(slack.SlashCommand)
|
|
logger.Info("processing houston command", zap.Any("payload", cmd))
|
|
if !ok {
|
|
logger.Error("event data to slash command conversion failed", zap.Any("data", evt))
|
|
return
|
|
}
|
|
|
|
err := action.setStatus(cmd, strings.TrimSpace(cmd.Text[len(internal.SetStatusParam):]))
|
|
if err != nil {
|
|
err := appcontext.GetSlackService().PostEphemeralByChannelID(err.Error(), cmd.UserID, false, cmd.ChannelID)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s failed to post ephemeral for create incident error. %+v", setStatusActionLogTag, err))
|
|
}
|
|
}
|
|
|
|
action.socketModeClient.Ack(*evt.Request)
|
|
}
|
|
|
|
// todo: this method has to be removed and usage has to be replaced with update incident V2 once update incident refactor goes live.
|
|
func (action *SetStatusCommandAction) setStatus(cmd slack.SlashCommand, status string) error {
|
|
logger.Info(fmt.Sprintf("%s received request to update the status to %s", setStatusActionLogTag, status))
|
|
|
|
return executeForHoustonChannel(cmd, func() error {
|
|
if strings.TrimSpace(strings.ToLower(status)) == strings.ToLower(incident.Resolved) {
|
|
message := "work in progress. Please resolve using `/houston` command for now."
|
|
err := appcontext.GetSlackService().PostEphemeralByChannelID(message, cmd.UserID, false, cmd.ChannelID)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s failed to post ephemeral for invalid slash command param. %+v", setStatusActionLogTag, err))
|
|
}
|
|
} else {
|
|
incidentEntity, err := appcontext.GetIncidentService().GetIncidentByChannelID(cmd.ChannelID)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s failed to fetch incident entity with channel ID: %s. %+v", setStatusActionLogTag, cmd.ChannelID, err))
|
|
return genericBackendError
|
|
}
|
|
if incidentEntity == nil {
|
|
logger.Error(fmt.Sprintf("%s no entry found for incident with channel ID: %s in DB", setStatusActionLogTag, cmd.ChannelID))
|
|
return genericBackendError
|
|
}
|
|
|
|
incidentStatusEntity, err := appcontext.GetIncidentRepo().GetIncidentStatusByStatusName(status)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s error in finding incident status for status name %s. %+v", setStatusActionLogTag, status, err))
|
|
return genericBackendError
|
|
}
|
|
if incidentStatusEntity == nil {
|
|
logger.Error(fmt.Sprintf("%s no entity found or status name %s", setStatusActionLogTag, status))
|
|
return fmt.Errorf("%s is not a valid status", status)
|
|
}
|
|
|
|
statusID := incidentStatusEntity.ID
|
|
|
|
tags, err := appcontext.GetTagRepo().FindTagsByTeamId(incidentEntity.TeamId)
|
|
if err != nil || tags == nil {
|
|
logger.Error(fmt.Sprintf("failure while getting tags for incident id: %v", incidentEntity.ID))
|
|
return genericBackendError
|
|
}
|
|
var flag = true
|
|
for _, t := range *tags {
|
|
if t.Optional == false {
|
|
incidentTag, err := appcontext.GetIncidentRepo().GetIncidentTagByTagId(incidentEntity.ID, t.Id)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s failed to get the incident tag for incidentId: %d. %+v", setStatusActionLogTag, incidentEntity.ID, err))
|
|
return genericBackendError
|
|
}
|
|
if nil == incidentTag {
|
|
flag = false
|
|
break
|
|
}
|
|
if t.Type == "free_text" {
|
|
if incidentTag.FreeTextValue == nil || len(*incidentTag.FreeTextValue) == 0 {
|
|
flag = false
|
|
break
|
|
}
|
|
|
|
} else {
|
|
if incidentTag.TagValueIds == nil || len(incidentTag.TagValueIds) == 0 {
|
|
flag = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
incidentEntity.Status = statusID
|
|
incidentEntity.UpdatedBy = cmd.UserID
|
|
incidentEntity.UpdatedAt = time.Now()
|
|
|
|
if incidentStatusEntity.IsTerminalStatus {
|
|
if flag == false {
|
|
msgOption := slack.MsgOptionText(fmt.Sprintf("`Please set tag value`"), false)
|
|
_, errMessage := action.socketModeClient.PostEphemeral(cmd.ChannelID, cmd.UserID, msgOption)
|
|
if errMessage != nil {
|
|
logger.Error("post response failed for ResolveIncident", zap.Error(errMessage))
|
|
}
|
|
} else {
|
|
now := time.Now()
|
|
incidentEntity.EndTime = &now
|
|
}
|
|
|
|
}
|
|
err = appcontext.GetIncidentRepo().UpdateIncident(incidentEntity)
|
|
if err != nil {
|
|
logger.Error("UpdateIncident error",
|
|
zap.String("incident_slack_channel_id", cmd.ChannelID), zap.String("channel", incidentEntity.IncidentName),
|
|
zap.String("user_id", cmd.UserID), zap.Error(err))
|
|
}
|
|
|
|
go func() {
|
|
errMessage := util.PostIncidentStatusUpdateMessage(cmd.UserID, incidentStatusEntity.Name, cmd.ChannelID, action.socketModeClient)
|
|
if errMessage != nil {
|
|
logger.Error("post response failed for IncidentUpdateStatus", zap.Error(errMessage))
|
|
return
|
|
}
|
|
|
|
msgUpdate := NewIncidentChannelMessageUpdateAction(
|
|
action.socketModeClient,
|
|
appcontext.GetIncidentRepo(),
|
|
appcontext.GetTeamRepo(),
|
|
appcontext.GetSeverityRepo(),
|
|
)
|
|
msgUpdate.ProcessAction(incidentEntity.SlackChannel)
|
|
}()
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|