def on_failure(self, target, tries): """ :type target: TestTarget :type tries: int """ if not tries and self.managed: display.notice('%s failed' % target.name)
def setup(self): """Setup the cloud resource before delegation and register a cleanup callback.""" super(GcpCloudProvider, self).setup() if not self._use_static_config(): display.notice( 'static configuration could not be used. are you missing a template file?' )
def on_failure(self, target, tries): """ :type target: TestTarget :type tries: int """ if not tries and self.managed: display.notice('If %s failed due to permissions, the IAM test policy may need to be updated. ' 'For help, consult @mattclay or @gundalow on GitHub or #ansible-devel on IRC.' % target.name)
def on_failure(self, target, tries): """ :type target: TestTarget :type tries: int """ if not tries and self.managed: display.notice('If %s failed due to permissions, the test policy may need to be updated. ' 'For help, consult @mattclay or @gundalow on GitHub or #ansible-devel on IRC.' % target.name)
def _setup_dynamic(self): """Create a CloudStack simulator using docker.""" config = self._read_config_template() self.container_name = self.DOCKER_SIMULATOR_NAME results = docker_inspect(self.args, self.container_name) if results and not results[0]['State']['Running']: docker_rm(self.args, self.container_name) results = [] if results: display.info('Using the existing CloudStack simulator docker container.', verbosity=1) else: display.info('Starting a new CloudStack simulator docker container.', verbosity=1) docker_pull(self.args, self.image) docker_run(self.args, self.image, ['-d', '-p', '8888:8888', '--name', self.container_name]) if not self.args.explain: display.notice('The CloudStack simulator will probably be ready in 5 - 10 minutes.') container_id = get_docker_container_id() if container_id: display.info('Running in docker container: %s' % container_id, verbosity=1) self.host = self._get_simulator_address() display.info('Found CloudStack simulator container address: %s' % self.host, verbosity=1) else: self.host = 'localhost' self.port = 8888 self.endpoint = 'http://%s:%d' % (self.host, self.port) self._wait_for_service() if self.args.explain: values = dict( HOST=self.host, PORT=str(self.port), ) else: credentials = self._get_credentials() if self.args.docker: host = self.DOCKER_SIMULATOR_NAME else: host = self.host values = dict( HOST=host, PORT=str(self.port), KEY=credentials['apikey'], SECRET=credentials['secretkey'], ) config = self._populate_config_template(config, values) self._write_config(config)
def cleanup(self): """Clean up the cloud resource and any temporary configuration files after tests complete.""" if self.container_name: if is_shippable(): docker_rm(self.args, self.container_name) elif not self.args.explain: display.notice('Remember to run `docker rm -f %s` when finished testing.' % self.container_name) super(CsCloudProvider, self).cleanup()
def command_integration_filtered(args, targets, all_targets): """ :type args: IntegrationConfig :type targets: tuple[IntegrationTarget] :type all_targets: tuple[IntegrationTarget] """ found = False passed = [] failed = [] targets_iter = iter(targets) all_targets_dict = dict((target.name, target) for target in all_targets) setup_errors = [] setup_targets_executed = set() for target in all_targets: for setup_target in target.setup_once + target.setup_always: if setup_target not in all_targets_dict: setup_errors.append('Target "%s" contains invalid setup target: %s' % (target.name, setup_target)) if setup_errors: raise ApplicationError('Found %d invalid setup aliases:\n%s' % (len(setup_errors), '\n'.join(setup_errors))) test_dir = os.path.expanduser('~/ansible_testing') if not args.explain and any('needs/ssh/' in target.aliases for target in targets): max_tries = 20 display.info('SSH service required for tests. Checking to make sure we can connect.') for i in range(1, max_tries + 1): try: run_command(args, ['ssh', '-o', 'BatchMode=yes', 'localhost', 'id'], capture=True) display.info('SSH service responded.') break except SubprocessError: if i == max_tries: raise seconds = 3 display.warning('SSH service not responding. Waiting %d second(s) before checking again.' % seconds) time.sleep(seconds) start_at_task = args.start_at_task results = {} for target in targets_iter: if args.start_at and not found: found = target.name == args.start_at if not found: continue if args.list_targets: print(target.name) continue tries = 2 if args.retry_on_error else 1 verbosity = args.verbosity cloud_environment = get_cloud_environment(args, target) original_environment = EnvironmentDescription(args) display.info('>>> Environment Description\n%s' % original_environment, verbosity=3) try: while tries: tries -= 1 try: run_setup_targets(args, test_dir, target.setup_once, all_targets_dict, setup_targets_executed, False) start_time = time.time() run_setup_targets(args, test_dir, target.setup_always, all_targets_dict, setup_targets_executed, True) if not args.explain: # create a fresh test directory for each test target remove_tree(test_dir) make_dirs(test_dir) if target.script_path: command_integration_script(args, target) else: command_integration_role(args, target, start_at_task) start_at_task = None end_time = time.time() results[target.name] = dict( name=target.name, type=target.type, aliases=target.aliases, modules=target.modules, run_time_seconds=int(end_time - start_time), setup_once=target.setup_once, setup_always=target.setup_always, coverage=args.coverage, coverage_label=args.coverage_label, python_version=args.python_version, ) break except SubprocessError: if cloud_environment: cloud_environment.on_failure(target, tries) if not original_environment.validate(target.name, throw=False): raise if not tries: raise display.warning('Retrying test target "%s" with maximum verbosity.' % target.name) display.verbosity = args.verbosity = 6 original_environment.validate(target.name, throw=True) passed.append(target) except Exception as ex: failed.append(target) if args.continue_on_error: display.error(ex) continue display.notice('To resume at this test target, use the option: --start-at %s' % target.name) next_target = next(targets_iter, None) if next_target: display.notice('To resume after this test target, use the option: --start-at %s' % next_target.name) raise finally: display.verbosity = args.verbosity = verbosity if not args.explain: results_path = 'test/results/data/%s-%s.json' % (args.command, re.sub(r'[^0-9]', '-', str(datetime.datetime.utcnow().replace(microsecond=0)))) data = dict( targets=results, ) with open(results_path, 'w') as results_fd: results_fd.write(json.dumps(data, sort_keys=True, indent=4)) if failed: raise ApplicationError('The %d integration test(s) listed below (out of %d) failed. See error output above for details:\n%s' % ( len(failed), len(passed) + len(failed), '\n'.join(target.name for target in failed)))
def categorize_changes(args, paths, verbose_command=None): """ :type args: TestConfig :type paths: list[str] :type verbose_command: str :rtype: ChangeDescription """ mapper = PathMapper(args) commands = { 'sanity': set(), 'units': set(), 'integration': set(), 'windows-integration': set(), 'network-integration': set(), } focused_commands = collections.defaultdict(set) deleted_paths = set() original_paths = set() additional_paths = set() no_integration_paths = set() for path in paths: if not os.path.exists(path): deleted_paths.add(path) continue original_paths.add(path) dependent_paths = mapper.get_dependent_paths(path) if not dependent_paths: continue display.info('Expanded "%s" to %d dependent file(s):' % (path, len(dependent_paths)), verbosity=2) for dependent_path in dependent_paths: display.info(dependent_path, verbosity=2) additional_paths.add(dependent_path) additional_paths -= set(paths) # don't count changed paths as additional paths if additional_paths: display.info('Expanded %d changed file(s) into %d additional dependent file(s).' % (len(paths), len(additional_paths))) paths = sorted(set(paths) | additional_paths) display.info('Mapping %d changed file(s) to tests.' % len(paths)) none_count = 0 for path in paths: tests = mapper.classify(path) if tests is None: focused_target = False display.info('%s -> all' % path, verbosity=1) tests = all_tests(args) # not categorized, run all tests display.warning('Path not categorized: %s' % path) else: focused_target = tests.pop(FOCUSED_TARGET, False) and path in original_paths tests = dict((key, value) for key, value in tests.items() if value) if focused_target and not any('integration' in command for command in tests): no_integration_paths.add(path) # path triggers no integration tests if verbose_command: result = '%s: %s' % (verbose_command, tests.get(verbose_command) or 'none') # identify targeted integration tests (those which only target a single integration command) if 'integration' in verbose_command and tests.get(verbose_command): if not any('integration' in command for command in tests if command != verbose_command): if focused_target: result += ' (focused)' result += ' (targeted)' else: result = '%s' % tests if not tests.get(verbose_command): # minimize excessive output from potentially thousands of files which do not trigger tests none_count += 1 verbosity = 2 else: verbosity = 1 if args.verbosity >= verbosity: display.info('%s -> %s' % (path, result), verbosity=1) for command, target in tests.items(): commands[command].add(target) if focused_target: focused_commands[command].add(target) if none_count > 0 and args.verbosity < 2: display.notice('Omitted %d file(s) that triggered no tests.' % none_count) for command in commands: commands[command].discard('none') if any(t == 'all' for t in commands[command]): commands[command] = set(['all']) commands = dict((c, sorted(commands[c])) for c in commands if commands[c]) focused_commands = dict((c, sorted(focused_commands[c])) for c in focused_commands) for command in commands: if commands[command] == ['all']: commands[command] = [] # changes require testing all targets, do not filter targets changes = ChangeDescription() changes.command = verbose_command changes.changed_paths = sorted(original_paths) changes.deleted_paths = sorted(deleted_paths) changes.regular_command_targets = commands changes.focused_command_targets = focused_commands changes.no_integration_paths = sorted(no_integration_paths) return changes
def command_integration_filtered(args, targets): """ :type args: IntegrationConfig :type targets: tuple[IntegrationTarget] """ found = False targets_iter = iter(targets) test_dir = os.path.expanduser('~/ansible_testing') if not args.explain: remove_tree(test_dir) make_dirs(test_dir) if any('needs/ssh/' in target.aliases for target in targets): max_tries = 20 display.info('SSH service required for tests. Checking to make sure we can connect.') for i in range(1, max_tries + 1): try: run_command(args, ['ssh', '-o', 'BatchMode=yes', 'localhost', 'id'], capture=True) display.info('SSH service responded.') break except SubprocessError as ex: if i == max_tries: raise ex seconds = 3 display.warning('SSH service not responding. Waiting %d second(s) before checking again.' % seconds) time.sleep(seconds) start_at_task = args.start_at_task for target in targets_iter: if args.start_at and not found: found = target.name == args.start_at if not found: continue tries = 2 if args.retry_on_error else 1 verbosity = args.verbosity try: while tries: tries -= 1 try: if target.script_path: command_integration_script(args, target) else: command_integration_role(args, target, start_at_task) start_at_task = None break except SubprocessError: if not tries: raise display.warning('Retrying test target "%s" with maximum verbosity.' % target.name) display.verbosity = args.verbosity = 6 except: display.notice('To resume at this test target, use the option: --start-at %s' % target.name) next_target = next(targets_iter, None) if next_target: display.notice('To resume after this test target, use the option: --start-at %s' % next_target.name) raise finally: display.verbosity = args.verbosity = verbosity
def command_integration_filtered(args, targets): """ :type args: IntegrationConfig :type targets: tuple[IntegrationTarget] """ found = False passed = [] failed = [] targets_iter = iter(targets) test_dir = os.path.expanduser('~/ansible_testing') if not args.explain and any('needs/ssh/' in target.aliases for target in targets): max_tries = 20 display.info( 'SSH service required for tests. Checking to make sure we can connect.' ) for i in range(1, max_tries + 1): try: run_command(args, ['ssh', '-o', 'BatchMode=yes', 'localhost', 'id'], capture=True) display.info('SSH service responded.') break except SubprocessError: if i == max_tries: raise seconds = 3 display.warning( 'SSH service not responding. Waiting %d second(s) before checking again.' % seconds) time.sleep(seconds) start_at_task = args.start_at_task for target in targets_iter: if args.start_at and not found: found = target.name == args.start_at if not found: continue if args.list_targets: print(target.name) continue tries = 2 if args.retry_on_error else 1 verbosity = args.verbosity cloud_environment = get_cloud_environment(args, target) original_environment = EnvironmentDescription(args) display.info('>>> Environment Description\n%s' % original_environment, verbosity=3) try: while tries: tries -= 1 if not args.explain: # create a fresh test directory for each test target remove_tree(test_dir) make_dirs(test_dir) try: if target.script_path: command_integration_script(args, target) else: command_integration_role(args, target, start_at_task) start_at_task = None break except SubprocessError: if cloud_environment: cloud_environment.on_failure(target, tries) if not original_environment.validate(target.name, throw=False): raise if not tries: raise display.warning( 'Retrying test target "%s" with maximum verbosity.' % target.name) display.verbosity = args.verbosity = 6 original_environment.validate(target.name, throw=True) passed.append(target) except Exception as ex: failed.append(target) if args.continue_on_error: display.error(ex) continue display.notice( 'To resume at this test target, use the option: --start-at %s' % target.name) next_target = next(targets_iter, None) if next_target: display.notice( 'To resume after this test target, use the option: --start-at %s' % next_target.name) raise finally: display.verbosity = args.verbosity = verbosity if failed: raise ApplicationError( 'The %d integration test(s) listed below (out of %d) failed. See error output above for details:\n%s' % (len(failed), len(passed) + len(failed), '\n'.join( target.name for target in failed)))
def command_integration_filtered(args, targets): """ :type args: IntegrationConfig :type targets: tuple[IntegrationTarget] """ found = False targets_iter = iter(targets) test_dir = os.path.expanduser('~/ansible_testing') if not args.explain: remove_tree(test_dir) make_dirs(test_dir) if any('needs/ssh/' in target.aliases for target in targets): max_tries = 20 display.info( 'SSH service required for tests. Checking to make sure we can connect.' ) for i in range(1, max_tries + 1): try: run_command(args, ['ssh', '-o', 'BatchMode=yes', 'localhost', 'id'], capture=True) display.info('SSH service responded.') break except SubprocessError as ex: if i == max_tries: raise ex seconds = 3 display.warning( 'SSH service not responding. Waiting %d second(s) before checking again.' % seconds) time.sleep(seconds) start_at_task = args.start_at_task for target in targets_iter: if args.start_at and not found: found = target.name == args.start_at if not found: continue tries = 2 if args.retry_on_error else 1 verbosity = args.verbosity try: while tries: tries -= 1 try: if target.script_path: command_integration_script(args, target) else: command_integration_role(args, target, start_at_task) start_at_task = None break except SubprocessError: if not tries: raise display.warning( 'Retrying test target "%s" with maximum verbosity.' % target.name) display.verbosity = args.verbosity = 6 except: display.notice( 'To resume at this test target, use the option: --start-at %s' % target.name) next_target = next(targets_iter, None) if next_target: display.notice( 'To resume after this test target, use the option: --start-at %s' % next_target.name) raise finally: display.verbosity = args.verbosity = verbosity
def _setup_dynamic(self): """Create a CloudStack simulator using docker.""" config = self._read_config_template() self.container_name = self.DOCKER_SIMULATOR_NAME results = docker_inspect(self.args, self.container_name) if results and not results[0]['State']['Running']: docker_rm(self.args, self.container_name) results = [] if results: display.info( 'Using the existing CloudStack simulator docker container.', verbosity=1) else: display.info( 'Starting a new CloudStack simulator docker container.', verbosity=1) docker_pull(self.args, self.image) docker_run( self.args, self.image, ['-d', '-p', '8888:8888', '--name', self.container_name]) # apply work-around for OverlayFS issue # https://github.com/docker/for-linux/issues/72#issuecomment-319904698 docker_exec(self.args, self.container_name, [ 'find', '/var/lib/mysql', '-type', 'f', '-exec', 'touch', '{}', ';' ]) if not self.args.explain: display.notice( 'The CloudStack simulator will probably be ready in 2 - 4 minutes.' ) container_id = get_docker_container_id() if container_id: display.info('Running in docker container: %s' % container_id, verbosity=1) self.host = self._get_simulator_address() display.info('Found CloudStack simulator container address: %s' % self.host, verbosity=1) else: self.host = 'localhost' self.port = 8888 self.endpoint = 'http://%s:%d' % (self.host, self.port) self._wait_for_service() if self.args.explain: values = dict( HOST=self.host, PORT=str(self.port), ) else: credentials = self._get_credentials() if self.args.docker: host = self.DOCKER_SIMULATOR_NAME else: host = self.host values = dict( HOST=host, PORT=str(self.port), KEY=credentials['apikey'], SECRET=credentials['secretkey'], ) display.sensitive.add(values['SECRET']) config = self._populate_config_template(config, values) self._write_config(config)