← Back to team overview

nagios-charmers team mailing list archive

[Merge] ~peppepetra86/charm-nagios:extra_contacts into charm-nagios:master

 

Giuseppe Petralia has proposed merging ~peppepetra86/charm-nagios:extra_contacts into charm-nagios:master.

Commit message:
Added new configuration option extra_contacts

Requested reviews:
  Paul Goins (vultaire)
  Stuart Bishop (stub)
  BootStack Reviewers (bootstack-reviewers)

For more details, see:
https://code.launchpad.net/~peppepetra86/charm-nagios/+git/charm-nagios/+merge/388119

Implemented a new configuration option named `extra_contacts`, which allows us to define extra Nagios administrator contacts. This is useful because it enables integrating Nagios notifications with new platforms (e.g. RocketChat, Slack).

LP: 1827006
-- 
Your team Nagios Charm developers is subscribed to branch charm-nagios:master.
diff --git a/README.md b/README.md
index a71ef83..81cfce5 100644
--- a/README.md
+++ b/README.md
@@ -73,9 +73,11 @@ Will get you the public IP of the web interface.
 
 - `password` - Password to use for administrative access instead of a generated password.
 
+- `extra_contacts` - List of extra administrator contacts to configure. Useful for integrating with external notification services (e.g. Slack, RocketChat)
+
 ### SSL Configuration
 
-- `ssl` - Determinant configuration for enabling SSL. Valid options are "on", "off", "only". The "only" option disables HTTP traffic on Apache in favor of HTTPS. This setting may cause unexpected behavior with existing nagios charm deployments. 
+- `ssl` - Determinant configuration for enabling SSL. Valid options are "on", "off", "only". The "only" option disables HTTP traffic on Apache in favor of HTTPS. This setting may cause unexpected behavior with existing nagios charm deployments.
 
 - `ssl_cert` - Base64 encoded SSL certificate. Deploys to configured ssl_domain certificate name as `/etc/ssl/certs/{ssl_domain}.pem`.   If left blank, the certificate and key will be autogenerated as self-signed.
 
@@ -104,7 +106,7 @@ If you purchased keys from a certificate authority:
 
 #### Web Interface username/password
 
-Login: nagiosadmin  
+Login: nagiosadmin
 Password: see below
 
 To fetch the Nagios Administrative password you have to retrieve them from
diff --git a/config.yaml b/config.yaml
index 5221c7a..48411be 100644
--- a/config.yaml
+++ b/config.yaml
@@ -115,7 +115,7 @@ options:
     admin_pager:
         type: string
         default: pageroot@localhost
-        description: >
+        description: |
             Email address used for the admin pager, used by $ADMINPAGER$ in
             notification commands.
     enable_pagerduty:
@@ -290,3 +290,21 @@ options:
         description: |
             Defines the IP or Host Name to send snmp traps to. Leave blank (empty) to disable
             the traps functionality.
+    extra_contacts:
+        default: ''
+        type: string
+        description: |
+            Define extra contacts for Nagios. They will be appended in the
+            default administrators contact group. This is useful for adding
+            notification integrations with external services.
+            Contacts are passed as a YAML array, and must have a contact name,
+            a command to be executed for host notifications and a command to
+            be executed for service notifications. These commands may use all
+            relevant Nagios macros ($HOSTNAME$, $SERVICENAME$, etc). Refer to
+            the Nagios documentation for more information.
+            Only [A-Za-z0-9_-] contact names are valid. Be careful with
+            commands, since they are not sanitized.
+            Example
+            - name: contact_name_1
+              host: /custom/command/for/host $HOSTNAME$
+              service: /custom/command/for/service $SERVICENAME$
diff --git a/hooks/templates/contacts-cfg.tmpl b/hooks/templates/contacts-cfg.tmpl
index f182fcf..d6bf7b3 100644
--- a/hooks/templates/contacts-cfg.tmpl
+++ b/hooks/templates/contacts-cfg.tmpl
@@ -31,6 +31,39 @@ define contact{
         }
 {% endfor %}
 
+###############################################################################
+###############################################################################
+#
+# EXTRA CONTACTS
+#
+###############################################################################
+###############################################################################
+
+{% for contact in extra_contacts %}
+
+define contact{
+        contact_name                    {{ contact.name }}
+        alias                           {{ contact.name }}
+        service_notification_period     24x7
+        host_notification_period        24x7
+        service_notification_options    w,u,c,r
+        host_notification_options       d,r
+        service_notification_commands   notify-service-by-{{ contact.name }}
+        host_notification_commands      notify-host-by-{{ contact.name }}
+        }
+
+
+define command {
+        command_name                    notify-service-by-{{ contact.name }}
+        command_line                    {{ contact.service }}
+}
+
+define command {
+        command_name                    notify-host-by-{{ contact.name }}
+        command_line                    {{ contact.host }}
+}
+
+{% endfor %}
 
 ###############################################################################
 ###############################################################################
@@ -46,6 +79,5 @@ define contact{
 define contactgroup{
         contactgroup_name       admins
         alias                   Nagios Administrators
-        members                 {{ contactgroup_members }}
+        members                 {{ contactgroup_members }}{% for contact in extra_contacts %}, {{ contact.name }}{% endfor %}
         }
-
diff --git a/hooks/upgrade_charm.py b/hooks/upgrade_charm.py
index bbbb8ac..f3191e3 100755
--- a/hooks/upgrade_charm.py
+++ b/hooks/upgrade_charm.py
@@ -12,6 +12,7 @@ import stat
 import errno
 import shutil
 import subprocess
+import yaml
 from charmhelpers.contrib import ssl
 from charmhelpers.core import hookenv, host
 from charmhelpers import fetch
@@ -58,6 +59,52 @@ def warn_legacy_relations():
                 "WARNING")
 
 
+# Parses a list of extra Nagios contacts from a YAML string
+# Does basic sanitization only
+def get_extra_contacts(yaml_string, log=False):
+    # Final result
+    extra_contacts = []
+
+    # Valid characters for contact names
+    valid_name_chars = (
+        'abcdefghijklmnopqrstuvwxyz'
+        'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+        '0123456789_-'
+    )
+
+    try:
+        extra_contacts_raw = yaml.load(yaml_string, Loader=yaml.SafeLoader) or []
+        if not isinstance(extra_contacts_raw, list):
+            raise ValueError('not a list')
+
+        for contact in extra_contacts_raw:
+            if {'name', 'host', 'service'} > set(contact.keys()):
+                if log:
+                    hookenv.log(
+                        'Contact {} is missing fields.'.format(contact))
+                continue
+
+            if set(contact['name']) >= set(valid_name_chars):
+                if log:
+                    hookenv.log(
+                        'Contact name {} is illegal'.format(contact['name']))
+                continue
+
+            if '\n' in (contact['host'] + contact['service']):
+                if log:
+                    hookenv.log('Line breaks not allowed in commands')
+                continue
+
+            extra_contacts.append(contact)
+
+    except (ValueError, yaml.error.YAMLError) as e:
+        if log:
+            hookenv.log(
+                'Invalid "extra_contacts" configuration: {}'.format(e))
+
+    return extra_contacts
+
+
 # If the charm has extra configuration provided, write that to the
 # proper nagios3 configuration file, otherwise remove the config
 def write_extra_config():
@@ -205,6 +252,10 @@ def update_contacts():
     if forced_contactgroup_members:
         resulting_members = resulting_members + ',' + ','.join(forced_contactgroup_members)
 
+    # Parse extra_contacts
+    extra_contacts = get_extra_contacts(
+        hookenv.config('extra_contacts'), log=True)
+
     template_values = {'admin_service_notification_period': hookenv.config('admin_service_notification_period'),
                        'admin_host_notification_period': hookenv.config('admin_host_notification_period'),
                        'admin_service_notification_options': hookenv.config('admin_service_notification_options'),
@@ -212,7 +263,8 @@ def update_contacts():
                        'admin_service_notification_commands': hookenv.config('admin_service_notification_commands'),
                        'admin_host_notification_commands': hookenv.config('admin_host_notification_commands'),
                        'admin_email': hookenv.config('admin_email'),
-                       'contactgroup_members': resulting_members}
+                       'contactgroup_members': resulting_members,
+                       'extra_contacts': extra_contacts}
 
     with open('hooks/templates/contacts-cfg.tmpl', 'r') as f:
         templateDef = f.read()

Follow ups