Repository: ansible/ansible

Issue:
module/file: attributes: cannot use a string pattern on a bytes-like object
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
`file` module with the `attributes` parameter.

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```ansible 2.3.0.0```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
N/A

##### 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.
-->
- `Arch Linux 4.10.13-1-ARCH x86_64`
- `Python 2.7.13`
- `Python 3.6.1`

##### SUMMARY
<!--- Explain the problem briefly -->

The file module allows to specify extended attributes (for instance, 'C' to disable CoW), used by the `chattr` command.

Unfortunately, the exception _"cannot use a string pattern on a bytes-like object"_ is triggered at this location [module_utils/basic.py#2413](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/basic.py#L2413).

_As a sidenote, the documentation could be improved by adding an example with the attributes (`chattr` allows to specify "+C" or "-C" but the module calls `chattr =<attrs>` thus this is not allowed)._

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem,](url) using a minimal test-case.
For new features, show how the feature would be used.
-->
`ansible-playbook -v -c local -i 'localhost,' sample.yaml`

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: all
  tasks:
    - file:
        path: /var/log/journal
        attr: 'C'
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

Replacing `if PASSWD_ARG_RE.match(arg):` by `if PASSWD_ARG_RE.match(to_text(arg)):` in [module_utils/basic.py#2413](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/basic.py#L2413) yields the following expected result:

```
PLAY [all] *******************************************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [file] ******************************************************************************
changed: [localhost] => {"path": "/var/log/journal", "changed": true, "diff": {"before":
{"path": "/var/log/journal", "attributes": ""}, "after": {"path": "/var/log/journal",
"attributes": "C"}}, "uid": 0, "gid": 190, "owner": "root", "group": "systemd-journal",
"mode": "02755", "state": "directory", "size": 12, "invocation": {"module_args":
{"path": "/var/log/journal", "attr": "C", "attributes": "C", "recurse": false,
"force": false, "follow": false, "state": null, "original_basename": null,
"diff_peek": null, "validate": null, "src": null, "mode": null, "owner": null,
"group": null, "seuser": null, "serole": null, "selevel": null, "setype": null,
"content": null, "backup": null, "remote_src": null, "regexp": null,
"delimiter": null, "directory_mode": null, "unsafe_writes": null}}}

PLAY RECAP *******************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0
```

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
PLAY [all] *******************************************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [file] ******************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "details": "cannot use a string
pattern on a bytes-like object", "failed": true, "gid": 190, "group": "systemd-journal",
"mode": "02755", "msg": "chattr failed", "owner": "root", "path": "/var/log/journal",
"size": 12, "state": "directory", "uid": 0}
	to retry, use: --limit @/sample.retry

PLAY RECAP *******************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py
--- a/lib/ansible/module_utils/basic.py
+++ b/lib/ansible/module_utils/basic.py
@@ -2514,7 +2514,7 @@ def run_command(self, args, check_rc=False, close_fds=True, executable=None, dat
 
         clean_args = []
         is_passwd = False
-        for arg in to_clean_args:
+        for arg in (to_native(a) for a in to_clean_args):
             if is_passwd:
                 is_passwd = False
                 clean_args.append('********')


Test patch: