Merge remote-tracking branch 'origin/dmw'

- 3.x target test job support
- new 2.x->3.x Mitogen job
- 3.x runner regression
- 3.x importer regression
- #109
- #391
issue510
David Wilson 6 years ago
commit 9177764c3b

@ -14,7 +14,7 @@ batches = [
] ]
batches.extend( batches.extend(
['docker pull mitogen/%s-test' % (distro,)] ['docker pull %s' % (ci_lib.image_for_distro(distro),)]
for distro in ci_lib.DISTROS for distro in ci_lib.DISTROS
) )

@ -32,12 +32,14 @@ with ci_lib.Fold('job_setup'):
run("mkdir %s", HOSTS_DIR) run("mkdir %s", HOSTS_DIR)
run("ln -s %s/hosts/common-hosts %s", TESTS_DIR, HOSTS_DIR) run("ln -s %s/hosts/common-hosts %s", TESTS_DIR, HOSTS_DIR)
with open(os.path.join(HOSTS_DIR, 'target'), 'w') as fp: inventory_path = os.path.join(HOSTS_DIR, 'target')
with open(inventory_path, 'w') as fp:
fp.write('[test-targets]\n') fp.write('[test-targets]\n')
fp.writelines( fp.writelines(
"%(name)s " "%(name)s "
"ansible_host=%(hostname)s " "ansible_host=%(hostname)s "
"ansible_port=%(port)s " "ansible_port=%(port)s "
"ansible_python_interpreter=%(python_path)s "
"ansible_user=mitogen__has_sudo_nopw " "ansible_user=mitogen__has_sudo_nopw "
"ansible_password=has_sudo_nopw_password" "ansible_password=has_sudo_nopw_password"
"\n" "\n"
@ -45,8 +47,8 @@ with ci_lib.Fold('job_setup'):
for container in containers for container in containers
) )
# Build the binaries. ci_lib.dump_file(inventory_path)
# run("make -C %s", TESTS_DIR)
if not ci_lib.exists_in_path('sshpass'): if not ci_lib.exists_in_path('sshpass'):
run("sudo apt-get update") run("sudo apt-get update")
run("sudo apt-get install -y sshpass") run("sudo apt-get install -y sshpass")

@ -142,14 +142,26 @@ def get_docker_hostname():
return parsed.netloc.partition(':')[0] return parsed.netloc.partition(':')[0]
def image_for_distro(distro):
return 'mitogen/%s-test' % (distro.partition('-')[0],)
def make_containers(): def make_containers():
docker_hostname = get_docker_hostname() docker_hostname = get_docker_hostname()
firstbit = lambda s: (s+'-').split('-')[0]
secondbit = lambda s: (s+'-').split('-')[1]
return [ return [
{ {
"distro": distro, "distro": firstbit(distro),
"name": "target-%s-%s" % (distro, i), "name": "target-%s-%s" % (distro, i),
"hostname": docker_hostname, "hostname": docker_hostname,
"port": BASE_PORT + i, "port": BASE_PORT + i,
"python_path": (
'/usr/bin/python3'
if secondbit(distro) == 'py3'
else '/usr/bin/python'
)
} }
for i, distro in enumerate(DISTROS, 1) for i, distro in enumerate(DISTROS, 1)
] ]
@ -173,6 +185,16 @@ def start_containers(containers):
return containers return containers
def dump_file(path):
print()
print('--- %s ---' % (path,))
print()
with open(path, 'r') as fp:
print(fp.read().rstrip())
print('---')
print()
# SSH passes these through to the container when run interactively, causing # SSH passes these through to the container when run interactively, causing
# stdout to get messed up with libc warnings. # stdout to get messed up with libc warnings.
os.environ.pop('LANG', None) os.environ.pop('LANG', None)

@ -13,6 +13,6 @@ ci_lib.run_batches([
'pip install -qqqU debops==0.7.2 ansible==%s' % ci_lib.ANSIBLE_VERSION, 'pip install -qqqU debops==0.7.2 ansible==%s' % ci_lib.ANSIBLE_VERSION,
], ],
[ [
'docker pull mitogen/debian-test', 'docker pull %s' % (ci_lib.image_for_distro('debian'),),
], ],
]) ])

@ -55,6 +55,7 @@ with ci_lib.Fold('job_setup'):
'%(name)s ' '%(name)s '
'ansible_host=%(hostname)s ' 'ansible_host=%(hostname)s '
'ansible_port=%(port)d ' 'ansible_port=%(port)d '
'ansible_python_interpreter=%(python_path)s '
'\n' '\n'
% container % container
for container in containers for container in containers

@ -8,7 +8,7 @@ batches = [
'pip install -r tests/requirements.txt', 'pip install -r tests/requirements.txt',
], ],
[ [
'docker pull mitogen/%s-test' % (ci_lib.DISTRO,), 'docker pull %s' % (ci_lib.image_for_distro(ci_lib.DISTRO),),
] ]
] ]

@ -15,7 +15,7 @@ batches.append([
]) ])
batches.extend( batches.extend(
['docker pull mitogen/%s-test' % (distro,)] ['docker pull %s' % (ci_lib.image_for_distro(distro),)]
for distro in ci_lib.DISTROS for distro in ci_lib.DISTROS
) )

@ -32,6 +32,9 @@ matrix:
# 2.6 -> 2.7 # 2.6 -> 2.7
- python: "2.6" - python: "2.6"
env: MODE=mitogen DISTRO=centos7 env: MODE=mitogen DISTRO=centos7
# 2.6 -> 3.5
- python: "2.6"
env: MODE=mitogen DISTRO=debian-py3
# 3.6 -> 2.6 # 3.6 -> 2.6
- python: "3.6" - python: "3.6"
env: MODE=mitogen DISTRO=centos6 env: MODE=mitogen DISTRO=centos6

@ -255,7 +255,7 @@ class Runner(object):
self.service_context = service_context self.service_context = service_context
self.econtext = econtext self.econtext = econtext
self.detach = detach self.detach = detach
self.args = json.loads(json_args) self.args = json.loads(mitogen.core.to_text(json_args))
self.good_temp_dir = good_temp_dir self.good_temp_dir = good_temp_dir
self.extra_env = extra_env self.extra_env = extra_env
self.env = env self.env = env

@ -176,6 +176,11 @@ Fixes
print a useful hint on failure, as no useful error is normally logged to the print a useful hint on failure, as no useful error is normally logged to the
console by these tools. console by these tools.
* `#391 <https://github.com/dw/mitogen/issues/391>`_: file transfer from 2.x
controllers to 3.x targets was broken due to a regression caused by
refactoring, and compounded by `#426
<https://github.com/dw/mitogen/issues/426>`_.
* `#400 <https://github.com/dw/mitogen/issues/400>`_: work around a threading * `#400 <https://github.com/dw/mitogen/issues/400>`_: work around a threading
bug in the AWX display callback when running with high verbosity setting. bug in the AWX display callback when running with high verbosity setting.
@ -210,6 +215,12 @@ Core Library
receivers to wake with :class:`mitogen.core.ChannelError`, even when one receivers to wake with :class:`mitogen.core.ChannelError`, even when one
participant is not a parent of the other. participant is not a parent of the other.
* `#109 <https://github.com/dw/mitogen/issues/109>`_,
`57504ba6 <https://github.com/dw/mitogen/commit/57504ba6>`_: newer Python 3
releases explicitly populate :data:`sys.meta_path` with importer internals,
causing Mitogen to install itself at the end of the importer chain rather
than the front.
* `#387 <https://github.com/dw/mitogen/issues/387>`_, * `#387 <https://github.com/dw/mitogen/issues/387>`_,
`#413 <https://github.com/dw/mitogen/issues/413>`_: dead messages include an `#413 <https://github.com/dw/mitogen/issues/413>`_: dead messages include an
optional reason in their body. This is used to cause optional reason in their body. This is used to cause

@ -2791,7 +2791,7 @@ class ExternalContext(object):
self.importer = importer self.importer = importer
self.router.importer = importer self.router.importer = importer
sys.meta_path.append(self.importer) sys.meta_path.insert(0, self.importer)
def _setup_package(self): def _setup_package(self):
global mitogen global mitogen

@ -787,12 +787,12 @@ class FileService(Service):
raise IOError('%r is not a regular file.' % (path,)) raise IOError('%r is not a regular file.' % (path,))
return { return {
'size': st.st_size, u'size': st.st_size,
'mode': st.st_mode, u'mode': st.st_mode,
'owner': self._name_or_none(pwd.getpwuid, 0, 'pw_name'), u'owner': self._name_or_none(pwd.getpwuid, 0, 'pw_name'),
'group': self._name_or_none(grp.getgrgid, 0, 'gr_name'), u'group': self._name_or_none(grp.getgrgid, 0, 'gr_name'),
'mtime': st.st_mtime, u'mtime': st.st_mtime,
'atime': st.st_atime, u'atime': st.st_atime,
} }
def on_shutdown(self): def on_shutdown(self):

@ -5,11 +5,11 @@
tasks: tasks:
- name: Make 32MiB file - name: Make 32MiB file
connection: local delegate_to: localhost
shell: openssl rand 33554432 > /tmp/bigfile.in shell: openssl rand 33554432 > /tmp/bigfile.in
- name: Make 320MiB file - name: Make 320MiB file
connection: local delegate_to: localhost
shell: > shell: >
cat cat
/tmp/bigfile.in /tmp/bigfile.in
@ -47,21 +47,21 @@
file: file:
path: "{{item}}" path: "{{item}}"
state: absent state: absent
connection: local delegate_to: localhost
become: true become: true
with_items: with_items:
- /tmp/bigfile.out - /tmp/bigfile.out
- /tmp/bigbigfile.out - /tmp/bigbigfile.out
- name: Copy 32MiB file via localhost sudo - name: Copy 32MiB file via localhost sudo
connection: local delegate_to: localhost
become: true become: true
copy: copy:
src: /tmp/bigfile.in src: /tmp/bigfile.in
dest: /tmp/bigfile.out dest: /tmp/bigfile.out
- name: Copy 320MiB file via localhost sudo - name: Copy 320MiB file via localhost sudo
connection: local delegate_to: localhost
become: true become: true
copy: copy:
src: /tmp/bigbigfile.in src: /tmp/bigbigfile.in

@ -12,7 +12,7 @@ class MyError(Exception):
def get_sentinel_value(): def get_sentinel_value():
# Some proof we're even talking to the mitogen-test Docker image # Some proof we're even talking to the mitogen-test Docker image
return open('/etc/sentinel').read().decode() return open('/etc/sentinel', 'rb').read().decode()
def add(x, y): def add(x, y):

@ -233,6 +233,7 @@ class IterReadTest(testlib.TestCase):
func = staticmethod(mitogen.parent.iter_read) func = staticmethod(mitogen.parent.iter_read)
def make_proc(self): def make_proc(self):
# I produce text every 100ms.
args = [testlib.data_path('iter_read_generator.py')] args = [testlib.data_path('iter_read_generator.py')]
proc = subprocess.Popen(args, stdout=subprocess.PIPE) proc = subprocess.Popen(args, stdout=subprocess.PIPE)
mitogen.core.set_nonblock(proc.stdout.fileno()) mitogen.core.set_nonblock(proc.stdout.fileno())
@ -267,18 +268,22 @@ class IterReadTest(testlib.TestCase):
def test_deadline_exceeded_during_call(self): def test_deadline_exceeded_during_call(self):
proc = self.make_proc() proc = self.make_proc()
reader = self.func([proc.stdout.fileno()], time.time() + 0.4) deadline = time.time() + 0.4
reader = self.func([proc.stdout.fileno()], deadline)
try: try:
got = [] got = []
try: try:
for chunk in reader: for chunk in reader:
if time.time() > (deadline + 1.0):
assert 0, 'TimeoutError not raised'
got.append(chunk) got.append(chunk)
assert 0, 'TimeoutError not raised'
except mitogen.core.TimeoutError: except mitogen.core.TimeoutError:
# Give a little wiggle room in case of imperfect scheduling. # Give a little wiggle room in case of imperfect scheduling.
# Ideal number should be 9. # Ideal number should be 9.
self.assertLess(3, len(got)) self.assertLess(deadline, time.time())
self.assertLess(len(got), 5) self.assertLess(1, len(got))
self.assertLess(len(got), 20)
finally: finally:
proc.terminate() proc.terminate()
proc.stdout.close() proc.stdout.close()

@ -331,13 +331,17 @@ def get_docker_host():
class DockerizedSshDaemon(object): class DockerizedSshDaemon(object):
image = None distro, _, _py3 = (
os.environ.get('MITOGEN_TEST_DISTRO', 'debian')
def get_image(self): .partition('-')
if not self.image: )
distro = os.environ.get('MITOGEN_TEST_DISTRO', 'debian')
self.image = 'mitogen/%s-test' % (distro,) python_path = (
return self.image '/usr/bin/python3'
if _py3 == 'py3'
else '/usr/bin/python'
)
image = 'mitogen/%s-test' % (distro,)
# 22/tcp -> 0.0.0.0:32771 # 22/tcp -> 0.0.0.0:32771
PORT_RE = re.compile(r'([^/]+)/([^ ]+) -> ([^:]+):(.*)') PORT_RE = re.compile(r'([^/]+)/([^ ]+) -> ([^:]+):(.*)')
@ -363,7 +367,7 @@ class DockerizedSshDaemon(object):
'--privileged', '--privileged',
'--publish-all', '--publish-all',
'--name', self.container_name, '--name', self.container_name,
self.get_image() self.image,
] ]
subprocess__check_output(args) subprocess__check_output(args)
self._get_container_port() self._get_container_port()
@ -423,6 +427,7 @@ class DockerMixin(RouterMixin):
kwargs.setdefault('port', self.dockerized_ssh.port) kwargs.setdefault('port', self.dockerized_ssh.port)
kwargs.setdefault('check_host_keys', 'ignore') kwargs.setdefault('check_host_keys', 'ignore')
kwargs.setdefault('ssh_debug_level', 3) kwargs.setdefault('ssh_debug_level', 3)
kwargs.setdefault('python_path', self.dockerized_ssh.python_path)
return self.router.ssh(**kwargs) return self.router.ssh(**kwargs)
def docker_ssh_any(self, **kwargs): def docker_ssh_any(self, **kwargs):

Loading…
Cancel
Save