Exemplo n.º 1
0
class SuiteStarter:  # pylint:disable=too-many-instance-attributes
    """Suite starter main program."""

    announcement = None

    def __init__(self):
        """Initialize SuiteStarter by creating a rabbitmq publisher and subscriber."""
        self.etos = ETOS(
            "ETOS Suite Starter", os.getenv("HOSTNAME"), "ETOS Suite Starter"
        )
        self._configure()

        self.etos.config.rabbitmq_subscriber_from_environment()
        self.etos.config.rabbitmq_publisher_from_environment()
        self.etos.start_subscriber()
        self.etos.start_publisher()

        self.etos.subscriber.subscribe(
            "EiffelTestExecutionRecipeCollectionCreatedEvent",
            self.suite_runner_callback,
            can_nack=True,
        )

    def _configure(self):
        """Configure ETOS library."""
        self.etos.config.set("suite_runner", os.getenv("SUITE_RUNNER"))

    def suite_runner_callback(self, event, _):
        """Start a suite runner on a TERCC event.

        :param event: EiffelTestExecutionRecipeCollectionCreatedEvent (TERCC)
        :type event: :obj: `eiffellib.events.base_event.EiffelTestExecutionRecipeCollectionCreatedEvent`  # noqa pylint:disable=line-too-long
        :return: Whether event was ACK:ed or not.
        :rtype: bool
        """
        suite_id = event.meta.event_id
        FORMAT_CONFIG.identifier = suite_id
        LOGGER.info("Received a TERCC event. Build data for ESR.")
        data = {
            "EiffelTestExecutionRecipeCollectionCreatedEvent": json.dumps(event.json)
        }
        data["etos_configmap"] = os.getenv("ETOS_CONFIGMAP")
        data["docker_image"] = self.etos.config.get("suite_runner")
        data["suite_id"] = suite_id
        with_sidecar = os.getenv("ETOS_SIDECAR_ENABLED", "false").lower() == "true"
        if with_sidecar:
            data["sidecar_image"] = os.getenv("ETOS_SIDECAR_IMAGE")

        job = Job(in_cluster=bool(os.getenv("DOCKER_CONTEXT")))
        job_name = job.uniqueify(f"suite-runner-{suite_id}").lower()
        data["job_name"] = job_name

        LOGGER.info("Data: %r", data)
        try:
            assert data["EiffelTestExecutionRecipeCollectionCreatedEvent"]
            assert data["etos_configmap"], "Missing ETOS_CONFIGMAP in environment"
            assert data["docker_image"], "Missing SUITE_RUNNER in environment"
        except AssertionError as exception:
            LOGGER.critical("Incomplete data for ESR. %r", exception)
            raise

        if with_sidecar:
            body = job.load_yaml(ESR_YAML_WITH_SIDECAR.format(**data))
        else:
            body = job.load_yaml(ESR_YAML.format(**data))
        LOGGER.info("Starting new executor: %r", job_name)
        job.create_job(body)
        LOGGER.info("ESR successfully launched.")
        return True

    def run(self):
        """Run the SuiteStarter main loop.

        Checks if required data has been received within the same context
        and if it does, trigger a runner job within a thread.
        The thread is never joined and is daemonized. This means that if SuiteStarter
        would exit, all tests running within will also exit.
        """
        body = (
            "Suite starter is running and listening to "
            "events in the Eiffel context.\n"
            "Configmap:\n"
            f"ETOS Suite Runner: {os.getenv('SUITE_RUNNER')}\n"
        )
        self.etos.monitor.keep_alive(body)  # Blocking.
Exemplo n.º 2
0
class SuiteStarter:  # pylint:disable=too-many-instance-attributes
    """Suite starter main program."""

    announcement = None

    def __init__(self):
        """Initialize SuiteStarter by creating a rabbitmq publisher and subscriber."""
        self.etos = ETOS("ETOS Suite Starter", os.getenv("HOSTNAME"),
                         "ETOS Suite Starter")
        self._configure()

        self.etos.config.rabbitmq_subscriber_from_environment()
        self.etos.config.rabbitmq_publisher_from_environment()
        self.etos.start_subscriber()
        self.etos.start_publisher()

        self.etos.subscriber.subscribe(
            "EiffelTestExecutionRecipeCollectionCreatedEvent",
            self.suite_runner_callback,
            can_nack=True,
        )

    def _configure(self):
        """Configure ETOS library."""
        self.etos.config.set("suite_runner", os.getenv("SUITE_RUNNER"))

    def suite_runner_callback(self, event, _):
        """Start a suite runner on a TERCC event.

        :param event: EiffelTestExecutionRecipeCollectionCreatedEvent (TERCC)
        :type event: :obj: `eiffellib.events.base_event.EiffelTestExecutionRecipeCollectionCreatedEvent`  # noqa pylint:disable=line-too-long
        :return: Whether event was ACK:ed or not.
        :rtype: bool
        """
        suite_id = event.meta.event_id
        data = {
            "EiffelTestExecutionRecipeCollectionCreatedEvent":
            json.dumps(event.json)
        }
        data["etos_configmap"] = os.getenv("ETOS_CONFIGMAP")
        data["docker_image"] = self.etos.config.get("suite_runner")
        data["suite_id"] = suite_id

        job = Job(in_cluster=bool(os.getenv("DOCKER_CONTEXT")))
        job_name = job.uniqueify("suite-runner-{}".format(suite_id)).lower()
        data["job_name"] = job_name

        assert data["EiffelTestExecutionRecipeCollectionCreatedEvent"]
        assert data["etos_configmap"], "Missing ETOS_CONFIGMAP in environment"
        assert data["docker_image"], "Missing SUITE_RUNNER in environment"

        body = job.load_yaml(ESR_YAML.format(**data))
        _logger.info("Starting new executor: %s", job_name)
        job.create_job(body)
        return True

    def run(self):
        """Run the SuiteStarter main loop.

        Checks if required data has been received within the same context
        and if it does, trigger a runner job within a thread.
        The thread is never joined and is daemonized. This means that if SuiteStarter
        would exit, all tests running within will also exit.
        """
        body = ("Suite starter is running and listening to "
                "events in the Eiffel context.\n"
                "Configmap:\n"
                "ETOS Suite Runner: {}\n".format(os.getenv("SUITE_RUNNER")))
        self.etos.monitor.keep_alive(body)  # Blocking.