← Back to team overview

nagios-charmers team mailing list archive

[Merge] ~xavpaice/charm-nagios:lint-20.08 into charm-nagios:master

 

Xav Paice has proposed merging ~xavpaice/charm-nagios:lint-20.08 into charm-nagios:master with ~xavpaice/charm-nagios:blacken-20.08 as a prerequisite.

Commit message:
Extra Linting completed for 20.08 charm release

Requested reviews:
  Nagios Charm developers (nagios-charmers)

For more details, see:
https://code.launchpad.net/~xavpaice/charm-nagios/+git/nagios-charm/+merge/388634
-- 
Your team Nagios Charm developers is requested to review the proposed merge of ~xavpaice/charm-nagios:lint-20.08 into charm-nagios:master.
diff --git a/hooks/common.py b/hooks/common.py
index 3bff942..b320880 100644
--- a/hooks/common.py
+++ b/hooks/common.py
@@ -1,17 +1,17 @@
-import subprocess
-import socket
 import os
 import os.path
 import re
 import shutil
+import socket
+import subprocess
 import tempfile
 
 from charmhelpers.core.hookenv import (
+    config,
     log,
     network_get,
     network_get_primary_address,
     unit_get,
-    config,
 )
 
 from pynag import Model
@@ -28,16 +28,18 @@ PLUGIN_PATH = "/usr/lib/nagios/plugins"
 Model.cfg_file = INPROGRESS_CFG
 Model.pynag_directory = INPROGRESS_CONF_D
 
-reduce_RE = re.compile(r"[\W_]")
+REDUCE_RE = re.compile(r"[\W_]")
 
 
 def check_ip(n):
     try:
         socket.inet_pton(socket.AF_INET, n)
+
         return True
     except socket.error:
         try:
             socket.inet_pton(socket.AF_INET6, n)
+
             return True
         except socket.error:
             return False
@@ -48,10 +50,12 @@ def get_local_ingress_address(binding="website"):
     log("Getting hostname for binding %s" % binding)
     try:
         network_info = network_get(binding)
+
         if network_info is not None and "ingress-addresses" in network_info:
             log("Using ingress-addresses")
             hostname = network_info["ingress-addresses"][0]
             log(hostname)
+
             return hostname
     except NotImplementedError:
         # We'll fallthrough to the Pre 2.3 code below.
@@ -66,29 +70,36 @@ def get_local_ingress_address(binding="website"):
         hostname = unit_get("private-address")
         log("Using unit_get private address")
     log(hostname)
+
     return hostname
 
 
 def get_remote_relation_attr(remote_unit, attr_name, relation_id=None):
     args = ["relation-get", attr_name, remote_unit]
+
     if relation_id is not None:
         args.extend(["-r", relation_id])
+
     return subprocess.check_output(args).strip()
 
 
 def get_ip_and_hostname(remote_unit, relation_id=None):
     hostname = get_remote_relation_attr(remote_unit, "ingress-address", relation_id)
+
     if hostname is None or not len(hostname):
         hostname = get_remote_relation_attr(remote_unit, "private-address", relation_id)
 
     if hostname is None or not len(hostname):
         log("relation-get failed")
+
         return 2
+
     if check_ip(hostname):
         # Some providers don't provide hostnames, so use the remote unit name.
         ip_address = hostname
     else:
         ip_address = socket.getaddrinfo(hostname, None)[0][4][0]
+
     return (ip_address, remote_unit.replace("/", "-"))
 
 
@@ -98,11 +109,13 @@ def refresh_hostgroups():  # noqa:C901
     hosts = [x["host_name"] for x in Model.Host.objects.all if x["host_name"]]
 
     hgroups = {}
+
     for host in hosts:
         try:
             (service, unit_id) = host.rsplit("-", 1)
         except ValueError:
             continue
+
         if service in hgroups:
             hgroups[service].append(host)
         else:
@@ -114,6 +127,7 @@ def refresh_hostgroups():  # noqa:C901
 
     # Delete the ones not in hgroups
     to_delete = set(auto_hgroups).difference(set(hgroups.keys()))
+
     for hgroup_name in to_delete:
         try:
             hgroup = Model.Hostgroup.objects.get_by_shortname(hgroup_name)
@@ -138,7 +152,7 @@ def _make_check_command(args):
     args = [str(arg) for arg in args]
     # There is some worry of collision, but the uniqueness of the initial
     # command should be enough.
-    signature = reduce_RE.sub("_", "".join([os.path.basename(arg) for arg in args]))
+    signature = REDUCE_RE.sub("_", "".join([os.path.basename(arg) for arg in args]))
     Model.Command.objects.reload_cache()
     try:
         cmd = Model.Command.objects.get_by_shortname(signature)
@@ -147,6 +161,7 @@ def _make_check_command(args):
         cmd.set_attribute("command_name", signature)
         cmd.set_attribute("command_line", " ".join(args))
         cmd.save()
+
     return signature
 
 
@@ -163,19 +178,23 @@ def customize_http(service, name, extra):
     path = extra.get("path", "/")
     args = [port, path]
     cmd_args = [plugin, "-p", '"$ARG1$"', "-u", '"$ARG2$"']
+
     if "status" in extra:
         _extend_args(args, cmd_args, "-e", extra["status"])
+
     if "host" in extra:
         _extend_args(args, cmd_args, "-H", extra["host"])
         cmd_args.extend(("-I", "$HOSTADDRESS$"))
     else:
         cmd_args.extend(("-H", "$HOSTADDRESS$"))
     check_timeout = config("check_timeout")
+
     if check_timeout is not None:
         cmd_args.extend(("-t", check_timeout))
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
@@ -183,16 +202,20 @@ def customize_mysql(service, name, extra):
     plugin = os.path.join(PLUGIN_PATH, "check_mysql")
     args = []
     cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
+
     if "user" in extra:
         _extend_args(args, cmd_args, "-u", extra["user"])
+
     if "password" in extra:
         _extend_args(args, cmd_args, "-p", extra["password"])
     check_timeout = config("check_timeout")
+
     if check_timeout is not None:
         cmd_args.extend(("-t", check_timeout))
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
@@ -201,11 +224,13 @@ def customize_pgsql(service, name, extra):
     args = []
     cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
     check_timeout = config("check_timeout")
+
     if check_timeout is not None:
         cmd_args.extend(("-t", check_timeout))
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
@@ -213,6 +238,7 @@ def customize_nrpe(service, name, extra):
     plugin = os.path.join(PLUGIN_PATH, "check_nrpe")
     args = []
     cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
+
     if name in ("mem", "swap"):
         cmd_args.extend(("-c", "check_%s" % name))
     elif "command" in extra:
@@ -220,61 +246,77 @@ def customize_nrpe(service, name, extra):
     else:
         cmd_args.extend(("-c", extra))
     check_timeout = config("check_timeout")
+
     if check_timeout is not None:
         cmd_args.extend(("-t", check_timeout))
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
 def customize_rpc(service, name, extra):
-    """ Customize the check_rpc plugin to check things like nfs."""
+    """Customize the check_rpc plugin to check things like nfs."""
     plugin = os.path.join(PLUGIN_PATH, "check_rpc")
     args = []
     # /usr/lib/nagios/plugins/check_rpc -H <host> -C <rpc_command>
     cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
+
     if "rpc_command" in extra:
         cmd_args.extend(("-C", extra["rpc_command"]))
+
     if "program_version" in extra:
         cmd_args.extend(("-c", extra["program_version"]))
 
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
 def customize_tcp(service, name, extra):
-    """ Customize tcp can be used to check things like memcached. """
+    """Customize tcp can be used to check things like memcached."""
     plugin = os.path.join(PLUGIN_PATH, "check_tcp")
     args = []
     # /usr/lib/nagios/plugins/check_tcp -H <host> -E
     cmd_args = [plugin, "-H", "$HOSTADDRESS$", "-E"]
+
     if "port" in extra:
         cmd_args.extend(("-p", extra["port"]))
+
     if "string" in extra:
         cmd_args.extend(("-s", "'{}'".format(extra["string"])))
+
     if "expect" in extra:
         cmd_args.extend(("-e", extra["expect"]))
+
     if "warning" in extra:
         cmd_args.extend(("-w", extra["warning"]))
+
     if "critical" in extra:
         cmd_args.extend(("-c", extra["critical"]))
+
     if "timeout" in extra:
         cmd_args.extend(("-t", extra["timeout"]))
     check_timeout = config("check_timeout")
+
     if check_timeout is not None:
         cmd_args.extend(("-t", check_timeout))
 
     check_command = _make_check_command(cmd_args)
     cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
     service.set_attribute("check_command", cmd)
+
     return True
 
 
 def customize_service(service, family, name, extra):
-    """ The monitors.yaml names are mapped to methods that customize services. """
+    """Map names to service methods.
+
+    The monitors.yaml names are mapped to methods that customize services.
+    """
     customs = {
         "http": customize_http,
         "mysql": customize_mysql,
@@ -283,17 +325,19 @@ def customize_service(service, family, name, extra):
         "rpc": customize_rpc,
         "pgsql": customize_pgsql,
     }
+
     if family in customs:
         return customs[family](service, name, extra)
+
     return False
 
 
 def update_localhost():
-    """ Update the localhost definition to use the ubuntu icons."""
-
+    """Update the localhost definition to use the ubuntu icons."""
     Model.cfg_file = MAIN_NAGIOS_CFG
     Model.pynag_directory = os.path.join(MAIN_NAGIOS_DIR, "conf.d")
     hosts = Model.Host.objects.filter(host_name="localhost", object_type="host")
+
     for host in hosts:
         host.icon_image = "base/ubuntu.png"
         host.icon_image_alt = "Ubuntu Linux"
@@ -318,6 +362,7 @@ def get_pynag_host(target_id, owner_unit=None, owner_relation=None):
         host.save()
         host = Model.Host.objects.get_by_shortname(target_id)
     apply_host_policy(target_id, owner_unit, owner_relation)
+
     return host
 
 
@@ -325,6 +370,7 @@ def get_pynag_service(target_id, service_name):
     services = Model.Service.objects.filter(
         host_name=target_id, service_description=service_name
     )
+
     if len(services) == 0:
         service = Model.Service()
         service.set_filename(CHARM_CFG)
@@ -333,6 +379,7 @@ def get_pynag_service(target_id, service_name):
         service.set_attribute("use", "generic-service")
     else:
         service = services[0]
+
     return service
 
 
@@ -369,6 +416,7 @@ def initialize_inprogress_config():
         shutil.rmtree(INPROGRESS_DIR)
     shutil.copytree(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
     _replace_in_config(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
+
     if os.path.exists(CHARM_CFG):
         os.unlink(CHARM_CFG)
 
@@ -376,10 +424,13 @@ def initialize_inprogress_config():
 def flush_inprogress_config():
     if not os.path.exists(INPROGRESS_DIR):
         return
+
     if os.path.exists(MAIN_NAGIOS_BAK):
         shutil.rmtree(MAIN_NAGIOS_BAK)
+
     if os.path.exists(MAIN_NAGIOS_DIR):
         shutil.move(MAIN_NAGIOS_DIR, MAIN_NAGIOS_BAK)
     shutil.move(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
-    # now that directory has been changed need to update the config file to reflect the real stuff..
+    # now that directory has been changed need to update the config file to
+    # reflect the real stuff..
     _commit_in_config(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
diff --git a/hooks/monitors_relation_changed.py b/hooks/monitors_relation_changed.py
index e3d5a5a..6df3303 100755
--- a/hooks/monitors_relation_changed.py
+++ b/hooks/monitors_relation_changed.py
@@ -16,36 +16,32 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import sys
 import os
-import yaml
 import re
+import sys
 from collections import defaultdict
 
 from charmhelpers.core.hookenv import (
-    relation_get,
+    DEBUG,
     ingress_address,
+    log,
     related_units,
+    relation_get,
     relation_ids,
-    log,
-    DEBUG,
 )
 
 from common import (
     customize_service,
+    flush_inprogress_config,
     get_pynag_host,
     get_pynag_service,
-    refresh_hostgroups,
     initialize_inprogress_config,
-    flush_inprogress_config,
+    refresh_hostgroups,
 )
 
+import yaml
 
-REQUIRED_REL_DATA_KEYS = [
-    "target-address",
-    "monitors",
-    "target-id",
-]
+REQUIRED_REL_DATA_KEYS = ["target-address", "monitors", "target-id"]
 
 
 def _prepare_relation_data(unit, rid):
@@ -56,6 +52,7 @@ def _prepare_relation_data(unit, rid):
             unit, rid
         )
         log(msg, level=DEBUG)
+
         return {}
 
     if rid.split(":")[0] == "nagios":
@@ -76,6 +73,7 @@ def _prepare_relation_data(unit, rid):
                 key, unit, rid
             )
             log(msg, level=DEBUG)
+
             return {}
 
     return relation_data
@@ -83,10 +81,12 @@ def _prepare_relation_data(unit, rid):
 
 def _collect_relation_data():
     all_relations = defaultdict(dict)
+
     for relname in ["nagios", "monitors"]:
         for relid in relation_ids(relname):
             for unit in related_units(relid):
                 relation_data = _prepare_relation_data(unit=unit, rid=relid)
+
                 if relation_data:
                     all_relations[relid][unit] = relation_data
 
@@ -98,8 +98,10 @@ def main(argv):  # noqa: C901
     # and target-address' so the hook can be tested without being in a hook
     # context.
     #
+
     if len(argv) > 1:
         relation_settings = {"monitors": open(argv[1]).read(), "target-id": argv[2]}
+
         if len(argv) > 3:
             relation_settings["target-address"] = argv[3]
         all_relations = {"monitors:99": {"testing/0": relation_settings}}
@@ -108,11 +110,13 @@ def main(argv):  # noqa: C901
 
     # Hack to work around http://pad.lv/1025478
     targets_with_addresses = set()
+
     for relid, units in all_relations.iteritems():
         for unit, relation_settings in units.items():
             if "target-id" in relation_settings:
                 targets_with_addresses.add(relation_settings["target-id"])
     new_all_relations = {}
+
     for relid, units in all_relations.iteritems():
         for unit, relation_settings in units.items():
             if relation_settings["target-id"] in targets_with_addresses:
@@ -124,11 +128,14 @@ def main(argv):  # noqa: C901
     initialize_inprogress_config()
     # make a dict of machine ids to target-id hostnames
     all_hosts = {}
+
     for relid, units in all_relations.items():
         for unit, relation_settings in units.iteritems():
             machine_id = relation_settings.get("machine_id", None)
+
             if machine_id:
                 all_hosts[machine_id] = relation_settings["target-id"]
+
     for relid, units in all_relations.items():
         apply_relation_config(relid, units, all_hosts)
     refresh_hostgroups()
@@ -142,10 +149,13 @@ def apply_relation_config(relid, units, all_hosts):  # noqa: C901
         target_id = relation_settings["target-id"]
         machine_id = relation_settings.get("machine_id", None)
         parent_host = None
+
         if machine_id:
             container_regex = re.compile(r"(\d+)/lx[cd]/\d+")
+
             if container_regex.search(machine_id):
                 parent_machine = container_regex.search(machine_id).group(1)
+
                 if parent_machine in all_hosts:
                     parent_host = all_hosts[parent_machine]
 
@@ -159,9 +169,11 @@ def apply_relation_config(relid, units, all_hosts):  # noqa: C901
 
         # Output nagios config
         host = get_pynag_host(target_id)
+
         if not target_address:
             raise Exception("No Target Address provied by NRPE service!")
         host.set_attribute("address", target_address)
+
         if parent_host:
             # We assume that we only want one parent and will overwrite any
             # existing parents for this host.
@@ -172,6 +184,7 @@ def apply_relation_config(relid, units, all_hosts):  # noqa: C901
             for mon_name, mon in mons.iteritems():
                 service_name = "%s-%s" % (target_id, mon_name)
                 service = get_pynag_service(target_id, service_name)
+
                 if customize_service(service, mon_family, mon_name, mon):
                     service.save()
                 else:
diff --git a/hooks/upgrade_charm.py b/hooks/upgrade_charm.py
index 5091f9a..ca410ef 100755
--- a/hooks/upgrade_charm.py
+++ b/hooks/upgrade_charm.py
@@ -3,25 +3,26 @@
 # Rewritten from bash to python 3/2/2014 for charm helper inclusion
 # of SSL-Everywhere!
 import base64
-from jinja2 import Template
+import errno
 import glob
+import grp
 import os
-
-# import re
 import pwd
-import grp
-import string
-import stat
-import errno
 import shutil
+import stat
+import string
 import subprocess
-import yaml
+
+from charmhelpers import fetch
 from charmhelpers.contrib import ssl
 from charmhelpers.core import hookenv, host
-from charmhelpers import fetch
 
 from common import update_localhost
 
+from jinja2 import Template
+
+import yaml
+
 # Gather facts
 legacy_relations = hookenv.config("legacy")
 extra_config = hookenv.config("extraconfig")
@@ -55,7 +56,7 @@ SSL_CONFIGURED = ssl_config in ["on", "only", "true"]
 
 
 def warn_legacy_relations():
-    """Checks the charm relations for legacy relations.
+    """Check the charm relations for legacy relations.
 
     Inserts warnings into the log about legacy relations, as they will be removed
     in the future
@@ -70,7 +71,7 @@ def warn_legacy_relations():
 
 
 def parse_extra_contacts(yaml_string):
-    """Parses a list of extra Nagios contacts from a YAML string.
+    """Parse a list of extra Nagios contacts from a YAML string.
 
     Does basic sanitization only
     """
@@ -82,6 +83,7 @@ def parse_extra_contacts(yaml_string):
 
     try:
         extra_contacts_raw = yaml.load(yaml_string, Loader=yaml.SafeLoader) or []
+
         if not isinstance(extra_contacts_raw, list):
             raise ValueError("not a list")
 
@@ -90,6 +92,7 @@ def parse_extra_contacts(yaml_string):
                 hookenv.log(
                     "Contact {} is missing fields.".format(contact), hookenv.WARNING
                 )
+
                 continue
 
             if set(contact["name"]) > set(valid_name_chars):
@@ -97,10 +100,12 @@ def parse_extra_contacts(yaml_string):
                     "Contact name {} is illegal".format(contact["name"]),
                     hookenv.WARNING,
                 )
+
                 continue
 
             if "\n" in (contact["host"] + contact["service"]):
                 hookenv.log("Line breaks not allowed in commands", hookenv.WARNING)
+
                 continue
 
             contact["name"] = contact["name"].lower()
@@ -111,6 +116,7 @@ def parse_extra_contacts(yaml_string):
         hookenv.log(
             'Invalid "extra_contacts" configuration: {}'.format(e), hookenv.WARNING
         )
+
     if len(extra_contacts_raw) != len(extra_contacts):
         hookenv.log(
             "Invalid extra_contacts config, found {} contacts defined, "
@@ -125,10 +131,12 @@ def parse_extra_contacts(yaml_string):
 # proper nagios3 configuration file, otherwise remove the config
 def write_extra_config():
     # Be predjudice about this - remove the file always.
+
     if host.file_hash("/etc/nagios3/conf.d/extra.cfg") is not None:
         os.remove("/etc/nagios3/conf.d/extra.cfg")
     # If we have a config, then write it. the hook reconfiguration will
     # handle the details
+
     if extra_config is not None:
         host.write_file("/etc/nagios3/conf.d/extra.cfg", extra_config)
 
@@ -150,6 +158,7 @@ def fixpath(path):
     if os.path.isdir(path):
         st = os.stat(path)
         os.chmod(path, st.st_mode | stat.S_IXOTH)
+
     if path != "/":
         fixpath(os.path.split(path)[0])
 
@@ -163,6 +172,7 @@ def enable_livestatus_config():
         # Make the directory and fix perms on it
         hookenv.log("Fixing perms on livestatus_path")
         livestatus_dir = os.path.dirname(livestatus_path)
+
         if not os.path.isdir(livestatus_dir):
             hookenv.log("Making path for livestatus_dir")
             mkdir_p(livestatus_dir)
@@ -202,16 +212,16 @@ def enable_pagerduty_config():
         }
 
         with open("hooks/templates/pagerduty_nagios_cfg.tmpl", "r") as f:
-            templateDef = f.read()
+            template_def = f.read()
 
-        t = Template(templateDef)
+        t = Template(template_def)
         with open(pagerduty_cfg, "w") as f:
             f.write(t.render(template_values))
 
         with open("hooks/templates/nagios-pagerduty-flush-cron.tmpl", "r") as f2:
-            templateDef = f2.read()
+            template_def = f2.read()
 
-        t2 = Template(templateDef)
+        t2 = Template(template_def)
         with open(pagerduty_cron, "w") as f2:
             f2.write(t2.render(template_values))
 
@@ -219,6 +229,7 @@ def enable_pagerduty_config():
         shutil.copy("files/pagerduty_nagios.pl", "/usr/local/bin/pagerduty_nagios.pl")
 
         # Create the pagerduty queue dir
+
         if not os.path.isdir(pagerduty_path):
             hookenv.log("Making path for pagerduty_path")
             mkdir_p(pagerduty_path)
@@ -228,14 +239,18 @@ def enable_pagerduty_config():
         os.chown(pagerduty_path, uid, gid)
     else:
         # Clean up the files if we don't want pagerduty
+
         if os.path.isfile(pagerduty_cfg):
             os.remove(pagerduty_cfg)
+
         if os.path.isfile(pagerduty_cron):
             os.remove(pagerduty_cron)
 
     # Update contacts for admin
+
     if enable_pagerduty:
         # avoid duplicates
+
         if "pagerduty" not in contactgroup_members:
             forced_contactgroup_members.append("pagerduty")
 
@@ -249,6 +264,7 @@ def enable_traps_config():
         if os.path.isfile(traps_cfg):
             os.remove(traps_cfg)
         hookenv.log("Send traps feature is disabled")
+
         return
 
     hookenv.log("Send traps feature is enabled, target address is %s" % send_traps_to)
@@ -259,9 +275,9 @@ def enable_traps_config():
     template_values = {"send_traps_to": send_traps_to}
 
     with open("hooks/templates/traps.tmpl", "r") as f:
-        templateDef = f.read()
+        template_def = f.read()
 
-    t = Template(templateDef)
+    t = Template(template_def)
     with open(traps_cfg, "w") as f:
         f.write(t.render(template_values))
 
@@ -271,17 +287,20 @@ def update_contacts():
     admin_members = ""
     contacts = []
     admin_email = list(filter(None, set(hookenv.config("admin_email").split(","))))
+
     if len(admin_email) == 0:
         hookenv.log("admin_email is unset, this isn't valid config")
         hookenv.status_set("blocked", "admin_email is not configured")
         exit(1)
     hookenv.status_set("active", "ready")
+
     if len(admin_email) == 1:
         hookenv.log("Setting one admin email address '%s'" % admin_email[0])
         contacts = [{"contact_name": "root", "alias": "Root", "email": admin_email[0]}]
     elif len(admin_email) > 1:
         hookenv.log("Setting %d admin email addresses" % len(admin_email))
         contacts = []
+
         for email in admin_email:
             contact_name = email.replace("@", "").replace(".", "").lower()
             contact_alias = contact_name.capitalize()
@@ -292,6 +311,7 @@ def update_contacts():
         admin_members = ", ".join([c["contact_name"] for c in contacts])
 
     resulting_members = contactgroup_members
+
     if admin_members:
         # if multiple admin emails are passed ignore contactgroup_members
         resulting_members = admin_members
@@ -338,8 +358,10 @@ def update_contacts():
 
 def ssl_configured():
     allowed_options = ["on", "only"]
+
     if str(ssl_config).lower() in allowed_options:
         return True
+
     return False
 
 
@@ -359,8 +381,10 @@ chain_file = "/etc/ssl/certs/%s.csr" % (cert_domain)
 def check_ssl_files():
     key = os.path.exists(deploy_key_path)
     cert = os.path.exists(deploy_cert_path)
+
     if key is False or cert is False:
         return False
+
     return True
 
 
@@ -370,9 +394,11 @@ def decode_ssl_keys():
         hookenv.log("Writing key from config ssl_key: %s" % key_file)
         with open(key_file, "w") as f:
             f.write(str(base64.b64decode(hookenv.config("ssl_key"))))
+
     if hookenv.config("ssl_cert"):
         with open(cert_file, "w") as f:
             f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))
+
     if hookenv.config("ssl_chain"):
         with open(chain_file, "w") as f:
             f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))
@@ -382,10 +408,13 @@ def enable_ssl():
     # Set the basename of all ssl files
 
     # Validate that we have configs, and generate a self signed certificate.
+
     if not hookenv.config("ssl_cert"):
         # bail if keys already exist
+
         if os.path.exists(cert_file):
             hookenv.log("Keys exist, not creating keys!", "WARNING")
+
             return
         # Generate a self signed key using CharmHelpers
         hookenv.log("Generating Self Signed Certificate", "INFO")
@@ -405,6 +434,7 @@ def update_config():
     local_host_name = "nagios"
     principal_unitname = hookenv.principal_unit()
     # Fallback to using "primary" if it exists.
+
     if principal_unitname:
         local_host_name = principal_unitname
     else:
@@ -437,16 +467,16 @@ def update_config():
     }
 
     with open("hooks/templates/nagios-cfg.tmpl", "r") as f:
-        templateDef = f.read()
+        template_def = f.read()
 
-    t = Template(templateDef)
+    t = Template(template_def)
     with open(nagios_cfg, "w") as f:
         f.write(t.render(template_values))
 
     with open("hooks/templates/localhost_nagios2.cfg.tmpl", "r") as f:
-        templateDef = f.read()
+        template_def = f.read()
 
-    t = Template(templateDef)
+    t = Template(template_def)
     with open("/etc/nagios3/conf.d/localhost_nagios2.cfg", "w") as f:
         f.write(t.render(template_values))
 
@@ -456,9 +486,9 @@ def update_config():
 def update_cgi_config():
     template_values = {"nagiosadmin": nagiosadmin, "ro_password": ro_password}
     with open("hooks/templates/nagios-cgi.tmpl", "r") as f:
-        templateDef = f.read()
+        template_def = f.read()
 
-    t = Template(templateDef)
+    t = Template(template_def)
     with open(nagios_cgi_cfg, "w") as f:
         f.write(t.render(template_values))
 
@@ -472,12 +502,12 @@ def update_cgi_config():
 # note: i tried to use cheetah, and it barfed, several times. It can go play
 # in a fire. I'm jusing jinja2.
 def update_apache():
-    """
+    """Add SSL keys to default-ssl config.
+
     Nagios3 is deployed as a global apache application from the archive.
     We'll get a little funky and add the SSL keys to the default-ssl config
     which sets our keys, including the self-signed ones, as the host keyfiles.
     """
-
     # Start by Setting the ports.conf
 
     with open("hooks/templates/ports-cfg.jinja2", "r") as f:
@@ -489,6 +519,7 @@ def update_apache():
         f.write(t.render({"enable_http": HTTP_ENABLED}))
 
     # Next setup the default-ssl.conf
+
     if os.path.exists(chain_file) and os.path.getsize(chain_file) > 0:
         ssl_chain = chain_file
     else:
@@ -515,6 +546,7 @@ def update_apache():
     # Configure the behavior of http sites
     sites = glob.glob("/etc/apache2/sites-available/*.conf")
     non_ssl = set(sites) - {ssl_conf}
+
     for each in non_ssl:
         site = os.path.basename(each).rsplit(".", 1)[0]
         Apache2Site(site).action(enabled=HTTP_ENABLED)
@@ -549,6 +581,7 @@ class Apache2Site:
     def _enable(self):
         hookenv.log("Apache2Site: Enabling %s..." % self.site, "INFO")
         self._call(["a2ensite", self.site])
+
         if self.port == 443:
             self._call(["a2enmod", "ssl"])
         hookenv.open_port(self.port)
@@ -562,6 +595,7 @@ class Apache2Site:
 def update_password(account, password):
     """Update the charm and Apache's record of the password for the supplied account."""
     account_file = "".join(["/var/lib/juju/nagios.", account, ".passwd"])
+
     if password:
         with open(account_file, "w") as f:
             f.write(password)
@@ -580,6 +614,7 @@ write_extra_config()
 # enable_traps_config and enable_pagerduty_config modify forced_contactgroup_members
 # they need to run before update_contacts that will consume that global var.
 enable_traps_config()
+
 if ssl_configured():
     enable_ssl()
 enable_pagerduty_config()
@@ -591,8 +626,10 @@ update_localhost()
 update_cgi_config()
 update_contacts()
 update_password("nagiosro", ro_password)
+
 if password:
     update_password(nagiosadmin, password)
+
 if nagiosadmin != "nagiosadmin":
     update_password("nagiosadmin", False)
 
diff --git a/hooks/website_relation_joined.py b/hooks/website_relation_joined.py
index 706a561..126e7cd 100755
--- a/hooks/website_relation_joined.py
+++ b/hooks/website_relation_joined.py
@@ -15,18 +15,15 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import common
+from charmhelpers.core.hookenv import config, log, relation_set
 
-from charmhelpers.core.hookenv import (
-    config,
-    log,
-    relation_set,
-)
+import common
 
 
 def main():
     relation_data = {"hostname": common.get_local_ingress_address()}
     sslcfg = config()["ssl"]
+
     if sslcfg == "only":
         relation_data["port"] = 443
     else:
diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py
index a31034c..7ab5b1a 100644
--- a/tests/functional/conftest.py
+++ b/tests/functional/conftest.py
@@ -42,9 +42,11 @@ async def model(controller):
     model = await controller.add_model(model_name)
     yield model
     await model.disconnect()
+
     if os.getenv("PYTEST_KEEP_MODEL"):
         return
     await controller.destroy_model(model_name)
+
     while model_name in await controller.list_models():
         await asyncio.sleep(1)
 
@@ -60,7 +62,7 @@ async def current_model():
 
 @pytest.fixture
 async def get_app(model):
-    """Return the application requested."""
+    """Return the application requested."""  # noqa D202
 
     async def _get_app(name):
         try:
@@ -73,11 +75,12 @@ async def get_app(model):
 
 @pytest.fixture
 async def get_unit(model):
-    """Return the requested <app_name>/<unit_number> unit."""
+    """Return the requested <app_name>/<unit_number> unit."""  # noqa D202
 
     async def _get_unit(name):
         try:
             (app_name, unit_number) = name.split("/")
+
             return model.applications[app_name].units[unit_number]
         except (KeyError, ValueError):
             raise JujuError("Cannot find unit {}".format(name))
@@ -87,7 +90,7 @@ async def get_unit(model):
 
 @pytest.fixture
 async def get_entity(model, get_unit, get_app):
-    """Return a unit or an application."""
+    """Return a unit or an application."""  # noqa D202
 
     async def _get_entity(name):
         try:
@@ -103,7 +106,7 @@ async def get_entity(model, get_unit, get_app):
 
 @pytest.fixture
 async def run_command(get_unit):
-    """Run a command on a unit."""
+    """Run a command on a unit."""  # noqa D202
 
     async def _run_command(cmd, target):
         """
@@ -114,6 +117,7 @@ async def run_command(get_unit):
         """
         unit = target if type(target) is juju.unit.Unit else await get_unit(target)
         action = await unit.run(cmd)
+
         return action.results
 
     return _run_command
@@ -121,16 +125,16 @@ async def run_command(get_unit):
 
 @pytest.fixture
 async def file_stat(run_command):
-    """
-    Run stat on a file.
+    """Run stat on a file.
 
     :param path: File path
     :param target: Unit object or unit name string
-    """
+    """  # noqa D202
 
     async def _file_stat(path, target):
         cmd = STAT_FILE % path
         results = await run_command(cmd, target)
+
         return json.loads(results["Stdout"])
 
     return _file_stat
@@ -138,16 +142,17 @@ async def file_stat(run_command):
 
 @pytest.fixture
 async def file_contents(run_command):
-    """Return the contents of a file."""
+    """Return the contents of a file."""  # noqa D202
 
     async def _file_contents(path, target):
         """Return the contents of a file.
 
-            :param path: File path
-            :param target: Unit object or unit name string
+        :param path: File path
+        :param target: Unit object or unit name string
         """
         cmd = "cat {}".format(path)
         results = await run_command(cmd, target)
+
         return results["Stdout"]
 
     return _file_contents
@@ -155,7 +160,7 @@ async def file_contents(run_command):
 
 @pytest.fixture
 async def reconfigure_app(get_app, model):
-    """Apply a different config to the requested app."""
+    """Apply a different config to the requested app."""  # noqa D202
 
     async def _reconfigure_app(cfg, target):
         application = (
@@ -172,7 +177,7 @@ async def reconfigure_app(get_app, model):
 
 @pytest.fixture
 async def create_group(run_command):
-    """Create the UNIX group specified."""
+    """Create the UNIX group specified."""  # noqa D202
 
     async def _create_group(group_name, target):
         cmd = "sudo groupadd %s" % group_name
@@ -185,11 +190,7 @@ pytestmark = pytest.mark.asyncio
 
 CHARM_BUILD_DIR = os.getenv("CHARM_BUILD_DIR", "..").rstrip("/")
 
-SERIES = [
-    "trusty",
-    "xenial",
-    "bionic",
-]
+SERIES = ["trusty", "xenial", "bionic"]
 
 
 ############
@@ -210,6 +211,7 @@ async def relatives(model, series):
     )
 
     mysql = "mysql"
+
     if series != "trusty":
         mysql = "percona-cluster"
 
@@ -224,7 +226,7 @@ async def relatives(model, series):
     )
     await model.block_until(
         lambda: mysql_app.units[0].workload_status == "active"
-        and mysql_app.units[0].agent_status == "idle"
+        and mysql_app.units[0].agent_status == "idle"  # noqa W503
     )
 
     yield {
@@ -256,10 +258,11 @@ async def deploy_app(relatives, model, series):
     )
     await model.block_until(
         lambda: nagios_app.units[0].agent_status == "idle"
-        and relatives["mysql"]["app"].units[0].agent_status == "idle"
+        and relatives["mysql"]["app"].units[0].agent_status == "idle"  # noqa W503
     )
 
     yield nagios_app
+
     if os.getenv("PYTEST_KEEP_MODEL"):
         return
 
@@ -277,6 +280,7 @@ class Agent:
 
     def is_active(self, status):
         u = self.u
+
         return u.agent_status == status and u.workload_status == "active"
 
     async def block_until_or_timeout(self, lambda_f, **kwargs):
@@ -299,6 +303,7 @@ async def unit(model, deploy_app):
     """Return the unit we've deployed."""
     unit = Agent(deploy_app.units[0], deploy_app)
     await unit.block_until(lambda: unit.is_active("idle"))
+
     return unit
 
 
@@ -306,4 +311,5 @@ async def unit(model, deploy_app):
 async def auth(file_contents, unit):
     """Return the basic auth credentials."""
     nagiospwd = await file_contents("/var/lib/juju/nagios.passwd", unit.u)
+
     return "nagiosadmin", nagiospwd.strip()
diff --git a/tests/functional/test_config.py b/tests/functional/test_config.py
index 1b9310a..6bc36a6 100644
--- a/tests/functional/test_config.py
+++ b/tests/functional/test_config.py
@@ -1,5 +1,7 @@
 from async_generator import asynccontextmanager
+
 import pytest
+
 import requests
 
 pytestmark = pytest.mark.asyncio
@@ -18,8 +20,7 @@ async def config(unit, item, test_value, post_test):
 
 @pytest.fixture(params=["on", "only"])
 async def ssl(unit, request):
-    """
-    Enable SSL before a test, then disable after test
+    """Enable SSL before a test, then disable after test.
 
     :param Agent unit:              unit from the fixture
     :param request:                 test parameters
@@ -30,8 +31,7 @@ async def ssl(unit, request):
 
 @pytest.fixture
 async def extra_config(unit):
-    """
-    Enable extraconfig for a test, and revert afterwards
+    """Enable extraconfig for a test, and revert afterwards.
 
     :param Agent unit:              unit from the fixture
     """
@@ -48,8 +48,7 @@ async def extra_config(unit):
 
 @pytest.fixture
 async def livestatus_path(unit):
-    """
-    Enable livestatus before a test, then disable after test
+    """Enable livestatus before a test, then disable after test.
 
     :param Agent unit:              unit from the fixture
     """
@@ -60,8 +59,7 @@ async def livestatus_path(unit):
 
 @pytest.fixture()
 async def enable_pagerduty(unit):
-    """
-    Enable enable_pagerduty before first test, then disable after last test
+    """Enable enable_pagerduty before first test, then disable after last test.
 
     :param Agent unit:              unit from the fixture
     """
diff --git a/tests/functional/test_deploy.py b/tests/functional/test_deploy.py
index 32503c2..efbafb7 100644
--- a/tests/functional/test_deploy.py
+++ b/tests/functional/test_deploy.py
@@ -1,4 +1,5 @@
 import pytest
+
 import requests
 
 pytestmark = pytest.mark.asyncio
diff --git a/tests/unit/test_website_relation_joined.py b/tests/unit/test_website_relation_joined.py
index b4ca91a..7dff088 100644
--- a/tests/unit/test_website_relation_joined.py
+++ b/tests/unit/test_website_relation_joined.py
@@ -1,6 +1,7 @@
 import unittest.mock as mock
 
 import pytest
+
 import website_relation_joined
 
 
diff --git a/tox.ini b/tox.ini
index 8f1b11b..17cb36f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -48,33 +48,7 @@ ignore =  # TODO remove most of these
     D101,
     D102,
     D103,
-    D104,
     D107,
-    D202,
-    D205,
-    D208,
-    D210,
-    D400,
-    D401,
-    I100,
-    I101,
-    I201,
-    I202,
-    E201,
-    E202,
-    E231,
-    E121,
-    E126,
-    E131,
-    D201,
-    E302,
-    E501,
-    N806,
-    N816,
-    W503,
-    W504
-
-
 max-line-length = 88
 max-complexity = 10
 

Follow ups