# Buggy code
def parse(self, inventory, loader, path, cache=True):
    super(InventoryModule, self).parse(inventory, loader, path)

    cache_key = self._get_cache_prefix(path)

    # file is config file
    self._config_data = self._read_config_data(path)

    msg = ""
    if not self._config_data:
        msg = "File empty. this is not my config file"
    elif "plugin" in self._config_data and self._config_data["plugin"] != self.NAME:
        msg = "plugin config file, but not for us: %s" % self._config_data["plugin"]
    elif "plugin" not in self._config_data and "clouds" not in self._config_data:
        msg = "it's not a plugin configuration nor a clouds.yaml file"
    elif not HAS_SDK:
        msg = "openstacksdk is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped."

    if msg:
        raise AnsibleParserError(msg)

    # The user has pointed us at a clouds.yaml file. Use defaults for
    # everything.
    if "clouds" in self._config_data:
        self._config_data = {}

    if cache:
        cache = self.get_option("cache")
    source_data = None
    if cache:
        try:
            source_data = self.cache.get(cache_key)
        except KeyError:
            pass

    if not source_data:
        clouds_yaml_path = self._config_data.get("clouds_yaml_path")
        if clouds_yaml_path:
            config_files = clouds_yaml_path + client_config.CONFIG_FILES
        else:
            config_files = None

        # TODO(mordred) Integrate openstack's logging with ansible's logging
        sdk.enable_logging()

        cloud_inventory = sdk_inventory.OpenStackInventory(
            config_files=config_files, private=self._config_data.get("private", False)
        )
        only_clouds = self._config_data.get("only_clouds", [])
        if only_clouds and not isinstance(only_clouds, list):
            raise ValueError(
                "OpenStack Inventory Config Error: only_clouds must be a list"
            )
        if only_clouds:
            new_clouds = []
            for cloud in cloud_inventory.clouds:
                if cloud.name in only_clouds:
                    new_clouds.append(cloud)
            cloud_inventory.clouds = new_clouds

        expand_hostvars = self._config_data.get("expand_hostvars", False)
        fail_on_errors = self._config_data.get("fail_on_errors", False)

        source_data = cloud_inventory.list_hosts(
            expand=expand_hostvars, fail_on_cloud_config=fail_on_errors
        )

        if self.cache is not None:
            self.cache.set(cache_key, source_data)

    self._populate_from_source(source_data)


# Traceback (fail_on_error)
File "/Users/alancoding/.virtualenvs/ansible/bin/ansible-inventory", line 4, in <module>
__import__('pkg_resources').run_script('ansible==2.8.0.dev0', 'ansible-inventory')
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/pkg_resources/__init__.py", line 661, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1441, in run_script
exec(code, namespace, namespace)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/EGG-INFO/scripts/ansible-inventory", line 110, in <module>
exit_code = cli.run()
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/cli/inventory.py", line 136, in run
self.loader, self.inventory, self.vm = self._play_prereqs(self.options)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/cli/__init__.py", line 787, in _play_prereqs
inventory = InventoryManager(loader=loader, sources=options.inventory)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/inventory/manager.py", line 145, in __init__
self.parse_sources(cache=True)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/inventory/manager.py", line 205, in parse_sources
parse = self.parse_source(source, cache=cache)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/inventory/manager.py", line 270, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/plugins/inventory/auto.py", line 55, in parse
plugin.parse(inventory, loader, path, cache=cache)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/ansible-2.8.0.dev0-py2.7.egg/ansible/plugins/inventory/openstack.py", line 197, in parse
expand=expand_hostvars, fail_on_cloud_config=fail_on_errors)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/inventory.py", line 66, in list_hosts
for server in cloud.list_servers(detailed=expand):
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 2123, in list_servers
filters=filters)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 2146, in _list_servers
for server in servers
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 3138, in _expand_server
return meta.get_hostvars_from_server(self, server)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/meta.py", line 482, in get_hostvars_from_server
server_vars = add_server_interfaces(cloud, server)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/meta.py", line 447, in add_server_interfaces
server['addresses'] = _get_supplemental_addresses(cloud, server)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/meta.py", line 407, in _get_supplemental_addresses
if (cloud.has_service('network') and cloud._has_floating_ips() and
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 1419, in has_service
endpoint = self.get_session_endpoint(service_key)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 1389, in get_session_endpoint
return self.config.get_session_endpoint(service_key)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/config/cloud_region.py", line 596, in get_session_endpoint
traceback.print_stack()
Traceback (most recent call last):
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/openstack/config/cloud_region.py", line 592, in get_session_endpoint
**version_kwargs
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/keystoneauth1/session.py", line 1113, in get_endpoint
return auth.get_endpoint(self, **kwargs)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/keystoneauth1/identity/base.py", line 380, in get_endpoint
allow_version_hack=allow_version_hack, **kwargs)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/keystoneauth1/identity/base.py", line 279, in get_endpoint_data
service_name=service_name)
File "/Users/alancoding/.virtualenvs/ansible/lib/python2.7/site-packages/keystoneauth1/access/service_catalog.py", line 462, in endpoint_data_for
raise exceptions.EndpointNotFound(msg)
EndpointNotFound: public endpoint for network service not found

# Fixed code
def parse(self, inventory, loader, path, cache=True):
    super(InventoryModule, self).parse(inventory, loader, path)

    cache_key = self._get_cache_prefix(path)

    # file is config file
    self._config_data = self._read_config_data(path)

    msg = ""
    if not self._config_data:
        msg = "File empty. this is not my config file"
    elif "plugin" in self._config_data and self._config_data["plugin"] != self.NAME:
        msg = "plugin config file, but not for us: %s" % self._config_data["plugin"]
    elif "plugin" not in self._config_data and "clouds" not in self._config_data:
        msg = "it's not a plugin configuration nor a clouds.yaml file"
    elif not HAS_SDK:
        msg = "openstacksdk is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped."

    if msg:
        raise AnsibleParserError(msg)

    # The user has pointed us at a clouds.yaml file. Use defaults for
    # everything.
    if "clouds" in self._config_data:
        self._config_data = {}

    if cache:
        cache = self.get_option("cache")
    source_data = None
    if cache:
        try:
            source_data = self.cache.get(cache_key)
        except KeyError:
            pass

    if not source_data:
        clouds_yaml_path = self._config_data.get("clouds_yaml_path")
        if clouds_yaml_path:
            config_files = clouds_yaml_path + client_config.CONFIG_FILES
        else:
            config_files = None

        # Redict logging to stderr so it does not mix with output
        # particular ansible-inventory JSON output
        # TODO(mordred) Integrate openstack's logging with ansible's logging
        sdk.enable_logging(stream=sys.stderr)

        cloud_inventory = sdk_inventory.OpenStackInventory(
            config_files=config_files, private=self._config_data.get("private", False)
        )
        only_clouds = self._config_data.get("only_clouds", [])
        if only_clouds and not isinstance(only_clouds, list):
            raise ValueError(
                "OpenStack Inventory Config Error: only_clouds must be a list"
            )
        if only_clouds:
            new_clouds = []
            for cloud in cloud_inventory.clouds:
                if cloud.name in only_clouds:
                    new_clouds.append(cloud)
            cloud_inventory.clouds = new_clouds

        expand_hostvars = self._config_data.get("expand_hostvars", False)
        fail_on_errors = self._config_data.get("fail_on_errors", False)

        source_data = cloud_inventory.list_hosts(
            expand=expand_hostvars, fail_on_cloud_config=fail_on_errors
        )

        if self.cache is not None:
            self.cache.set(cache_key, source_data)

    self._populate_from_source(source_data)