Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added email groups and changed notif-profiles to selectively send to groups. #175

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
72 changes: 58 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ Ex. `emailer_only` would be located at `consul-alerts/config/notif-profiles/emai
".{1,}" : { "type" : "string" }
}
},
"NotifTypeList": {
"type": "object",
"title": "Hash of types for a given Notifier.",
"description": "A listing of Notifier names with a listing value indicating the types for that Notifier to use. (e.g. EmailNotifier can have receiver types like 'admins' that refer to a list of email addresses)"
},
"VarOverrides": {
"type": "object",
"title": "Hash of Notifier variables to override.",
Expand Down Expand Up @@ -247,6 +252,9 @@ Ex. `emailer_only` would be located at `consul-alerts/config/notif-profiles/emai
"NotifList": {
"log":false,
"email":true
},
"NotifTypeList": {
"email": ["admins", "users"]
}
}
```
Expand Down Expand Up @@ -399,20 +407,56 @@ The email and smtp details needs to be configured:

prefix: `consul-alerts/config/notifiers/email/`

| key | description |
|--------------|----------------------------------------------------------------------------------|
| enabled | Enable the email notifier. [Default: false] |
| cluster-name | The name of the cluster. [Default: "Consul Alerts"] |
| url | The SMTP server url |
| port | The SMTP server port |
| username | The SMTP username |
| password | The SMTP password |
| sender-alias | The sender alias. [Default: "Consul Alerts"] |
| sender-email | The sender email |
| receivers | The emails of the receivers. JSON array of string |
| template | Path to custom email template. [Default: internal template] |
| one-per-alert| Whether to send one email per alert [Default: false] |
| one-per-node | Whether to send one email per node [Default: false] (overriden by one-per-alert) |
| key | description |
|--------------|-------------------------------------------------------------------------------------------------------|
| enabled | Enable the email notifier. [Default: false] |
| cluster-name | The name of the cluster. [Default: "Consul Alerts"] |
| url | The SMTP server url |
| port | The SMTP server port |
| username | The SMTP username |
| password | The SMTP password |
| sender-alias | The sender alias. [Default: "Consul Alerts"] |
| sender-email | The sender email |
| receivers | Types of email receivers and associated email addresses. Expanded below since receivers is a folder. |
| template | Path to custom email template. [Default: internal template] |
| one-per-alert| Whether to send one email per alert [Default: false] |
| one-per-node | Whether to send one email per node [Default: false] (overriden by one-per-alert) |

This email receivers configuration allows custom keys nested under:

prefix: `consul-alerts/config/notifiers/email/receivers/`

|key | description |
|------------|-------------------------------------------------------------------------------------------------------------------------------------|
| any-string | A list of email addresses that will be used when the corresponding key is used in the NotifTypeList of a NotifProfile. JSON array. |
| any-string | Another list of email addresses as above. Any number of such key/value pairs can be nested under receivers. See example below. |

**Example email configuration:**

**Key:** `consul-alerts/config/notifiers/emailer/`

**Value:**
```
{
"enabled": true,
"url": "smtp.example.com",
"port": 587,
"username": "someuser",
"password": "password1",
"sender-email": "[email protected]",
"receivers/"
}
```

**Example email receivers configuration (note the keys can be whatever you want, and you refer to the keys in NotifProfile under NotifTypeList):**
**Key:** `consul-alerts/config/notifiers/emailer/receivers/`
```
{
"admins": ["[email protected]", "[email protected]"],
"users": ["[email protected]", "[email protected]"],
"any-collection-of-emails-you-want": ["[email protected]", "[email protected]", "[email protected]"]
}
```

The template can be any go html template. An `TemplateData` instance will be passed to the template.

Expand Down
27 changes: 14 additions & 13 deletions check-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,20 @@ func (c *CheckProcessor) notify(alerts []consul.Check) {
for i, alert := range alerts {
profileInfo := consulClient.GetProfileInfo(alert.Node, alert.ServiceID, alert.CheckID, alert.Status)
messages[i] = notifier.Message{
Node: alert.Node,
ServiceId: alert.ServiceID,
Service: alert.ServiceName,
CheckId: alert.CheckID,
Check: alert.Name,
Status: alert.Status,
Output: alert.Output,
Notes: alert.Notes,
Interval: profileInfo.Interval,
RmdCheck: time.Now(),
NotifList: profileInfo.NotifList,
VarOverrides: profileInfo.VarOverrides,
Timestamp: time.Now(),
Node: alert.Node,
ServiceId: alert.ServiceID,
Service: alert.ServiceName,
CheckId: alert.CheckID,
Check: alert.Name,
Status: alert.Status,
Output: alert.Output,
Notes: alert.Notes,
Interval: profileInfo.Interval,
RmdCheck: time.Now(),
NotifList: profileInfo.NotifList,
//NotifTypeList: profileInfo.NotifTypeList,
VarOverrides: profileInfo.VarOverrides,
Timestamp: time.Now(),
}
if profileInfo.Interval > 0 {
switch alert.Status {
Expand Down
30 changes: 27 additions & 3 deletions consul/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,16 @@ func (c *ConsulAlertClient) LoadConfig() {
valErr = loadCustomValue(&config.Notifiers.Email.Password, val, ConfigTypeString)
case "consul-alerts/config/notifiers/email/port":
valErr = loadCustomValue(&config.Notifiers.Email.Port, val, ConfigTypeInt)
case "consul-alerts/config/notifiers/email/receivers":
valErr = loadCustomValue(&config.Notifiers.Email.Receivers, val, ConfigTypeStrArray)
case "consul-alerts/config/notifiers/email/receivers/":
kvmTemp := c.KvMap("consul-alerts/config/notifiers/email/receivers")
// only want the key at the end, so split on slashes and take the last item
kvm := make(map[string][]string, len(kvmTemp))
for k, v := range kvmTemp {
kSplit := strings.Split(k, "/")
kvm[kSplit[len(kSplit)-1]] = v
}
convertedVal, _ := json.Marshal(kvm)
valErr = loadCustomValue(&config.Notifiers.Email.Receivers, convertedVal, ConfigTypeStrMap)
case "consul-alerts/config/notifiers/email/sender-alias":
valErr = loadCustomValue(&config.Notifiers.Email.SenderAlias, val, ConfigTypeString)
case "consul-alerts/config/notifiers/email/sender-email":
Expand Down Expand Up @@ -294,7 +302,7 @@ func loadCustomValue(configVariable interface{}, data []byte, cType configType)
arrConfig := configVariable.(*[]string)
err = json.Unmarshal(data, arrConfig)
case ConfigTypeStrMap:
mapConfig := configVariable.(*map[string]string)
mapConfig := configVariable.(*map[string][]string)
err = json.Unmarshal(data, mapConfig)
}
return err
Expand Down Expand Up @@ -475,6 +483,22 @@ func (c *ConsulAlertClient) CustomNotifiers() (customNotifs map[string]string) {
return customNotifs
}

// KvMap returns a map of KV pairs found directly inside the passed path
func (c *ConsulAlertClient) KvMap(kvPath string) (kvMap map[string][]string) {
if kvPairs, _, err := c.api.KV().List(kvPath, nil); err == nil {
kvMap = make(map[string][]string)
for _, kvPair := range kvPairs {
if strings.HasSuffix(kvPair.Key, "/") {
continue
}
itemList := []string{}
json.Unmarshal(kvPair.Value, &itemList)
kvMap[string(kvPair.Key)] = itemList
}
}
return kvMap
}

func (c *ConsulAlertClient) NewAlertsWithFilter(nodeName string, serviceName string, checkName string, statuses []string, ignoreBlacklist bool) []Check {
allChecks, _, _ := c.api.KV().List("consul-alerts/checks", nil)
alerts := make([]Check, 0)
Expand Down
9 changes: 5 additions & 4 deletions consul/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ type Status struct {

// ProfileInfo is for reading in JSON from profile keys
type ProfileInfo struct {
Interval int
NotifList map[string]bool
VarOverrides notifier.Notifiers
Interval int
NotifList map[string]bool
NotifTypeList map[string][]string
VarOverrides notifier.Notifiers
}

// Consul interface provides access to consul client
Expand Down Expand Up @@ -119,7 +120,7 @@ func DefaultAlertConfig() *ConsulAlertConfig {
ClusterName: "Consul-Alerts",
Enabled: false,
SenderAlias: "Consul Alerts",
Receivers: []string{},
Receivers: map[string][]string{},
}

log := &notifier.LogNotifier{
Expand Down
Loading