Repository: ansible/ansible

Issue:
[WIP] Make network plugins PY3 complaint
<!---

-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
asa
dellos6
dellos9
dellos10
eos
ios
iosxr
junos
nxos
sros
vyos

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
2.4
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

##### SUMMARY
<!--- Explain the problem briefly -->
Issue to track py3 compliance for network modules
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
@ganeshrn Let me know if you need any help in this ? I would like to help here.

Resolving patch:
diff --git a/lib/ansible/module_utils/iosxr.py b/lib/ansible/module_utils/iosxr.py
--- a/lib/ansible/module_utils/iosxr.py
+++ b/lib/ansible/module_utils/iosxr.py
@@ -26,6 +26,7 @@
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
+from ansible.module_utils._text import to_text
 from ansible.module_utils.basic import env_fallback, return_values
 from ansible.module_utils.network_common import to_list, ComplexList
 from ansible.module_utils.connection import exec_command
@@ -42,18 +43,19 @@
     'provider': dict(type='dict')
 }
 
+
 def check_args(module, warnings):
     provider = module.params['provider'] or {}
     for key in iosxr_argument_spec:
         if key != 'provider' and module.params[key]:
-            warnings.append('argument %s has been deprecated and will be '
-                    'removed in a future version' % key)
+            warnings.append('argument %s has been deprecated and will be removed in a future version' % key)
 
     if provider:
         for param in ('password',):
             if provider.get(param):
                 module.no_log_values.update(return_values(provider[param]))
 
+
 def get_config(module, flags=[]):
     cmd = 'show running-config '
     cmd += ' '.join(flags)
@@ -64,8 +66,8 @@ def get_config(module, flags=[]):
     except KeyError:
         rc, out, err = exec_command(module, cmd)
         if rc != 0:
-            module.fail_json(msg='unable to retrieve current config', stderr=err)
-        cfg = str(out).strip()
+            module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_or_strict'))
+        cfg = to_text(out, errors='surrogate_or_strict').strip()
         _DEVICE_CONFIGS[cmd] = cfg
         return cfg
 
@@ -87,15 +89,16 @@ def run_commands(module, commands, check_rc=True):
         cmd = module.jsonify(cmd)
         rc, out, err = exec_command(module, cmd)
         if check_rc and rc != 0:
-            module.fail_json(msg=err, rc=rc)
-        responses.append(out)
+            module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
+        responses.append(to_text(out, errors='surrogate_or_strict'))
     return responses
 
+
 def load_config(module, commands, warnings, commit=False, replace=False, comment=None):
 
     rc, out, err = exec_command(module, 'configure terminal')
     if rc != 0:
-        module.fail_json(msg='unable to enter configuration mode', err=err)
+        module.fail_json(msg='unable to enter configuration mode', err=to_text(err, errors='surrogate_or_strict'))
 
     failed = False
     for command in to_list(commands):
@@ -109,7 +112,7 @@ def load_config(module, commands, warnings, commit=False, replace=False, comment
 
     if failed:
         exec_command(module, 'abort')
-        module.fail_json(msg=err, commands=commands, rc=rc)
+        module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), commands=commands, rc=rc)
 
     rc, diff, err = exec_command(module, 'show commit changes diff')
     if rc != 0:
@@ -128,4 +131,4 @@ def load_config(module, commands, warnings, commit=False, replace=False, comment
         diff = None
     exec_command(module, cmd)
 
-    return diff
+    return to_text(diff, errors='surrogate_or_strict')
diff --git a/lib/ansible/plugins/terminal/iosxr.py b/lib/ansible/plugins/terminal/iosxr.py
--- a/lib/ansible/plugins/terminal/iosxr.py
+++ b/lib/ansible/plugins/terminal/iosxr.py
@@ -25,27 +25,28 @@
 from ansible.plugins.terminal import TerminalBase
 from ansible.errors import AnsibleConnectionFailure
 
+
 class TerminalModule(TerminalBase):
 
     terminal_stdout_re = [
-        re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
-        re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$"),
-        re.compile(r']]>]]>[\r\n]?')
+        re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
+        re.compile(br"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$"),
+        re.compile(br']]>]]>[\r\n]?')
     ]
 
     terminal_stderr_re = [
-        re.compile(r"% ?Error"),
-        re.compile(r"% ?Bad secret"),
-        re.compile(r"invalid input", re.I),
-        re.compile(r"(?:incomplete|ambiguous) command", re.I),
-        re.compile(r"connection timed out", re.I),
-        re.compile(r"[^\r\n]+ not found", re.I),
-        re.compile(r"'[^']' +returned error code: ?\d+"),
+        re.compile(br"% ?Error"),
+        re.compile(br"% ?Bad secret"),
+        re.compile(br"invalid input", re.I),
+        re.compile(br"(?:incomplete|ambiguous) command", re.I),
+        re.compile(br"connection timed out", re.I),
+        re.compile(br"[^\r\n]+ not found", re.I),
+        re.compile(br"'[^']' +returned error code: ?\d+"),
     ]
 
     def on_open_shell(self):
         try:
-            for cmd in ['terminal length 0', 'terminal width 512', 'terminal exec prompt no-timestamp']:
+            for cmd in (b'terminal length 0', b'terminal width 512', b'terminal exec prompt no-timestamp'):
                 self._exec_cli_command(cmd)
         except AnsibleConnectionFailure:
             raise AnsibleConnectionFailure('unable to set terminal parameters')


Test patch:
diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt
--- a/test/sanity/pep8/legacy-files.txt
+++ b/test/sanity/pep8/legacy-files.txt
@@ -72,7 +72,6 @@ lib/ansible/module_utils/gce.py
 lib/ansible/module_utils/gcp.py
 lib/ansible/module_utils/infinibox.py
 lib/ansible/module_utils/ios.py
-lib/ansible/module_utils/iosxr.py
 lib/ansible/module_utils/json_utils.py
 lib/ansible/module_utils/junos.py
 lib/ansible/module_utils/known_hosts.py
@@ -854,7 +853,6 @@ lib/ansible/plugins/strategy/linear.py
 lib/ansible/plugins/terminal/asa.py
 lib/ansible/plugins/terminal/eos.py
 lib/ansible/plugins/terminal/ios.py
-lib/ansible/plugins/terminal/iosxr.py
 lib/ansible/plugins/terminal/junos.py
 lib/ansible/plugins/terminal/nxos.py
 lib/ansible/plugins/terminal/vyos.py