예제 #1
0
    def generate_fuzzer(
            self, evg_expansions: EvgExpansions) -> GeneratedConfiguration:
        """
        Generate configuration for the fuzzer task specified by the expansions.

        :param evg_expansions: Evergreen expansions describing what to generate.
        :return: Configuration to generate the specified task.
        """
        suite = evg_expansions.suite
        is_sharded = self.multiversion_util.is_suite_sharded(suite)
        version_config_list = get_version_configs(is_sharded)

        builder = EvgConfigBuilder()  # pylint: disable=no-value-for-parameter

        fuzzer_task_set = set()
        for version_config in version_config_list:
            fuzzer_params = evg_expansions.get_fuzzer_params(
                version_config, is_sharded)
            fuzzer_task = builder.generate_fuzzer(fuzzer_params)
            fuzzer_task_set = fuzzer_task_set.union(fuzzer_task.sub_tasks)

        existing_tasks = {ExistingTask(task) for task in fuzzer_task_set}
        existing_tasks.add({ExistingTask(f"{suite}_multiversion_gen")})
        builder.add_display_task(evg_expansions.task, existing_tasks,
                                 evg_expansions.build_variant)
        return builder.build(f"{evg_expansions.task}.json")
예제 #2
0
def _generate_evg_build_variant(
    source_build_variant: Variant,
    run_build_variant: str,
    bypass_build_variant: str,
) -> BuildVariant:
    """
    Generate a shrub build variant for the given run build variant.

    :param source_build_variant: The build variant to base configuration on.
    :param run_build_variant: The build variant to generate.
    :param bypass_build_variant: The build variant to get compile artifacts from.
    :return: Shrub build variant configuration.
    """
    display_name = f"! {source_build_variant.display_name}"
    run_on = source_build_variant.run_on
    modules = source_build_variant.modules

    expansions = source_build_variant.expansions
    expansions["burn_in_bypass"] = bypass_build_variant

    build_variant = BuildVariant(run_build_variant,
                                 display_name,
                                 expansions=expansions,
                                 modules=modules,
                                 run_on=run_on)
    build_variant.add_existing_task(ExistingTask(COMPILE_TASK))
    return build_variant
예제 #3
0
    def test_display_task_with_different_task_types(self):
        bv = under_test.BuildVariant("build variant")

        n_tasks = 5
        tasks = {Task(f"task {i}", []) for i in range(n_tasks)}
        n_task_groups = 3
        task_groups = {TaskGroup(f"task group {i}", []) for i in range(n_task_groups)}
        n_existing_tasks = 4
        existing_tasks = {ExistingTask(f"existing task {i}") for i in range(n_existing_tasks)}

        bv.display_task(
            "display",
            execution_tasks=tasks,
            execution_task_groups=task_groups,
            execution_existing_tasks=existing_tasks,
            distros=["the distro"],
        )

        d = bv.as_dict()

        assert d["name"] == "build variant"
        assert len(d["tasks"]) == n_tasks + n_task_groups  # Existing tasks should already exist.
        assert len(d["display_tasks"]) == 1
        display_task = d["display_tasks"][0]
        assert display_task["name"] == "display"
        assert len(display_task["execution_tasks"]) == n_tasks + n_task_groups + n_existing_tasks

        all_generated_execution_tasks = {t for t in display_task["execution_tasks"]}
        for task in chain(tasks, task_groups, existing_tasks):
            assert task.name in all_generated_execution_tasks

        for task in d["tasks"]:
            assert "the distro" in task["distros"]
예제 #4
0
    def _generate_fuzzer_tasks(self, build_variant: BuildVariant,
                               version_configs: List[str],
                               is_sharded: bool) -> None:
        """
        Generate fuzzer tasks and add them to the given build variant.

        :param build_variant: Build variant to add tasks to.
        :param version_configs: Version configurations to generate.
        :param is_sharded: Should configuration be generated for sharding.
        """
        tasks = set()
        for version_config in version_configs:
            fuzzer_config = self._get_fuzzer_options(version_config,
                                                     is_sharded)
            task_name = f"{fuzzer_config.name}_{version_config}"
            sub_tasks = gen_fuzzer.generate_fuzzer_sub_tasks(
                task_name, fuzzer_config)
            tasks = tasks.union(sub_tasks)

        existing_tasks = {
            ExistingTask(f"{self.options.suite}_multiversion_gen")
        }
        build_variant.display_task(self.task,
                                   tasks,
                                   execution_existing_tasks=existing_tasks)
예제 #5
0
def create_generate_tasks_config(build_variant: BuildVariant,
                                 tests_by_task: Dict,
                                 generate_config: GenerateConfig,
                                 repeat_config: RepeatConfig,
                                 evg_api: Optional[EvergreenApi],
                                 include_gen_task: bool = True,
                                 task_prefix: str = "burn_in") -> None:
    # pylint: disable=too-many-arguments,too-many-locals
    """
    Create the config for the Evergreen generate.tasks file.

    :param build_variant: Shrub configuration to add to.
    :param tests_by_task: Dictionary of tests to generate tasks for.
    :param generate_config: Configuration of what to generate.
    :param repeat_config: Configuration of how to repeat tests.
    :param evg_api: Evergreen API.
    :param include_gen_task: Should generating task be include in display task.
    :param task_prefix: Prefix all task names with this.
    """
    tasks = create_generated_tasks(tests_by_task, task_prefix, generate_config,
                                   repeat_config, evg_api)
    existing_tasks = {ExistingTask(BURN_IN_TESTS_GEN_TASK)
                      } if include_gen_task else None
    build_variant.display_task(BURN_IN_TESTS_TASK,
                               tasks,
                               execution_existing_tasks=existing_tasks)
def main(expansions_file: str = "expansions.yml",
         output_file: str = "powercycle_tasks.json") -> None:
    """Generate multiple powercycle tasks to run in evergreen."""

    config = make_config(expansions_file)
    build_variant = BuildVariant(config.build_variant)

    sub_tasks = set()
    for task_name in config.task_names:
        if "skip_compile" in task_name:
            commands, task_dependency = get_skip_compile_setup_commands()
        else:
            commands, task_dependency = get_setup_commands()

        commands.extend([
            FunctionCall("set up remote credentials", config.remote_credentials_vars),
            BuiltInCommand("timeout.update", config.timeout_params),
            FunctionCall("set up EC2 instance", config.set_up_ec2_instance_vars),
            FunctionCall("run powercycle test", config.run_powercycle_vars),
        ])

        sub_tasks.update({
            Task(
                name_generated_task(task_name, index, config.num_tasks, config.build_variant),
                commands, task_dependency)
            for index in range(config.num_tasks)
        })

    build_variant.display_task(
        config.current_task_name.replace("_gen", ""), sub_tasks, distros=[config.distro],
        execution_existing_tasks={ExistingTask(config.current_task_name)})
    shrub_project = ShrubProject.empty()
    shrub_project.add_build_variant(build_variant)

    write_file(output_file, shrub_project.json())
예제 #7
0
    def generate_archive_dist_test_debug_activator_task(self, variant: str):
        """
        Generate dummy task to activate the task that archives debug symbols.

        We can't activate it directly as it's not generated.
        """
        with self.lock:
            build_variant = self.get_build_variant(variant)
            build_variant.add_existing_task(
                ExistingTask(ACTIVATE_ARCHIVE_DIST_TEST_DEBUG_TASK))
def create_multiversion_generate_tasks_config(
        tests_by_task: Dict[str, TaskInfo], evg_api: EvergreenApi,
        generate_config: GenerateConfig) -> BuildVariant:
    """
    Create the multiversion config for the Evergreen generate.tasks file.

    :param tests_by_task: Dictionary of tests to generate tasks for.
    :param evg_api: Evergreen API.
    :param generate_config: Configuration of what to generate.
    :return: Shrub configuration with added tasks.
    """
    build_variant = BuildVariant(generate_config.build_variant)
    tasks = set()
    if tests_by_task:
        # Get the multiversion suites that will run in as part of burn_in_multiversion.
        multiversion_suites = get_named_suites_with_root_level_key(
            MULTIVERSION_CONFIG_KEY)
        for suite in multiversion_suites:
            idx = 0
            if suite["origin"] not in tests_by_task.keys():
                # Only generate burn in multiversion tasks for suites that would run the detected
                # changed tests.
                continue
            LOGGER.debug("Generating multiversion suite",
                         suite=suite["multiversion_name"])

            # We hardcode the number of fallback sub suites and the target resmoke time here
            # since burn_in_tests cares about individual tests and not entire suites. The config
            # options here are purely used to generate the proper multiversion suites to run
            # tests against.
            config_options = {
                "suite": suite["origin"],
                "fallback_num_sub_suites": 1,
                "project": generate_config.project,
                "build_variant": generate_config.build_variant,
                "task_id": generate_config.task_id,
                "task_name": suite["multiversion_name"],
                "target_resmoke_time": 60,
            }
            config_options.update(gen_resmoke.DEFAULT_CONFIG_VALUES)

            config_generator = gen_multiversion.EvergreenMultiversionConfigGenerator(
                evg_api, gen_resmoke.ConfigOptions(config_options))
            test_list = tests_by_task[suite["origin"]].tests
            for test in test_list:
                # Generate the multiversion tasks for each test.
                sub_tasks = config_generator.get_burn_in_tasks(test, idx)
                tasks = tasks.union(sub_tasks)
                idx += 1

    existing_tasks = {ExistingTask(f"{BURN_IN_MULTIVERSION_TASK}_gen")}
    build_variant.display_task(BURN_IN_MULTIVERSION_TASK,
                               tasks,
                               execution_existing_tasks=existing_tasks)
    return build_variant
예제 #9
0
    def add_display_task(self, display_task_name: str, execution_task_names: Set[str],
                         build_variant: str) -> None:
        """
        Add configuration to generate the specified display task.

        :param display_task_name: Name of display task to create.
        :param execution_task_names: Name of execution tasks to include in display task.
        :param build_variant: Name of build variant to add to.
        """
        execution_tasks = {ExistingTask(task_name) for task_name in execution_task_names}
        with self.lock:
            build_variant = self.get_build_variant(build_variant)
            build_variant.display_task(display_task_name, execution_existing_tasks=execution_tasks)
예제 #10
0
    def generate_config(self, build_variant: BuildVariant) -> None:
        """
        Generate evergreen configuration.

        :param build_variant: Build variant to add generated configuration to.
        """
        self.build_tasks = self.evg_api.tasks_by_build(self.options.build_id)

        tasks = self._generate_all_tasks()
        generating_task = {ExistingTask(task_name) for task_name in self.options.gen_task_set}
        distros = self._get_distro(build_variant.name)
        build_variant.display_task(self.options.display_task_name, execution_tasks=tasks,
                                   execution_existing_tasks=generating_task, distros=distros)
예제 #11
0
def create_fuzzer_task(options: ConfigOptions,
                       build_variant: BuildVariant) -> None:
    """
    Generate an evergreen configuration for fuzzers and add it to the given build variant.

    :param options: task options.
    :param build_variant: Build variant to add tasks to.
    """
    task_name = options.name
    sub_tasks = generate_fuzzer_sub_tasks(task_name, options)

    build_variant.display_task(
        task_name,
        sub_tasks,
        execution_existing_tasks={ExistingTask(f"{options.name}_gen")})
예제 #12
0
    def generate_evg_tasks(self, build_variant: BuildVariant) -> None:
        # pylint: disable=too-many-locals
        """
        Generate evergreen tasks for multiversion tests.

        The number of tasks generated equals
        (the number of version configs) * (the number of generated suites).

        :param build_variant: Build variant to add generated configuration to.
        """
        is_sharded = is_suite_sharded(TEST_SUITE_DIR, self.options.suite)
        version_configs = get_version_configs(is_sharded)

        if self.options.is_jstestfuzz:
            self._generate_fuzzer_tasks(build_variant, version_configs,
                                        is_sharded)
            return

        suites = self.generate_resmoke_suites()
        sub_tasks = set()
        for version_config in version_configs:
            idx = 0
            for suite in suites:
                # Generate the newly divided test suites
                source_suite = os.path.join(CONFIG_DIR, suite.name + ".yml")
                sub_tasks.add(
                    self._generate_sub_task(version_config,
                                            self.task, idx, source_suite,
                                            len(suites), is_sharded))
                idx += 1

            # Also generate the misc task.
            misc_suite_name = "{0}_misc".format(self.options.suite)
            misc_suite = os.path.join(CONFIG_DIR, misc_suite_name + ".yml")
            sub_tasks.add(
                self._generate_sub_task(version_config, self.task, idx,
                                        misc_suite, 1, is_sharded))
            idx += 1

        build_variant.display_task(
            self.task,
            sub_tasks,
            execution_existing_tasks={ExistingTask(f"{self.task}_gen")})
예제 #13
0
 def get_existing_tasks(self) -> Optional[Set[ExistingTask]]:
     """Get any existing tasks that should be included in the generated display task."""
     if self.generate_config.include_gen_task:
         return {ExistingTask(BURN_IN_TESTS_GEN_TASK)}
     return None