Repository: ansible/ansible

Issue:
ansible-vault decrypt --output - no longer working in ansible 2.4
##### ANSIBLE VERSION
```
ansible 2.4.0.0
```

In ansible 2.3.x, it was possible to do `ansible-vault decrypt example.txt --output -` to get the decrypted output into stdout. In fact, that is advertised in `ansible-vault decrypt --help`:

      --output=OUTPUT_FILE  output file name for encrypt or decrypt; use - for stdout

In Ansible 2.4, this is bugged and results in a file named `-`. 


Discussion:
@jleclanche Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information. 

Here are the items we could not find in your description:
- issue type
- ansible version
- component name

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->
cc @bcoca because this is a regression due to #29663 (525c318678a737a2fafc1b010b93ea7725d89215):

```py
 +        # add output if needed
 +        if self.action in self.can_output:
 +            self.parser.add_option('--output', default=None, dest='output_file',
 +                                   help='output file name for encrypt or decrypt; use - for stdout',
 +                                   action="callback", callback=CLI.unfrack_path, type='string')
 +
```

`CLI.unfrack_path` will always turn `-` into `/path/to/current/directory/-` which then fails comparisons to `-` in `parsing/vault/__init__.py`.
After upgrading PIP package ansible-vault to 1.0.5, this function is no longer working for me. Multiple systems, CentOS and Fedora. Could this be related?

```python
>>> from ansible_vault import Vault
>>> dictpass = Vault("passphrase")
>>> nodedict = dictpass.load(open('nodedict.yml').read())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/ansible_vault/api.py", line 18, in load
    return yaml.safe_load(self.vault.decrypt(stream))
  File "/usr/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py", line 543, in decrypt
    _matches = match_secrets(self.secrets, vault_id_matchers)
  File "/usr/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py", line 399, in match_secrets
    matches = [(vault_id, secret) for vault_id, secret in secrets if vault_id in target_vault_ids]
ValueError: need more than 1 value to unpack
```
No that doesn't seem related. You should file a separate issue for that.
@enrh :  I have the same issue I've filed a separate issue there:
https://github.com/ansible/ansible/issues/30969
fwiw, 'ansible-vault view example.txt'  can be used in lieu of 'ansible-vault decrypt example.txt --output= -' for the time being.

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
@@ -406,7 +406,10 @@ def unfrack_paths(option, opt, value, parser):
 
     @staticmethod
     def unfrack_path(option, opt, value, parser):
-        setattr(parser.values, option.dest, unfrackpath(value))
+        if value != '-':
+            setattr(parser.values, option.dest, unfrackpath(value))
+        else:
+            setattr(parser.values, option.dest, value)
 
     @staticmethod
     def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,


Test patch:
diff --git a/test/integration/targets/vault/runme.sh b/test/integration/targets/vault/runme.sh
--- a/test/integration/targets/vault/runme.sh
+++ b/test/integration/targets/vault/runme.sh
@@ -23,6 +23,8 @@ echo "This is a test file for edit2" > "${TEST_FILE_EDIT2}"
 FORMAT_1_1_HEADER="\$ANSIBLE_VAULT;1.1;AES256"
 FORMAT_1_2_HEADER="\$ANSIBLE_VAULT;1.2;AES256"
 
+VAULT_PASSWORD_FILE=vault-password
+
 # old format
 ansible-vault view "$@" --vault-password-file vault-password-ansible format_1_0_AES.yml
 
@@ -202,9 +204,16 @@ ansible-vault view "$@" --vault-id "tmp_new_password@${NEW_VAULT_PASSWORD}" --va
 ansible-vault decrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" "${TEST_FILE}"
 
 # reading/writing to/from stdin/stdin  (See https://github.com/ansible/ansible/issues/23567)
-ansible-vault encrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --output="${TEST_FILE_OUTPUT}" < "${TEST_FILE}"
-ansible-vault view "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" - < "${TEST_FILE_OUTPUT}"
-ansible-vault decrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --output=- < "${TEST_FILE_OUTPUT}"
+ansible-vault encrypt "$@" --vault-password-file "${VAULT_PASSWORD_FILE}" --output="${TEST_FILE_OUTPUT}" < "${TEST_FILE}"
+OUTPUT=$(ansible-vault decrypt "$@" --vault-password-file "${VAULT_PASSWORD_FILE}" --output=- < "${TEST_FILE_OUTPUT}")
+echo "${OUTPUT}" | grep 'This is a test file'
+
+OUTPUT_DASH=$(ansible-vault decrypt "$@" --vault-password-file "${VAULT_PASSWORD_FILE}" --output=- "${TEST_FILE_OUTPUT}")
+echo "${OUTPUT_DASH}" | grep 'This is a test file'
+
+OUTPUT_DASH_SPACE=$(ansible-vault decrypt "$@" --vault-password-file "${VAULT_PASSWORD_FILE}" --output - "${TEST_FILE_OUTPUT}")
+echo "${OUTPUT_DASH_SPACE}" | grep 'This is a test file'
+
 
 # test using an empty vault password file
 ansible-vault view "$@" --vault-password-file empty-password format_1_1_AES256.yml && :