pyinfra 3.1.1__py2.py3-none-any.whl → 3.3__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyinfra/api/arguments.py +9 -2
- pyinfra/api/arguments_typed.py +4 -5
- pyinfra/api/command.py +22 -3
- pyinfra/api/config.py +5 -2
- pyinfra/api/deploy.py +4 -2
- pyinfra/api/facts.py +3 -0
- pyinfra/api/host.py +15 -7
- pyinfra/api/operation.py +2 -1
- pyinfra/api/state.py +1 -1
- pyinfra/connectors/base.py +34 -8
- pyinfra/connectors/chroot.py +7 -2
- pyinfra/connectors/docker.py +24 -8
- pyinfra/connectors/dockerssh.py +7 -2
- pyinfra/connectors/local.py +7 -2
- pyinfra/connectors/ssh.py +9 -2
- pyinfra/connectors/sshuserclient/client.py +42 -14
- pyinfra/connectors/sshuserclient/config.py +2 -0
- pyinfra/connectors/terraform.py +1 -1
- pyinfra/connectors/util.py +13 -9
- pyinfra/context.py +9 -2
- pyinfra/facts/apk.py +8 -1
- pyinfra/facts/apt.py +68 -0
- pyinfra/facts/brew.py +13 -0
- pyinfra/facts/bsdinit.py +3 -0
- pyinfra/facts/cargo.py +5 -0
- pyinfra/facts/choco.py +6 -0
- pyinfra/facts/crontab.py +195 -0
- pyinfra/facts/deb.py +10 -0
- pyinfra/facts/dnf.py +5 -0
- pyinfra/facts/docker.py +16 -0
- pyinfra/facts/efibootmgr.py +113 -0
- pyinfra/facts/files.py +112 -7
- pyinfra/facts/flatpak.py +7 -0
- pyinfra/facts/freebsd.py +75 -0
- pyinfra/facts/gem.py +5 -0
- pyinfra/facts/git.py +12 -2
- pyinfra/facts/gpg.py +7 -0
- pyinfra/facts/hardware.py +13 -0
- pyinfra/facts/iptables.py +9 -1
- pyinfra/facts/launchd.py +5 -0
- pyinfra/facts/lxd.py +5 -0
- pyinfra/facts/mysql.py +9 -2
- pyinfra/facts/npm.py +5 -0
- pyinfra/facts/openrc.py +8 -0
- pyinfra/facts/opkg.py +245 -0
- pyinfra/facts/pacman.py +9 -1
- pyinfra/facts/pip.py +5 -0
- pyinfra/facts/pipx.py +82 -0
- pyinfra/facts/pkg.py +4 -0
- pyinfra/facts/pkgin.py +5 -0
- pyinfra/facts/podman.py +54 -0
- pyinfra/facts/postgres.py +10 -2
- pyinfra/facts/rpm.py +11 -0
- pyinfra/facts/runit.py +7 -0
- pyinfra/facts/selinux.py +16 -0
- pyinfra/facts/server.py +87 -79
- pyinfra/facts/snap.py +7 -0
- pyinfra/facts/systemd.py +5 -0
- pyinfra/facts/sysvinit.py +4 -0
- pyinfra/facts/upstart.py +5 -0
- pyinfra/facts/util/__init__.py +4 -1
- pyinfra/facts/util/units.py +30 -0
- pyinfra/facts/vzctl.py +5 -0
- pyinfra/facts/xbps.py +6 -1
- pyinfra/facts/yum.py +5 -0
- pyinfra/facts/zfs.py +41 -21
- pyinfra/facts/zypper.py +5 -0
- pyinfra/local.py +3 -2
- pyinfra/operations/apt.py +36 -22
- pyinfra/operations/crontab.py +189 -0
- pyinfra/operations/docker.py +61 -56
- pyinfra/operations/files.py +65 -1
- pyinfra/operations/freebsd/__init__.py +12 -0
- pyinfra/operations/freebsd/freebsd_update.py +70 -0
- pyinfra/operations/freebsd/pkg.py +219 -0
- pyinfra/operations/freebsd/service.py +116 -0
- pyinfra/operations/freebsd/sysrc.py +92 -0
- pyinfra/operations/git.py +23 -7
- pyinfra/operations/opkg.py +88 -0
- pyinfra/operations/pip.py +3 -2
- pyinfra/operations/pipx.py +90 -0
- pyinfra/operations/postgres.py +114 -27
- pyinfra/operations/runit.py +2 -0
- pyinfra/operations/server.py +9 -181
- pyinfra/operations/util/docker.py +44 -22
- pyinfra/operations/zfs.py +3 -3
- {pyinfra-3.1.1.dist-info → pyinfra-3.3.dist-info}/LICENSE.md +1 -1
- {pyinfra-3.1.1.dist-info → pyinfra-3.3.dist-info}/METADATA +25 -25
- pyinfra-3.3.dist-info/RECORD +187 -0
- pyinfra_cli/exceptions.py +5 -0
- pyinfra_cli/inventory.py +26 -9
- pyinfra_cli/log.py +3 -0
- pyinfra_cli/main.py +9 -8
- pyinfra_cli/prints.py +19 -4
- pyinfra_cli/util.py +3 -0
- pyinfra_cli/virtualenv.py +1 -1
- tests/test_cli/test_cli_deploy.py +15 -13
- tests/test_cli/test_cli_inventory.py +53 -0
- tests/test_connectors/test_ssh.py +302 -182
- tests/test_connectors/test_sshuserclient.py +68 -1
- pyinfra-3.1.1.dist-info/RECORD +0 -172
- {pyinfra-3.1.1.dist-info → pyinfra-3.3.dist-info}/WHEEL +0 -0
- {pyinfra-3.1.1.dist-info → pyinfra-3.3.dist-info}/entry_points.txt +0 -0
- {pyinfra-3.1.1.dist-info → pyinfra-3.3.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
3
|
from socket import error as socket_error, gaierror
|
|
4
|
-
from unittest import TestCase
|
|
5
|
-
from unittest.mock import MagicMock, call, mock_open, patch
|
|
4
|
+
from unittest import TestCase, mock
|
|
6
5
|
|
|
7
6
|
from paramiko import AuthenticationException, PasswordRequiredException, SSHException
|
|
8
7
|
|
|
9
8
|
import pyinfra
|
|
10
|
-
from pyinfra.api import Config, MaskString, State, StringCommand
|
|
9
|
+
from pyinfra.api import Config, Host, MaskString, State, StringCommand
|
|
11
10
|
from pyinfra.api.connect import connect_all
|
|
12
11
|
from pyinfra.api.exceptions import ConnectError, PyinfraError
|
|
13
12
|
|
|
@@ -21,11 +20,9 @@ def make_raise_exception_function(cls, *args, **kwargs):
|
|
|
21
20
|
return handler
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
@patch("pyinfra.connectors.ssh.SSHClient.get_transport", MagicMock())
|
|
25
|
-
@patch("pyinfra.connectors.ssh.open", mock_open(read_data="test!"), create=True)
|
|
26
23
|
class TestSSHConnector(TestCase):
|
|
27
24
|
def setUp(self):
|
|
28
|
-
self.fake_connect_patch = patch("pyinfra.connectors.ssh.SSHClient.connect")
|
|
25
|
+
self.fake_connect_patch = mock.patch("pyinfra.connectors.ssh.SSHClient.connect")
|
|
29
26
|
self.fake_connect_mock = self.fake_connect_patch.start()
|
|
30
27
|
|
|
31
28
|
def tearDown(self):
|
|
@@ -56,8 +53,8 @@ class TestSSHConnector(TestCase):
|
|
|
56
53
|
|
|
57
54
|
assert len(state.active_hosts) == 2
|
|
58
55
|
|
|
59
|
-
@patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True)
|
|
60
|
-
@patch("pyinfra.connectors.ssh_util.RSAKey.from_private_key_file")
|
|
56
|
+
@mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True)
|
|
57
|
+
@mock.patch("pyinfra.connectors.ssh_util.RSAKey.from_private_key_file")
|
|
61
58
|
def test_connect_exceptions(self, fake_key_open):
|
|
62
59
|
for exception_class in (
|
|
63
60
|
AuthenticationException,
|
|
@@ -81,10 +78,13 @@ class TestSSHConnector(TestCase):
|
|
|
81
78
|
def test_connect_with_rsa_ssh_key(self):
|
|
82
79
|
state = State(make_inventory(hosts=(("somehost", {"ssh_key": "testkey"}),)), Config())
|
|
83
80
|
|
|
84
|
-
with
|
|
85
|
-
"pyinfra.connectors.ssh_util.
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
with (
|
|
82
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
83
|
+
mock.patch(
|
|
84
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
85
|
+
) as fake_key_open,
|
|
86
|
+
):
|
|
87
|
+
fake_key = mock.MagicMock()
|
|
88
88
|
fake_key_open.return_value = fake_key
|
|
89
89
|
|
|
90
90
|
connect_all(state)
|
|
@@ -121,15 +121,23 @@ class TestSSHConnector(TestCase):
|
|
|
121
121
|
def test_connect_with_rsa_ssh_key_password(self):
|
|
122
122
|
state = State(
|
|
123
123
|
make_inventory(
|
|
124
|
-
hosts=(
|
|
124
|
+
hosts=(
|
|
125
|
+
(
|
|
126
|
+
"somehost",
|
|
127
|
+
{"ssh_key": "testkey", "ssh_key_password": "testpass"},
|
|
128
|
+
),
|
|
129
|
+
),
|
|
125
130
|
),
|
|
126
131
|
Config(),
|
|
127
132
|
)
|
|
128
133
|
|
|
129
|
-
with
|
|
130
|
-
"pyinfra.connectors.ssh_util.
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
with (
|
|
135
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
136
|
+
mock.patch(
|
|
137
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
138
|
+
) as fake_key_open,
|
|
139
|
+
):
|
|
140
|
+
fake_key = mock.MagicMock()
|
|
133
141
|
|
|
134
142
|
def fake_key_open_fail(*args, **kwargs):
|
|
135
143
|
if "password" not in kwargs:
|
|
@@ -148,13 +156,17 @@ class TestSSHConnector(TestCase):
|
|
|
148
156
|
def test_connect_with_rsa_ssh_key_password_from_prompt(self):
|
|
149
157
|
state = State(make_inventory(hosts=(("somehost", {"ssh_key": "testkey"}),)), Config())
|
|
150
158
|
|
|
151
|
-
with
|
|
152
|
-
"pyinfra.connectors.ssh_util.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
with (
|
|
160
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
161
|
+
mock.patch(
|
|
162
|
+
"pyinfra.connectors.ssh_util.getpass",
|
|
163
|
+
lambda *args, **kwargs: "testpass",
|
|
164
|
+
),
|
|
165
|
+
mock.patch(
|
|
166
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
167
|
+
) as fake_key_open,
|
|
168
|
+
):
|
|
169
|
+
fake_key = mock.MagicMock()
|
|
158
170
|
|
|
159
171
|
def fake_key_open_fail(*args, **kwargs):
|
|
160
172
|
if "password" not in kwargs:
|
|
@@ -175,12 +187,15 @@ class TestSSHConnector(TestCase):
|
|
|
175
187
|
def test_connect_with_rsa_ssh_key_missing_password(self):
|
|
176
188
|
state = State(make_inventory(hosts=(("somehost", {"ssh_key": "testkey"}),)), Config())
|
|
177
189
|
|
|
178
|
-
with
|
|
179
|
-
"pyinfra.connectors.ssh_util.
|
|
180
|
-
|
|
190
|
+
with (
|
|
191
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
192
|
+
mock.patch(
|
|
193
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
194
|
+
) as fake_key_open,
|
|
195
|
+
):
|
|
181
196
|
fake_key_open.side_effect = make_raise_exception_function(PasswordRequiredException)
|
|
182
197
|
|
|
183
|
-
fake_key = MagicMock()
|
|
198
|
+
fake_key = mock.MagicMock()
|
|
184
199
|
fake_key_open.return_value = fake_key
|
|
185
200
|
|
|
186
201
|
with self.assertRaises(PyinfraError) as e:
|
|
@@ -193,26 +208,37 @@ class TestSSHConnector(TestCase):
|
|
|
193
208
|
def test_connect_with_rsa_ssh_key_wrong_password(self):
|
|
194
209
|
state = State(
|
|
195
210
|
make_inventory(
|
|
196
|
-
hosts=(
|
|
211
|
+
hosts=(
|
|
212
|
+
(
|
|
213
|
+
"somehost",
|
|
214
|
+
{"ssh_key": "testkey", "ssh_key_password": "testpass"},
|
|
215
|
+
),
|
|
216
|
+
),
|
|
197
217
|
),
|
|
198
218
|
Config(),
|
|
199
219
|
)
|
|
200
220
|
|
|
201
|
-
fake_fail_from_private_key_file = MagicMock()
|
|
221
|
+
fake_fail_from_private_key_file = mock.MagicMock()
|
|
202
222
|
fake_fail_from_private_key_file.side_effect = make_raise_exception_function(SSHException)
|
|
203
223
|
|
|
204
|
-
with
|
|
205
|
-
"pyinfra.connectors.ssh_util.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
224
|
+
with (
|
|
225
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
226
|
+
mock.patch(
|
|
227
|
+
"pyinfra.connectors.ssh_util.DSSKey.from_private_key_file",
|
|
228
|
+
fake_fail_from_private_key_file,
|
|
229
|
+
),
|
|
230
|
+
mock.patch(
|
|
231
|
+
"pyinfra.connectors.ssh_util.ECDSAKey.from_private_key_file",
|
|
232
|
+
fake_fail_from_private_key_file,
|
|
233
|
+
),
|
|
234
|
+
mock.patch(
|
|
235
|
+
"pyinfra.connectors.ssh_util.Ed25519Key.from_private_key_file",
|
|
236
|
+
fake_fail_from_private_key_file,
|
|
237
|
+
),
|
|
238
|
+
mock.patch(
|
|
239
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
240
|
+
) as fake_key_open,
|
|
241
|
+
):
|
|
216
242
|
|
|
217
243
|
def fake_key_open_fail(*args, **kwargs):
|
|
218
244
|
if "password" not in kwargs:
|
|
@@ -221,7 +247,7 @@ class TestSSHConnector(TestCase):
|
|
|
221
247
|
|
|
222
248
|
fake_key_open.side_effect = fake_key_open_fail
|
|
223
249
|
|
|
224
|
-
fake_key = MagicMock()
|
|
250
|
+
fake_key = mock.MagicMock()
|
|
225
251
|
fake_key_open.return_value = fake_key
|
|
226
252
|
|
|
227
253
|
with self.assertRaises(PyinfraError) as e:
|
|
@@ -234,14 +260,18 @@ class TestSSHConnector(TestCase):
|
|
|
234
260
|
def test_connect_with_dss_ssh_key(self):
|
|
235
261
|
state = State(make_inventory(hosts=(("somehost", {"ssh_key": "testkey"}),)), Config())
|
|
236
262
|
|
|
237
|
-
with
|
|
238
|
-
"pyinfra.connectors.ssh_util.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
263
|
+
with (
|
|
264
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
265
|
+
mock.patch(
|
|
266
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
267
|
+
) as fake_rsa_key_open,
|
|
268
|
+
mock.patch(
|
|
269
|
+
"pyinfra.connectors.ssh_util.DSSKey.from_private_key_file",
|
|
270
|
+
) as fake_key_open,
|
|
271
|
+
): # noqa
|
|
242
272
|
fake_rsa_key_open.side_effect = make_raise_exception_function(SSHException)
|
|
243
273
|
|
|
244
|
-
fake_key = MagicMock()
|
|
274
|
+
fake_key = mock.MagicMock()
|
|
245
275
|
fake_key_open.return_value = fake_key
|
|
246
276
|
|
|
247
277
|
connect_all(state)
|
|
@@ -276,16 +306,25 @@ class TestSSHConnector(TestCase):
|
|
|
276
306
|
def test_connect_with_dss_ssh_key_password(self):
|
|
277
307
|
state = State(
|
|
278
308
|
make_inventory(
|
|
279
|
-
hosts=(
|
|
309
|
+
hosts=(
|
|
310
|
+
(
|
|
311
|
+
"somehost",
|
|
312
|
+
{"ssh_key": "testkey", "ssh_key_password": "testpass"},
|
|
313
|
+
),
|
|
314
|
+
),
|
|
280
315
|
),
|
|
281
316
|
Config(),
|
|
282
317
|
)
|
|
283
318
|
|
|
284
|
-
with
|
|
285
|
-
"pyinfra.connectors.ssh_util.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
319
|
+
with (
|
|
320
|
+
mock.patch("pyinfra.connectors.ssh_util.path.isfile", lambda *args, **kwargs: True),
|
|
321
|
+
mock.patch(
|
|
322
|
+
"pyinfra.connectors.ssh_util.RSAKey.from_private_key_file",
|
|
323
|
+
) as fake_rsa_key_open,
|
|
324
|
+
mock.patch(
|
|
325
|
+
"pyinfra.connectors.ssh_util.DSSKey.from_private_key_file",
|
|
326
|
+
) as fake_dss_key_open,
|
|
327
|
+
): # noqa
|
|
289
328
|
|
|
290
329
|
def fake_rsa_key_open_fail(*args, **kwargs):
|
|
291
330
|
if "password" not in kwargs:
|
|
@@ -294,7 +333,7 @@ class TestSSHConnector(TestCase):
|
|
|
294
333
|
|
|
295
334
|
fake_rsa_key_open.side_effect = fake_rsa_key_open_fail
|
|
296
335
|
|
|
297
|
-
fake_dss_key = MagicMock()
|
|
336
|
+
fake_dss_key = mock.MagicMock()
|
|
298
337
|
|
|
299
338
|
def fake_dss_key_func(*args, **kwargs):
|
|
300
339
|
if "password" not in kwargs:
|
|
@@ -343,12 +382,12 @@ class TestSSHConnector(TestCase):
|
|
|
343
382
|
# SSH command tests
|
|
344
383
|
#
|
|
345
384
|
|
|
346
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
385
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
347
386
|
def test_run_shell_command(self, fake_ssh_client):
|
|
348
|
-
fake_ssh = MagicMock()
|
|
349
|
-
fake_stdin = MagicMock()
|
|
350
|
-
fake_stdout = MagicMock()
|
|
351
|
-
fake_ssh.exec_command.return_value = fake_stdin, fake_stdout, MagicMock()
|
|
387
|
+
fake_ssh = mock.MagicMock()
|
|
388
|
+
fake_stdin = mock.MagicMock()
|
|
389
|
+
fake_stdout = mock.MagicMock()
|
|
390
|
+
fake_ssh.exec_command.return_value = fake_stdin, fake_stdout, mock.MagicMock()
|
|
352
391
|
|
|
353
392
|
fake_ssh_client.return_value = fake_ssh
|
|
354
393
|
|
|
@@ -376,12 +415,16 @@ class TestSSHConnector(TestCase):
|
|
|
376
415
|
|
|
377
416
|
fake_ssh.exec_command.assert_called_with("sh -c 'echo Šablony'", get_pty=False)
|
|
378
417
|
|
|
379
|
-
@patch("pyinfra.connectors.ssh.click")
|
|
380
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
418
|
+
@mock.patch("pyinfra.connectors.ssh.click")
|
|
419
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
381
420
|
def test_run_shell_command_masked(self, fake_ssh_client, fake_click):
|
|
382
|
-
fake_ssh = MagicMock()
|
|
383
|
-
fake_stdout = MagicMock()
|
|
384
|
-
fake_ssh.exec_command.return_value =
|
|
421
|
+
fake_ssh = mock.MagicMock()
|
|
422
|
+
fake_stdout = mock.MagicMock()
|
|
423
|
+
fake_ssh.exec_command.return_value = (
|
|
424
|
+
mock.MagicMock(),
|
|
425
|
+
fake_stdout,
|
|
426
|
+
mock.MagicMock(),
|
|
427
|
+
)
|
|
385
428
|
|
|
386
429
|
fake_ssh_client.return_value = fake_ssh
|
|
387
430
|
|
|
@@ -409,11 +452,15 @@ class TestSSHConnector(TestCase):
|
|
|
409
452
|
err=True,
|
|
410
453
|
)
|
|
411
454
|
|
|
412
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
455
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
413
456
|
def test_run_shell_command_success_exit_code(self, fake_ssh_client):
|
|
414
|
-
fake_ssh = MagicMock()
|
|
415
|
-
fake_stdout = MagicMock()
|
|
416
|
-
fake_ssh.exec_command.return_value =
|
|
457
|
+
fake_ssh = mock.MagicMock()
|
|
458
|
+
fake_stdout = mock.MagicMock()
|
|
459
|
+
fake_ssh.exec_command.return_value = (
|
|
460
|
+
mock.MagicMock(),
|
|
461
|
+
fake_stdout,
|
|
462
|
+
mock.MagicMock(),
|
|
463
|
+
)
|
|
417
464
|
|
|
418
465
|
fake_ssh_client.return_value = fake_ssh
|
|
419
466
|
|
|
@@ -429,11 +476,15 @@ class TestSSHConnector(TestCase):
|
|
|
429
476
|
assert len(out) == 2
|
|
430
477
|
assert out[0] is True
|
|
431
478
|
|
|
432
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
479
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
433
480
|
def test_run_shell_command_error(self, fake_ssh_client):
|
|
434
|
-
fake_ssh = MagicMock()
|
|
435
|
-
fake_stdout = MagicMock()
|
|
436
|
-
fake_ssh.exec_command.return_value =
|
|
481
|
+
fake_ssh = mock.MagicMock()
|
|
482
|
+
fake_stdout = mock.MagicMock()
|
|
483
|
+
fake_ssh.exec_command.return_value = (
|
|
484
|
+
mock.MagicMock(),
|
|
485
|
+
fake_stdout,
|
|
486
|
+
mock.MagicMock(),
|
|
487
|
+
)
|
|
437
488
|
|
|
438
489
|
fake_ssh_client.return_value = fake_ssh
|
|
439
490
|
|
|
@@ -449,25 +500,37 @@ class TestSSHConnector(TestCase):
|
|
|
449
500
|
assert len(out) == 2
|
|
450
501
|
assert out[0] is False
|
|
451
502
|
|
|
452
|
-
@patch("pyinfra.connectors.util.getpass")
|
|
453
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
503
|
+
@mock.patch("pyinfra.connectors.util.getpass")
|
|
504
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
454
505
|
def test_run_shell_command_sudo_password_automatic_prompt(
|
|
455
506
|
self,
|
|
456
507
|
fake_ssh_client,
|
|
457
508
|
fake_getpass,
|
|
458
509
|
):
|
|
459
|
-
fake_ssh = MagicMock()
|
|
460
|
-
first_fake_stdout = MagicMock()
|
|
461
|
-
second_fake_stdout = MagicMock()
|
|
462
|
-
third_fake_stdout = MagicMock()
|
|
510
|
+
fake_ssh = mock.MagicMock()
|
|
511
|
+
first_fake_stdout = mock.MagicMock()
|
|
512
|
+
second_fake_stdout = mock.MagicMock()
|
|
513
|
+
third_fake_stdout = mock.MagicMock()
|
|
463
514
|
|
|
464
515
|
first_fake_stdout.__iter__.return_value = ["sudo: a password is required\r"]
|
|
465
516
|
second_fake_stdout.__iter__.return_value = ["/tmp/pyinfra-sudo-askpass-XXXXXXXXXXXX"]
|
|
466
517
|
|
|
467
518
|
fake_ssh.exec_command.side_effect = [
|
|
468
|
-
(
|
|
469
|
-
|
|
470
|
-
|
|
519
|
+
(
|
|
520
|
+
mock.MagicMock(),
|
|
521
|
+
first_fake_stdout,
|
|
522
|
+
mock.MagicMock(),
|
|
523
|
+
), # command w/o sudo password
|
|
524
|
+
(
|
|
525
|
+
mock.MagicMock(),
|
|
526
|
+
second_fake_stdout,
|
|
527
|
+
mock.MagicMock(),
|
|
528
|
+
), # SUDO_ASKPASS_COMMAND
|
|
529
|
+
(
|
|
530
|
+
mock.MagicMock(),
|
|
531
|
+
third_fake_stdout,
|
|
532
|
+
mock.MagicMock(),
|
|
533
|
+
), # command with sudo pw
|
|
471
534
|
]
|
|
472
535
|
|
|
473
536
|
fake_ssh_client.return_value = fake_ssh
|
|
@@ -500,25 +563,37 @@ class TestSSHConnector(TestCase):
|
|
|
500
563
|
get_pty=False,
|
|
501
564
|
)
|
|
502
565
|
|
|
503
|
-
@patch("pyinfra.connectors.util.getpass")
|
|
504
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
566
|
+
@mock.patch("pyinfra.connectors.util.getpass")
|
|
567
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
505
568
|
def test_run_shell_command_sudo_password_automatic_prompt_with_special_chars_in_password(
|
|
506
569
|
self,
|
|
507
570
|
fake_ssh_client,
|
|
508
571
|
fake_getpass,
|
|
509
572
|
):
|
|
510
|
-
fake_ssh = MagicMock()
|
|
511
|
-
first_fake_stdout = MagicMock()
|
|
512
|
-
second_fake_stdout = MagicMock()
|
|
513
|
-
third_fake_stdout = MagicMock()
|
|
573
|
+
fake_ssh = mock.MagicMock()
|
|
574
|
+
first_fake_stdout = mock.MagicMock()
|
|
575
|
+
second_fake_stdout = mock.MagicMock()
|
|
576
|
+
third_fake_stdout = mock.MagicMock()
|
|
514
577
|
|
|
515
578
|
first_fake_stdout.__iter__.return_value = ["sudo: a password is required\r"]
|
|
516
579
|
second_fake_stdout.__iter__.return_value = ["/tmp/pyinfra-sudo-askpass-XXXXXXXXXXXX"]
|
|
517
580
|
|
|
518
581
|
fake_ssh.exec_command.side_effect = [
|
|
519
|
-
(
|
|
520
|
-
|
|
521
|
-
|
|
582
|
+
(
|
|
583
|
+
mock.MagicMock(),
|
|
584
|
+
first_fake_stdout,
|
|
585
|
+
mock.MagicMock(),
|
|
586
|
+
), # command w/o sudo password
|
|
587
|
+
(
|
|
588
|
+
mock.MagicMock(),
|
|
589
|
+
second_fake_stdout,
|
|
590
|
+
mock.MagicMock(),
|
|
591
|
+
), # SUDO_ASKPASS_COMMAND
|
|
592
|
+
(
|
|
593
|
+
mock.MagicMock(),
|
|
594
|
+
third_fake_stdout,
|
|
595
|
+
mock.MagicMock(),
|
|
596
|
+
), # command with sudo pw
|
|
522
597
|
]
|
|
523
598
|
|
|
524
599
|
fake_ssh_client.return_value = fake_ssh
|
|
@@ -554,8 +629,8 @@ class TestSSHConnector(TestCase):
|
|
|
554
629
|
# SSH file put/get tests
|
|
555
630
|
#
|
|
556
631
|
|
|
557
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
558
|
-
@patch("pyinfra.connectors.util.getpass")
|
|
632
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
633
|
+
@mock.patch("pyinfra.connectors.util.getpass")
|
|
559
634
|
def test_run_shell_command_retry_for_sudo_password(
|
|
560
635
|
self,
|
|
561
636
|
fake_getpass,
|
|
@@ -563,9 +638,9 @@ class TestSSHConnector(TestCase):
|
|
|
563
638
|
):
|
|
564
639
|
fake_getpass.return_value = "PASSWORD"
|
|
565
640
|
|
|
566
|
-
fake_ssh = MagicMock()
|
|
567
|
-
fake_stdin = MagicMock()
|
|
568
|
-
fake_stdout = MagicMock()
|
|
641
|
+
fake_ssh = mock.MagicMock()
|
|
642
|
+
fake_stdin = mock.MagicMock()
|
|
643
|
+
fake_stdout = mock.MagicMock()
|
|
569
644
|
fake_stderr = ["sudo: a password is required"]
|
|
570
645
|
fake_ssh.exec_command.return_value = fake_stdin, fake_stdout, fake_stderr
|
|
571
646
|
|
|
@@ -594,16 +669,16 @@ class TestSSHConnector(TestCase):
|
|
|
594
669
|
# SSH file put/get tests
|
|
595
670
|
#
|
|
596
671
|
|
|
597
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
598
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
672
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
673
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
599
674
|
def test_put_file(self, fake_sftp_client, fake_ssh_client):
|
|
600
675
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
601
676
|
State(inventory, Config())
|
|
602
677
|
host = inventory.get_host("anotherhost")
|
|
603
678
|
host.connect()
|
|
604
679
|
|
|
605
|
-
fake_open = mock_open(read_data="test!")
|
|
606
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
680
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
681
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
607
682
|
status = host.put_file(
|
|
608
683
|
"not-a-file",
|
|
609
684
|
"not-another-file",
|
|
@@ -611,25 +686,33 @@ class TestSSHConnector(TestCase):
|
|
|
611
686
|
)
|
|
612
687
|
|
|
613
688
|
assert status is True
|
|
689
|
+
|
|
690
|
+
# Adding debug prints to understand the mock calls
|
|
691
|
+
print(fake_sftp_client.from_transport().putfo.mock_calls)
|
|
692
|
+
|
|
614
693
|
fake_sftp_client.from_transport().putfo.assert_called_with(
|
|
615
694
|
fake_open(),
|
|
616
695
|
"not-another-file",
|
|
617
696
|
)
|
|
618
697
|
|
|
619
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
620
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
698
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
699
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
621
700
|
def test_put_file_sudo(self, fake_sftp_client, fake_ssh_client):
|
|
622
701
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
623
702
|
State(inventory, Config())
|
|
624
703
|
host = inventory.get_host("anotherhost")
|
|
625
704
|
host.connect()
|
|
626
705
|
|
|
627
|
-
stdout_mock = MagicMock()
|
|
706
|
+
stdout_mock = mock.MagicMock()
|
|
628
707
|
stdout_mock.channel.recv_exit_status.return_value = 0
|
|
629
|
-
fake_ssh_client().exec_command.return_value =
|
|
708
|
+
fake_ssh_client().exec_command.return_value = (
|
|
709
|
+
mock.MagicMock(),
|
|
710
|
+
stdout_mock,
|
|
711
|
+
mock.MagicMock(),
|
|
712
|
+
)
|
|
630
713
|
|
|
631
|
-
fake_open = mock_open(read_data="test!")
|
|
632
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
714
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
715
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
633
716
|
status = host.put_file(
|
|
634
717
|
"not-a-file",
|
|
635
718
|
"not another file",
|
|
@@ -642,20 +725,20 @@ class TestSSHConnector(TestCase):
|
|
|
642
725
|
|
|
643
726
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
644
727
|
[
|
|
645
|
-
call(
|
|
728
|
+
mock.call(
|
|
646
729
|
(
|
|
647
730
|
"sh -c 'setfacl -m u:ubuntu:r "
|
|
648
731
|
"/tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24'"
|
|
649
732
|
),
|
|
650
733
|
get_pty=False,
|
|
651
734
|
),
|
|
652
|
-
call(
|
|
735
|
+
mock.call(
|
|
653
736
|
(
|
|
654
737
|
"sudo -H -n -u ubuntu sh -c 'cp /tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24 '\"'\"'not another file'\"'\"''" # noqa: E501
|
|
655
738
|
),
|
|
656
739
|
get_pty=False,
|
|
657
740
|
),
|
|
658
|
-
call(
|
|
741
|
+
mock.call(
|
|
659
742
|
("sh -c 'rm -f /tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24'"),
|
|
660
743
|
get_pty=False,
|
|
661
744
|
),
|
|
@@ -667,20 +750,24 @@ class TestSSHConnector(TestCase):
|
|
|
667
750
|
"/tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24",
|
|
668
751
|
)
|
|
669
752
|
|
|
670
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
671
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
753
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
754
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
672
755
|
def test_put_file_doas(self, fake_sftp_client, fake_ssh_client):
|
|
673
756
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
674
757
|
State(inventory, Config())
|
|
675
758
|
host = inventory.get_host("anotherhost")
|
|
676
759
|
host.connect()
|
|
677
760
|
|
|
678
|
-
stdout_mock = MagicMock()
|
|
761
|
+
stdout_mock = mock.MagicMock()
|
|
679
762
|
stdout_mock.channel.recv_exit_status.return_value = 0
|
|
680
|
-
fake_ssh_client().exec_command.return_value =
|
|
763
|
+
fake_ssh_client().exec_command.return_value = (
|
|
764
|
+
mock.MagicMock(),
|
|
765
|
+
stdout_mock,
|
|
766
|
+
mock.MagicMock(),
|
|
767
|
+
)
|
|
681
768
|
|
|
682
|
-
fake_open = mock_open(read_data="test!")
|
|
683
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
769
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
770
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
684
771
|
status = host.put_file(
|
|
685
772
|
"not-a-file",
|
|
686
773
|
"not another file",
|
|
@@ -693,20 +780,20 @@ class TestSSHConnector(TestCase):
|
|
|
693
780
|
|
|
694
781
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
695
782
|
[
|
|
696
|
-
call(
|
|
783
|
+
mock.call(
|
|
697
784
|
(
|
|
698
785
|
"sh -c 'setfacl -m u:ubuntu:r "
|
|
699
786
|
"/tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24'"
|
|
700
787
|
),
|
|
701
788
|
get_pty=False,
|
|
702
789
|
),
|
|
703
|
-
call(
|
|
790
|
+
mock.call(
|
|
704
791
|
(
|
|
705
792
|
"doas -n -u ubuntu sh -c 'cp /tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24 '\"'\"'not another file'\"'\"''" # noqa: E501
|
|
706
793
|
),
|
|
707
794
|
get_pty=False,
|
|
708
795
|
),
|
|
709
|
-
call(
|
|
796
|
+
mock.call(
|
|
710
797
|
("sh -c 'rm -f /tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24'"),
|
|
711
798
|
get_pty=False,
|
|
712
799
|
),
|
|
@@ -718,20 +805,24 @@ class TestSSHConnector(TestCase):
|
|
|
718
805
|
"/tmp/pyinfra-de01e82cb691e8a31369da3c7c8f17341c44ac24",
|
|
719
806
|
)
|
|
720
807
|
|
|
721
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
722
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
808
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
809
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
723
810
|
def test_put_file_su_user_fail_acl(self, fake_sftp_client, fake_ssh_client):
|
|
724
811
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
725
812
|
State(inventory, Config())
|
|
726
813
|
host = inventory.get_host("anotherhost")
|
|
727
814
|
host.connect()
|
|
728
815
|
|
|
729
|
-
stdout_mock = MagicMock()
|
|
816
|
+
stdout_mock = mock.MagicMock()
|
|
730
817
|
stdout_mock.channel.recv_exit_status.return_value = 1
|
|
731
|
-
fake_ssh_client().exec_command.return_value =
|
|
818
|
+
fake_ssh_client().exec_command.return_value = (
|
|
819
|
+
mock.MagicMock(),
|
|
820
|
+
stdout_mock,
|
|
821
|
+
mock.MagicMock(),
|
|
822
|
+
)
|
|
732
823
|
|
|
733
|
-
fake_open = mock_open(read_data="test!")
|
|
734
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
824
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
825
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
735
826
|
status = host.put_file(
|
|
736
827
|
"not-a-file",
|
|
737
828
|
"not-another-file",
|
|
@@ -754,23 +845,29 @@ class TestSSHConnector(TestCase):
|
|
|
754
845
|
"/tmp/pyinfra-43db9984686317089fefcf2e38de527e4cb44487",
|
|
755
846
|
)
|
|
756
847
|
|
|
757
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
758
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
848
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
849
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
759
850
|
def test_put_file_su_user_fail_copy(self, fake_sftp_client, fake_ssh_client):
|
|
760
851
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
761
852
|
State(inventory, Config())
|
|
853
|
+
|
|
762
854
|
host = inventory.get_host("anotherhost")
|
|
855
|
+
assert isinstance(host, Host)
|
|
763
856
|
host.connect()
|
|
764
857
|
|
|
765
|
-
stdout_mock = MagicMock()
|
|
766
|
-
exit_codes = [0, 1]
|
|
858
|
+
stdout_mock = mock.MagicMock()
|
|
859
|
+
exit_codes = [0, 0, 1]
|
|
767
860
|
stdout_mock.channel.recv_exit_status.side_effect = lambda: exit_codes.pop(0)
|
|
768
|
-
fake_ssh_client().exec_command.return_value =
|
|
861
|
+
fake_ssh_client().exec_command.return_value = (
|
|
862
|
+
mock.MagicMock(),
|
|
863
|
+
stdout_mock,
|
|
864
|
+
mock.MagicMock(),
|
|
865
|
+
)
|
|
769
866
|
|
|
770
|
-
fake_open = mock_open(read_data="test!")
|
|
771
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
867
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
868
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
772
869
|
status = host.put_file(
|
|
773
|
-
|
|
870
|
+
fake_open(),
|
|
774
871
|
"not-another-file",
|
|
775
872
|
print_output=True,
|
|
776
873
|
_su_user="centos",
|
|
@@ -786,7 +883,7 @@ class TestSSHConnector(TestCase):
|
|
|
786
883
|
get_pty=False,
|
|
787
884
|
)
|
|
788
885
|
|
|
789
|
-
fake_ssh_client().exec_command.
|
|
886
|
+
fake_ssh_client().exec_command.assert_any_call(
|
|
790
887
|
(
|
|
791
888
|
"su centos -c 'sh -c '\"'\"'cp "
|
|
792
889
|
"/tmp/pyinfra-43db9984686317089fefcf2e38de527e4cb44487 "
|
|
@@ -800,20 +897,24 @@ class TestSSHConnector(TestCase):
|
|
|
800
897
|
"/tmp/pyinfra-43db9984686317089fefcf2e38de527e4cb44487",
|
|
801
898
|
)
|
|
802
899
|
|
|
803
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
804
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
900
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
901
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
805
902
|
def test_put_file_sudo_custom_temp_file(self, fake_sftp_client, fake_ssh_client):
|
|
806
903
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
807
904
|
State(inventory, Config())
|
|
808
905
|
host = inventory.get_host("anotherhost")
|
|
809
906
|
host.connect()
|
|
810
907
|
|
|
811
|
-
stdout_mock = MagicMock()
|
|
908
|
+
stdout_mock = mock.MagicMock()
|
|
812
909
|
stdout_mock.channel.recv_exit_status.return_value = 0
|
|
813
|
-
fake_ssh_client().exec_command.return_value =
|
|
910
|
+
fake_ssh_client().exec_command.return_value = (
|
|
911
|
+
mock.MagicMock(),
|
|
912
|
+
stdout_mock,
|
|
913
|
+
mock.MagicMock(),
|
|
914
|
+
)
|
|
814
915
|
|
|
815
|
-
fake_open = mock_open(read_data="test!")
|
|
816
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
916
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
917
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
817
918
|
status = host.put_file(
|
|
818
919
|
"not-a-file",
|
|
819
920
|
"not another file",
|
|
@@ -826,7 +927,7 @@ class TestSSHConnector(TestCase):
|
|
|
826
927
|
assert status is True
|
|
827
928
|
|
|
828
929
|
fake_ssh_client().exec_command.assert_called_with(
|
|
829
|
-
("sh -c 'rm -f
|
|
930
|
+
("sh -c 'rm -f /a-different-tempfile'"),
|
|
830
931
|
get_pty=False,
|
|
831
932
|
)
|
|
832
933
|
|
|
@@ -835,16 +936,16 @@ class TestSSHConnector(TestCase):
|
|
|
835
936
|
"/a-different-tempfile",
|
|
836
937
|
)
|
|
837
938
|
|
|
838
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
839
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
939
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
940
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
840
941
|
def test_get_file(self, fake_sftp_client, fake_ssh_client):
|
|
841
942
|
inventory = make_inventory(hosts=("somehost",))
|
|
842
943
|
State(inventory, Config())
|
|
843
944
|
host = inventory.get_host("somehost")
|
|
844
945
|
host.connect()
|
|
845
946
|
|
|
846
|
-
fake_open = mock_open(read_data="test!")
|
|
847
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
947
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
948
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
848
949
|
status = host.get_file(
|
|
849
950
|
"not-a-file",
|
|
850
951
|
"not-another-file",
|
|
@@ -857,20 +958,24 @@ class TestSSHConnector(TestCase):
|
|
|
857
958
|
fake_open(),
|
|
858
959
|
)
|
|
859
960
|
|
|
860
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
861
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
961
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
962
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
862
963
|
def test_get_file_sudo(self, fake_sftp_client, fake_ssh_client):
|
|
863
964
|
inventory = make_inventory(hosts=("somehost",))
|
|
864
965
|
State(inventory, Config())
|
|
865
966
|
host = inventory.get_host("somehost")
|
|
866
967
|
host.connect()
|
|
867
968
|
|
|
868
|
-
stdout_mock = MagicMock()
|
|
969
|
+
stdout_mock = mock.MagicMock()
|
|
869
970
|
stdout_mock.channel.recv_exit_status.return_value = 0
|
|
870
|
-
fake_ssh_client().exec_command.return_value =
|
|
971
|
+
fake_ssh_client().exec_command.return_value = (
|
|
972
|
+
mock.MagicMock(),
|
|
973
|
+
stdout_mock,
|
|
974
|
+
mock.MagicMock(),
|
|
975
|
+
)
|
|
871
976
|
|
|
872
|
-
fake_open = mock_open(read_data="test!")
|
|
873
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
977
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
978
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
874
979
|
status = host.get_file(
|
|
875
980
|
"not-a-file",
|
|
876
981
|
"not-another-file",
|
|
@@ -883,14 +988,14 @@ class TestSSHConnector(TestCase):
|
|
|
883
988
|
|
|
884
989
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
885
990
|
[
|
|
886
|
-
call(
|
|
991
|
+
mock.call(
|
|
887
992
|
(
|
|
888
993
|
"sudo -H -n -u ubuntu sh -c 'cp not-a-file "
|
|
889
994
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r /tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'" # noqa
|
|
890
995
|
),
|
|
891
996
|
get_pty=False,
|
|
892
997
|
),
|
|
893
|
-
call(
|
|
998
|
+
mock.call(
|
|
894
999
|
(
|
|
895
1000
|
"sudo -H -n -u ubuntu sh -c 'rm -f "
|
|
896
1001
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'"
|
|
@@ -905,16 +1010,20 @@ class TestSSHConnector(TestCase):
|
|
|
905
1010
|
fake_open(),
|
|
906
1011
|
)
|
|
907
1012
|
|
|
908
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
1013
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
909
1014
|
def test_get_file_sudo_copy_fail(self, fake_ssh_client):
|
|
910
1015
|
inventory = make_inventory(hosts=("somehost",))
|
|
911
1016
|
State(inventory, Config())
|
|
912
1017
|
host = inventory.get_host("somehost")
|
|
913
1018
|
host.connect()
|
|
914
1019
|
|
|
915
|
-
stdout_mock = MagicMock()
|
|
1020
|
+
stdout_mock = mock.MagicMock()
|
|
916
1021
|
stdout_mock.channel.recv_exit_status.return_value = 1
|
|
917
|
-
fake_ssh_client().exec_command.return_value =
|
|
1022
|
+
fake_ssh_client().exec_command.return_value = (
|
|
1023
|
+
mock.MagicMock(),
|
|
1024
|
+
stdout_mock,
|
|
1025
|
+
mock.MagicMock(),
|
|
1026
|
+
)
|
|
918
1027
|
|
|
919
1028
|
status = host.get_file(
|
|
920
1029
|
"not-a-file",
|
|
@@ -928,7 +1037,7 @@ class TestSSHConnector(TestCase):
|
|
|
928
1037
|
|
|
929
1038
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
930
1039
|
[
|
|
931
|
-
call(
|
|
1040
|
+
mock.call(
|
|
932
1041
|
(
|
|
933
1042
|
"sudo -H -n -u ubuntu sh -c 'cp not-a-file "
|
|
934
1043
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r /tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'" # noqa
|
|
@@ -938,20 +1047,24 @@ class TestSSHConnector(TestCase):
|
|
|
938
1047
|
],
|
|
939
1048
|
)
|
|
940
1049
|
|
|
941
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
942
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
1050
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
1051
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
943
1052
|
def test_get_file_sudo_remove_fail(self, fake_sftp_client, fake_ssh_client):
|
|
944
1053
|
inventory = make_inventory(hosts=("somehost",))
|
|
945
1054
|
State(inventory, Config())
|
|
946
1055
|
host = inventory.get_host("somehost")
|
|
947
1056
|
host.connect()
|
|
948
1057
|
|
|
949
|
-
stdout_mock = MagicMock()
|
|
1058
|
+
stdout_mock = mock.MagicMock()
|
|
950
1059
|
stdout_mock.channel.recv_exit_status.side_effect = [0, 1]
|
|
951
|
-
fake_ssh_client().exec_command.return_value =
|
|
1060
|
+
fake_ssh_client().exec_command.return_value = (
|
|
1061
|
+
mock.MagicMock(),
|
|
1062
|
+
stdout_mock,
|
|
1063
|
+
mock.MagicMock(),
|
|
1064
|
+
)
|
|
952
1065
|
|
|
953
|
-
fake_open = mock_open(read_data="test!")
|
|
954
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
1066
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
1067
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
955
1068
|
status = host.get_file(
|
|
956
1069
|
"not-a-file",
|
|
957
1070
|
"not-another-file",
|
|
@@ -964,14 +1077,14 @@ class TestSSHConnector(TestCase):
|
|
|
964
1077
|
|
|
965
1078
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
966
1079
|
[
|
|
967
|
-
call(
|
|
1080
|
+
mock.call(
|
|
968
1081
|
(
|
|
969
1082
|
"sudo -H -n -u ubuntu sh -c 'cp not-a-file "
|
|
970
1083
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r /tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'" # noqa
|
|
971
1084
|
),
|
|
972
1085
|
get_pty=False,
|
|
973
1086
|
),
|
|
974
|
-
call(
|
|
1087
|
+
mock.call(
|
|
975
1088
|
(
|
|
976
1089
|
"sudo -H -n -u ubuntu sh -c 'rm -f "
|
|
977
1090
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'"
|
|
@@ -986,20 +1099,24 @@ class TestSSHConnector(TestCase):
|
|
|
986
1099
|
fake_open(),
|
|
987
1100
|
)
|
|
988
1101
|
|
|
989
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
990
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
1102
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
1103
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
991
1104
|
def test_get_file_su_user(self, fake_sftp_client, fake_ssh_client):
|
|
992
1105
|
inventory = make_inventory(hosts=("somehost",))
|
|
993
1106
|
State(inventory, Config())
|
|
994
1107
|
host = inventory.get_host("somehost")
|
|
995
1108
|
host.connect()
|
|
996
1109
|
|
|
997
|
-
stdout_mock = MagicMock()
|
|
1110
|
+
stdout_mock = mock.MagicMock()
|
|
998
1111
|
stdout_mock.channel.recv_exit_status.return_value = 0
|
|
999
|
-
fake_ssh_client().exec_command.return_value =
|
|
1112
|
+
fake_ssh_client().exec_command.return_value = (
|
|
1113
|
+
mock.MagicMock(),
|
|
1114
|
+
stdout_mock,
|
|
1115
|
+
mock.MagicMock(),
|
|
1116
|
+
)
|
|
1000
1117
|
|
|
1001
|
-
fake_open = mock_open(read_data="test!")
|
|
1002
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
1118
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
1119
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
1003
1120
|
status = host.get_file(
|
|
1004
1121
|
"not-a-file",
|
|
1005
1122
|
"not-another-file",
|
|
@@ -1011,7 +1128,7 @@ class TestSSHConnector(TestCase):
|
|
|
1011
1128
|
|
|
1012
1129
|
fake_ssh_client().exec_command.assert_has_calls(
|
|
1013
1130
|
[
|
|
1014
|
-
call(
|
|
1131
|
+
mock.call(
|
|
1015
1132
|
(
|
|
1016
1133
|
"su centos -c 'sh -c '\"'\"'cp not-a-file "
|
|
1017
1134
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r "
|
|
@@ -1019,7 +1136,7 @@ class TestSSHConnector(TestCase):
|
|
|
1019
1136
|
),
|
|
1020
1137
|
get_pty=False,
|
|
1021
1138
|
),
|
|
1022
|
-
call(
|
|
1139
|
+
mock.call(
|
|
1023
1140
|
(
|
|
1024
1141
|
"su centos -c 'sh -c '\"'\"'rm -f "
|
|
1025
1142
|
"/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'\"'\"''"
|
|
@@ -1034,8 +1151,8 @@ class TestSSHConnector(TestCase):
|
|
|
1034
1151
|
fake_open(),
|
|
1035
1152
|
)
|
|
1036
1153
|
|
|
1037
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
1038
|
-
@patch("pyinfra.connectors.ssh.SFTPClient")
|
|
1154
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
1155
|
+
@mock.patch("pyinfra.connectors.ssh.SFTPClient")
|
|
1039
1156
|
def test_get_sftp_fail(self, fake_sftp_client, fake_ssh_client):
|
|
1040
1157
|
inventory = make_inventory(hosts=("anotherhost",))
|
|
1041
1158
|
State(inventory, Config())
|
|
@@ -1044,8 +1161,8 @@ class TestSSHConnector(TestCase):
|
|
|
1044
1161
|
|
|
1045
1162
|
fake_sftp_client.from_transport.side_effect = make_raise_exception_function(SSHException)
|
|
1046
1163
|
|
|
1047
|
-
fake_open = mock_open(read_data="test!")
|
|
1048
|
-
with patch("pyinfra.api.util.open", fake_open, create=True):
|
|
1164
|
+
fake_open = mock.mock_open(read_data="test!")
|
|
1165
|
+
with mock.patch("pyinfra.api.util.open", fake_open, create=True):
|
|
1049
1166
|
with self.assertRaises(ConnectError):
|
|
1050
1167
|
host.put_file(
|
|
1051
1168
|
"not-a-file",
|
|
@@ -1053,8 +1170,8 @@ class TestSSHConnector(TestCase):
|
|
|
1053
1170
|
print_output=True,
|
|
1054
1171
|
)
|
|
1055
1172
|
|
|
1056
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
1057
|
-
@patch("pyinfra.connectors.ssh.sleep")
|
|
1173
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
1174
|
+
@mock.patch("pyinfra.connectors.ssh.sleep")
|
|
1058
1175
|
def test_ssh_connect_fail_retry(self, fake_sleep, fake_ssh_client):
|
|
1059
1176
|
for exception_class in (
|
|
1060
1177
|
SSHException,
|
|
@@ -1081,8 +1198,8 @@ class TestSSHConnector(TestCase):
|
|
|
1081
1198
|
fake_sleep.assert_called_once()
|
|
1082
1199
|
assert fake_ssh_client().connect.call_count == 2
|
|
1083
1200
|
|
|
1084
|
-
@patch("pyinfra.connectors.ssh.SSHClient")
|
|
1085
|
-
@patch("pyinfra.connectors.ssh.sleep")
|
|
1201
|
+
@mock.patch("pyinfra.connectors.ssh.SSHClient")
|
|
1202
|
+
@mock.patch("pyinfra.connectors.ssh.sleep")
|
|
1086
1203
|
def test_ssh_connect_fail_success(self, fake_sleep, fake_ssh_client):
|
|
1087
1204
|
for exception_class in (
|
|
1088
1205
|
SSHException,
|
|
@@ -1101,7 +1218,10 @@ class TestSSHConnector(TestCase):
|
|
|
1101
1218
|
unresposivehost = inventory.get_host("unresposivehost")
|
|
1102
1219
|
assert unresposivehost.data.ssh_connect_retries == 1
|
|
1103
1220
|
|
|
1104
|
-
fake_ssh_client().connect.side_effect = [
|
|
1221
|
+
fake_ssh_client().connect.side_effect = [
|
|
1222
|
+
exception_class(),
|
|
1223
|
+
mock.MagicMock(),
|
|
1224
|
+
]
|
|
1105
1225
|
|
|
1106
1226
|
unresposivehost.connect(show_errors=False, raise_exceptions=True)
|
|
1107
1227
|
fake_sleep.assert_called_once()
|