def wait(self): """Wait for instance to respond to ansible ping.""" extra_vars = [ 'ansible_connection=winrm', 'ansible_host=%s' % self.core_ci.connection.hostname, 'ansible_user=%s' % self.core_ci.connection.username, 'ansible_password=%s' % self.core_ci.connection.password, 'ansible_port=%s' % self.core_ci.connection.port, 'ansible_winrm_server_cert_validation=ignore', ] name = 'windows_%s' % self.core_ci.version env = ansible_environment(self.core_ci.args) cmd = ['ansible', '-m', 'win_ping', '-i', '%s,' % name, name, '-e', ' '.join(extra_vars)] for dummy in range(1, 120): try: intercept_command(self.core_ci.args, cmd, 'ping', env=env) return except SubprocessError: time.sleep(10) raise ApplicationError('Timeout waiting for %s/%s instance %s.' % (self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
def wait(self): """Wait for instance to respond to ansible ping.""" extra_vars = [ 'ansible_host=%s' % self.core_ci.connection.hostname, 'ansible_port=%s' % self.core_ci.connection.port, 'ansible_connection=local', 'ansible_ssh_private_key_file=%s' % self.core_ci.ssh_key.key, ] name = '%s-%s' % (self.core_ci.platform, self.core_ci.version.replace('.', '-')) env = ansible_environment(self.core_ci.args) cmd = [ 'ansible', '-m', '%s_command' % self.core_ci.platform, '-a', 'commands=?', '-u', self.core_ci.connection.username, '-i', '%s,' % name, '-e', ' '.join(extra_vars), name, ] for dummy in range(1, 90): try: intercept_command(self.core_ci.args, cmd, 'ping', env=env) return except SubprocessError: time.sleep(10) raise ApplicationError('Timeout waiting for %s/%s instance %s.' % (self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
def wait(self): """Wait for instance to respond to ansible ping.""" extra_vars = [ 'ansible_connection=winrm', 'ansible_host=%s' % self.core_ci.connection.hostname, 'ansible_user=%s' % self.core_ci.connection.username, 'ansible_password=%s' % self.core_ci.connection.password, 'ansible_port=%s' % self.core_ci.connection.port, 'ansible_winrm_server_cert_validation=ignore', ] name = 'windows_%s' % self.core_ci.version env = ansible_environment(self.core_ci.args) cmd = [ 'ansible', '-m', 'win_ping', '-i', '%s,' % name, name, '-e', ' '.join(extra_vars) ] for _ in range(1, 120): try: intercept_command(self.core_ci.args, cmd, 'ping', env=env) return except SubprocessError: sleep(10) continue raise ApplicationError('Timeout waiting for %s/%s instance %s.' % (self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
def wait(self): """Wait for instance to respond to ansible ping.""" extra_vars = [ 'ansible_host=%s' % self.core_ci.connection.hostname, 'ansible_port=%s' % self.core_ci.connection.port, 'ansible_connection=local', 'ansible_ssh_private_key_file=%s' % self.core_ci.ssh_key.key, ] name = '%s-%s' % (self.core_ci.platform, self.core_ci.version.replace('.', '-')) env = ansible_environment(self.core_ci.args) cmd = [ 'ansible', '-m', '%s_command' % self.core_ci.platform, '-a', 'commands=?', '-u', self.core_ci.connection.username, '-i', '%s,' % name, '-e', ' '.join(extra_vars), name, ] for dummy in range(1, 90): try: intercept_command(self.core_ci.args, cmd, 'ping', env=env) return except SubprocessError: time.sleep(10) raise ApplicationError('Timeout waiting for %s/%s instance %s.' % (self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
def command_units(args): """ :type args: UnitsConfig """ changes = get_changes_filter(args) require = (args.require or []) + changes include, exclude = walk_external_targets(walk_units_targets(), args.include, args.exclude, require) if not include: raise AllTargetsSkipped() if args.delegate: raise Delegate(require=changes) install_command_requirements(args) version_commands = [] for version in SUPPORTED_PYTHON_VERSIONS: # run all versions unless version given, in which case run only that version if args.python and version != args.python_version: continue env = ansible_environment(args) cmd = [ 'pytest', '--boxed', '-r', 'a', '--color', 'yes' if args.color else 'no', '--junit-xml', 'test/results/junit/python%s-units.xml' % version, ] if args.collect_only: cmd.append('--collect-only') if args.verbosity: cmd.append('-' + ('v' * args.verbosity)) if exclude: cmd += ['--ignore=%s' % target.path for target in exclude] cmd += [target.path for target in include] version_commands.append((version, cmd, env)) for version, command, env in version_commands: display.info('Unit test with Python %s' % version) try: intercept_command(args, command, target_name='units', env=env, python_version=version) except SubprocessError as ex: # pytest exits with status code 5 when all tests are skipped, which isn't an error for our use case if ex.status != 5: raise
def command_integration_script(args, target): """ :type args: IntegrationConfig :type target: IntegrationTarget """ display.info('Running %s integration test script' % target.name) cmd = ['./%s' % os.path.basename(target.script_path)] if args.verbosity: cmd.append('-' + ('v' * args.verbosity)) env = integration_environment(args, target, cmd) cwd = target.path intercept_command(args, cmd, target_name=target.name, env=env, cwd=cwd)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: SanityResult """ with open('test/sanity/ansible-doc/skip.txt', 'r') as skip_fd: skip_modules = set(skip_fd.read().splitlines()) modules = sorted( set(m for i in targets.include_external for m in i.modules) - set(m for i in targets.exclude_external for m in i.modules) - skip_modules) if not modules: return SanitySkipped(self.name, python_version=python_version) # ansible-doc fails due to async syntax errors on Python 3.7 currently if python_version == '3.7': return SanitySkipped(self.name, python_version=python_version) env = ansible_environment(args, color=False) cmd = ['ansible-doc'] + modules try: stdout, stderr = intercept_command(args, cmd, target_name='ansible-doc', env=env, capture=True, python_version=python_version) status = 0 except SubprocessError as ex: stdout = ex.stdout stderr = ex.stderr status = ex.status if status: summary = u'%s' % SubprocessError( cmd=cmd, status=status, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) if stdout: display.info(stdout.strip(), verbosity=3) if stderr: summary = u'Output on stderr from ansible-doc is considered an error.\n\n%s' % SubprocessError( cmd, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: TestResult """ with open('test/sanity/ansible-doc/skip.txt', 'r') as skip_fd: skip_modules = set(skip_fd.read().splitlines()) modules = sorted(set(m for i in targets.include_external for m in i.modules) - set(m for i in targets.exclude_external for m in i.modules) - skip_modules) if not modules: return SanitySkipped(self.name, python_version=python_version) module_paths = dict((t.module, t.path) for t in targets.targets if t.module) env = ansible_environment(args, color=False) cmd = ['ansible-doc'] + modules try: stdout, stderr = intercept_command(args, cmd, target_name='ansible-doc', env=env, capture=True, python_version=python_version) status = 0 except SubprocessError as ex: stdout = ex.stdout stderr = ex.stderr status = ex.status if stderr: errors = stderr.strip().splitlines() messages = [self.parse_error(e, module_paths) for e in errors] if messages and all(messages): return SanityFailure(self.name, messages=messages, python_version=python_version) if status: summary = u'%s' % SubprocessError(cmd=cmd, status=status, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) if stdout: display.info(stdout.strip(), verbosity=3) if stderr: summary = u'Output on stderr from ansible-doc is considered an error.\n\n%s' % SubprocessError(cmd, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: TestResult """ #skip_file = 'test/sanity/import/skip.txt' skip_file = os.path.join( os.path.dirname(ansible_test.__file__), 'lib/sanity/import/skip.txt' ) skip_paths = read_lines_without_comments(skip_file, remove_blank_lines=True) skip_paths_set = set(skip_paths) paths = sorted( i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' and (i.path.startswith('lib/ansible/modules/') or i.path.startswith('lib/ansible/module_utils/')) and i.path not in skip_paths_set ) if not paths: return SanitySkipped(self.name, python_version=python_version) env = ansible_environment(args, color=False) # create a clean virtual environment to minimize the available imports beyond the python standard library virtual_environment_path = os.path.abspath('test/runner/.tox/minimal-py%s' % python_version.replace('.', '')) virtual_environment_bin = os.path.join(virtual_environment_path, 'bin') remove_tree(virtual_environment_path) python = find_python(python_version) cmd = [python, '-m', 'virtualenv', virtual_environment_path, '--python', python, '--no-setuptools', '--no-wheel'] if not args.coverage: cmd.append('--no-pip') run_command(args, cmd, capture=True) # add the importer to our virtual environment so it can be accessed through the coverage injector importer_path = os.path.join(virtual_environment_bin, 'importer.py') if not args.explain: os.symlink(os.path.abspath('test/sanity/import/importer.py'), importer_path) # create a minimal python library python_path = os.path.abspath('test/runner/.tox/import/lib') ansible_path = os.path.join(python_path, 'ansible') ansible_init = os.path.join(ansible_path, '__init__.py') ansible_link = os.path.join(ansible_path, 'module_utils') if not args.explain: make_dirs(ansible_path) with open(ansible_init, 'w'): pass if not os.path.exists(ansible_link): os.symlink('../../../../../../lib/ansible/module_utils', ansible_link) # activate the virtual environment env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH']) env['PYTHONPATH'] = python_path # make sure coverage is available in the virtual environment if needed if args.coverage: run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['setuptools']), env=env) run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['coverage']), env=env) run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'setuptools'], env=env) run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'pip'], env=env) cmd = ['importer.py'] data = '\n'.join(paths) display.info(data, verbosity=4) results = [] virtualenv_python = os.path.join(virtual_environment_bin, 'python') try: stdout, stderr = intercept_command(args, cmd, self.name, env, capture=True, data=data, python_version=python_version, virtualenv=virtualenv_python) if stdout or stderr: raise SubprocessError(cmd, stdout=stdout, stderr=stderr) except SubprocessError as ex: if ex.status != 10 or ex.stderr or not ex.stdout: raise pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$' results = parse_to_list_of_dict(pattern, ex.stdout) results = [SanityMessage( message=r['message'], path=r['path'], line=int(r['line']), column=int(r['column']), ) for r in results] results = [result for result in results if result.path not in skip_paths_set] if results: return SanityFailure(self.name, messages=results, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: TestResult """ with open('test/sanity/import/skip.txt', 'r') as skip_fd: skip_paths = skip_fd.read().splitlines() skip_paths_set = set(skip_paths) paths = sorted( i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' and (i.path.startswith('lib/ansible/modules/') or i.path.startswith('lib/ansible/module_utils/')) and i.path not in skip_paths_set ) if not paths: return SanitySkipped(self.name, python_version=python_version) env = ansible_environment(args, color=False) # create a clean virtual environment to minimize the available imports beyond the python standard library virtual_environment_path = os.path.abspath('test/runner/.tox/minimal-py%s' % python_version.replace('.', '')) virtual_environment_bin = os.path.join(virtual_environment_path, 'bin') remove_tree(virtual_environment_path) cmd = ['virtualenv', virtual_environment_path, '--python', find_python(python_version), '--no-setuptools', '--no-wheel'] if not args.coverage: cmd.append('--no-pip') run_command(args, cmd, capture=True) # add the importer to our virtual environment so it can be accessed through the coverage injector importer_path = os.path.join(virtual_environment_bin, 'importer.py') if not args.explain: os.symlink(os.path.abspath('test/sanity/import/importer.py'), importer_path) # activate the virtual environment env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH']) env['PYTHONPATH'] = os.path.abspath('test/sanity/import/lib') # make sure coverage is available in the virtual environment if needed if args.coverage: run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['setuptools']), env=env) run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['coverage']), env=env) run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'setuptools'], env=env) run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'pip'], env=env) cmd = ['importer.py'] data = '\n'.join(paths) display.info(data, verbosity=4) results = [] try: stdout, stderr = intercept_command(args, cmd, data=data, target_name=self.name, env=env, capture=True, python_version=python_version, path=env['PATH']) if stdout or stderr: raise SubprocessError(cmd, stdout=stdout, stderr=stderr) except SubprocessError as ex: if ex.status != 10 or ex.stderr or not ex.stdout: raise pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$' results = [re.search(pattern, line).groupdict() for line in ex.stdout.splitlines()] results = [SanityMessage( message=r['message'], path=r['path'], line=int(r['line']), column=int(r['column']), ) for r in results] results = [result for result in results if result.path not in skip_paths] if results: return SanityFailure(self.name, messages=results, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: SanityResult """ with open('test/sanity/import/skip.txt', 'r') as skip_fd: skip_paths = skip_fd.read().splitlines() skip_paths_set = set(skip_paths) paths = sorted( i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' and (i.path.startswith('lib/ansible/modules/') or i.path.startswith( 'lib/ansible/module_utils/')) and i.path not in skip_paths_set) if not paths: return SanitySkipped(self.name, python_version=python_version) env = ansible_environment(args, color=False) # create a clean virtual environment to minimize the available imports beyond the python standard library virtual_environment_path = os.path.abspath( 'test/runner/.tox/minimal-py%s' % python_version.replace('.', '')) virtual_environment_bin = os.path.join(virtual_environment_path, 'bin') remove_tree(virtual_environment_path) cmd = [ 'virtualenv', virtual_environment_path, '--python', 'python%s' % python_version, '--no-setuptools', '--no-wheel' ] if not args.coverage: cmd.append('--no-pip') run_command(args, cmd, capture=True) # add the importer to our virtual environment so it can be accessed through the coverage injector importer_path = os.path.join(virtual_environment_bin, 'importer.py') if not args.explain: os.symlink(os.path.abspath('test/runner/importer.py'), importer_path) # activate the virtual environment env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH']) env['PYTHONPATH'] = os.path.abspath('test/runner/import/lib') # make sure coverage is available in the virtual environment if needed if args.coverage: run_command(args, generate_pip_install('pip', 'sanity.import', packages=['setuptools']), env=env) run_command(args, generate_pip_install('pip', 'sanity.import', packages=['coverage']), env=env) run_command(args, [ 'pip', 'uninstall', '--disable-pip-version-check', '-y', 'setuptools' ], env=env) run_command(args, [ 'pip', 'uninstall', '--disable-pip-version-check', '-y', 'pip' ], env=env) cmd = ['importer.py'] + paths results = [] try: stdout, stderr = intercept_command(args, cmd, target_name=self.name, env=env, capture=True, python_version=python_version, path=env['PATH']) if stdout or stderr: raise SubprocessError(cmd, stdout=stdout, stderr=stderr) except SubprocessError as ex: if ex.status != 10 or ex.stderr or not ex.stdout: raise pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$' results = [ re.search(pattern, line).groupdict() for line in ex.stdout.splitlines() ] results = [ SanityMessage( message=r['message'], path=r['path'], line=int(r['line']), column=int(r['column']), ) for r in results ] results = [ result for result in results if result.path not in skip_paths ] if results: return SanityFailure(self.name, messages=results, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)
def command_integration_role(args, target, start_at_task): """ :type args: IntegrationConfig :type target: IntegrationTarget :type start_at_task: str | None """ display.info('Running %s integration test role' % target.name) vars_file = 'integration_config.yml' if isinstance(args, WindowsIntegrationConfig): inventory = 'inventory.winrm' hosts = 'windows' gather_facts = False elif isinstance(args, NetworkIntegrationConfig): inventory = args.inventory or 'inventory.networking' hosts = target.name[:target.name.find('_')] gather_facts = False else: inventory = 'inventory' hosts = 'testhost' gather_facts = True cloud_environment = get_cloud_environment(args, target) if cloud_environment: hosts = cloud_environment.inventory_hosts or hosts playbook = ''' - hosts: %s gather_facts: %s roles: - { role: %s } ''' % (hosts, gather_facts, target.name) with tempfile.NamedTemporaryFile(dir='test/integration', prefix='%s-' % target.name, suffix='.yml') as pb_fd: pb_fd.write(playbook.encode('utf-8')) pb_fd.flush() filename = os.path.basename(pb_fd.name) display.info('>>> Playbook: %s\n%s' % (filename, playbook.strip()), verbosity=3) cmd = ['ansible-playbook', filename, '-i', inventory, '-e', '@%s' % vars_file] if start_at_task: cmd += ['--start-at-task', start_at_task] if args.tags: cmd += ['--tags', args.tags] if args.skip_tags: cmd += ['--skip-tags', args.skip_tags] if args.diff: cmd += ['--diff'] if args.verbosity: cmd.append('-' + ('v' * args.verbosity)) env = integration_environment(args, target, cmd) cwd = 'test/integration' env['ANSIBLE_ROLES_PATH'] = os.path.abspath('test/integration/targets') intercept_command(args, cmd, target_name=target.name, env=env, cwd=cwd)
def test(self, args, targets, python_version): """ :type args: SanityConfig :type targets: SanityTargets :type python_version: str :rtype: TestResult """ skip_file = 'test/sanity/ansible-doc/skip.txt' skip_modules = set( read_lines_without_comments(skip_file, remove_blank_lines=True)) plugin_type_blacklist = set([ # not supported by ansible-doc 'action', 'cliconf', 'filter', 'httpapi', 'netconf', 'terminal', 'test', ]) modules = sorted( set(m for i in targets.include_external for m in i.modules) - set(m for i in targets.exclude_external for m in i.modules) - skip_modules) plugins = [ os.path.splitext(i.path)[0].split('/')[-2:] + [i.path] for i in targets.include if os.path.splitext(i.path)[1] == '.py' and os.path.basename(i.path) != '__init__.py' and re.search(r'^lib/ansible/plugins/[^/]+/', i.path) and i.path != 'lib/ansible/plugins/cache/base.py' ] doc_targets = collections.defaultdict(list) target_paths = collections.defaultdict(dict) for module in modules: doc_targets['module'].append(module) for plugin_type, plugin_name, plugin_path in plugins: if plugin_type in plugin_type_blacklist: continue doc_targets[plugin_type].append(plugin_name) target_paths[plugin_type][plugin_name] = plugin_path if not doc_targets: return SanitySkipped(self.name, python_version=python_version) target_paths['module'] = dict( (t.module, t.path) for t in targets.targets if t.module) env = ansible_environment(args, color=False) error_messages = [] for doc_type in sorted(doc_targets): cmd = ['ansible-doc', '-t', doc_type] + sorted( doc_targets[doc_type]) try: stdout, stderr = intercept_command( args, cmd, target_name='ansible-doc', env=env, capture=True, python_version=python_version) status = 0 except SubprocessError as ex: stdout = ex.stdout stderr = ex.stderr status = ex.status if stderr: errors = stderr.strip().splitlines() messages = [self.parse_error(e, target_paths) for e in errors] if messages and all(messages): error_messages += messages continue if status: summary = u'%s' % SubprocessError( cmd=cmd, status=status, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) if stdout: display.info(stdout.strip(), verbosity=3) if stderr: summary = u'Output on stderr from ansible-doc is considered an error.\n\n%s' % SubprocessError( cmd, stderr=stderr) return SanityFailure(self.name, summary=summary, python_version=python_version) if error_messages: return SanityFailure(self.name, messages=error_messages, python_version=python_version) return SanitySuccess(self.name, python_version=python_version)