Skip to content
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": "no-reply@example.com",
"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": ["admin1@example.com", "admin2@example.com"],
"users": ["user1@ample.com", "user2@example.com"],
"any-collection-of-emails-you-want": ["a@example.com", "b@example.com", "c@example.com"]
}
```

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