# Buggy code
def token_list(kubeconfig=None, rootfs=None):
    """
    .. versionadded:: TBD

    List bootstrap tokens on the server

    kubeconfig
       The kubeconfig file to use when talking to the cluster. The
       default values in /etc/kubernetes/admin.conf

    rootfs
       The path to the real host root filesystem

    CLI Example:

    .. code-block:: bash

       salt '*' kubeadm.token_list

    """
    cmd = ["kubeadm", "token", "list"]

    parameters = [("kubeconfig", kubeconfig), ("rootfs", rootfs)]
    for parameter, value in parameters:
        if value:
            cmd.extend(["--{}".format(parameter), str(value)])

    lines = _cmd(cmd).splitlines()

    # Find the header and parse it.  We do not need to validate the
    # content, as the regex will take care of future changes.
    header = lines.pop(0)
    header = [i.lower() for i in re.findall(r"(\w+(?:\s\w+)*)", header)]

    tokens = []
    for line in lines:
        # TODO(aplanas): descriptions with multiple spaces can break
        # the parser.
        values = re.findall(r"(\S+(?:\s\S+)*)", line)
        if len(header) != len(values):
            log.error("Error parsing line: {}".format(line))
            continue
        tokens.append({key: value for key, value in zip(header, values)})
    return tokens


# Traceback (IndexError)
[INFO    ] Executing command ['kubeadm', 'token', 'list'] in directory '/root'
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
IndexError: pop from empty list
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
load_entry_point('salt==3001', 'console_scripts', 'salt-call')()
File "/usr/lib/python3/dist-packages/salt/scripts.py", line 472, in salt_call
client.run()
File "/usr/lib/python3/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 121, in run
ret = self.call()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 228, in call
ret["return"] = self.minion.executors[fname](
File "/usr/lib/python3/dist-packages/salt/executors/direct_call.py", line 12, in execute
return func(*args, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 114, in join_params
"token": _token(create_if_needed),
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 55, in _token
tokens = token_list()
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 337, in token_list
header = lines.pop(0)
IndexError: pop from empty list
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
load_entry_point('salt==3001', 'console_scripts', 'salt-call')()
File "/usr/lib/python3/dist-packages/salt/scripts.py", line 472, in salt_call
client.run()
File "/usr/lib/python3/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 121, in run
ret = self.call()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 228, in call
ret["return"] = self.minion.executors[fname](
File "/usr/lib/python3/dist-packages/salt/executors/direct_call.py", line 12, in execute
return func(*args, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 114, in join_params
"token": _token(create_if_needed),
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 55, in _token
tokens = token_list()
File "/usr/lib/python3/dist-packages/salt/modules/kubeadm.py", line 337, in token_list
header = lines.pop(0)
IndexError: pop from empty list

# Fixed code
def token_list(kubeconfig=None, rootfs=None):
    """
    .. versionadded:: TBD

    List bootstrap tokens on the server

    kubeconfig
       The kubeconfig file to use when talking to the cluster. The
       default values in /etc/kubernetes/admin.conf

    rootfs
       The path to the real host root filesystem

    CLI Example:

    .. code-block:: bash

       salt '*' kubeadm.token_list

    """
    cmd = ["kubeadm", "token", "list"]

    parameters = [("kubeconfig", kubeconfig), ("rootfs", rootfs)]
    for parameter, value in parameters:
        if value:
            cmd.extend(["--{}".format(parameter), str(value)])

    lines = _cmd(cmd).splitlines()

    tokens = []
    if lines:
        # Find the header and parse it.  We do not need to validate
        # the content, as the regex will take care of future changes.
        header = lines.pop(0)
        header = [i.lower() for i in re.findall(r"(\w+(?:\s\w+)*)", header)]

        for line in lines:
            # TODO(aplanas): descriptions with multiple spaces can
            # break the parser.
            values = re.findall(r"(\S+(?:\s\S+)*)", line)
            if len(header) != len(values):
                log.error("Error parsing line: {}".format(line))
                continue
            tokens.append({key: value for key, value in zip(header, values)})
    return tokens