Repository: ansible/ansible

Issue:
running vaultpass as an executable barfs, a bytes-like object is required, not 'str'
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
<!--- Name of the plugin/task/feature -->
Ansible CLI vault password executable

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0
  config file = /opt/app/ansible.cfg
  configured module search path = ['./library']
```

##### CONFIGURATION
na

##### OS / ENVIRONMENT
ubuntu 16.04 on docker

##### SUMMARY
<!--- Explain the problem briefly -->
I use `--vault-password-file=vaultpasswordscript.py` to inject my vault password. It has worked fine until today. I'm not sure what changed- the Ansible code hasn't changed, nor has my simple script. But it fails as follows:

```ansible-playbook -i ec2.py playbook.yml --vault-password-file=vaultpass.py -vvv
ERROR! Unexpected Exception: a bytes-like object is required, not 'str'
the full traceback was:

Traceback (most recent call last):
  File "/usr/local/bin/ansible-playbook", line 103, in <module>
    exit_code = cli.run()
  File "/usr/local/lib/python3.5/dist-packages/ansible/cli/playbook.py", line 116, in run
    vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=loader)
  File "/usr/local/lib/python3.5/dist-packages/ansible/cli/__init__.py", line 633, in read_vault_password_file
    vault_pass = stdout.strip('\r\n')
TypeError: a bytes-like object is required, not 'str'
```

I have today's `devel` branch checked out, which is somewhere around [this commit](https://github.com/ansible/ansible/tree/d22f7b49191dd0598e2f7f9fd9d0944cc0d4e7a6).

The relevant code is [at the bottom of `cli/__init__`](https://github.com/ansible/ansible/blob/309f54b709d489114841530663642b7f3ad262ec/lib/ansible/cli/__init__.py#L624). It needs some coercion or for `universal_newlines=True` to be added to the [subprocess.Popen on line 627](https://github.com/ansible/ansible/blob/309f54b709d489114841530663642b7f3ad262ec/lib/ansible/cli/__init__.py#L627). I may submit a PR with this one-line change but I'm not going to deal with tests or other ramifications, leaving it for someone more aware than myself.

~~The workaround is to not return a newline from my `vaultpass.py`~~ (edit: this doesn't fix it)


Discussion:

Resolving patch:
diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py
--- a/lib/ansible/cli/__init__.py
+++ b/lib/ansible/cli/__init__.py
@@ -173,7 +173,7 @@ def ask_vault_passwords():
 
         # enforce no newline chars at the end of passwords
         if vault_pass:
-            vault_pass = to_bytes(vault_pass, errors='strict', nonstring='simplerepr').strip()
+            vault_pass = to_text(vault_pass, errors='surrogate_or_strict', nonstring='simplerepr').strip()
 
         return vault_pass
 
@@ -189,7 +189,7 @@ def ask_new_vault_passwords():
             pass
 
         if new_vault_pass:
-            new_vault_pass = to_bytes(new_vault_pass, errors='strict', nonstring='simplerepr').strip()
+            new_vault_pass = to_text(new_vault_pass, errors='surrogate_or_strict', nonstring='simplerepr').strip()
 
         return new_vault_pass
 
@@ -630,7 +630,7 @@ def read_vault_password_file(vault_password_file, loader):
             stdout, stderr = p.communicate()
             if p.returncode != 0:
                 raise AnsibleError("Vault password script %s returned non-zero (%s): %s" % (this_path, p.returncode, p.stderr))
-            vault_pass = stdout.strip('\r\n')
+            vault_pass = stdout.strip(b'\r\n')
         else:
             try:
                 f = open(this_path, "rb")
@@ -639,7 +639,7 @@ def read_vault_password_file(vault_password_file, loader):
             except (OSError, IOError) as e:
                 raise AnsibleError("Could not read vault password file %s: %s" % (this_path, e))
 
-        return vault_pass
+        return to_text(vault_pass, errors='surrogate_or_strict')
 
     def get_opt(self, k, defval=""):
         """


Test patch: