A few changes to better align with what I know think it's the best setup in Webex Teams

- Move away from Webhook to APIRUL
- Make the Room ID a require field
- Set Authorization Credentails via Headers

Signed-off-by: gotjosh <josue.abreu@gmail.com>
This commit is contained in:
gotjosh 2022-11-09 14:16:00 +00:00
parent 9e2608ebff
commit ac0dc96127
No known key found for this signature in database
GPG Key ID: A6E1DDE38FF3C74E
6 changed files with 82 additions and 22 deletions

View File

@ -520,8 +520,12 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
if webex.HTTPConfig == nil {
webex.HTTPConfig = c.Global.HTTPConfig
}
if webex.WebhookURL == nil {
return fmt.Errorf("no webex webhook URL provided")
if webex.APIURL == nil {
if c.Global.WebexAPIURL == nil {
return fmt.Errorf("no global Webex URL set")
}
webex.APIURL = c.Global.WebexAPIURL
}
}
@ -624,6 +628,7 @@ func DefaultGlobalConfig() GlobalConfig {
WeChatAPIURL: mustParseURL("https://qyapi.weixin.qq.com/cgi-bin/"),
VictorOpsAPIURL: mustParseURL("https://alert.victorops.com/integrations/generic/20131114/alert/"),
TelegramAPIUrl: mustParseURL("https://api.telegram.org"),
WebexAPIURL: mustParseURL("https://webexapis.com/v1/messages"),
}
}
@ -747,6 +752,7 @@ type GlobalConfig struct {
VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"`
VictorOpsAPIKeyFile string `yaml:"victorops_api_key_file,omitempty" json:"victorops_api_key_file,omitempty"`
TelegramAPIUrl *URL `yaml:"telegram_api_url,omitempty" json:"telegram_api_url,omitempty"`
WebexAPIURL *URL `yaml:"webex_api_url,omitempty" json:"webex_api_url,omitempty"`
}
// UnmarshalYAML implements the yaml.Unmarshaler interface for GlobalConfig.

View File

@ -867,6 +867,7 @@ func TestEmptyFieldsAndRegex(t *testing.T) {
WeChatAPIURL: mustParseURL("https://qyapi.weixin.qq.com/cgi-bin/"),
VictorOpsAPIURL: mustParseURL("https://alert.victorops.com/integrations/generic/20131114/alert/"),
TelegramAPIUrl: mustParseURL("https://api.telegram.org"),
WebexAPIURL: mustParseURL("https://webexapis.com/v1/messages"),
},
Templates: []string{

View File

@ -178,17 +178,26 @@ func (nc *NotifierConfig) SendResolved() bool {
type WebexConfig struct {
NotifierConfig `yaml:",inline" json:",inline"`
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
APIURL *URL `yaml:"api_url,omitempty" json:"api_url,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
RoomID string `yaml:"room_id,omitempty" json:"room_id,omitempty"`
RoomID string `yaml:"room_id" json:"room_id"`
BotToken Secret `yaml:"bot_token" yaml:"bot_token"`
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *WebexConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
*c = DefaultWebexConfig
type plain WebexConfig
return unmarshal((*plain)(c))
if err := unmarshal((*plain)(c)); err != nil {
return err
}
if c.RoomID == "" {
return fmt.Errorf("missing room_id on webex_config")
}
return nil
}
// DiscordConfig configures notifications via Discord.

View File

@ -14,6 +14,7 @@
package config
import (
"errors"
"strings"
"testing"
@ -866,6 +867,39 @@ func TestWeChatTypeMatcher(t *testing.T) {
}
}
func TestWebexConfiguration(t *testing.T) {
tc := []struct {
name string
in string
expected error
}{
{
name: "with no room_id - it fails",
in: `
bot_token: xyz123
`,
expected: errors.New("missing room_id on webex_config"),
},
{
name: "with room_id and bot_token present - it succeeds",
in: `
room_id: 2
bot_token: xyz123
`,
},
}
for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
var cfg WebexConfig
err := yaml.UnmarshalStrict([]byte(tt.in), &cfg)
require.Equal(t, tt.expected, err)
})
}
}
func newBoolPointer(b bool) *bool {
return &b
}

View File

@ -40,11 +40,18 @@ type Notifier struct {
logger log.Logger
client *http.Client
retrier *notify.Retrier
webhookURL *config.SecretURL
APIURL *config.URL
}
// New returns a new Webex notifier.
func New(c *config.WebexConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) {
if c.HTTPConfig.Authorization == nil && c.HTTPConfig.BearerToken == "" {
c.HTTPConfig.Authorization = &commoncfg.Authorization{
Type: "Bearer",
Credentials: commoncfg.Secret(c.BotToken),
}
}
client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "webex", httpOpts...)
if err != nil {
return nil, err
@ -56,7 +63,7 @@ func New(c *config.WebexConfig, t *template.Template, l log.Logger, httpOpts ...
logger: l,
client: client,
retrier: &notify.Retrier{},
webhookURL: c.WebhookURL,
APIURL: c.APIURL,
}
return n, nil
@ -102,7 +109,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
return false, err
}
resp, err := notify.PostJSON(ctx, n.client, n.webhookURL.String(), &payload)
resp, err := notify.PostJSON(ctx, n.client, n.APIURL.String(), &payload)
if err != nil {
return true, notify.RedactURL(err)
}

View File

@ -41,7 +41,7 @@ func TestWebexRetry(t *testing.T) {
notifier, err := New(
&config.WebexConfig{
HTTPConfig: &commoncfg.HTTPClientConfig{},
WebhookURL: &config.SecretURL{URL: testWebhookURL},
APIURL: &config.URL{URL: testWebhookURL},
},
test.CreateTmpl(t),
log.NewNopLogger(),
@ -85,15 +85,18 @@ func TestWebexTemplating(t *testing.T) {
for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
var out []byte
var header http.Header
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error
out, err = io.ReadAll(r.Body)
header = r.Header.Clone()
require.NoError(t, err)
}))
defer srv.Close()
u, _ := url.Parse(srv.URL)
tt.cfg.WebhookURL = &config.SecretURL{URL: u}
tt.cfg.APIURL = &config.URL{URL: u}
tt.cfg.BotToken = "xxxyyyzz"
tt.cfg.HTTPConfig = &commoncfg.HTTPClientConfig{}
notifierWebex, err := New(tt.cfg, test.CreateTmpl(t), log.NewNopLogger())
require.NoError(t, err)
@ -127,7 +130,7 @@ func TestWebexTemplating(t *testing.T) {
if tt.errMsg == "" {
require.NoError(t, err)
fmt.Println(string(out))
require.Equal(t, "sss", header.Get("Authorization"))
require.JSONEq(t, tt.expJSON, string(out))
} else {
require.Error(t, err)