def test_request_and_wait(self): """Test that the external log area provider can checkout log areas. Approval criteria: - The external log area provider shall request an external provider and checkout log areas. Test steps:: 1. Initialize an external provider. 2. Send a checkout request via the external log area provider. 3. Verify that the provider returns a list of checked out log areas. """ etos = ETOS("testing_etos", "testing_etos", "testing_etos") etos.config.set("WAIT_FOR_LOG_AREA_TIMEOUT", 10) jsontas = JsonTas() identity = PackageURL.from_string("pkg:testing/etos") jsontas.dataset.merge( { "identity": identity, "artifact_id": "artifactid", "artifact_created": "artifactcreated", "artifact_published": "artifactpublished", "tercc": "tercc", "dataset": {}, "context": "context", } ) start_id = "1" test_id = "logarea123" provider_id = "test_request_and_wait" # First request is 'start'. # Second request is 'status'. # Third request is 'stop' which should not be requested in this test. with FakeServer( ["ok", "ok", "no_content"], [ {"id": start_id}, {"log_areas": [{"test_id": test_id}], "status": "DONE"}, {}, ], ) as server: ruleset = { "id": provider_id, "status": {"host": server.host}, "start": {"host": server.host}, "stop": {"host": server.host}, } self.logger.info("STEP: Initialize an external provider.") provider = Provider(etos, jsontas, ruleset) self.logger.info( "STEP: Send a checkout request via the external log area provider." ) log_areas = provider.request_and_wait_for_log_areas() self.logger.info( "STEP: Verify that the provider returns a list of checked out log areas." ) dict_log_areas = [log_area.as_dict for log_area in log_areas] test_log_areas = [LogArea(provider_id=provider_id, test_id=test_id).as_dict] self.assertEqual(dict_log_areas, test_log_areas)
def test_provider_stop_many(self): """Test that it is possible to checkin an external log area provider with many log areas. Approval criteria: - It shall be possible to send stop to an external log area provider with multiple log areas. Test steps:: 1. Initialize an external provider. 2. Send a stop request for multiple log areas. 3. Verify that the stop endpoint is called. """ etos = ETOS("testing_etos", "testing_etos", "testing_etos") etos.config.set("WAIT_FOR_LOG_AREA_TIMEOUT", 1) jsontas = JsonTas() log_areas = [ LogArea(test_log_area=1), LogArea(test_log_area=2), ] jsontas.dataset.merge( { "identity": PackageURL.from_string("pkg:testing/etos"), "artifact_id": "artifactid", "artifact_created": "artifactcreated", "artifact_published": "artifactpublished", "tercc": "tercc", "dataset": {}, "context": "context", "logs": log_areas, } ) dict_log_areas = [log_area.as_dict for log_area in log_areas] with FakeServer("no_content", {}) as server: ruleset = {"id": "test_provider_stop_many", "stop": {"host": server.host}} self.logger.info("STEP: Initialize an external provider.") provider = Provider(etos, jsontas, ruleset) self.logger.info("STEP: Send a stop request for multiple log areas.") provider.checkin_all() self.logger.info("STEP: Verify that the stop endpoint is called.") self.assertEqual(server.nbr_of_requests, 1) self.assertEqual(server.requests, [dict_log_areas])
def build_log_areas(self, response): """Build log area objects from external log area provider response. :param response: The response from the external log area provider. :type response: dict :return: A list of log areas. :rtype: list """ return [ LogArea(provider_id=self.id, **log_area) for log_area in response.get("log_areas", []) ]
def test_provider_stop_timeout(self): """Test that the checkin method raises a TimeoutError when timed out. Approval criteria: - The checkin method shall raise TimeoutError when timed out. Test steps:: 1. Initialize an external provider. 2. Send a stop request for log areas that times out. 3. Verify that the checkin method raises a TimeoutError. """ etos = ETOS("testing_etos", "testing_etos", "testing_etos") etos.config.set("WAIT_FOR_LOG_AREA_TIMEOUT", 1) jsontas = JsonTas() jsontas.dataset.merge( { "identity": PackageURL.from_string("pkg:testing/etos"), "artifact_id": "artifactid", "artifact_created": "artifactcreated", "artifact_published": "artifactpublished", "tercc": "tercc", "dataset": {}, "context": "context", } ) log_area = LogArea(test_log_area=1) with FakeServer("bad_request", {}) as server: ruleset = { "id": "test_provider_stop_timeout", "stop": {"host": server.host}, } self.logger.info("STEP: Initialize an external provider.") provider = Provider(etos, jsontas, ruleset) self.logger.info("STEP: Send a stop request that fails.") with self.assertRaises(TimeoutError): self.logger.info( "STEP: Verify that the checkin method raises a TimeoutError." ) provider.checkin(log_area)
def release(response, task_id): """Release an environment. :param response: Response object to edit and return. :type response: :obj:`falcon.response` :param task_id: Task to release. :type task_id: str """ try: task_result = APP.AsyncResult(task_id) result = { "status": task_result.status, } response.status = falcon.HTTP_200 if task_result.result: etos = ETOS( "ETOS Environment Provider", os.getenv("HOSTNAME"), "Environment Provider", ) jsontas = JsonTas() registry = ProviderRegistry(etos, jsontas) failure = None for suite in task_result.result.get("suites", []): try: iut = suite.get("iut") ruleset = registry.get_iut_provider_by_id( iut.get("provider_id")) provider = IutProvider(etos, jsontas, ruleset["iut"]) provider.checkin(Iut(**iut)) except Exception as exception: # pylint:disable=broad-except failure = exception try: executor = suite.get("executor") ruleset = registry.get_execution_space_provider_by_id( executor.get("provider_id")) provider = ExecutionSpaceProvider( etos, jsontas, ruleset["execution_space"]) provider.checkin(ExecutionSpace(**executor)) except Exception as exception: # pylint:disable=broad-except failure = exception try: log_area = suite.get("log_area") ruleset = registry.get_log_area_provider_by_id( log_area.get("provider_id")) provider = LogAreaProvider(etos, jsontas, ruleset["log"]) provider.checkin(LogArea(**log_area)) except Exception as exception: # pylint:disable=broad-except failure = exception task_result.forget() if failure: raise failure response.media = {**result} else: response.media = { "warning": f"Nothing to release with task_id '{task_id}'", **result, } except Exception as exception: # pylint:disable=broad-except traceback.print_exc() response.media = { "error": str(exception), "details": traceback.format_exc(), **result, }
def release_environment(etos, jsontas, provider_registry, task_result, release_id): # pylint:disable=too-many-locals """Release an already requested environment. :param etos: ETOS library instance. :type etos: :obj:`etos_lib.ETOS` :param jsontas: JSONTas instance. :type jsontas: :obj:`jsontas.jsontas.JsonTas` :param provider_registry: The provider registry to get environments from. :type provider_registry: :obj:`environment_provider.lib.registry.ProviderRegistry` :param celery_worker: The worker holding the task results. :type celery_worker: :obj:`celery.Celery` :param release_id: The environment ID to release. :type release_id: str :return: Whether or not the release was successful together with a message should the release not be successful. :rtype tuple """ if task_result is None or not task_result.result: return False, f"Nothing to release with task_id {release_id}" failure = None for suite in task_result.result.get("suites", []): etos.config.set("SUITE_ID", suite.get("suite_id")) iut = suite.get("iut") iut_ruleset = provider_registry.get_iut_provider_by_id( iut.get("provider_id")).get("iut") executor = suite.get("executor") executor_ruleset = provider_registry.get_execution_space_provider_by_id( executor.get("provider_id")).get("execution_space") log_area = suite.get("log_area") log_area_ruleset = provider_registry.get_log_area_provider_by_id( log_area.get("provider_id")).get("log") if iut_ruleset.get("type", "jsontas") == "external": success, exception = checkin_provider( Iut(**iut), ExternalIutProvider(etos, jsontas, iut_ruleset)) else: success, exception = checkin_provider( Iut(**iut), IutProvider(etos, jsontas, iut_ruleset)) if not success: failure = exception success, exception = checkin_provider( LogArea(**log_area), LogAreaProvider(etos, jsontas, log_area_ruleset)) if not success: failure = exception success, exception = checkin_provider( ExecutionSpace(**executor), ExecutionSpaceProvider(etos, jsontas, executor_ruleset), ) if not success: failure = exception task_result.forget() if failure: # Return the traceback from exception stored in failure. return False, "".join( traceback.format_exception(failure, value=failure, tb=failure.__traceback__)) return True, ""