2015-09-25 14:14:30 +00:00
|
|
|
// Copyright 2015 Prometheus Team
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-10-29 13:34:24 +00:00
|
|
|
"strings"
|
2016-02-26 08:35:00 +00:00
|
|
|
"time"
|
2015-09-25 14:14:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2015-12-17 12:05:06 +00:00
|
|
|
// DefaultWebhookConfig defines default values for Webhook configurations.
|
|
|
|
DefaultWebhookConfig = WebhookConfig{
|
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-11-20 14:10:38 +00:00
|
|
|
// DefaultEmailConfig defines default values for Email configurations.
|
|
|
|
DefaultEmailConfig = EmailConfig{
|
2015-12-17 12:05:06 +00:00
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: false,
|
|
|
|
},
|
2016-03-04 18:42:06 +00:00
|
|
|
HTML: `{{ template "email.default.html" . }}`,
|
|
|
|
RequireTLS: true,
|
2015-11-20 14:10:38 +00:00
|
|
|
}
|
2015-11-26 17:19:46 +00:00
|
|
|
|
|
|
|
// DefaultEmailSubject defines the default Subject header of an Email.
|
|
|
|
DefaultEmailSubject = `{{ template "email.default.subject" . }}`
|
2015-11-20 14:10:38 +00:00
|
|
|
|
|
|
|
// DefaultPagerdutyConfig defines default values for PagerDuty configurations.
|
|
|
|
DefaultPagerdutyConfig = PagerdutyConfig{
|
2015-12-17 12:05:06 +00:00
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: true,
|
|
|
|
},
|
2015-11-26 17:19:46 +00:00
|
|
|
Description: `{{ template "pagerduty.default.description" .}}`,
|
|
|
|
Client: `{{ template "pagerduty.default.client" . }}`,
|
|
|
|
ClientURL: `{{ template "pagerduty.default.clientURL" . }}`,
|
|
|
|
Details: map[string]string{
|
2015-12-03 11:40:50 +00:00
|
|
|
"firing": `{{ template "pagerduty.default.instances" .Alerts.Firing }}`,
|
|
|
|
"resolved": `{{ template "pagerduty.default.instances" .Alerts.Resolved }}`,
|
|
|
|
"num_firing": `{{ .Alerts.Firing | len }}`,
|
|
|
|
"num_resolved": `{{ .Alerts.Resolved | len }}`,
|
2015-11-26 17:19:46 +00:00
|
|
|
},
|
2015-11-20 14:10:38 +00:00
|
|
|
}
|
|
|
|
|
2015-11-12 11:57:20 +00:00
|
|
|
// DefaultSlackConfig defines default values for Slack configurations.
|
2015-09-25 14:14:30 +00:00
|
|
|
DefaultSlackConfig = SlackConfig{
|
2015-12-17 12:05:06 +00:00
|
|
|
NotifierConfig: NotifierConfig{
|
2016-01-05 18:01:21 +00:00
|
|
|
VSendResolved: false,
|
2015-12-17 12:05:06 +00:00
|
|
|
},
|
2015-11-30 12:52:41 +00:00
|
|
|
Color: `{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}`,
|
|
|
|
Username: `{{ template "slack.default.username" . }}`,
|
2015-11-26 17:19:46 +00:00
|
|
|
Title: `{{ template "slack.default.title" . }}`,
|
2015-11-30 12:52:41 +00:00
|
|
|
TitleLink: `{{ template "slack.default.titlelink" . }}`,
|
2016-02-16 10:54:30 +00:00
|
|
|
IconEmoji: `{{ template "slack.default.iconemoji" . }}`,
|
2015-11-26 17:19:46 +00:00
|
|
|
Pretext: `{{ template "slack.default.pretext" . }}`,
|
|
|
|
Text: `{{ template "slack.default.text" . }}`,
|
|
|
|
Fallback: `{{ template "slack.default.fallback" . }}`,
|
2015-09-25 14:14:30 +00:00
|
|
|
}
|
2015-11-24 22:29:25 +00:00
|
|
|
|
2016-01-05 19:52:08 +00:00
|
|
|
// DefaultHipchatConfig defines default values for Hipchat configurations.
|
|
|
|
DefaultHipchatConfig = HipchatConfig{
|
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: false,
|
|
|
|
},
|
|
|
|
Color: `{{ if eq .Status "firing" }}red{{ else }}green{{ end }}`,
|
|
|
|
From: `{{ template "hipchat.default.from" . }}`,
|
|
|
|
Notify: false,
|
|
|
|
Message: `{{ template "hipchat.default.message" . }}`,
|
|
|
|
MessageFormat: `text`,
|
|
|
|
}
|
|
|
|
|
2015-11-24 22:29:25 +00:00
|
|
|
// DefaultOpsGenieConfig defines default values for OpsGenie configurations.
|
|
|
|
DefaultOpsGenieConfig = OpsGenieConfig{
|
2015-12-17 12:05:06 +00:00
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: true,
|
|
|
|
},
|
2015-11-26 17:19:46 +00:00
|
|
|
Description: `{{ template "opsgenie.default.description" . }}`,
|
2015-11-30 10:21:08 +00:00
|
|
|
Source: `{{ template "opsgenie.default.source" . }}`,
|
2015-11-24 22:29:25 +00:00
|
|
|
// TODO: Add a details field with all the alerts.
|
|
|
|
}
|
2016-02-26 08:35:00 +00:00
|
|
|
|
|
|
|
// DefaultPushoverConfig defines default values for Pushover configurations.
|
|
|
|
DefaultPushoverConfig = PushoverConfig{
|
|
|
|
NotifierConfig: NotifierConfig{
|
|
|
|
VSendResolved: true,
|
|
|
|
},
|
|
|
|
Title: `{{ template "pushover.default.title" . }}`,
|
|
|
|
Message: `{{ template "pushover.default.message" . }}`,
|
|
|
|
URL: `{{ template "pushover.default.url" . }}`,
|
|
|
|
Priority: `{{ if eq .Status "firing" }}2{{ else }}0{{ end }}`, // emergency (firing) or normal
|
|
|
|
Retry: duration(1 * time.Minute),
|
|
|
|
Expire: duration(1 * time.Hour),
|
|
|
|
}
|
2015-11-20 14:10:38 +00:00
|
|
|
)
|
2015-10-09 10:03:15 +00:00
|
|
|
|
2015-12-17 12:05:06 +00:00
|
|
|
// NotifierConfig contains base options common across all notifier configurations.
|
|
|
|
type NotifierConfig struct {
|
|
|
|
VSendResolved bool `yaml:"send_resolved"`
|
2015-09-25 14:14:30 +00:00
|
|
|
}
|
|
|
|
|
2015-12-17 12:05:06 +00:00
|
|
|
func (nc *NotifierConfig) SendResolved() bool {
|
|
|
|
return nc.VSendResolved
|
2015-09-25 14:14:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-12 11:57:20 +00:00
|
|
|
// EmailConfig configures notifications via mail.
|
2015-09-25 14:14:30 +00:00
|
|
|
type EmailConfig struct {
|
2015-12-23 07:31:50 +00:00
|
|
|
NotifierConfig `yaml:",inline"`
|
2015-12-17 12:05:06 +00:00
|
|
|
|
2015-09-25 14:14:30 +00:00
|
|
|
// Email address to notify.
|
2016-04-15 03:12:47 +00:00
|
|
|
To string `yaml:"to"`
|
|
|
|
From string `yaml:"from"`
|
|
|
|
Smarthost string `yaml:"smarthost,omitempty"`
|
|
|
|
AuthUsername string `yaml:"auth_username"`
|
|
|
|
AuthPassword Secret `yaml:"auth_password"`
|
|
|
|
AuthSecret Secret `yaml:"auth_secret"`
|
|
|
|
AuthIdentity string `yaml:"auth_identity"`
|
|
|
|
Headers map[string]string `yaml:"headers"`
|
|
|
|
HTML string `yaml:"html"`
|
|
|
|
RequireTLS bool `yaml:"require_tls"`
|
2015-09-25 14:14:30 +00:00
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *EmailConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2015-10-11 10:34:05 +00:00
|
|
|
*c = DefaultEmailConfig
|
2015-09-25 14:14:30 +00:00
|
|
|
type plain EmailConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-10-29 13:34:24 +00:00
|
|
|
if c.To == "" {
|
|
|
|
return fmt.Errorf("missing to address in email config")
|
|
|
|
}
|
|
|
|
// Header names are case-insensitive, check for collisions.
|
2015-11-20 14:10:38 +00:00
|
|
|
normalizedHeaders := map[string]string{}
|
2015-10-29 13:34:24 +00:00
|
|
|
for h, v := range c.Headers {
|
2016-03-03 14:06:11 +00:00
|
|
|
normalized := strings.Title(h)
|
2015-11-20 14:10:38 +00:00
|
|
|
if _, ok := normalizedHeaders[normalized]; ok {
|
|
|
|
return fmt.Errorf("duplicate header %q in email config", normalized)
|
2015-10-29 13:34:24 +00:00
|
|
|
}
|
2015-11-20 14:10:38 +00:00
|
|
|
normalizedHeaders[normalized] = v
|
2015-10-29 13:34:24 +00:00
|
|
|
}
|
2015-11-20 14:10:38 +00:00
|
|
|
c.Headers = normalizedHeaders
|
2015-10-29 13:34:24 +00:00
|
|
|
|
2015-09-25 14:14:30 +00:00
|
|
|
return checkOverflow(c.XXX, "email config")
|
|
|
|
}
|
|
|
|
|
2015-11-20 14:10:38 +00:00
|
|
|
// PagerdutyConfig configures notifications via PagerDuty.
|
|
|
|
type PagerdutyConfig struct {
|
2015-12-23 07:31:50 +00:00
|
|
|
NotifierConfig `yaml:",inline"`
|
2015-12-17 12:05:06 +00:00
|
|
|
|
2015-12-03 11:40:50 +00:00
|
|
|
ServiceKey Secret `yaml:"service_key"`
|
2015-11-20 14:10:38 +00:00
|
|
|
URL string `yaml:"url"`
|
2015-11-26 17:19:46 +00:00
|
|
|
Client string `yaml:"client"`
|
|
|
|
ClientURL string `yaml:"client_url"`
|
2015-11-20 14:10:38 +00:00
|
|
|
Description string `yaml:"description"`
|
|
|
|
Details map[string]string `yaml:"details"`
|
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultPagerdutyConfig
|
|
|
|
type plain PagerdutyConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.ServiceKey == "" {
|
|
|
|
return fmt.Errorf("missing service key in PagerDuty config")
|
|
|
|
}
|
|
|
|
return checkOverflow(c.XXX, "pagerduty config")
|
|
|
|
}
|
|
|
|
|
2015-11-12 11:57:20 +00:00
|
|
|
// SlackConfig configures notifications via Slack.
|
2015-09-25 14:14:30 +00:00
|
|
|
type SlackConfig struct {
|
2015-12-23 07:31:50 +00:00
|
|
|
NotifierConfig `yaml:",inline"`
|
2015-12-17 12:05:06 +00:00
|
|
|
|
2015-12-03 11:40:50 +00:00
|
|
|
APIURL Secret `yaml:"api_url"`
|
2015-09-25 14:14:30 +00:00
|
|
|
|
|
|
|
// Slack channel override, (like #other-channel or @username).
|
2015-11-30 12:52:41 +00:00
|
|
|
Channel string `yaml:"channel"`
|
|
|
|
Username string `yaml:"username"`
|
|
|
|
Color string `yaml:"color"`
|
2015-09-25 14:14:30 +00:00
|
|
|
|
2015-10-09 08:48:25 +00:00
|
|
|
Title string `yaml:"title"`
|
|
|
|
TitleLink string `yaml:"title_link"`
|
|
|
|
Pretext string `yaml:"pretext"`
|
|
|
|
Text string `yaml:"text"`
|
|
|
|
Fallback string `yaml:"fallback"`
|
2016-02-16 10:54:30 +00:00
|
|
|
IconEmoji string `yaml:"icon_emoji"`
|
2015-10-29 13:34:24 +00:00
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
2015-10-09 08:48:25 +00:00
|
|
|
}
|
|
|
|
|
2015-09-25 14:14:30 +00:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultSlackConfig
|
|
|
|
type plain SlackConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.Channel == "" {
|
|
|
|
return fmt.Errorf("missing channel in Slack config")
|
|
|
|
}
|
|
|
|
return checkOverflow(c.XXX, "slack config")
|
|
|
|
}
|
|
|
|
|
2016-01-05 19:52:08 +00:00
|
|
|
// HipchatConfig configures notifications via Hipchat.
|
|
|
|
type HipchatConfig struct {
|
|
|
|
NotifierConfig `yaml:",inline"`
|
|
|
|
|
|
|
|
APIURL string `yaml:"api_url"`
|
|
|
|
AuthToken Secret `yaml:"auth_token"`
|
|
|
|
RoomID string `yaml:"room_id"`
|
|
|
|
From string `yaml:"from"`
|
|
|
|
Notify bool `yaml:"notify"`
|
|
|
|
Message string `yaml:"message"`
|
|
|
|
MessageFormat string `yaml:"message_format"`
|
|
|
|
Color string `yaml:"color"`
|
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *HipchatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultHipchatConfig
|
|
|
|
type plain HipchatConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.RoomID == "" {
|
|
|
|
return fmt.Errorf("missing room id in Hipchat config")
|
|
|
|
}
|
|
|
|
|
|
|
|
return checkOverflow(c.XXX, "hipchat config")
|
|
|
|
}
|
|
|
|
|
2015-11-12 11:57:20 +00:00
|
|
|
// WebhookConfig configures notifications via a generic webhook.
|
2015-09-25 14:14:30 +00:00
|
|
|
type WebhookConfig struct {
|
2015-12-23 07:31:50 +00:00
|
|
|
NotifierConfig `yaml:",inline"`
|
2015-12-17 12:05:06 +00:00
|
|
|
|
2015-09-25 14:14:30 +00:00
|
|
|
// URL to send POST request to.
|
|
|
|
URL string `yaml:"url"`
|
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2015-12-17 12:05:06 +00:00
|
|
|
*c = DefaultWebhookConfig
|
2015-09-25 14:14:30 +00:00
|
|
|
type plain WebhookConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.URL == "" {
|
|
|
|
return fmt.Errorf("missing URL in webhook config")
|
|
|
|
}
|
2016-06-28 22:19:09 +00:00
|
|
|
return checkOverflow(c.XXX, "webhook config")
|
2015-09-25 14:14:30 +00:00
|
|
|
}
|
2015-11-24 22:29:25 +00:00
|
|
|
|
|
|
|
// OpsGenieConfig configures notifications via OpsGenie.
|
|
|
|
type OpsGenieConfig struct {
|
2015-12-23 07:31:50 +00:00
|
|
|
NotifierConfig `yaml:",inline"`
|
2015-12-17 12:05:06 +00:00
|
|
|
|
2015-12-03 11:40:50 +00:00
|
|
|
APIKey Secret `yaml:"api_key"`
|
2015-11-24 22:29:25 +00:00
|
|
|
APIHost string `yaml:"api_host"`
|
|
|
|
Description string `yaml:"description"`
|
2015-11-26 17:19:46 +00:00
|
|
|
Source string `yaml:"source"`
|
2015-11-24 22:29:25 +00:00
|
|
|
Details map[string]string `yaml:"details"`
|
2016-03-10 19:30:21 +00:00
|
|
|
Teams string `yaml:"teams"`
|
|
|
|
Tags string `yaml:"tags"`
|
2015-11-24 22:29:25 +00:00
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultOpsGenieConfig
|
|
|
|
type plain OpsGenieConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.APIKey == "" {
|
2015-11-25 10:38:29 +00:00
|
|
|
return fmt.Errorf("missing API key in OpsGenie config")
|
2015-11-24 22:29:25 +00:00
|
|
|
}
|
|
|
|
return checkOverflow(c.XXX, "opsgenie config")
|
|
|
|
}
|
2016-02-26 08:35:00 +00:00
|
|
|
|
|
|
|
type duration time.Duration
|
|
|
|
|
|
|
|
func (d *duration) UnmarshalText(text []byte) error {
|
|
|
|
parsed, err := time.ParseDuration(string(text))
|
|
|
|
if err == nil {
|
|
|
|
*d = duration(parsed)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d duration) MarshalText() ([]byte, error) {
|
|
|
|
return []byte(time.Duration(d).String()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type PushoverConfig struct {
|
|
|
|
NotifierConfig `yaml:",inline"`
|
|
|
|
|
|
|
|
UserKey Secret `yaml:"user_key"`
|
|
|
|
Token Secret `yaml:"token"`
|
|
|
|
Title string `yaml:"title"`
|
|
|
|
Message string `yaml:"message"`
|
|
|
|
URL string `yaml:"url"`
|
|
|
|
Priority string `yaml:"priority"`
|
|
|
|
Retry duration `yaml:"retry"`
|
|
|
|
Expire duration `yaml:"expire"`
|
|
|
|
|
|
|
|
// Catches all undefined fields and must be empty after parsing.
|
|
|
|
XXX map[string]interface{} `yaml:",inline"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultPushoverConfig
|
|
|
|
type plain PushoverConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if c.UserKey == "" {
|
|
|
|
return fmt.Errorf("missing user key in Pushover config")
|
|
|
|
}
|
|
|
|
if c.Token == "" {
|
|
|
|
return fmt.Errorf("missing token in Pushover config")
|
|
|
|
}
|
|
|
|
return checkOverflow(c.XXX, "pushover config")
|
|
|
|
}
|