# Buggy code
def _generate_minion_id():
    """
    Get list of possible host names and convention names.

    :return:
    """
    # There are three types of hostnames:
    # 1. Network names. How host is accessed from the network.
    # 2. Host aliases. They might be not available in all the network or only locally (/etc/hosts)
    # 3. Convention names, an internal nodename.

    class DistinctList(list):
        """
        List, which allows one to append only distinct objects.
        Needs to work on Python 2.6, because of collections.OrderedDict only since 2.7 version.
        Override 'filter()' for custom filtering.
        """

        localhost_matchers = [
            r"localhost.*",
            r"ip6-.*",
            r"127[.]\d",
            r"0\.0\.0\.0",
            r"::1.*",
            r"ipv6-.*",
            r"fe00::.*",
            r"fe02::.*",
            r"1.0.0.*.ip6.arpa",
        ]

        def append(self, p_object):
            if p_object and p_object not in self and not self.filter(p_object):
                super(self.__class__, self).append(p_object)
            return self

        def extend(self, iterable):
            for obj in iterable:
                self.append(obj)
            return self

        def filter(self, element):
            "Returns True if element needs to be filtered"
            for rgx in self.localhost_matchers:
                if re.match(rgx, element):
                    return True

        def first(self):
            return self and self[0] or None

    hosts = (
        DistinctList()
        .append(socket.getfqdn())
        .append(platform.node())
        .append(socket.gethostname())
    )
    if not hosts:
        try:
            for a_nfo in socket.getaddrinfo(
                hosts.first() or "localhost",
                None,
                socket.AF_INET,
                socket.SOCK_RAW,
                socket.IPPROTO_IP,
                socket.AI_CANONNAME,
            ):
                if len(a_nfo) > 3:
                    hosts.append(a_nfo[3])
        except socket.gaierror:
            log.warning(
                "Cannot resolve address {addr} info via socket: {message}".format(
                    addr=hosts.first() or "localhost (N/A)", message=socket.gaierror
                )
            )
    # Universal method for everywhere (Linux, Slowlaris, Windows etc)
    for f_name in (
        "/etc/hostname",
        "/etc/nodename",
        "/etc/hosts",
        r"{win}\system32\drivers\etc\hosts".format(win=os.getenv("WINDIR")),
    ):
        try:
            with salt.utils.files.fopen(f_name) as f_hdl:
                for line in f_hdl:
                    line = salt.utils.stringutils.to_unicode(line)
                    hst = line.strip().split("#")[0].strip().split()
                    if hst:
                        if hst[0][:4] in ("127.", "::1") or len(hst) == 1:
                            hosts.extend(hst)
        except IOError:
            pass

    # include public and private ipaddresses
    return hosts.extend(
        [addr for addr in ip_addrs() if not ipaddress.ip_address(addr).is_loopback]
    )


# Traceback (UnicodeError)
[ERROR   ] encoding with 'idna' codec failed (UnicodeError: label too long)
Traceback (most recent call last):
File "/usr/local/lib/python3.6/encodings/idna.py", line 167, in encode
raise UnicodeError("label too long")
UnicodeError: label too long

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/salt/utils/parsers.py", line 210, in parse_args
process_option_func()
File "/usr/local/lib/python3.6/site-packages/salt/utils/parsers.py", line 548, in process_config_dir
self.config.update(self.setup_config())
File "/usr/local/lib/python3.6/site-packages/salt/utils/parsers.py", line 2727, in setup_config
cache_minion_id=True)
File "/usr/local/lib/python3.6/site-packages/salt/config/__init__.py", line 2397, in minion_config
minion_id=minion_id)
File "/usr/local/lib/python3.6/site-packages/salt/config/__init__.py", line 3733, in apply_minion_config
cache_minion_id=cache_minion_id)
File "/usr/local/lib/python3.6/site-packages/salt/config/__init__.py", line 3615, in get_id
newid = salt.utils.network.generate_minion_id()
File "/usr/local/lib/python3.6/site-packages/salt/utils/network.py", line 177, in generate_minion_id
ret = salt.utils.stringutils.to_unicode(_generate_minion_id().first())
File "/usr/local/lib/python3.6/site-packages/salt/utils/network.py", line 140, in _generate_minion_id
hosts = DistinctList().append(socket.getfqdn()).append(platform.node()).append(socket.gethostname())
File "/usr/local/lib/python3.6/socket.py", line 673, in getfqdn
hostname, aliases, ipaddrs = gethostbyaddr(name)
UnicodeError: encoding with 'idna' codec failed (UnicodeError: label too long)
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
TypeError: '>=' not supported between instances of 'UnicodeError' and 'int'
Traceback (most recent call last):
File "/usr/local/lib/python3.6/encodings/idna.py", line 167, in encode
raise UnicodeError("label too long")
UnicodeError: label too long

# Fixed code
def _generate_minion_id():
    """
    Get list of possible host names and convention names.

    :return:
    """
    # There are three types of hostnames:
    # 1. Network names. How host is accessed from the network.
    # 2. Host aliases. They might be not available in all the network or only locally (/etc/hosts)
    # 3. Convention names, an internal nodename.

    class DistinctList(list):
        """
        List, which allows one to append only distinct objects.
        Needs to work on Python 2.6, because of collections.OrderedDict only since 2.7 version.
        Override 'filter()' for custom filtering.
        """

        localhost_matchers = [
            r"localhost.*",
            r"ip6-.*",
            r"127[.]\d",
            r"0\.0\.0\.0",
            r"::1.*",
            r"ipv6-.*",
            r"fe00::.*",
            r"fe02::.*",
            r"1.0.0.*.ip6.arpa",
        ]

        def append(self, p_object):
            if p_object and p_object not in self and not self.filter(p_object):
                super(self.__class__, self).append(p_object)
            return self

        def extend(self, iterable):
            for obj in iterable:
                self.append(obj)
            return self

        def filter(self, element):
            "Returns True if element needs to be filtered"
            for rgx in self.localhost_matchers:
                if re.match(rgx, element):
                    return True

        def first(self):
            return self and self[0] or None

    hosts = DistinctList([])

    try:
        hosts.append(socket.getfqdn())
    except ValueError:
        pass

    try:
        hosts.append(platform.node())
    except ValueError:
        pass

    try:
        hosts.append(socket.gethostname())
    except ValueError:
        pass

    if not hosts:
        try:
            for a_nfo in socket.getaddrinfo(
                hosts.first() or "localhost",
                None,
                socket.AF_INET,
                socket.SOCK_RAW,
                socket.IPPROTO_IP,
                socket.AI_CANONNAME,
            ):
                if len(a_nfo) > 3:
                    hosts.append(a_nfo[3])
        except socket.gaierror:
            log.warning(
                "Cannot resolve address {addr} info via socket: {message}".format(
                    addr=hosts.first() or "localhost (N/A)", message=socket.gaierror
                )
            )
    # Universal method for everywhere (Linux, Slowlaris, Windows etc)
    for f_name in (
        "/etc/hostname",
        "/etc/nodename",
        "/etc/hosts",
        r"{win}\system32\drivers\etc\hosts".format(win=os.getenv("WINDIR")),
    ):
        try:
            with salt.utils.files.fopen(f_name) as f_hdl:
                for line in f_hdl:
                    line = salt.utils.stringutils.to_unicode(line)
                    hst = line.strip().split("#")[0].strip().split()
                    if hst:
                        if hst[0][:4] in ("127.", "::1") or len(hst) == 1:
                            hosts.extend(hst)
        except IOError:
            pass

    # include public and private ipaddresses
    return hosts.extend(
        [addr for addr in ip_addrs() if not ipaddress.ip_address(addr).is_loopback]
    )