* Allow the user to circumvent adding -tt on ssh commands to help aid in
debugging ssh related problems.
* Move config to the plugin
* Set version_added
* Change yaml section to "connection"
* Fix ssh unit tests
... | ... |
@@ -401,6 +401,10 @@ |
401 | 401 |
# only be disabled if your sftp version has problems with batch mode |
402 | 402 |
#sftp_batch_mode = False |
403 | 403 |
|
404 |
+# The -tt argument is passed to ssh when pipelining is not enabled because sudo |
|
405 |
+# requires a tty by default. |
|
406 |
+#use_tty = True |
|
407 |
+ |
|
404 | 408 |
[persistent_connection] |
405 | 409 |
|
406 | 410 |
# Configures the persistent connection timeout value in seconds. This value is |
... | ... |
@@ -185,6 +185,15 @@ DOCUMENTATION = ''' |
185 | 185 |
env: [{name: ANSIBLE_SCP_IF_SSH}] |
186 | 186 |
ini: |
187 | 187 |
- {key: scp_if_ssh, section: ssh_connection} |
188 |
+ use_tty: |
|
189 |
+ version_added: '2.5' |
|
190 |
+ default: True |
|
191 |
+ description: add -tt to ssh commands to force tty allocation |
|
192 |
+ env: [{name: ANSIBLE_SSH_USETTY}] |
|
193 |
+ ini: |
|
194 |
+ - {key: usetty, section: ssh_connection} |
|
195 |
+ type: boolean |
|
196 |
+ yaml: {key: connection.usetty} |
|
188 | 197 |
''' |
189 | 198 |
|
190 | 199 |
import errno |
... | ... |
@@ -957,7 +966,11 @@ class Connection(ConnectionBase): |
957 | 957 |
|
958 | 958 |
ssh_executable = self._play_context.ssh_executable |
959 | 959 |
|
960 |
- if not in_data and sudoable: |
|
960 |
+ # -tt can cause various issues in some environments so allow the user |
|
961 |
+ # to disable it as a troubleshooting method. |
|
962 |
+ use_tty = self.get_option('use_tty') |
|
963 |
+ |
|
964 |
+ if not in_data and sudoable and use_tty: |
|
961 | 965 |
args = (ssh_executable, '-tt', self.host, cmd) |
962 | 966 |
else: |
963 | 967 |
args = (ssh_executable, self.host, cmd) |
... | ... |
@@ -80,6 +80,8 @@ class TestConnectionBaseClass(unittest.TestCase): |
80 | 80 |
conn._build_command.return_value = 'ssh something something' |
81 | 81 |
conn._run = MagicMock() |
82 | 82 |
conn._run.return_value = (0, 'stdout', 'stderr') |
83 |
+ conn.get_option = MagicMock() |
|
84 |
+ conn.get_option.return_value = True |
|
83 | 85 |
|
84 | 86 |
res, stdout, stderr = conn.exec_command('ssh') |
85 | 87 |
res, stdout, stderr = conn.exec_command('ssh', 'this is some data') |
... | ... |
@@ -538,6 +540,8 @@ class TestSSHConnectionRetries(object): |
538 | 538 |
|
539 | 539 |
self.conn._build_command = MagicMock() |
540 | 540 |
self.conn._build_command.return_value = 'ssh' |
541 |
+ self.conn.get_option = MagicMock() |
|
542 |
+ self.conn.get_option.return_value = True |
|
541 | 543 |
|
542 | 544 |
return_code, b_stdout, b_stderr = self.conn.exec_command('ssh', 'some data') |
543 | 545 |
assert return_code == 0 |
... | ... |
@@ -563,6 +567,8 @@ class TestSSHConnectionRetries(object): |
563 | 563 |
|
564 | 564 |
self.conn._build_command = MagicMock() |
565 | 565 |
self.conn._build_command.return_value = 'ssh' |
566 |
+ self.conn.get_option = MagicMock() |
|
567 |
+ self.conn.get_option.return_value = True |
|
566 | 568 |
|
567 | 569 |
pytest.raises(AnsibleConnectionFailure, self.conn.exec_command, 'ssh', 'some data') |
568 | 570 |
assert self.mock_popen.call_count == 10 |
... | ... |
@@ -575,6 +581,8 @@ class TestSSHConnectionRetries(object): |
575 | 575 |
|
576 | 576 |
self.conn._build_command = MagicMock() |
577 | 577 |
self.conn._build_command.return_value = 'ssh' |
578 |
+ self.conn.get_option = MagicMock() |
|
579 |
+ self.conn.get_option.return_value = True |
|
578 | 580 |
|
579 | 581 |
self.mock_popen.side_effect = [Exception('bad')] * 10 |
580 | 582 |
pytest.raises(Exception, self.conn.exec_command, 'ssh', 'some data') |