155 lines
3.7 KiB
Go
155 lines
3.7 KiB
Go
package endpoint
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/influxdata/influxdb"
|
|
)
|
|
|
|
var _ influxdb.NotificationEndpoint = &WebHook{}
|
|
|
|
const (
|
|
webhookTokenSuffix = "-token"
|
|
webhookUsernameSuffix = "-username"
|
|
webhookPasswordSuffix = "-password"
|
|
)
|
|
|
|
// WebHook is the notification endpoint config of webhook.
|
|
type WebHook struct {
|
|
Base
|
|
// Path is the API path of WebHook
|
|
URL string `json:"url"`
|
|
// Token is the bearer token for authorization
|
|
Token influxdb.SecretField `json:"token,omitempty"`
|
|
Username influxdb.SecretField `json:"username,omitempty"`
|
|
Password influxdb.SecretField `json:"password,omitempty"`
|
|
AuthMethod string `json:"authmethod"`
|
|
Method string `json:"method"`
|
|
ContentTemplate string `json:"contentTemplate"`
|
|
}
|
|
|
|
// BackfillSecretKeys fill back fill the secret field key during the unmarshalling
|
|
// if value of that secret field is not nil.
|
|
func (s *WebHook) BackfillSecretKeys() {
|
|
if s.Token.Key == "" && s.Token.Value != nil {
|
|
s.Token.Key = s.ID.String() + webhookTokenSuffix
|
|
}
|
|
if s.Username.Key == "" && s.Username.Value != nil {
|
|
s.Username.Key = s.ID.String() + webhookUsernameSuffix
|
|
}
|
|
if s.Password.Key == "" && s.Password.Value != nil {
|
|
s.Password.Key = s.ID.String() + webhookPasswordSuffix
|
|
}
|
|
}
|
|
|
|
// SecretFields return available secret fields.
|
|
func (s WebHook) SecretFields() []influxdb.SecretField {
|
|
arr := make([]influxdb.SecretField, 0)
|
|
if s.Token.Key != "" {
|
|
arr = append(arr, s.Token)
|
|
}
|
|
if s.Username.Key != "" {
|
|
arr = append(arr, s.Username)
|
|
}
|
|
if s.Password.Key != "" {
|
|
arr = append(arr, s.Password)
|
|
}
|
|
return arr
|
|
}
|
|
|
|
var goodWebHookAuthMethod = map[string]bool{
|
|
"none": true,
|
|
"basic": true,
|
|
"bearer": true,
|
|
}
|
|
|
|
var goodHTTPMethod = map[string]bool{
|
|
http.MethodGet: true,
|
|
http.MethodPost: true,
|
|
http.MethodPut: true,
|
|
}
|
|
|
|
// Valid returns error if some configuration is invalid
|
|
func (s WebHook) Valid() error {
|
|
if err := s.Base.valid(); err != nil {
|
|
return err
|
|
}
|
|
if s.URL == "" {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: "webhook endpoint URL is empty",
|
|
}
|
|
}
|
|
if _, err := url.Parse(s.URL); err != nil {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: fmt.Sprintf("webhook endpoint URL is invalid: %s", err.Error()),
|
|
}
|
|
}
|
|
if !goodHTTPMethod[s.Method] {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: "invalid webhook http method",
|
|
}
|
|
}
|
|
if !goodWebHookAuthMethod[s.AuthMethod] {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: "invalid webhook auth method",
|
|
}
|
|
}
|
|
if s.AuthMethod == "basic" &&
|
|
(s.Username.Key != s.ID.String()+webhookUsernameSuffix ||
|
|
s.Password.Key != s.ID.String()+webhookPasswordSuffix) {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: "invalid webhook username/password for basic auth",
|
|
}
|
|
}
|
|
if s.AuthMethod == "bearer" && s.Token.Key != webhookTokenSuffix {
|
|
return &influxdb.Error{
|
|
Code: influxdb.EInvalid,
|
|
Msg: "invalid webhook token for bearer auth",
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type webhookAlias WebHook
|
|
|
|
// MarshalJSON implement json.Marshaler interface.
|
|
func (s WebHook) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(
|
|
struct {
|
|
webhookAlias
|
|
Type string `json:"type"`
|
|
}{
|
|
webhookAlias: webhookAlias(s),
|
|
Type: s.Type(),
|
|
})
|
|
}
|
|
|
|
// Type returns the type.
|
|
func (s WebHook) Type() string {
|
|
return WebhookType
|
|
}
|
|
|
|
// ParseResponse will parse the http response from webhook.
|
|
func (s WebHook) ParseResponse(resp *http.Response) error {
|
|
if resp.StatusCode != http.StatusOK {
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return &influxdb.Error{
|
|
Msg: string(body),
|
|
}
|
|
}
|
|
return nil
|
|
}
|