# Buggy code
def run(self, tmp=None, task_vars=None):
    if self._task.environment and any(self._task.environment):
        self._display.warning(
            "The telnet task does not support the environment keyword"
        )

    result = super(ActionModule, self).run(tmp, task_vars)
    del tmp  # tmp no longer has any effect

    if self._play_context.check_mode:
        # in --check mode, always skip this module execution
        result["skipped"] = True
        result["msg"] = "The telnet task does not support check mode"
    else:
        result["changed"] = True
        result["failed"] = False

        host = self._task.args.get("host", self._play_context.remote_addr)
        user = self._task.args.get("user", self._play_context.remote_user)
        password = self._task.args.get("password", self._play_context.password)

        # FIXME, default to play_context?
        port = self._task.args.get("port", "23")
        timeout = self._task.args.get("timeout", 120)
        pause = self._task.args.get("pause", 1)

        send_newline = self._task.args.get("send_newline", False)

        login_prompt = self._task.args.get("login_prompt", "login: ")
        password_prompt = self._task.args.get("password_prompt", "Password: ")
        prompts = self._task.args.get("prompts", ["$ "])
        commands = self._task.args.get("command") or self._task.args.get("commands")

        if isinstance(commands, text_type):
            commands = commands.split(",")

        if isinstance(commands, list) and commands:
            tn = telnetlib.Telnet(host, port, timeout)

            output = []
            try:
                if send_newline:
                    tn.write("\n")

                tn.read_until(login_prompt)
                tn.write("%s\n" % to_native(user))

                if password:
                    tn.read_until(password_prompt)
                    tn.write("%s\n" % to_native(password))

                tn.expect(prompts)

                for cmd in commands:
                    display.vvvvv(">>> %s" % cmd)
                    tn.write("%s\n" % to_native(cmd))
                    index, match, out = tn.expect(prompts)
                    display.vvvvv("<<< %s" % cmd)
                    output.append(out)
                    sleep(pause)

                tn.write("exit\n")

            except EOFError as e:
                result["failed"] = True
                result["msg"] = "Telnet action failed: %s" % to_native(e)
            finally:
                if tn:
                    tn.close()
                result["output"] = output
        else:
            result["failed"] = True
            result["msg"] = "Telnet requires a command to execute"

    return result


# Traceback (TypeError)
ansible-playbook telnet_test.yml  -vvvv
ansible-playbook 2.4.3.0
config file = /home/am/test_cswt/ansible.cfg
configured module search path = ['/home/am/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/am/env2/lib/python3.6/site-packages/ansible
executable location = /home/am/env2/bin/ansible-playbook
python version = 3.6.3 (default, Feb  8 2018, 12:39:01) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
Using /home/am/test_cswt/ansible.cfg as config file
[DEPRECATION WARNING]: [defaults]hostfile option, The key is misleading as it can also be a list of hosts, a directory or a list of paths . This feature will be removed in version 2.8. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
setting up inventory plugins
Parsed /home/am/test_cswt/hosts inventory source with ini plugin
Loading callback plugin default of type stdout, v2.0 from /home/am/env2/lib/python3.6/site-packages/ansible/plugins/callback/default.py

PLAYBOOK: telnet_test.yml ******************************************************************************************************************************************************************************************************************
1 plays in telnet_test.yml

PLAY [show version] ************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [telnet] ******************************************************************************************************************************************************************************************************************************
task path: /home/am/test_cswt/telnet_test.yml:8
The full traceback is:
Traceback (most recent call last):
File "/home/am/env2/lib/python3.6/site-packages/ansible/executor/task_executor.py", line 130, in run
res = self._execute()
File "/home/am/env2/lib/python3.6/site-packages/ansible/executor/task_executor.py", line 528, in _execute
result = self._handler.run(task_vars=variables)
File "/home/am/env2/lib/python3.6/site-packages/ansible/plugins/action/telnet.py", line 57, in run
tn.read_until(login_prompt)
File "/usr/local/lib/python3.6/telnetlib.py", line 302, in read_until
i = self.cookedq.find(match)
TypeError: a bytes-like object is required, not 'AnsibleUnicode'
fatal: [x.x.x.x]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
to retry, use: --limit @/home/xxxx/test_cswt/telnet_test.retry

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
x.x.x.x              : ok=0    changed=0    unreachable=0    failed=1

# Fixed code
def run(self, tmp=None, task_vars=None):
    if self._task.environment and any(self._task.environment):
        self._display.warning(
            "The telnet task does not support the environment keyword"
        )

    result = super(ActionModule, self).run(tmp, task_vars)
    del tmp  # tmp no longer has any effect

    if self._play_context.check_mode:
        # in --check mode, always skip this module execution
        result["skipped"] = True
        result["msg"] = "The telnet task does not support check mode"
    else:
        result["changed"] = True
        result["failed"] = False

        host = self._task.args.get("host", self._play_context.remote_addr)
        user = self._task.args.get("user", self._play_context.remote_user)
        password = self._task.args.get("password", self._play_context.password)

        # FIXME, default to play_context?
        port = self._task.args.get("port", "23")
        timeout = self._task.args.get("timeout", 120)
        pause = self._task.args.get("pause", 1)

        send_newline = self._task.args.get("send_newline", False)

        login_prompt = self._task.args.get("login_prompt", "login: ")
        password_prompt = self._task.args.get("password_prompt", "Password: ")
        prompts = self._task.args.get("prompts", ["$ "])
        commands = self._task.args.get("command") or self._task.args.get("commands")

        if isinstance(commands, text_type):
            commands = commands.split(",")

        if isinstance(commands, list) and commands:
            tn = telnetlib.Telnet(host, port, timeout)

            output = []
            try:
                if send_newline:
                    tn.write(b"\n")

                tn.read_until(to_bytes(login_prompt))
                tn.write(to_bytes(user + "\n"))

                if password:
                    tn.read_until(to_bytes(password_prompt))
                    tn.write(to_bytes(password + "\n"))

                tn.expect(list(map(to_bytes, prompts)))

                for cmd in commands:
                    display.vvvvv(">>> %s" % cmd)
                    tn.write(to_bytes(cmd + "\n"))
                    index, match, out = tn.expect(list(map(to_bytes, prompts)))
                    display.vvvvv("<<< %s" % cmd)
                    output.append(out)
                    sleep(pause)

                tn.write(b"exit\n")

            except EOFError as e:
                result["failed"] = True
                result["msg"] = "Telnet action failed: %s" % to_native(e)
            finally:
                if tn:
                    tn.close()
                result["output"] = output
        else:
            result["failed"] = True
            result["msg"] = "Telnet requires a command to execute"

    return result