Skip to content

Commit c8e163b

Browse files
author
eloubersac
committed
Merge branch 'develop' of github.com:signal18/replication-manager into develop
2 parents 7975951 + 88ca56d commit c8e163b

File tree

4 files changed

+193
-16
lines changed

4 files changed

+193
-16
lines changed

config/config.go

-4
Original file line numberDiff line numberDiff line change
@@ -847,10 +847,6 @@ type PeerCluster struct {
847847
Cloud18ExtDbOps string `json:"cloud18-external-dbops"`
848848
Cloud18ExtSysOps string `json:"cloud18-external-sysops"`
849849
Cloud18InfraCertifications string `json:"cloud18-infra-certifications"`
850-
Cloud18Alert bool `json:"cloud18-alert,string"`
851-
Cloud18AlertSlackChannel string `json:"cloud18-alert-slack-channel"`
852-
Cloud18AlertSlackURL string `json:"cloud18-alert-slack-url"`
853-
Cloud18AlertSlackUser string `json:"cloud18-alert-slack-user"`
854850
}
855851

856852
type Partner struct {

share/dashboard_react/src/services/clusterService.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ function resetSlaveAll(clusterName, serverId, baseURL) {
372372
return getApi(baseURL).get(`clusters/${clusterName}/servers/${serverId}/actions/reset-slave-all`)
373373
}
374374

375-
function cancelServerJob(clusterName, serverId, baseURL) {
376-
return getApi(baseURL).get(`clusters/${clusterName}/servers/${serverId}/actions/cancel-job`)
375+
function cancelServerJob(clusterName, serverId, taskName, baseURL) {
376+
return getApi(baseURL).get(`clusters/${clusterName}/servers/${serverId}/actions/job-cancel/${taskName}`)
377377
}
378378
//#endregion Server management APIs
379379

utils/alert/slackman/slackman.go

+26-10
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package slackman
22

33
import (
44
"net/url"
5+
"strings"
56
"sync"
67
"time"
78

89
"github.com/bluele/logrus_slack"
10+
"github.com/mattermost/mattermost-server/v6/model"
11+
"github.com/signal18/replication-manager/utils/meethelper"
912
"github.com/sirupsen/logrus"
1013
)
1114

@@ -21,7 +24,7 @@ type SlackConfig struct {
2124

2225
type SlackmanHook struct {
2326
Config SlackConfig
24-
hook *logrus_slack.SlackHook // Webhook URL
27+
hook logrus.Hook // Webhook URL
2528
Enabled bool
2629
mu sync.Mutex
2730
}
@@ -94,21 +97,34 @@ func (s *SlackManager) Activate(hooktype string, useLock bool) bool {
9497
return false
9598
}
9699

97-
url, err := url.Parse(sh.Config.URL)
100+
URL, err := url.Parse(sh.Config.URL)
98101
if err != nil {
99102
s.Errorf("Failed to parse Slack URL: %v", err)
100103
return false
101104
}
102105

103-
sh.hook = &logrus_slack.SlackHook{
104-
HookURL: url.String(),
105-
AcceptedLevels: sh.Config.AcceptedLevels,
106-
Channel: sh.Config.Channel,
107-
IconEmoji: sh.Config.Icon,
108-
Username: sh.Config.User,
109-
Timeout: sh.Config.Timeout,
106+
if strings.Contains(URL.Host, "slack.com") {
107+
sh.hook = &logrus_slack.SlackHook{
108+
HookURL: URL.String(),
109+
AcceptedLevels: sh.Config.AcceptedLevels,
110+
Channel: sh.Config.Channel,
111+
IconEmoji: sh.Config.Icon,
112+
Username: sh.Config.User,
113+
Timeout: sh.Config.Timeout,
114+
}
115+
} else {
116+
sh.hook = &meethelper.MeetHook{
117+
WebhookURL: URL.String(),
118+
AcceptedLevels: sh.Config.AcceptedLevels,
119+
Timeout: sh.Config.Timeout,
120+
FieldHeader: "Replication Manager alert",
121+
Model: model.IncomingWebhookRequest{
122+
ChannelName: sh.Config.Channel,
123+
Username: sh.Config.User,
124+
IconEmoji: sh.Config.Icon,
125+
},
126+
}
110127
}
111-
112128
s.AddHook(sh.hook)
113129

114130
sh.Enabled = true

utils/meethelper/meethook.go

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package meethelper
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"net/http"
10+
"time"
11+
12+
"github.com/mattermost/mattermost-server/v6/model"
13+
"github.com/sirupsen/logrus"
14+
)
15+
16+
type MeetHook struct {
17+
WebhookURL string
18+
AcceptedLevels []logrus.Level
19+
Timeout time.Duration
20+
Async bool
21+
FieldHeader string
22+
Model model.IncomingWebhookRequest
23+
24+
hook *WebHook
25+
}
26+
27+
var ErrTimeout = errors.New("Request timed out")
28+
29+
func (sh *MeetHook) Fire(e *logrus.Entry) error {
30+
if sh.hook == nil {
31+
sh.hook = NewWebHook(sh.WebhookURL)
32+
}
33+
34+
payload := sh.Model
35+
color := LevelColorMap[e.Level]
36+
37+
attachment := model.SlackAttachment{}
38+
payload.Attachments = []*model.SlackAttachment{&attachment}
39+
40+
if len(e.Data) > 0 {
41+
attachment.Text = sh.FieldHeader
42+
43+
for k, v := range e.Data {
44+
field := &model.SlackAttachmentField{}
45+
46+
field.Title = k
47+
if str, ok := v.(string); ok {
48+
field.Value = str
49+
} else {
50+
field.Value = fmt.Sprint(v)
51+
}
52+
53+
if len(field.Value.(string)) <= 20 {
54+
field.Short = true
55+
}
56+
attachment.Fields = append(attachment.Fields, field)
57+
}
58+
attachment.Pretext = e.Message
59+
} else {
60+
attachment.Text = e.Message
61+
}
62+
attachment.Fallback = e.Message
63+
attachment.Color = color
64+
65+
if sh.Async {
66+
go sh.postMessage(&payload)
67+
return nil
68+
}
69+
70+
return sh.postMessage(&payload)
71+
}
72+
73+
func (sh *MeetHook) postMessage(payload *model.IncomingWebhookRequest) error {
74+
if sh.Timeout <= 0 {
75+
return sh.hook.PostWebhookMessage(payload)
76+
}
77+
78+
ech := make(chan error, 1)
79+
go func(ch chan error) {
80+
ch <- nil
81+
ch <- sh.hook.PostWebhookMessage(payload)
82+
}(ech)
83+
<-ech
84+
85+
select {
86+
case err := <-ech:
87+
return err
88+
case <-time.After(sh.Timeout):
89+
return ErrTimeout
90+
}
91+
}
92+
93+
// Levels sets which levels to sent to slack
94+
func (sh *MeetHook) Levels() []logrus.Level {
95+
if sh.AcceptedLevels == nil {
96+
return AllLevels
97+
}
98+
return sh.AcceptedLevels
99+
}
100+
101+
var LevelColorMap = map[logrus.Level]string{
102+
logrus.DebugLevel: "#9B30FF",
103+
logrus.InfoLevel: "good",
104+
logrus.WarnLevel: "warning",
105+
logrus.ErrorLevel: "danger",
106+
logrus.FatalLevel: "danger",
107+
logrus.PanicLevel: "danger",
108+
}
109+
110+
// Supported log levels
111+
var AllLevels = []logrus.Level{
112+
logrus.DebugLevel,
113+
logrus.InfoLevel,
114+
logrus.WarnLevel,
115+
logrus.ErrorLevel,
116+
logrus.FatalLevel,
117+
logrus.PanicLevel,
118+
}
119+
120+
// LevelThreshold - Returns every logging level above and including the given parameter.
121+
func LevelThreshold(l logrus.Level) []logrus.Level {
122+
for i := range AllLevels {
123+
if AllLevels[i] == l {
124+
return AllLevels[i:]
125+
}
126+
}
127+
return []logrus.Level{}
128+
}
129+
130+
type WebHook struct {
131+
hookURL string
132+
}
133+
134+
func NewWebHook(hookURL string) *WebHook {
135+
return &WebHook{hookURL}
136+
}
137+
138+
func (wh *WebHook) PostWebhookMessage(payload *model.IncomingWebhookRequest) error {
139+
140+
values, err := json.Marshal(payload)
141+
if err != nil {
142+
fmt.Println("PostWebhookMessage: cannot marshal payload:", err)
143+
return err
144+
}
145+
146+
req, err := http.NewRequest("POST", wh.hookURL, bytes.NewBuffer(values))
147+
if err != nil {
148+
return fmt.Errorf("failed to create POST request: %v", err)
149+
}
150+
151+
client := &http.Client{}
152+
153+
req.Header.Set("Content-Type", "application/json")
154+
resp, err := client.Do(req)
155+
if err != nil {
156+
return fmt.Errorf("failed POST request to %s: %v", wh.hookURL, err)
157+
}
158+
defer resp.Body.Close()
159+
160+
if resp.StatusCode != 200 {
161+
t, _ := io.ReadAll(resp.Body)
162+
return errors.New(string(t))
163+
}
164+
return nil
165+
}

0 commit comments

Comments
 (0)