Skip to content

Commit 706a94b

Browse files
committed
Merge remote-tracking branch 'origin/v028' into stable
* origin/v028: (383 commits) Bump version for release. docs: update Changelog for 0.2.8. issue #627: add test and tweak Reaper behaviour. docs: lots more changelog concision docs: changelog concision docs: more changelog tweaks docs: reorder chapters docs: versionless <title> docs: update supported Ansible version, mention unsupported features docs: changelog fixes/tweaks issue #590: update Changelog. issue #621: send ADD_ROUTE earlier and add test for early logging. issue #590: whoops, import missing test modules issue #590: rework ParentEnumerationMethod to recursively handle bad modules issue #627: reduce the default pool size in a child to 2. tests: add a few extra service tests. docs: some more hyperlink joy docs: more hyperlinks docs: add domainrefs plugin to make link aliases everywhere \o/ docs: link IS_DEAD in changelog docs: tweaks to better explain changelog race issue #533: update routing to account for DEL_ROUTE propagation race tests: use defer_sync() Rather than defer() + ancient sync_with_broker() tests: one case from doas_test was invoking su tests: hide memory-mapped files from lsof output issue #615: remove meaningless test issue #625: ignore SIGINT within MuxProcess issue #625: use exec() instead of subprocess in mitogen_ansible_playbook issue #615: regression test issue #615: update Changelog. issue #615: ensure 4GB max_message_size is configured for task workers. issue #615: update Changelog. issue #615: route a dead message to recipients when no reply is expected issue #615: fetch_file() might be called with AnsibleUnicode. issue #615: redirect 'fetch' action to 'mitogen_fetch'. issue #615: extricate slurp brainwrong from mitogen_fetch issue #615: ansible: import Ansible fetch.py action plug-in issue #533: include object identity of Stream in repr() docs: lots more changelog issue #595: add buildah to docs and changelog. docs: a few more internals.rst additions ci: update to Ansible 2.8.3 tests: another random string changed in 2.8.3 tests: fix sudo_flags_failure for Ansible 2.8.3 ci: fix procps command line format warning Whoops, merge together lgtm.yml and .lgtm.yml issue #440: log Python version during bootstrap. docs: update changelog issue #558: disable test on OSX to cope with boundless mediocrity issue #558, #582: preserve remote tmpdir if caller did not supply one issue #613: must await 'exit' and 'disconnect' in wait=False test Import LGTM config to disable some stuff Fix up another handful of LGTM errors. tests: work around AnsibleModule.run_command() race. docs: mention another __main__ safeguard docs: tweaks formatting error docs: make Sphinx install soft fail on Python 2. issue #598: allow disabling preempt in terraform issue #598: update Changelog. issue #605: update Changelog. issue #605: ansible: share a sem_t instead of a pthread_mutex_t issue #613: add tests for all the weird shutdown methods Add mitogen.core.now() and use it everywhere; closes #614. docs: move decorator docs into core.py and use autodecorator preamble_size: make it work on Python 3. docs: upgrade Sphinx to 2.1.2, require Python 3 to build docs. docs: fix Sphinx warnings, add LogHandler, more docstrings docs: tidy up some Changelog text issue #615: fix up FileService tests for new logic issue #615: another Py3x fix. issue #615: Py3x fix. issue #615: update Changelog. issue #615: use FileService for target->controll file transfers issue #482: another Py3 fix ci: try removing exclude: to make Azure jobs work again compat: fix Py2.4 SyntaxError issue #482: remove 'ssh' from checked processes ci: Py3 fix issue #279: add one more test for max_message_size issue #482: ci: add stray process checks to all jobs tests: fix format string error core: MitogenProtocol.is_privileged was not set in children issue #482: tests: fail DockerMixin tests if stray processes exist docs: update Changelog. issue #586: update Changelog. docs: update Changelog. [security] core: undirectional routing wasn't respected in some cases docs: tidy up Select.all() issue #612: update Changelog. master: fix TypeError pkgutil: fix Python3 compatibility parent: use protocol for getting remote_id docs: merge signals.rst into internals.rst os_fork: do not attempt to cork the active thread. parent: fix get_log_level() for split out loggers. issue #547: fix service_test failures. issue #547: update Changelog. issue #547: core/service: race/deadlock-free service pool init docs: update Changelog. ...
2 parents 2516429 + c82112a commit 706a94b

File tree

227 files changed

+9377
-3709
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

227 files changed

+9377
-3709
lines changed

.ci/ansible_tests.py

Lines changed: 26 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,11 +14,23 @@
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+
23+
interesting = ci_lib.get_interesting_procs()
24+
25+
1626
with ci_lib.Fold('unit_tests'):
1727
os.environ['SKIP_MITOGEN'] = '1'
1828
ci_lib.run('./run_tests -v')
1929

2030

31+
ci_lib.check_stray_processes(interesting)
32+
33+
2134
with ci_lib.Fold('docker_setup'):
2235
containers = ci_lib.make_containers()
2336
ci_lib.start_containers(containers)
@@ -56,8 +69,19 @@
5669
run("sudo apt-get update")
5770
run("sudo apt-get install -y sshpass")
5871

72+
run("bash -c 'sudo ln -vfs /usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.py /usr/lib/python2.7 || true'")
73+
run("bash -c 'sudo ln -vfs /usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.py $VIRTUAL_ENV/lib/python2.7 || true'")
5974

6075
with ci_lib.Fold('ansible'):
6176
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:]))
77+
try:
78+
run('./run_ansible_playbook.py %s -i "%s" %s',
79+
playbook, HOSTS_DIR, ' '.join(sys.argv[1:]))
80+
except:
81+
pause_if_interactive()
82+
raise
83+
84+
85+
ci_lib.check_stray_processes(interesting, containers)
86+
87+
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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515
Mito27_27:
1616
python.version: '2.7'
1717
MODE: mitogen
18+
Ans280_27:
19+
python.version: '2.7'
20+
MODE: localhost_ansible
1821

1922

2023
- job: Linux
@@ -87,3 +90,13 @@ jobs:
8790
#VER: 2.6.2
8891
#DISTROS: debian
8992
#STRATEGY: linear
93+
94+
Ansible_280_27:
95+
python.version: '2.7'
96+
MODE: ansible
97+
VER: 2.8.0
98+
99+
Ansible_280_35:
100+
python.version: '3.5'
101+
MODE: ansible
102+
VER: 2.8.0

.ci/ci_lib.py

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ def have_docker():
5757

5858
# -----------------
5959

60-
# Force stdout FD 1 to be a pipe, so tools like pip don't spam progress bars.
60+
# Force line buffering on stdout.
61+
sys.stdout = os.fdopen(1, 'w', 1)
6162

63+
# Force stdout FD 1 to be a pipe, so tools like pip don't spam progress bars.
6264
if 'TRAVIS_HOME' in os.environ:
6365
proc = subprocess.Popen(
6466
args=['stdbuf', '-oL', 'cat'],
@@ -86,8 +88,13 @@ def _argv(s, *args):
8688
def run(s, *args, **kwargs):
8789
argv = ['/usr/bin/time', '--'] + _argv(s, *args)
8890
print('Running: %s' % (argv,))
89-
ret = subprocess.check_call(argv, **kwargs)
90-
print('Finished running: %s' % (argv,))
91+
try:
92+
ret = subprocess.check_call(argv, **kwargs)
93+
print('Finished running: %s' % (argv,))
94+
except Exception:
95+
print('Exception occurred while running: %s' % (argv,))
96+
raise
97+
9198
return ret
9299

93100

@@ -208,6 +215,46 @@ def make_containers(name_prefix='', port_offset=0):
208215
return lst
209216

210217

218+
# ssh removed from here because 'linear' strategy relies on processes that hang
219+
# around after the Ansible run completes
220+
INTERESTING_COMMS = ('python', 'sudo', 'su', 'doas')
221+
222+
223+
def proc_is_docker(pid):
224+
try:
225+
fp = open('/proc/%s/cgroup' % (pid,), 'r')
226+
except IOError:
227+
return False
228+
229+
try:
230+
return 'docker' in fp.read()
231+
finally:
232+
fp.close()
233+
234+
235+
def get_interesting_procs(container_name=None):
236+
args = ['ps', 'ax', '-oppid=', '-opid=', '-ocomm=', '-ocommand=']
237+
if container_name is not None:
238+
args = ['docker', 'exec', container_name] + args
239+
240+
out = []
241+
for line in subprocess__check_output(args).decode().splitlines():
242+
ppid, pid, comm, rest = line.split(None, 3)
243+
if (
244+
(
245+
any(comm.startswith(s) for s in INTERESTING_COMMS) or
246+
'mitogen:' in rest
247+
) and
248+
(
249+
container_name is not None or
250+
(not proc_is_docker(pid))
251+
)
252+
):
253+
out.append((int(pid), line))
254+
255+
return sorted(out)
256+
257+
211258
def start_containers(containers):
212259
if os.environ.get('KEEP'):
213260
return
@@ -217,6 +264,7 @@ def start_containers(containers):
217264
"docker rm -f %(name)s || true" % container,
218265
"docker run "
219266
"--rm "
267+
"--cpuset-cpus 0,1 "
220268
"--detach "
221269
"--privileged "
222270
"--cap-add=SYS_PTRACE "
@@ -228,9 +276,44 @@ def start_containers(containers):
228276
]
229277
for container in containers
230278
])
279+
280+
for container in containers:
281+
container['interesting'] = get_interesting_procs(container['name'])
282+
231283
return containers
232284

233285

286+
def verify_procs(hostname, old, new):
287+
oldpids = set(pid for pid, _ in old)
288+
if any(pid not in oldpids for pid, _ in new):
289+
print('%r had stray processes running:' % (hostname,))
290+
for pid, line in new:
291+
if pid not in oldpids:
292+
print('New process:', line)
293+
294+
print()
295+
return False
296+
297+
return True
298+
299+
300+
def check_stray_processes(old, containers=None):
301+
ok = True
302+
303+
new = get_interesting_procs()
304+
if old is not None:
305+
ok &= verify_procs('test host machine', old, new)
306+
307+
for container in containers or ():
308+
ok &= verify_procs(
309+
container['name'],
310+
container['interesting'],
311+
get_interesting_procs(container['name'])
312+
)
313+
314+
assert ok, 'stray processes were found'
315+
316+
234317
def dump_file(path):
235318
print()
236319
print('--- %s ---' % (path,))

.ci/debops_common_tests.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import print_function
44
import os
55
import shutil
6+
import sys
67

78
import ci_lib
89

@@ -67,9 +68,15 @@
6768
os.environ['ANSIBLE_HOST_KEY_CHECKING'] = 'False'
6869

6970

71+
interesting = ci_lib.get_interesting_procs()
72+
7073
with ci_lib.Fold('first_run'):
71-
ci_lib.run('debops common')
74+
ci_lib.run('debops common %s', ' '.join(sys.argv[1:]))
75+
76+
ci_lib.check_stray_processes(interesting, containers)
7277

7378

7479
with ci_lib.Fold('second_run'):
75-
ci_lib.run('debops common')
80+
ci_lib.run('debops common %s', ' '.join(sys.argv[1:]))
81+
82+
ci_lib.check_stray_processes(interesting, containers)

.ci/localhost_ansible_install.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python
2+
3+
import ci_lib
4+
5+
batches = [
6+
[
7+
# Must be installed separately, as PyNACL indirect requirement causes
8+
# newer version to be installed if done in a single pip run.
9+
'pip install "pycparser<2.19" "idna<2.7"',
10+
'pip install '
11+
'-r tests/requirements.txt '
12+
'-r tests/ansible/requirements.txt',
13+
]
14+
]
15+
16+
ci_lib.run_batches(batches)

.ci/localhost_ansible_tests.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python
2+
# Run tests/ansible/all.yml under Ansible and Ansible-Mitogen
3+
4+
import glob
5+
import os
6+
import shutil
7+
import sys
8+
9+
import ci_lib
10+
from ci_lib import run
11+
12+
13+
TESTS_DIR = os.path.join(ci_lib.GIT_ROOT, 'tests/ansible')
14+
IMAGE_PREP_DIR = os.path.join(ci_lib.GIT_ROOT, 'tests/image_prep')
15+
HOSTS_DIR = os.path.join(TESTS_DIR, 'hosts')
16+
KEY_PATH = os.path.join(TESTS_DIR, '../data/docker/mitogen__has_sudo_pubkey.key')
17+
18+
19+
with ci_lib.Fold('unit_tests'):
20+
os.environ['SKIP_MITOGEN'] = '1'
21+
ci_lib.run('./run_tests -v')
22+
23+
24+
with ci_lib.Fold('job_setup'):
25+
# Don't set -U as that will upgrade Paramiko to a non-2.6 compatible version.
26+
run("pip install -q virtualenv ansible==%s", ci_lib.ANSIBLE_VERSION)
27+
28+
os.chmod(KEY_PATH, int('0600', 8))
29+
if not ci_lib.exists_in_path('sshpass'):
30+
run("brew install http://git.io/sshpass.rb")
31+
32+
33+
with ci_lib.Fold('machine_prep'):
34+
ssh_dir = os.path.expanduser('~/.ssh')
35+
if not os.path.exists(ssh_dir):
36+
os.makedirs(ssh_dir, int('0700', 8))
37+
38+
key_path = os.path.expanduser('~/.ssh/id_rsa')
39+
shutil.copy(KEY_PATH, key_path)
40+
41+
auth_path = os.path.expanduser('~/.ssh/authorized_keys')
42+
os.system('ssh-keygen -y -f %s >> %s' % (key_path, auth_path))
43+
os.chmod(auth_path, int('0600', 8))
44+
45+
if os.path.expanduser('~mitogen__user1') == '~mitogen__user1':
46+
os.chdir(IMAGE_PREP_DIR)
47+
run("ansible-playbook -c local -i localhost, _user_accounts.yml")
48+
49+
50+
with ci_lib.Fold('ansible'):
51+
os.chdir(TESTS_DIR)
52+
playbook = os.environ.get('PLAYBOOK', 'all.yml')
53+
run('./run_ansible_playbook.py %s -l target %s',
54+
playbook, ' '.join(sys.argv[1:]))

.ci/mitogen_install.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
'docker pull %s' % (ci_lib.image_for_distro(ci_lib.DISTRO),),
1515
])
1616

17+
1718
ci_lib.run_batches(batches)

.ci/mitogen_tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@
1414
if not ci_lib.have_docker():
1515
os.environ['SKIP_DOCKER_TESTS'] = '1'
1616

17+
interesting = ci_lib.get_interesting_procs()
1718
ci_lib.run('./run_tests -v')
19+
ci_lib.check_stray_processes(interesting)

0 commit comments

Comments
 (0)