diff --git a/.travis.yml b/.travis.yml index 4aed8d0a..1f8c5c6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,11 +17,21 @@ install: - pip install -r dev_requirements.txt script: -- ${TRAVIS_BUILD_DIR}/.travis/${MODE}_tests.sh +- | + if [ -f "${TRAVIS_BUILD_DIR}/.travis/${MODE}_tests.sh" ]; then + ${TRAVIS_BUILD_DIR}/.travis/${MODE}_tests.sh; + else + ${TRAVIS_BUILD_DIR}/.travis/${MODE}_tests.py; + fi + services: - docker + +# To avoid matrix explosion, just test against oldest->newest and +# newest->oldest in various configuartions. + matrix: include: # Mitogen tests. @@ -34,85 +44,32 @@ matrix: # 2.6 -> 2.7 - python: "2.6" env: MODE=mitogen DISTRO=centos7 - # 2.6 -> 2.6 - - python: "2.6" - env: MODE=mitogen DISTRO=centos6 - # 3.6 -> 2.7 + # 3.6 -> 2.6 - python: "3.6" - env: MODE=mitogen DISTRO=debian + env: MODE=mitogen DISTRO=centos6 # Debops tests. - # 2.4.3.0; 2.7 -> 2.7 + # 2.4.6.0; 2.7 -> 2.7 - python: "2.7" - env: MODE=debops_common VER=2.4.3.0 - # 2.5.5; 2.7 -> 2.7 - - python: "2.7" - env: MODE=debops_common VER=2.6.1 - # 2.5.5; 3.6 -> 2.7 + env: MODE=debops_common VER=2.4.6.0 + # 2.5.7; 3.6 -> 2.7 - python: "3.6" - env: MODE=debops_common VER=2.6.1 + env: MODE=debops_common VER=2.6.2 # ansible_mitogen tests. - # 2.4.3.0; Debian; 2.7 -> 2.7 - - python: "2.7" - env: MODE=ansible VER=2.4.3.0 DISTRO=debian - # 2.5.5; Debian; 2.7 -> 2.7 - - python: "2.7" - env: MODE=ansible VER=2.5.5 DISTRO=debian - # 2.6.0; Debian; 2.7 -> 2.7 - - python: "2.7" - env: MODE=ansible VER=2.6.0 DISTRO=debian - # 2.6.1; Debian; 2.7 -> 2.7 - - python: "2.7" - env: MODE=ansible VER=2.6.1 DISTRO=debian - # Centos 7 Python2 - # Latest + # 2.6 -> {debian, centos6, centos7} - python: "2.6" - env: MODE=ansible VER=2.6.1 DISTRO=centos7 - # Backward Compatiability - - python: "2.7" - env: MODE=ansible VER=2.5.5 DISTRO=centos7 - - python: "2.7" - env: MODE=ansible VER=2.6.0 DISTRO=centos7 - - python: "2.7" - env: MODE=ansible VER=2.6.1 DISTRO=centos7 - - # Centos 7 Python3 - - python: "3.6" - env: MODE=ansible VER=2.5.5 DISTRO=centos7 - - python: "3.6" - env: MODE=ansible VER=2.6.0 DISTRO=centos7 - - python: "3.6" - env: MODE=ansible VER=2.6.1 DISTRO=centos7 - - - # Centos 6 Python2 - # Latest + env: MODE=ansible VER=2.4.6.0 - python: "2.6" - env: MODE=ansible VER=2.6.1 DISTRO=centos6 - # Backward Compatiability - - python: "2.6" - env: MODE=ansible VER=2.5.5 DISTRO=centos6 - - python: "2.6" - env: MODE=ansible VER=2.6.0 DISTRO=centos6 - - python: "2.7" - env: MODE=ansible VER=2.6.1 DISTRO=centos6 + env: MODE=ansible VER=2.6.2 - # Centos 6 Python3 + # 3.6 -> {debian, centos6, centos7} - python: "3.6" - env: MODE=ansible VER=2.5.5 DISTRO=centos6 + env: MODE=ansible VER=2.4.6.0 - python: "3.6" - env: MODE=ansible VER=2.6.0 DISTRO=centos6 - - python: "3.6" - env: MODE=ansible VER=2.6.1 DISTRO=centos6 + env: MODE=ansible VER=2.6.2 - # Sanity check our tests against vanilla Ansible, they should pass. + # Sanity check against vanilla Ansible. One job suffices. - python: "2.7" - env: MODE=ansible VER=2.5.5 DISTRO=debian STRATEGY=linear - - python: "2.7" - env: MODE=ansible VER=2.6.0 DISTRO=debian STRATEGY=linear - - python: "2.7" - env: MODE=ansible VER=2.6.1 DISTRO=debian STRATEGY=linear - - + env: MODE=ansible VER=2.6.2 DISTRO=debian STRATEGY=linear diff --git a/.travis/ansible_tests.py b/.travis/ansible_tests.py new file mode 100755 index 00000000..0c47ab27 --- /dev/null +++ b/.travis/ansible_tests.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# Run tests/ansible/all.yml under Ansible and Ansible-Mitogen + +import os +import sys + +import ci_lib +from ci_lib import run + + +BASE_PORT = 2201 +TESTS_DIR = os.path.join(ci_lib.GIT_ROOT, 'tests/ansible') +HOSTS_DIR = os.path.join(ci_lib.TMP, 'hosts') + + +with ci_lib.Fold('docker_setup'): + for i, distro in enumerate(ci_lib.DISTROS): + try: + run("docker rm -f target-%s", distro) + except: pass + + run(""" + docker run + --rm + --detach + --publish 0.0.0.0:%s:22/tcp + --name=target-%s + mitogen/%s-test + """, BASE_PORT + i, distro, distro,) + + +with ci_lib.Fold('job_setup'): + os.chdir(TESTS_DIR) + os.chmod('../data/docker/mitogen__has_sudo_pubkey.key', int('0600', 7)) + + # Don't set -U as that will upgrade Paramiko to a non-2.6 compatible version. + run("pip install -q ansible==%s", ci_lib.ANSIBLE_VERSION) + + run("mkdir %s", HOSTS_DIR) + run("ln -s %s/common-hosts %s", TESTS_DIR, HOSTS_DIR) + + with open(os.path.join(HOSTS_DIR, 'target'), 'w') as fp: + fp.write('[test-targets]\n') + for i, distro in enumerate(ci_lib.DISTROS): + fp.write("target-%s " + "ansible_host=%s " + "ansible_port=%s " + "ansible_user=mitogen__has_sudo_nopw " + "ansible_password=has_sudo_nopw_password" + "\n" % ( + distro, + ci_lib.DOCKER_HOSTNAME, + BASE_PORT + i, + )) + + # Build the binaries. + run("make -C %s", TESTS_DIR) + if not ci_lib.exists_in_path('sshpass'): + run("sudo apt-get update") + run("sudo apt-get install -y sshpass") + + +with ci_lib.Fold('ansible'): + run('/usr/bin/time ./run_ansible_playbook.sh all.yml -i "%s" %s', + HOSTS_DIR, ' '.join(sys.argv[1:])) diff --git a/.travis/ansible_tests.sh b/.travis/ansible_tests.sh deleted file mode 100755 index bc119149..00000000 --- a/.travis/ansible_tests.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -ex -# Run tests/ansible/all.yml under Ansible and Ansible-Mitogen - -TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-`pwd`}" -TMPDIR="/tmp/ansible-tests-$$" -ANSIBLE_VERSION="${VER:-2.6.1}" -export ANSIBLE_STRATEGY="${STRATEGY:-mitogen_linear}" -DISTRO="${DISTRO:-debian}" - -export PYTHONPATH="${PYTHONPATH}:${TRAVIS_BUILD_DIR}" - -# SSH passes these through to the container when run interactively, causing -# stdout to get messed up with libc warnings. -unset LANG LC_ALL - -function on_exit() -{ - rm -rf "$TMPDIR" - docker kill target || true -} - -trap on_exit EXIT -mkdir "$TMPDIR" - - -echo travis_fold:start:docker_setup -DOCKER_HOSTNAME="$(python ${TRAVIS_BUILD_DIR}/tests/show_docker_hostname.py)" - -docker run \ - --rm \ - --detach \ - --publish 0.0.0.0:2201:22/tcp \ - --name=target \ - mitogen/${DISTRO}-test -echo travis_fold:end:docker_setup - - -echo travis_fold:start:job_setup -pip install ansible=="${ANSIBLE_VERSION}" -cd ${TRAVIS_BUILD_DIR}/tests/ansible - -chmod go= ${TRAVIS_BUILD_DIR}/tests/data/docker/mitogen__has_sudo_pubkey.key -mkdir ${TMPDIR}/hosts -ln -s ${TRAVIS_BUILD_DIR}/tests/ansible/common-hosts ${TMPDIR}/hosts/common-hosts -echo '[test-targets]' > ${TMPDIR}/hosts/target -echo \ - target \ - ansible_host=$DOCKER_HOSTNAME \ - ansible_port=2201 \ - ansible_user=mitogen__has_sudo_nopw \ - ansible_password=has_sudo_nopw_password \ - >> ${TMPDIR}/hosts/target - -# Build the binaries. -make -C ${TRAVIS_BUILD_DIR}/tests/ansible - -[ ! "$(type -p sshpass)" ] && sudo apt install -y sshpass - -echo travis_fold:end:job_setup - - -echo travis_fold:start:ansible -/usr/bin/time ./run_ansible_playbook.sh \ - all.yml \ - -i "${TMPDIR}/hosts" "$@" -echo travis_fold:end:ansible diff --git a/.travis/ci_lib.py b/.travis/ci_lib.py new file mode 100644 index 00000000..828cae39 --- /dev/null +++ b/.travis/ci_lib.py @@ -0,0 +1,100 @@ + +from __future__ import absolute_import +from __future__ import print_function + +import atexit +import os +import subprocess +import sys +import shlex +import shutil +import tempfile + + +# +# check_output() monkeypatch cutpasted from testlib.py +# + +def subprocess__check_output(*popenargs, **kwargs): + # Missing from 2.6. + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, _ = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise subprocess.CalledProcessError(retcode, cmd) + return output + +if not hasattr(subprocess, 'check_output'): + subprocess.check_output = subprocess__check_output + +# ----------------- + +def _argv(s, *args): + if args: + s %= args + return shlex.split(s) + + +def run(s, *args, **kwargs): + argv = _argv(s, *args) + print('Running: %s' % (argv,)) + return subprocess.check_call(argv, **kwargs) + + +def get_output(s, *args, **kwargs): + argv = _argv(s, *args) + print('Running: %s' % (argv,)) + return subprocess.check_output(argv, **kwargs) + + +def exists_in_path(progname): + return any(os.path.exists(os.path.join(dirname, progname)) + for dirname in os.environ['PATH'].split(os.pathsep)) + + +class TempDir(object): + def __init__(self): + self.path = tempfile.mkdtemp(prefix='mitogen_ci_lib') + atexit.register(self.destroy) + + def destroy(self, rmtree=shutil.rmtree): + rmtree(self.path) + + +class Fold(object): + def __init__(self, name): + self.name = name + + def __enter__(self): + print('travis_fold:start:%s' % (self.name)) + + def __exit__(self, _1, _2, _3): + print('') + print('travis_fold:end:%s' % (self.name)) + + +os.environ.setdefault('ANSIBLE_STRATEGY', + os.environ.get('STRATEGY', 'mitogen_linear')) +ANSIBLE_VERSION = os.environ.get('VER', '2.6.2') +GIT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +DISTROS = os.environ.get('DISTROS', 'debian centos6 centos7').split() +TMP = TempDir().path + +os.environ['PYTHONDONTWRITEBYTECODE'] = 'x' +os.environ['PYTHONPATH'] = '%s:%s' % ( + os.environ.get('PYTHONPATH', ''), + GIT_ROOT +) + +DOCKER_HOSTNAME = subprocess.check_output([ + sys.executable, + os.path.join(GIT_ROOT, 'tests/show_docker_hostname.py'), +]).decode().strip() + +# SSH passes these through to the container when run interactively, causing +# stdout to get messed up with libc warnings. +os.environ.pop('LANG', None) +os.environ.pop('LC_ALL', None) diff --git a/tests/ansible/integration/runner/etc_environment.yml b/tests/ansible/integration/runner/etc_environment.yml index c1195b75..68ec980a 100644 --- a/tests/ansible/integration/runner/etc_environment.yml +++ b/tests/ansible/integration/runner/etc_environment.yml @@ -41,8 +41,8 @@ - file: path: /etc/environment - become: true state: absent + become: true - shell: echo $MAGIC_ETC_ENV register: echo @@ -52,9 +52,9 @@ - copy: dest: /etc/environment - become: true content: | MAGIC_ETC_ENV=555 + become: true - shell: echo $MAGIC_ENV_ENV register: echo @@ -64,5 +64,5 @@ - file: path: /etc/environment - become: true state: absent + become: true diff --git a/tests/image_prep/setup.yml b/tests/image_prep/setup.yml index 168d583c..7a589239 100644 --- a/tests/image_prep/setup.yml +++ b/tests/image_prep/setup.yml @@ -6,8 +6,8 @@ # Hacktacular.. but easiest place for it with current structure. sudo_group: MacOSX: admin - Debian: wheel - CentOS: sudo + Debian: sudo + CentOS: wheel - import_playbook: _container_setup.yml - import_playbook: _user_accounts.yml