diff --git a/contrib/inventory_builder/inventory.py b/contrib/inventory_builder/inventory.py
deleted file mode 100644
index 76e7c0c46641ceac87b2d1ce2c5baf849de645ec..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/inventory.py
+++ /dev/null
@@ -1,480 +0,0 @@
-#!/usr/bin/env python3
-# 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.
-#
-# Usage: inventory.py ip1 [ip2 ...]
-# Examples: inventory.py 10.10.1.3 10.10.1.4 10.10.1.5
-#
-# Advanced usage:
-# Add another host after initial creation: inventory.py 10.10.1.5
-# Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
-# Add hosts with different ip and access ip:
-# inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.1.3
-# Add hosts with a specific hostname, ip, and optional access ip:
-# inventory.py first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
-# Delete a host: inventory.py -10.10.1.3
-# Delete a host by id: inventory.py -node1
-#
-# Load a YAML or JSON file with inventory data: inventory.py load hosts.yaml
-# YAML file should be in the following format:
-#    group1:
-#      host1:
-#        ip: X.X.X.X
-#        var: val
-#    group2:
-#      host2:
-#        ip: X.X.X.X
-
-from collections import OrderedDict
-from ipaddress import ip_address
-from ruamel.yaml import YAML
-
-import os
-import re
-import subprocess
-import sys
-
-ROLES = ['all', 'kube_control_plane', 'kube_node', 'etcd', 'k8s_cluster',
-         'calico_rr']
-PROTECTED_NAMES = ROLES
-AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'print_hostnames',
-                      'load', 'add']
-_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
-                   '0': False, 'no': False, 'false': False, 'off': False}
-yaml = YAML()
-yaml.Representer.add_representer(OrderedDict, yaml.Representer.represent_dict)
-
-
-def get_var_as_bool(name, default):
-    value = os.environ.get(name, '')
-    return _boolean_states.get(value.lower(), default)
-
-# Configurable as shell vars start
-
-
-CONFIG_FILE = os.environ.get("CONFIG_FILE", "./inventory/sample/hosts.yaml")
-# Remove the reference of KUBE_MASTERS after some deprecation cycles.
-KUBE_CONTROL_HOSTS = int(os.environ.get("KUBE_CONTROL_HOSTS",
-                         os.environ.get("KUBE_MASTERS", 2)))
-# Reconfigures cluster distribution at scale
-SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 50))
-MASSIVE_SCALE_THRESHOLD = int(os.environ.get("MASSIVE_SCALE_THRESHOLD", 200))
-
-DEBUG = get_var_as_bool("DEBUG", True)
-HOST_PREFIX = os.environ.get("HOST_PREFIX", "node")
-USE_REAL_HOSTNAME = get_var_as_bool("USE_REAL_HOSTNAME", False)
-
-# Configurable as shell vars end
-
-
-class KubesprayInventory(object):
-
-    def __init__(self, changed_hosts=None, config_file=None):
-        self.config_file = config_file
-        self.yaml_config = {}
-        loadPreviousConfig = False
-        printHostnames = False
-        # See whether there are any commands to process
-        if changed_hosts and changed_hosts[0] in AVAILABLE_COMMANDS:
-            if changed_hosts[0] == "add":
-                loadPreviousConfig = True
-                changed_hosts = changed_hosts[1:]
-            elif changed_hosts[0] == "print_hostnames":
-                loadPreviousConfig = True
-                printHostnames = True
-            else:
-                self.parse_command(changed_hosts[0], changed_hosts[1:])
-                sys.exit(0)
-
-        # If the user wants to remove a node, we need to load the config anyway
-        if changed_hosts and changed_hosts[0][0] == "-":
-            loadPreviousConfig = True
-
-        if self.config_file and loadPreviousConfig:  # Load previous YAML file
-            try:
-                self.hosts_file = open(config_file, 'r')
-                self.yaml_config = yaml.load(self.hosts_file)
-            except OSError as e:
-                # I am assuming we are catching "cannot open file" exceptions
-                print(e)
-                sys.exit(1)
-
-        if printHostnames:
-            self.print_hostnames()
-            sys.exit(0)
-
-        self.ensure_required_groups(ROLES)
-
-        if changed_hosts:
-            changed_hosts = self.range2ips(changed_hosts)
-            self.hosts = self.build_hostnames(changed_hosts,
-                                              loadPreviousConfig)
-            self.purge_invalid_hosts(self.hosts.keys(), PROTECTED_NAMES)
-            self.set_all(self.hosts)
-            self.set_k8s_cluster()
-            etcd_hosts_count = 3 if len(self.hosts.keys()) >= 3 else 1
-            self.set_etcd(list(self.hosts.keys())[:etcd_hosts_count])
-            if len(self.hosts) >= SCALE_THRESHOLD:
-                self.set_kube_control_plane(list(self.hosts.keys())[
-                    etcd_hosts_count:(etcd_hosts_count + KUBE_CONTROL_HOSTS)])
-            else:
-                self.set_kube_control_plane(
-                  list(self.hosts.keys())[:KUBE_CONTROL_HOSTS])
-            self.set_kube_node(self.hosts.keys())
-            if len(self.hosts) >= SCALE_THRESHOLD:
-                self.set_calico_rr(list(self.hosts.keys())[:etcd_hosts_count])
-        else:  # Show help if no options
-            self.show_help()
-            sys.exit(0)
-
-        self.write_config(self.config_file)
-
-    def write_config(self, config_file):
-        if config_file:
-            with open(self.config_file, 'w') as f:
-                yaml.dump(self.yaml_config, f)
-
-        else:
-            print("WARNING: Unable to save config. Make sure you set "
-                  "CONFIG_FILE env var.")
-
-    def debug(self, msg):
-        if DEBUG:
-            print("DEBUG: {0}".format(msg))
-
-    def get_ip_from_opts(self, optstring):
-        if 'ip' in optstring:
-            return optstring['ip']
-        else:
-            raise ValueError("IP parameter not found in options")
-
-    def ensure_required_groups(self, groups):
-        for group in groups:
-            if group == 'all':
-                self.debug("Adding group {0}".format(group))
-                if group not in self.yaml_config:
-                    all_dict = OrderedDict([('hosts', OrderedDict({})),
-                                            ('children', OrderedDict({}))])
-                    self.yaml_config = {'all': all_dict}
-            else:
-                self.debug("Adding group {0}".format(group))
-                if group not in self.yaml_config['all']['children']:
-                    self.yaml_config['all']['children'][group] = {'hosts': {}}
-
-    def get_host_id(self, host):
-        '''Returns integer host ID (without padding) from a given hostname.'''
-        try:
-            short_hostname = host.split('.')[0]
-            return int(re.findall("\\d+$", short_hostname)[-1])
-        except IndexError:
-            raise ValueError("Host name must end in an integer")
-
-    # Keeps already specified hosts,
-    # and adds or removes the hosts provided as an argument
-    def build_hostnames(self, changed_hosts, loadPreviousConfig=False):
-        existing_hosts = OrderedDict()
-        highest_host_id = 0
-        # Load already existing hosts from the YAML
-        if loadPreviousConfig:
-            try:
-                for host in self.yaml_config['all']['hosts']:
-                    # Read configuration of an existing host
-                    hostConfig = self.yaml_config['all']['hosts'][host]
-                    existing_hosts[host] = hostConfig
-                    # If the existing host seems
-                    # to have been created automatically, detect its ID
-                    if host.startswith(HOST_PREFIX):
-                        host_id = self.get_host_id(host)
-                        if host_id > highest_host_id:
-                            highest_host_id = host_id
-            except Exception as e:
-                # I am assuming we are catching automatically
-                # created hosts without IDs
-                print(e)
-                sys.exit(1)
-
-        # FIXME(mattymo): Fix condition where delete then add reuses highest id
-        next_host_id = highest_host_id + 1
-        next_host = ""
-
-        all_hosts = existing_hosts.copy()
-        for host in changed_hosts:
-            # Delete the host from config the hostname/IP has a "-" prefix
-            if host[0] == "-":
-                realhost = host[1:]
-                if self.exists_hostname(all_hosts, realhost):
-                    self.debug("Marked {0} for deletion.".format(realhost))
-                    all_hosts.pop(realhost)
-                elif self.exists_ip(all_hosts, realhost):
-                    self.debug("Marked {0} for deletion.".format(realhost))
-                    self.delete_host_by_ip(all_hosts, realhost)
-            # Host/Argument starts with a digit,
-            # then we assume its an IP address
-            elif host[0].isdigit():
-                if ',' in host:
-                    ip, access_ip = host.split(',')
-                else:
-                    ip = host
-                    access_ip = host
-                if self.exists_hostname(all_hosts, host):
-                    self.debug("Skipping existing host {0}.".format(host))
-                    continue
-                elif self.exists_ip(all_hosts, ip):
-                    self.debug("Skipping existing host {0}.".format(ip))
-                    continue
-
-                if USE_REAL_HOSTNAME:
-                    cmd = ("ssh -oStrictHostKeyChecking=no "
-                           + access_ip + " 'hostname -s'")
-                    next_host = subprocess.check_output(cmd, shell=True)
-                    next_host = next_host.strip().decode('ascii')
-                else:
-                    # Generates a hostname because we have only an IP address
-                    next_host = "{0}{1}".format(HOST_PREFIX, next_host_id)
-                    next_host_id += 1
-                # Uses automatically generated node name
-                # in case we dont provide it.
-                all_hosts[next_host] = {'ansible_host': access_ip,
-                                        'ip': ip,
-                                        'access_ip': access_ip}
-            # Host/Argument starts with a letter, then we assume its a hostname
-            elif host[0].isalpha():
-                if ',' in host:
-                    try:
-                        hostname, ip, access_ip = host.split(',')
-                    except Exception:
-                        hostname, ip = host.split(',')
-                        access_ip = ip
-                if self.exists_hostname(all_hosts, host):
-                    self.debug("Skipping existing host {0}.".format(host))
-                    continue
-                elif self.exists_ip(all_hosts, ip):
-                    self.debug("Skipping existing host {0}.".format(ip))
-                    continue
-                all_hosts[hostname] = {'ansible_host': access_ip,
-                                       'ip': ip,
-                                       'access_ip': access_ip}
-        return all_hosts
-
-    # Expand IP ranges into individual addresses
-    def range2ips(self, hosts):
-        reworked_hosts = []
-
-        def ips(start_address, end_address):
-            try:
-                # Python 3.x
-                start = int(ip_address(start_address))
-                end = int(ip_address(end_address))
-            except Exception:
-                # Python 2.7
-                start = int(ip_address(str(start_address)))
-                end = int(ip_address(str(end_address)))
-            return [ip_address(ip).exploded for ip in range(start, end + 1)]
-
-        for host in hosts:
-            if '-' in host and not (host.startswith('-') or host[0].isalpha()):
-                start, end = host.strip().split('-')
-                try:
-                    reworked_hosts.extend(ips(start, end))
-                except ValueError:
-                    raise Exception("Range of ip_addresses isn't valid")
-            else:
-                reworked_hosts.append(host)
-        return reworked_hosts
-
-    def exists_hostname(self, existing_hosts, hostname):
-        return hostname in existing_hosts.keys()
-
-    def exists_ip(self, existing_hosts, ip):
-        for host_opts in existing_hosts.values():
-            if ip == self.get_ip_from_opts(host_opts):
-                return True
-        return False
-
-    def delete_host_by_ip(self, existing_hosts, ip):
-        for hostname, host_opts in existing_hosts.items():
-            if ip == self.get_ip_from_opts(host_opts):
-                del existing_hosts[hostname]
-                return
-        raise ValueError("Unable to find host by IP: {0}".format(ip))
-
-    def purge_invalid_hosts(self, hostnames, protected_names=[]):
-        for role in self.yaml_config['all']['children']:
-            if role != 'k8s_cluster' and self.yaml_config['all']['children'][role]['hosts']:  # noqa
-                all_hosts = self.yaml_config['all']['children'][role]['hosts'].copy()  # noqa
-                for host in all_hosts.keys():
-                    if host not in hostnames and host not in protected_names:
-                        self.debug(
-                            "Host {0} removed from role {1}".format(host, role))  # noqa
-                        del self.yaml_config['all']['children'][role]['hosts'][host]  # noqa
-        # purge from all
-        if self.yaml_config['all']['hosts']:
-            all_hosts = self.yaml_config['all']['hosts'].copy()
-            for host in all_hosts.keys():
-                if host not in hostnames and host not in protected_names:
-                    self.debug("Host {0} removed from role all".format(host))
-                    del self.yaml_config['all']['hosts'][host]
-
-    def add_host_to_group(self, group, host, opts=""):
-        self.debug("adding host {0} to group {1}".format(host, group))
-        if group == 'all':
-            if self.yaml_config['all']['hosts'] is None:
-                self.yaml_config['all']['hosts'] = {host: None}
-            self.yaml_config['all']['hosts'][host] = opts
-        elif group != 'k8s_cluster:children':
-            if self.yaml_config['all']['children'][group]['hosts'] is None:
-                self.yaml_config['all']['children'][group]['hosts'] = {
-                    host: None}
-            else:
-                self.yaml_config['all']['children'][group]['hosts'][host] = None  # noqa
-
-    def set_kube_control_plane(self, hosts):
-        for host in hosts:
-            self.add_host_to_group('kube_control_plane', host)
-
-    def set_all(self, hosts):
-        for host, opts in hosts.items():
-            self.add_host_to_group('all', host, opts)
-
-    def set_k8s_cluster(self):
-        k8s_cluster = {'children': {'kube_control_plane': None,
-                                    'kube_node': None}}
-        self.yaml_config['all']['children']['k8s_cluster'] = k8s_cluster
-
-    def set_calico_rr(self, hosts):
-        for host in hosts:
-            if host in self.yaml_config['all']['children']['kube_control_plane']: # noqa
-                self.debug("Not adding {0} to calico_rr group because it "
-                           "conflicts with kube_control_plane "
-                           "group".format(host))
-                continue
-            if host in self.yaml_config['all']['children']['kube_node']:
-                self.debug("Not adding {0} to calico_rr group because it "
-                           "conflicts with kube_node group".format(host))
-                continue
-            self.add_host_to_group('calico_rr', host)
-
-    def set_kube_node(self, hosts):
-        for host in hosts:
-            if len(self.yaml_config['all']['hosts']) >= SCALE_THRESHOLD:
-                if host in self.yaml_config['all']['children']['etcd']['hosts']:  # noqa
-                    self.debug("Not adding {0} to kube_node group because of "
-                               "scale deployment and host is in etcd "
-                               "group.".format(host))
-                    continue
-            if len(self.yaml_config['all']['hosts']) >= MASSIVE_SCALE_THRESHOLD:  # noqa
-                if host in self.yaml_config['all']['children']['kube_control_plane']['hosts']:  # noqa
-                    self.debug("Not adding {0} to kube_node group because of "
-                               "scale deployment and host is in "
-                               "kube_control_plane group.".format(host))
-                    continue
-            self.add_host_to_group('kube_node', host)
-
-    def set_etcd(self, hosts):
-        for host in hosts:
-            self.add_host_to_group('etcd', host)
-
-    def load_file(self, files=None):
-        '''Directly loads JSON to inventory.'''
-
-        if not files:
-            raise Exception("No input file specified.")
-
-        import json
-
-        for filename in list(files):
-            # Try JSON
-            try:
-                with open(filename, 'r') as f:
-                    data = json.load(f)
-            except ValueError:
-                raise Exception("Cannot read %s as JSON, or CSV", filename)
-
-            self.ensure_required_groups(ROLES)
-            self.set_k8s_cluster()
-            for group, hosts in data.items():
-                self.ensure_required_groups([group])
-                for host, opts in hosts.items():
-                    optstring = {'ansible_host': opts['ip'],
-                                 'ip': opts['ip'],
-                                 'access_ip': opts['ip']}
-                    self.add_host_to_group('all', host, optstring)
-                    self.add_host_to_group(group, host)
-            self.write_config(self.config_file)
-
-    def parse_command(self, command, args=None):
-        if command == 'help':
-            self.show_help()
-        elif command == 'print_cfg':
-            self.print_config()
-        elif command == 'print_ips':
-            self.print_ips()
-        elif command == 'print_hostnames':
-            self.print_hostnames()
-        elif command == 'load':
-            self.load_file(args)
-        else:
-            raise Exception("Invalid command specified.")
-
-    def show_help(self):
-        help_text = '''Usage: inventory.py ip1 [ip2 ...]
-Examples: inventory.py 10.10.1.3 10.10.1.4 10.10.1.5
-
-Available commands:
-help - Display this message
-print_cfg - Write inventory file to stdout
-print_ips - Write a space-delimited list of IPs from "all" group
-print_hostnames - Write a space-delimited list of Hostnames from "all" group
-add - Adds specified hosts into an already existing inventory
-
-Advanced usage:
-Create new or overwrite old inventory file: inventory.py 10.10.1.5
-Add another host after initial creation: inventory.py add 10.10.1.6
-Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
-Add hosts with different ip and access ip: inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.10.3
-Add hosts with a specific hostname, ip, and optional access ip: first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
-Delete a host: inventory.py -10.10.1.3
-Delete a host by id: inventory.py -node1
-
-Configurable env vars:
-DEBUG                   Enable debug printing. Default: True
-CONFIG_FILE             File to write config to Default: ./inventory/sample/hosts.yaml
-HOST_PREFIX             Host prefix for generated hosts. Default: node
-KUBE_CONTROL_HOSTS      Set the number of kube-control-planes. Default: 2
-SCALE_THRESHOLD         Separate ETCD role if # of nodes >= 50
-MASSIVE_SCALE_THRESHOLD Separate K8s control-plane and ETCD if # of nodes >= 200
-'''  # noqa
-        print(help_text)
-
-    def print_config(self):
-        yaml.dump(self.yaml_config, sys.stdout)
-
-    def print_hostnames(self):
-        print(' '.join(self.yaml_config['all']['hosts'].keys()))
-
-    def print_ips(self):
-        ips = []
-        for host, opts in self.yaml_config['all']['hosts'].items():
-            ips.append(self.get_ip_from_opts(opts))
-        print(' '.join(ips))
-
-
-def main(argv=None):
-    if not argv:
-        argv = sys.argv[1:]
-    KubesprayInventory(argv, CONFIG_FILE)
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/contrib/inventory_builder/requirements.txt b/contrib/inventory_builder/requirements.txt
deleted file mode 100644
index c54501a4bd39c6dff8511573107e53240b1a8aa1..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-configparser>=3.3.0
-ipaddress
-ruamel.yaml>=0.15.88
diff --git a/contrib/inventory_builder/setup.cfg b/contrib/inventory_builder/setup.cfg
deleted file mode 100644
index a775367e2005ceaefb8eb30e6b655deea26d9bc1..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[metadata]
-name = kubespray-inventory-builder
-version = 0.1
diff --git a/contrib/inventory_builder/setup.py b/contrib/inventory_builder/setup.py
deleted file mode 100644
index 43c5ca1b4969930cb18b03c78528e2e99ec147d2..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
-#
-# 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.
-
-# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
-import setuptools
-
-# In python < 2.7.4, a lazy loading of package `pbr` will break
-# setuptools if some other modules registered functions in `atexit`.
-# solution from: http://bugs.python.org/issue15881#msg170215
-try:
-    import multiprocessing  # noqa
-except ImportError:
-    pass
-
-setuptools.setup(
-    setup_requires=[],
-    pbr=False)
diff --git a/contrib/inventory_builder/test-requirements.txt b/contrib/inventory_builder/test-requirements.txt
deleted file mode 100644
index 98a662a4dde66e413991d8edbb9ba8a7a08f33ba..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/test-requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-hacking>=0.10.2
-mock>=1.3.0
-pytest>=2.8.0
diff --git a/contrib/inventory_builder/tests/test_inventory.py b/contrib/inventory_builder/tests/test_inventory.py
deleted file mode 100644
index 5d6649d683020d638e89e44b111b62c44bb37f91..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/tests/test_inventory.py
+++ /dev/null
@@ -1,595 +0,0 @@
-# Copyright 2016 Mirantis, Inc.
-#
-# 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.
-
-import inventory
-from io import StringIO
-import unittest
-from unittest import mock
-
-from collections import OrderedDict
-import sys
-
-path = "./contrib/inventory_builder/"
-if path not in sys.path:
-    sys.path.append(path)
-
-import inventory  # noqa
-
-
-class TestInventoryPrintHostnames(unittest.TestCase):
-
-    @mock.patch('ruamel.yaml.YAML.load')
-    def test_print_hostnames(self, load_mock):
-        mock_io = mock.mock_open(read_data='')
-        load_mock.return_value = OrderedDict({'all': {'hosts': {
-            'node1': {'ansible_host': '10.90.0.2',
-                      'ip': '10.90.0.2',
-                      'access_ip': '10.90.0.2'},
-            'node2': {'ansible_host': '10.90.0.3',
-                      'ip': '10.90.0.3',
-                      'access_ip': '10.90.0.3'}}}})
-        with mock.patch('builtins.open', mock_io):
-            with self.assertRaises(SystemExit) as cm:
-                with mock.patch('sys.stdout', new_callable=StringIO) as stdout:
-                    inventory.KubesprayInventory(
-                        changed_hosts=["print_hostnames"],
-                        config_file="file")
-            self.assertEqual("node1 node2\n", stdout.getvalue())
-            self.assertEqual(cm.exception.code, 0)
-
-
-class TestInventory(unittest.TestCase):
-    @mock.patch('inventory.sys')
-    def setUp(self, sys_mock):
-        sys_mock.exit = mock.Mock()
-        super(TestInventory, self).setUp()
-        self.data = ['10.90.3.2', '10.90.3.3', '10.90.3.4']
-        self.inv = inventory.KubesprayInventory()
-
-    def test_get_ip_from_opts(self):
-        optstring = {'ansible_host': '10.90.3.2',
-                     'ip': '10.90.3.2',
-                     'access_ip': '10.90.3.2'}
-        expected = "10.90.3.2"
-        result = self.inv.get_ip_from_opts(optstring)
-        self.assertEqual(expected, result)
-
-    def test_get_ip_from_opts_invalid(self):
-        optstring = "notanaddr=value something random!chars:D"
-        self.assertRaisesRegex(ValueError, "IP parameter not found",
-                               self.inv.get_ip_from_opts, optstring)
-
-    def test_ensure_required_groups(self):
-        groups = ['group1', 'group2']
-        self.inv.ensure_required_groups(groups)
-        for group in groups:
-            self.assertIn(group, self.inv.yaml_config['all']['children'])
-
-    def test_get_host_id(self):
-        hostnames = ['node99', 'no99de01', '01node01', 'node1.domain',
-                     'node3.xyz123.aaa']
-        expected = [99, 1, 1, 1, 3]
-        for hostname, expected in zip(hostnames, expected):
-            result = self.inv.get_host_id(hostname)
-            self.assertEqual(expected, result)
-
-    def test_get_host_id_invalid(self):
-        bad_hostnames = ['node', 'no99de', '01node', 'node.111111']
-        for hostname in bad_hostnames:
-            self.assertRaisesRegex(ValueError, "Host name must end in an",
-                                   self.inv.get_host_id, hostname)
-
-    def test_build_hostnames_add_duplicate(self):
-        changed_hosts = ['10.90.0.2']
-        expected = OrderedDict([('node3',
-                                 {'ansible_host': '10.90.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '10.90.0.2'})])
-        self.inv.yaml_config['all']['hosts'] = expected
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_two(self):
-        changed_hosts = ['10.90.0.2', '10.90.0.3']
-        expected = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        self.inv.yaml_config['all']['hosts'] = OrderedDict()
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_three(self):
-        changed_hosts = ['10.90.0.2', '10.90.0.3', '10.90.0.4']
-        expected = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'}),
-            ('node3', {'ansible_host': '10.90.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '10.90.0.4'})])
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_one(self):
-        changed_hosts = ['10.90.0.2']
-        expected = OrderedDict([('node1',
-                                 {'ansible_host': '10.90.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '10.90.0.2'})])
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_delete_first(self):
-        changed_hosts = ['-10.90.0.2']
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        self.inv.yaml_config['all']['hosts'] = existing_hosts
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_delete_by_hostname(self):
-        changed_hosts = ['-node1']
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        self.inv.yaml_config['all']['hosts'] = existing_hosts
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_exists_hostname_positive(self):
-        hostname = 'node1'
-        expected = True
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.exists_hostname(existing_hosts, hostname)
-        self.assertEqual(expected, result)
-
-    def test_exists_hostname_negative(self):
-        hostname = 'node99'
-        expected = False
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.exists_hostname(existing_hosts, hostname)
-        self.assertEqual(expected, result)
-
-    def test_exists_ip_positive(self):
-        ip = '10.90.0.2'
-        expected = True
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.exists_ip(existing_hosts, ip)
-        self.assertEqual(expected, result)
-
-    def test_exists_ip_negative(self):
-        ip = '10.90.0.200'
-        expected = False
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        result = self.inv.exists_ip(existing_hosts, ip)
-        self.assertEqual(expected, result)
-
-    def test_delete_host_by_ip_positive(self):
-        ip = '10.90.0.2'
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        self.inv.delete_host_by_ip(existing_hosts, ip)
-        self.assertEqual(expected, existing_hosts)
-
-    def test_delete_host_by_ip_negative(self):
-        ip = '10.90.0.200'
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'})])
-        self.assertRaisesRegex(ValueError, "Unable to find host",
-                               self.inv.delete_host_by_ip, existing_hosts, ip)
-
-    def test_purge_invalid_hosts(self):
-        proper_hostnames = ['node1', 'node2']
-        bad_host = 'doesnotbelong2'
-        existing_hosts = OrderedDict([
-            ('node1', {'ansible_host': '10.90.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '10.90.0.2'}),
-            ('node2', {'ansible_host': '10.90.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '10.90.0.3'}),
-            ('doesnotbelong2', {'whateveropts=ilike'})])
-        self.inv.yaml_config['all']['hosts'] = existing_hosts
-        self.inv.purge_invalid_hosts(proper_hostnames)
-        self.assertNotIn(
-            bad_host, self.inv.yaml_config['all']['hosts'].keys())
-
-    def test_add_host_to_group(self):
-        group = 'etcd'
-        host = 'node1'
-        opts = {'ip': '10.90.0.2'}
-
-        self.inv.add_host_to_group(group, host, opts)
-        self.assertEqual(
-            self.inv.yaml_config['all']['children'][group]['hosts'].get(host),
-            None)
-
-    def test_set_kube_control_plane(self):
-        group = 'kube_control_plane'
-        host = 'node1'
-
-        self.inv.set_kube_control_plane([host])
-        self.assertIn(
-            host, self.inv.yaml_config['all']['children'][group]['hosts'])
-
-    def test_set_all(self):
-        hosts = OrderedDict([
-            ('node1', 'opt1'),
-            ('node2', 'opt2')])
-
-        self.inv.set_all(hosts)
-        for host, opt in hosts.items():
-            self.assertEqual(
-                self.inv.yaml_config['all']['hosts'].get(host), opt)
-
-    def test_set_k8s_cluster(self):
-        group = 'k8s_cluster'
-        expected_hosts = ['kube_node', 'kube_control_plane']
-
-        self.inv.set_k8s_cluster()
-        for host in expected_hosts:
-            self.assertIn(
-                host,
-                self.inv.yaml_config['all']['children'][group]['children'])
-
-    def test_set_kube_node(self):
-        group = 'kube_node'
-        host = 'node1'
-
-        self.inv.set_kube_node([host])
-        self.assertIn(
-            host, self.inv.yaml_config['all']['children'][group]['hosts'])
-
-    def test_set_etcd(self):
-        group = 'etcd'
-        host = 'node1'
-
-        self.inv.set_etcd([host])
-        self.assertIn(
-            host, self.inv.yaml_config['all']['children'][group]['hosts'])
-
-    def test_scale_scenario_one(self):
-        num_nodes = 50
-        hosts = OrderedDict()
-
-        for hostid in range(1, num_nodes+1):
-            hosts["node" + str(hostid)] = ""
-
-        self.inv.set_all(hosts)
-        self.inv.set_etcd(list(hosts.keys())[0:3])
-        self.inv.set_kube_control_plane(list(hosts.keys())[0:2])
-        self.inv.set_kube_node(hosts.keys())
-        for h in range(3):
-            self.assertFalse(
-                list(hosts.keys())[h] in
-                self.inv.yaml_config['all']['children']['kube_node']['hosts'])
-
-    def test_scale_scenario_two(self):
-        num_nodes = 500
-        hosts = OrderedDict()
-
-        for hostid in range(1, num_nodes+1):
-            hosts["node" + str(hostid)] = ""
-
-        self.inv.set_all(hosts)
-        self.inv.set_etcd(list(hosts.keys())[0:3])
-        self.inv.set_kube_control_plane(list(hosts.keys())[3:5])
-        self.inv.set_kube_node(hosts.keys())
-        for h in range(5):
-            self.assertFalse(
-                list(hosts.keys())[h] in
-                self.inv.yaml_config['all']['children']['kube_node']['hosts'])
-
-    def test_range2ips_range(self):
-        changed_hosts = ['10.90.0.2', '10.90.0.4-10.90.0.6', '10.90.0.8']
-        expected = ['10.90.0.2',
-                    '10.90.0.4',
-                    '10.90.0.5',
-                    '10.90.0.6',
-                    '10.90.0.8']
-        result = self.inv.range2ips(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_range2ips_incorrect_range(self):
-        host_range = ['10.90.0.4-a.9b.c.e']
-        self.assertRaisesRegex(Exception, "Range of ip_addresses isn't valid",
-                               self.inv.range2ips, host_range)
-
-    def test_build_hostnames_create_with_one_different_ips(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2']
-        expected = OrderedDict([('node1',
-                                 {'ansible_host': '192.168.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '192.168.0.2'})])
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_create_with_two_different_ips(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2', '10.90.0.3,192.168.0.3']
-        expected = OrderedDict([
-            ('node1', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node2', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'})])
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_create_with_three_different_ips(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2',
-                         '10.90.0.3,192.168.0.3',
-                         '10.90.0.4,192.168.0.4']
-        expected = OrderedDict([
-            ('node1', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node2', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node3', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_overwrite_one_with_different_ips(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2']
-        expected = OrderedDict([('node1',
-                                 {'ansible_host': '192.168.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '192.168.0.2'})])
-        existing = OrderedDict([('node5',
-                                 {'ansible_host': '192.168.0.5',
-                                  'ip': '10.90.0.5',
-                                  'access_ip': '192.168.0.5'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_overwrite_three_with_different_ips(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2']
-        expected = OrderedDict([('node1',
-                                 {'ansible_host': '192.168.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '192.168.0.2'})])
-        existing = OrderedDict([
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'}),
-            ('node5', {'ansible_host': '192.168.0.5',
-                       'ip': '10.90.0.5',
-                       'access_ip': '192.168.0.5'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_different_ips_add_duplicate(self):
-        changed_hosts = ['10.90.0.2,192.168.0.2']
-        expected = OrderedDict([('node3',
-                                 {'ansible_host': '192.168.0.2',
-                                  'ip': '10.90.0.2',
-                                  'access_ip': '192.168.0.2'})])
-        existing = expected
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_two_different_ips_into_one_existing(self):
-        changed_hosts = ['10.90.0.3,192.168.0.3', '10.90.0.4,192.168.0.4']
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-
-        existing = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_two_different_ips_into_two_existing(self):
-        changed_hosts = ['10.90.0.4,192.168.0.4', '10.90.0.5,192.168.0.5']
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'}),
-            ('node5', {'ansible_host': '192.168.0.5',
-                       'ip': '10.90.0.5',
-                       'access_ip': '192.168.0.5'})])
-
-        existing = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    def test_build_hostnames_add_two_different_ips_into_three_existing(self):
-        changed_hosts = ['10.90.0.5,192.168.0.5', '10.90.0.6,192.168.0.6']
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'}),
-            ('node5', {'ansible_host': '192.168.0.5',
-                       'ip': '10.90.0.5',
-                       'access_ip': '192.168.0.5'}),
-            ('node6', {'ansible_host': '192.168.0.6',
-                       'ip': '10.90.0.6',
-                       'access_ip': '192.168.0.6'})])
-
-        existing = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    # Add two IP addresses into a config that has
-    # three already defined IP addresses. One of the IP addresses
-    # is a duplicate.
-    def test_build_hostnames_add_two_duplicate_one_overlap(self):
-        changed_hosts = ['10.90.0.4,192.168.0.4', '10.90.0.5,192.168.0.5']
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'}),
-            ('node5', {'ansible_host': '192.168.0.5',
-                       'ip': '10.90.0.5',
-                       'access_ip': '192.168.0.5'})])
-
-        existing = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
-
-    # Add two duplicate IP addresses into a config that has
-    # three already defined IP addresses
-    def test_build_hostnames_add_two_duplicate_two_overlap(self):
-        changed_hosts = ['10.90.0.3,192.168.0.3', '10.90.0.4,192.168.0.4']
-        expected = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-
-        existing = OrderedDict([
-            ('node2', {'ansible_host': '192.168.0.2',
-                       'ip': '10.90.0.2',
-                       'access_ip': '192.168.0.2'}),
-            ('node3', {'ansible_host': '192.168.0.3',
-                       'ip': '10.90.0.3',
-                       'access_ip': '192.168.0.3'}),
-            ('node4', {'ansible_host': '192.168.0.4',
-                       'ip': '10.90.0.4',
-                       'access_ip': '192.168.0.4'})])
-        self.inv.yaml_config['all']['hosts'] = existing
-        result = self.inv.build_hostnames(changed_hosts, True)
-        self.assertEqual(expected, result)
diff --git a/contrib/inventory_builder/tox.ini b/contrib/inventory_builder/tox.ini
deleted file mode 100644
index c9c70428cc41cd87a7ecb5848592097b3e5182cd..0000000000000000000000000000000000000000
--- a/contrib/inventory_builder/tox.ini
+++ /dev/null
@@ -1,34 +0,0 @@
-[tox]
-minversion = 1.6
-skipsdist = True
-envlist = pep8
-
-[testenv]
-allowlist_externals = py.test
-usedevelop = True
-deps =
-    -r{toxinidir}/requirements.txt
-    -r{toxinidir}/test-requirements.txt
-setenv = VIRTUAL_ENV={envdir}
-passenv =
-    http_proxy
-    HTTP_PROXY
-    https_proxy
-    HTTPS_PROXY
-    no_proxy
-    NO_PROXY
-commands = pytest -vv #{posargs:./tests}
-
-[testenv:pep8]
-usedevelop = False
-allowlist_externals = bash
-commands =
-    bash -c "find {toxinidir}/* -type f -name '*.py' -print0 | xargs -0 flake8"
-
-[testenv:venv]
-commands = {posargs}
-
-[flake8]
-show-source = true
-builtins = _
-exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg