# Buggy code
def update_cache(self, scan_only_new_hosts=False):
    """Make calls to foreman and save the output in a cache"""

    self.groups = dict()
    self.hosts = dict()

    for host in self._get_hosts():
        if host["name"] in self.cache.keys() and scan_only_new_hosts:
            continue
        dns_name = host["name"]

        host_data = self._get_host_data_by_id(host["id"])
        host_params = host_data.get("all_parameters", {})

        # Create ansible groups for hostgroup
        group = "hostgroup"
        val = host.get("%s_title" % group) or host.get("%s_name" % group)
        if val:
            safe_key = self.to_safe("%s%s_%s" % (self.group_prefix, group, val.lower()))
            self.inventory[safe_key].append(dns_name)

        # Create ansible groups for environment, location and organization
        for group in ["environment", "location", "organization"]:
            val = host.get("%s_name" % group)
            if val:
                safe_key = self.to_safe(
                    "%s%s_%s" % (self.group_prefix, group, val.lower())
                )
                self.inventory[safe_key].append(dns_name)

        for group in ["lifecycle_environment", "content_view"]:
            val = host.get("content_facet_attributes", {}).get("%s_name" % group)
            if val:
                safe_key = self.to_safe(
                    "%s%s_%s" % (self.group_prefix, group, val.lower())
                )
                self.inventory[safe_key].append(dns_name)

        params = self._resolve_params(host_params)

        # Ansible groups by parameters in host groups and Foreman host
        # attributes.
        groupby = dict()
        for k, v in params.items():
            groupby[k] = self.to_safe(str(v))

        # The name of the ansible groups is given by group_patterns:
        for pattern in self.group_patterns:
            try:
                key = pattern.format(**groupby)
                self.inventory[key].append(dns_name)
            except KeyError:
                pass  # Host not part of this group

        if self.want_hostcollections:
            hostcollections = host_data.get("host_collections")

            if hostcollections:
                # Create Ansible groups for host collections
                for hostcollection in hostcollections:
                    safe_key = self.to_safe(
                        "%shostcollection_%s"
                        % (self.group_prefix, hostcollection["name"].lower())
                    )
                    self.inventory[safe_key].append(dns_name)

            self.hostcollections[dns_name] = hostcollections

        self.cache[dns_name] = host
        self.params[dns_name] = params
        self.facts[dns_name] = self._get_facts(host)
        self.inventory["all"].append(dns_name)
    self._write_cache()


# Traceback (RuntimeError)
1.419 INFO     Updating inventory 3: Satellite
1.435 INFO     Reading Ansible inventory source: /var/lib/awx/venv/awx/lib/python2.7/site-packages/awx/plugins/inventory/foreman.py
Traceback (most recent call last):
File "/usr/bin/awx-manage", line 9, in <module>
load_entry_point('awx==3.3.0', 'console_scripts', 'awx-manage')()
File "/lib/python2.7/site-packages/awx/__init__.py", line 116, in manage
File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
utility.execute()
File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 356, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 994, in handle
File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 245, in load_inventory_source
File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 180, in load
File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 163, in command_to_json
RuntimeError: ansible-inventory failed (rc=1) with stdout:

stderr:
[WARNING]:  * Failed to parse /var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py with script plugin: Inventory script
(/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py) had an execution error: Traceback
(most recent call last):   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py", line 444, in <module>
sys.exit(not ForemanInventory().run())   File
"/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py", line 439, in run
self.get_inventory()   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py", line 389, in get_inventory
self.update_cache()   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py", line 314, in update_cache
groupby[k] = self.to_safe(str(v)) UnicodeEncodeError: 'ascii' codec can't
encode character u'\\xe9' in position 23: ordinal not in range(128)

[WARNING]: Unable to parse /var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/foreman.py as an inventory source

ERROR! No inventory was parsed, please check your configuration and options.

# Fixed code
def update_cache(self, scan_only_new_hosts=False):
    """Make calls to foreman and save the output in a cache"""

    self.groups = dict()
    self.hosts = dict()

    for host in self._get_hosts():
        if host["name"] in self.cache.keys() and scan_only_new_hosts:
            continue
        dns_name = host["name"]

        host_data = self._get_host_data_by_id(host["id"])
        host_params = host_data.get("all_parameters", {})

        # Create ansible groups for hostgroup
        group = "hostgroup"
        val = host.get("%s_title" % group) or host.get("%s_name" % group)
        if val:
            safe_key = self.to_safe(
                "%s%s_%s" % (to_text(self.group_prefix), group, to_text(val).lower())
            )
            self.inventory[safe_key].append(dns_name)

        # Create ansible groups for environment, location and organization
        for group in ["environment", "location", "organization"]:
            val = host.get("%s_name" % group)
            if val:
                safe_key = self.to_safe(
                    "%s%s_%s"
                    % (to_text(self.group_prefix), group, to_text(val).lower())
                )
                self.inventory[safe_key].append(dns_name)

        for group in ["lifecycle_environment", "content_view"]:
            val = host.get("content_facet_attributes", {}).get("%s_name" % group)
            if val:
                safe_key = self.to_safe(
                    "%s%s_%s"
                    % (to_text(self.group_prefix), group, to_text(val).lower())
                )
                self.inventory[safe_key].append(dns_name)

        params = self._resolve_params(host_params)

        # Ansible groups by parameters in host groups and Foreman host
        # attributes.
        groupby = dict()
        for k, v in params.items():
            groupby[k] = self.to_safe(to_text(v))

        # The name of the ansible groups is given by group_patterns:
        for pattern in self.group_patterns:
            try:
                key = pattern.format(**groupby)
                self.inventory[key].append(dns_name)
            except KeyError:
                pass  # Host not part of this group

        if self.want_hostcollections:
            hostcollections = host_data.get("host_collections")

            if hostcollections:
                # Create Ansible groups for host collections
                for hostcollection in hostcollections:
                    safe_key = self.to_safe(
                        "%shostcollection_%s"
                        % (self.group_prefix, hostcollection["name"].lower())
                    )
                    self.inventory[safe_key].append(dns_name)

            self.hostcollections[dns_name] = hostcollections

        self.cache[dns_name] = host
        self.params[dns_name] = params
        self.facts[dns_name] = self._get_facts(host)
        self.inventory["all"].append(dns_name)
    self._write_cache()