notify: add markdown support for wechat (#2309)
* notify: add markdown support for wechat Signed-off-by: Jason Cooper <master@deamwork.com> * docs: update WeChat receiver configuration document Signed-off-by: Jason Cooper <master@deamwork.com> * fix: check WeChat msgType, apply default if not present Signed-off-by: Jason Cooper <master@deamwork.com> * chore: remove unnecessary comment Signed-off-by: Jason Cooper <master@deamwork.com> * fix: simplify msgType process Signed-off-by: Jason Cooper <master@deamwork.com> * docs: wechat configs document update Signed-off-by: Jason Cooper <master@deamwork.com> * fix: apply error message suggestions Signed-off-by: Jason Cooper <master@deamwork.com> * test: add test for regex Signed-off-by: Jason Cooper <master@deamwork.com> * fix: wechat message safe param Signed-off-by: Jason Cooper <master@deamwork.com>
This commit is contained in:
parent
1895fde856
commit
277c9ed462
|
@ -396,21 +396,38 @@ type WechatConfig struct {
|
|||
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
|
||||
APISecret Secret `yaml:"api_secret,omitempty" json:"api_secret,omitempty"`
|
||||
CorpID string `yaml:"corp_id,omitempty" json:"corp_id,omitempty"`
|
||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||
APIURL *URL `yaml:"api_url,omitempty" json:"api_url,omitempty"`
|
||||
ToUser string `yaml:"to_user,omitempty" json:"to_user,omitempty"`
|
||||
ToParty string `yaml:"to_party,omitempty" json:"to_party,omitempty"`
|
||||
ToTag string `yaml:"to_tag,omitempty" json:"to_tag,omitempty"`
|
||||
AgentID string `yaml:"agent_id,omitempty" json:"agent_id,omitempty"`
|
||||
APISecret Secret `yaml:"api_secret,omitempty" json:"api_secret,omitempty"`
|
||||
CorpID string `yaml:"corp_id,omitempty" json:"corp_id,omitempty"`
|
||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||
APIURL *URL `yaml:"api_url,omitempty" json:"api_url,omitempty"`
|
||||
ToUser string `yaml:"to_user,omitempty" json:"to_user,omitempty"`
|
||||
ToParty string `yaml:"to_party,omitempty" json:"to_party,omitempty"`
|
||||
ToTag string `yaml:"to_tag,omitempty" json:"to_tag,omitempty"`
|
||||
AgentID string `yaml:"agent_id,omitempty" json:"agent_id,omitempty"`
|
||||
MessageType string `yaml:"message_type,omitempty" json:"message_type,omitempty"`
|
||||
}
|
||||
|
||||
const wechatValidTypesRe = `^(text|markdown)$`
|
||||
|
||||
var wechatTypeMatcher = regexp.MustCompile(wechatValidTypesRe)
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (c *WechatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
*c = DefaultWechatConfig
|
||||
type plain WechatConfig
|
||||
return unmarshal((*plain)(c))
|
||||
if err := unmarshal((*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.MessageType == "" {
|
||||
c.MessageType = "text"
|
||||
}
|
||||
|
||||
if !wechatTypeMatcher.MatchString(c.MessageType) {
|
||||
return errors.Errorf("WeChat message type %q does not match valid options %s", c.MessageType, wechatValidTypesRe)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpsGenieConfig configures notifications via OpsGenie.
|
||||
|
|
|
@ -590,6 +590,21 @@ func TestOpsgenieTypeMatcher(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestWeChatTypeMatcher(t *testing.T) {
|
||||
good := []string{"text", "markdown"}
|
||||
for _, g := range good {
|
||||
if !wechatTypeMatcher.MatchString(g) {
|
||||
t.Fatalf("failed to match with %s", g)
|
||||
}
|
||||
}
|
||||
bad := []string{"TEXT", "MarkDOwn"}
|
||||
for _, b := range bad {
|
||||
if wechatTypeMatcher.MatchString(b) {
|
||||
t.Errorf("mistakenly match with %s", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newBoolPointer(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
|
|
@ -711,6 +711,8 @@ API](http://admin.wechat.com/wiki/index.php?title=Customer_Service_Messages).
|
|||
|
||||
# API request data as defined by the WeChat API.
|
||||
[ message: <tmpl_string> | default = '{{ template "wechat.default.message" . }}' ]
|
||||
# Type of the message type, supported values are `text` and `markdown`.
|
||||
[ message_type: <string> | default = 'text' ]
|
||||
[ agent_id: <string> | default = '{{ template "wechat.default.agent_id" . }}' ]
|
||||
[ to_user: <string> | default = '{{ template "wechat.default.to_user" . }}' ]
|
||||
[ to_party: <string> | default = '{{ template "wechat.default.to_party" . }}' ]
|
||||
|
|
|
@ -51,13 +51,14 @@ type token struct {
|
|||
}
|
||||
|
||||
type weChatMessage struct {
|
||||
Text weChatMessageContent `yaml:"text,omitempty" json:"text,omitempty"`
|
||||
ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"`
|
||||
ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"`
|
||||
Totag string `yaml:"totag,omitempty" json:"totag,omitempty"`
|
||||
AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"`
|
||||
Safe string `yaml:"safe,omitempty" json:"safe,omitempty"`
|
||||
Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"`
|
||||
Text weChatMessageContent `yaml:"text,omitempty" json:"text,omitempty"`
|
||||
ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"`
|
||||
ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"`
|
||||
Totag string `yaml:"totag,omitempty" json:"totag,omitempty"`
|
||||
AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"`
|
||||
Safe string `yaml:"safe,omitempty" json:"safe,omitempty"`
|
||||
Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"`
|
||||
Markdown weChatMessageContent `yaml:"markdown,omitempty" json:"markdown,omitempty"`
|
||||
}
|
||||
|
||||
type weChatMessageContent struct {
|
||||
|
@ -135,16 +136,23 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
|||
}
|
||||
|
||||
msg := &weChatMessage{
|
||||
Text: weChatMessageContent{
|
||||
Content: tmpl(n.conf.Message),
|
||||
},
|
||||
ToUser: tmpl(n.conf.ToUser),
|
||||
ToParty: tmpl(n.conf.ToParty),
|
||||
Totag: tmpl(n.conf.ToTag),
|
||||
AgentID: tmpl(n.conf.AgentID),
|
||||
Type: "text",
|
||||
Type: n.conf.MessageType,
|
||||
Safe: "0",
|
||||
}
|
||||
|
||||
if msg.Type == "markdown" {
|
||||
msg.Markdown = weChatMessageContent{
|
||||
Content: tmpl(n.conf.Message),
|
||||
}
|
||||
} else {
|
||||
msg.Text = weChatMessageContent{
|
||||
Content: tmpl(n.conf.Message),
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("templating error: %s", err)
|
||||
}
|
||||
|
|
|
@ -67,3 +67,26 @@ func TestWechatRedactedURLOnNotify(t *testing.T) {
|
|||
|
||||
test.AssertNotifyLeaksNoSecret(t, ctx, notifier, secret, token)
|
||||
}
|
||||
|
||||
func TestWechatMessageTypeSelector(t *testing.T) {
|
||||
secret, token := "secret", "token"
|
||||
ctx, u, fn := test.GetContextWithCancelingURL(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{"access_token":"%s"}`, token)
|
||||
})
|
||||
defer fn()
|
||||
|
||||
notifier, err := New(
|
||||
&config.WechatConfig{
|
||||
APIURL: &config.URL{URL: u},
|
||||
HTTPConfig: &commoncfg.HTTPClientConfig{},
|
||||
CorpID: "corpid",
|
||||
APISecret: config.Secret(secret),
|
||||
MessageType: "markdown",
|
||||
},
|
||||
test.CreateTmpl(t),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
test.AssertNotifyLeaksNoSecret(t, ctx, notifier, secret, token)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue