From 97d108f415e362081da3a3c4adb459d7799d5bcd Mon Sep 17 00:00:00 2001 From: ubergesundheit Date: Tue, 7 Feb 2017 15:48:38 +0100 Subject: [PATCH] do not fail when container could't killed --- actions/notify_slack.go | 92 +++++++++++++++++++++++++++++++++++++++++ container/client.go | 2 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 actions/notify_slack.go diff --git a/actions/notify_slack.go b/actions/notify_slack.go new file mode 100644 index 0000000..2f4b219 --- /dev/null +++ b/actions/notify_slack.go @@ -0,0 +1,92 @@ +package actions + +import ( + "fmt" + "net/http" + "strings" + + "github.com/mozillazg/request" +) + +// SlackNotifier is used to make the https requests to a specified slack +// webhook URL +type SlackNotifier struct { + slackURL string + identity string +} + +const ( + slackMessageStartup = "Watchtower startup" + slackMessageError = "Some errors while checking and redeployment (Please check logs):" + slackMessageSuccess = "Successfully redeployed images:" +) + +// NewSlackNotifier instantiates a new SlackNotifier with an URL and an identifier which will +// be prepended to each message it sends +func NewSlackNotifier(slackURL, identity string) *SlackNotifier { + identity = strings.Trim(identity, " ") + + if len(identity) != 0 { + identity = fmt.Sprintf("[%s]: ", identity) + } + + return &SlackNotifier{ + slackURL: slackURL, + identity: identity, + } +} + +func (s SlackNotifier) sendNotification(json map[string]interface{}) { + c := new(http.Client) + req := request.NewRequest(c) + req.Json = json + _, err := req.Post(s.slackURL) + + if err != nil { + fmt.Println(err) + } +} + +// NotifyStartup sends a startup message to slack +func (s SlackNotifier) NotifyStartup() { + s.sendNotification(map[string]interface{}{ + "text": fmt.Sprintf("%s%s", s.identity, slackMessageStartup), + }) +} + +func buildAttachment(items []string, title, color string) map[string]interface{} { + + var fields []map[string]string + + for _, item := range items { + fields = append(fields, map[string]string{"value": item, "short": "false"}) + } + + return map[string]interface{}{ + "fallback": title + strings.Join(items, ", "), + "color": color, + "title": title, + "fields": fields, + } +} + +// NotifyContainerUpdate sends a Message after updating containers which yielded either success or errors or both +func (s SlackNotifier) NotifyContainerUpdate(successfulContainers, errorMessages []string) { + + var attachments []map[string]interface{} + + if len(successfulContainers) != 0 { + attachments = append(attachments, buildAttachment(successfulContainers, slackMessageSuccess, "good")) + } + + if len(errorMessages) != 0 { + attachments = append(attachments, buildAttachment(errorMessages, slackMessageError, "danger")) + } + + // add a pretext to the first attachment + attachments[0]["pretext"] = s.identity + + s.sendNotification(map[string]interface{}{ + "attachments": attachments, + }) +} diff --git a/container/client.go b/container/client.go index 7fe12b4..c3a083f 100644 --- a/container/client.go +++ b/container/client.go @@ -114,7 +114,7 @@ func (client dockerClient) StopContainer(c Container, timeout time.Duration) err log.Infof("Stopping %s (%s) with %s", c.Name(), c.ID(), signal) if err := client.api.ContainerKill(bg, c.ID(), signal); err != nil { - return err + fmt.Errorf("Container %s (%s) could not be killed", c.Name(), c.ID()) } // Wait for container to exit, but proceed anyway after the timeout elapses