Repository: ansible/ansible
Pull request: Add TTY check and argument to disable it (#50603)
##### SUMMARY
Fixes #50603

Runs a TTY check before launching the editor and raises an error if false. One can add the --no-check flag to override this check and launch the editor anyways.
##### ISSUE TYPE
- Bugfix Pull Request


##### COMPONENT NAME
ansible-vault create
##### ADDITIONAL INFORMATION
Running the command 
```
bash $(ansible-vault --vault-password-file=key create file.yaml) 
```
now returns the following output instead of creating an invisible editor window.
```
~/ansible$ bash $(ansible-vault create --vault-password-file=key file.yaml)
[WARNING]: You are running the development version of Ansible. You should only run Ansible from "devel" if you are
modifying the Ansible engine, or trying out features under development. This is a rapidly changing source of code and
can become unstable at any point.
ERROR! not a tty, editor cannot be opened
bash: usage:: No such file or directory
```


Problem statement:
Ansible-vault shows no editor if put inside $()

##### SUMMARY
<!--- Explain the problem briefly below -->

Essentially the issue is that with Ansible 2.5, if you put `ansible-vault --vault-password-file=key create file.yaml` inside `$(ansible-vault --vault-password-file=key create file.yaml)`, it will launch the $EDITOR of choice however, it'll not actually show the graphical UI of said editor, with vim giving the warning:

> Vim: Warning: Output is not to a terminal

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
ansible-vault create


##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.5.1
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.15rc1 (default, Nov 12 2018, 14:31:15) [GCC 7.3.0]

```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below

ALLOW_WORLD_READABLE_TMPFILES(/etc/ansible/ansible.cfg) = True
```

##### OS / ENVIRONMENT
Host OS:
```
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:        18.04
Codename:       bionic

```

Remote OS:
```
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:        18.04
Codename:       bionic

```

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml

Run ansible-vault command within $() either in the shell or a script.
bash $(ansible-vault --vault-password-file=key create file.yaml) 

OR

local var=$(ansible-vault --vault-password-file=key create file.yaml)

```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
Open up the $EDITOR with the cli UI of said editor.

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below
You can blindly use the $EDITOR but can't see what you type.
```

Hints from issue discussion:
Files identified in the description:
None

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
This is expected, that most editors will not be able to display, if displaying in the terminal and without a tty.

A pre-check could be added to see if we have a tty, before launching editor.  However, we would need to handle the case that the editor does not display in the terminal and is a true gui app.  We wouldn't want to fail on those cases, so we may need some form of config toggle to enable that pre-check.

We don't plan on implementing this functionality right now, and have labeled this as waiting_on_contributor.

Commit message: Fix formatting

Patch to review:
diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py
index 6ea330ab4efc1c..59660ac98dcfd7 100644
--- a/lib/ansible/cli/vault.py
+++ b/lib/ansible/cli/vault.py
@@ -76,6 +76,7 @@ def init_parser(self):
         create_parser = subparsers.add_parser('create', help='Create new vault encrypted file', parents=[vault_id, common])
         create_parser.set_defaults(func=self.execute_create)
         create_parser.add_argument('args', help='Filename', metavar='file_name', nargs='*')
+        create_parser.add_argument('-n', '--no-check', default=False, help='skip TTY check', dest='no_check', action='store_true')
 
         decrypt_parser = subparsers.add_parser('decrypt', help='Decrypt vault encrypted file', parents=[output, common])
         decrypt_parser.set_defaults(func=self.execute_decrypt)
@@ -427,8 +428,11 @@ def execute_create(self):
         if len(context.CLIARGS['args']) > 1:
             raise AnsibleOptionsError("ansible-vault create can take only one filename argument")
 
-        self.editor.create_file(context.CLIARGS['args'][0], self.encrypt_secret,
-                                vault_id=self.encrypt_vault_id)
+        if sys.stdout.isatty() or context.CLIARGS['no_check']:
+            self.editor.create_file(context.CLIARGS['args'][0], self.encrypt_secret,
+                                    vault_id=self.encrypt_vault_id)
+        else:
+            raise AnsibleOptionsError("not a tty, editor cannot be opened")
 
     def execute_edit(self):
         ''' open and decrypt an existing vaulted file in an editor, that will be encrypted again when closed'''


Code review comments:
diff_hunk: @@ -76,6 +76,7 @@ def init_parser(self):
         create_parser = subparsers.add_parser('create', help='Create new vault encrypted file', parents=[vault_id, common])
         create_parser.set_defaults(func=self.execute_create)
         create_parser.add_argument('args', help='Filename', metavar='file_name', nargs='*')
+        create_parser.add_argument('-n', '--no-check', default=False, help='skip TTY check', dest='no_check', action='store_true')
path: lib/ansible/cli/vault.py
text: @user1:
This argument name should be more descriptive, such as `--skip-tty-check`.  We also recommend dropping the shortopt of `-n` as that is overloaded and would lead to more confusion.