Exemplo n.º 1
0
    async def _run_job(self, job):
        # Get stage from pipeline
        pf = PipelineStageFactory()
        config = PipelineStageConfig(job['stage_name'], job['stage_config'])
        stage = pf.create_pipeline_stage(config)

        # Load input artifact payloads from cache
        loaded_artifacts = []
        for artifact in job['artifacts']:
            art_obj = Artifact(stage._config)
            art_obj.meta_from_dict(artifact)
            loaded = self._backend.load_artifact(art_obj)
            if loaded is None:
                self._log("Could not find payload for artifact")
                raise Exception("Could not find payload for artifact")
            loaded_artifacts.append(loaded)

        # Execute the task
        exec_task = self._executor.create_task(stage, loaded_artifacts)
        result = await exec_task.generate_artifacts()

        for art in result:
            art._creation_time = float(time.time())
            art._dependency_hash = Artifact.dependency_hash(loaded_artifacts)
            self._backend.save_artifact(art)
        self._backend.log_pipeline_stage_run_complete(
            config, Artifact.dependency_hash(loaded_artifacts))

        return result
Exemplo n.º 2
0
class TestPipelineStageLoader(unittest.TestCase):
    def setUp(self):
        self.filename = 'file.json'
        self.factory = PipelineStageFactory()
        self.fs = isolated_filesystem()
        self.fs.__enter__()

    def tearDown(self):
        self.fs.__exit__(None, None, None)

    def test_stage_export(self):
        for stage in pipetree.STAGES:
            if not hasattr(pipetree.stage, stage):
                raise StageDoesNotExistError(stage=stage)
        pass

    def test_load_valid_pipeline_config(self):
        with open(self.filename, 'w') as f:
            f.write(PIPELINE_CONFIG)
        loader = PipelineConfigLoader()
        for config in loader.load_file(self.filename):
            self.factory.create_pipeline_stage(config)

    def test_load_stage_without_filepath(self):
        with open(self.filename, 'w') as f:
            f.write(PIPELINE_NOFILEPATH_CONFIG)
        loader = PipelineConfigLoader()
        try:
            for config in loader.load_file(self.filename):
                self.factory.create_pipeline_stage(config)
            print('This should have raised an invalid config file error')
            self.fail()
        except InvalidConfigurationFileError:
            pass
Exemplo n.º 3
0
 def setUp(self):
     self.data = {
         "inputs": [],
         "execute": "tests.functional.module.executor_function.function",
         "type": "ExecutorPipelineStage"
     }
     self.config = PipelineStageConfig('WriteBytes', self.data)
     self.factory = PipelineStageFactory()
Exemplo n.º 4
0
 def pregenerate_artifacts(self, backend):
     pf = PipelineStageFactory()
     config = PipelineStageConfig("StageA",
                                  self.generate_pipeline_config()["StageA"])
     stage = pf.create_pipeline_stage(config)
     arts = []
     for art in stage.yield_artifacts():
         backend.save_artifact(art)
         arts.append(art)
     return arts
Exemplo n.º 5
0
    def test_create_tasks(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        executor = RemoteSQSExecutor(
            aws_profile="testing",
            task_queue_name=self.test_queue_task_name,
            result_queue_name=self.test_queue_result_name,
            loop=loop)

        pf = PipelineStageFactory()
        stage = pf.create_pipeline_stage(self.stage_config)
        input_artifacts = [Artifact(self.stage_config)]
        executor.create_task(stage, input_artifacts)

        async def process_loop(executor, stage, input_artifacts):
            exit_loop = False
            while not exit_loop:
                await asyncio.sleep(2.0)
                for message in executor._task_queue.receive_messages(
                        MessageAttributeNames=[
                            'stage_config_hash', 'dependency_hash'
                        ]):
                    print("Retrieved message")
                    print(message.body)
                    print(message.message_attributes)
                    if message.message_attributes is None:
                        self.assertEqual(0, "Message attributes absent")

                    m_config_hash = message.message_attributes.\
                        get('stage_config_hash').get('StringValue')
                    m_dependency_hash = message.message_attributes.\
                        get('dependency_hash').get('StringValue')
                    config_hash = stage._config.hash()
                    dependency_hash = Artifact.dependency_hash(input_artifacts)

                    self.assertEqual(config_hash, m_config_hash)
                    self.assertEqual(dependency_hash, m_dependency_hash)
                    message.delete()
                    exit_loop = True
            for task in asyncio.Task.all_tasks():
                task.cancel()
            raise CancelledError

        try:
            loop.run_until_complete(
                asyncio.wait([
                    executor._process_queue(),
                    process_loop(executor, stage, input_artifacts)
                ]))
        except CancelledError:
            print('CancelledError raised: closing event loop.')
Exemplo n.º 6
0
class PipelineFactory(object):
    def __init__(self):
        self._stage_factory = PipelineStageFactory()
        self._loader = PipelineConfigLoader()

    def generate_pipeline_from_file(self, config_file):
        configs = []
        for config in self._loader.load_file(config_file):
            configs.append(config)
        stages = self._generate_stages(configs)
        return Pipeline(stages)

    def generate_pipeline_from_dict(self, config_data):
        if not isinstance(config_data, OrderedDict):
            raise TypeError('generate_pipeline_from_dict requires an '
                            'OrderedDict to preserve the loading order '
                            'of the pipeline stages. Found %s instead.' %
                            type(config_data))
        configs = []
        for name, data in config_data.items():
            config = PipelineStageConfig(name, data)
            configs.append(config)
        stages = self._generate_stages(configs)
        return Pipeline(stages)

    def _generate_stages(self, configs):
        stages = OrderedDict()
        for config in configs:
            self._add_stage(stages, config)
        return stages

    def _add_stage(self, stages, config):
        stage = self._stage_factory.create_pipeline_stage(config)
        if stage.validate_prereqs(stages):
            stages[stage.name] = stage
Exemplo n.º 7
0
    async def _run_job(self, job):
        # Get stage from pipeline
        pf = PipelineStageFactory()
        config = PipelineStageConfig(job['stage_name'], job['stage_config'])
        stage = pf.create_pipeline_stage(config)

        # Load artifact payloads from cache
        loaded_artifacts = []
        for artifact in job['artifacts']:
            art_obj = Artifact(stage._config)
            art_obj.meta_from_dict(artifact)
            print(art_obj._pipeline_stage)
            loaded = self._backend.load_artifact(art_obj)
            if loaded is None:
                raise Exception("Could not find payload for artifact")
            loaded_artifacts.append(loaded)

        # Execute the task
        exec_task = self._executor.create_task(stage, loaded_artifacts)
        result = await exec_task.generate_artifacts()
        return result
Exemplo n.º 8
0
class TestExecutorPipelineStage(unittest.TestCase):
    def setUp(self):
        self.data = {
            "inputs": [],
            "execute": "tests.functional.module.executor_function.function",
            "type": "ExecutorPipelineStage"
        }
        self.config = PipelineStageConfig('WriteBytes', self.data)
        self.factory = PipelineStageFactory()

    def test_init_executor(self):
        stage = self.factory.create_pipeline_stage(self.config)
        res = []

        for x in stage.yield_artifacts():
            res = list(x)

        self.assertEqual(res, ['foo', 'bar', 'baz'])
Exemplo n.º 9
0
 def setUp(self):
     self.filename = 'file.json'
     self.factory = PipelineStageFactory()
     self.fs = isolated_filesystem()
     self.fs.__enter__()
Exemplo n.º 10
0
    def test_executor_server_integration(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

        executor = RemoteSQSExecutor(
            aws_profile=self.test_profile,
            task_queue_name=self.test_queue_task_name,
            result_queue_name=self.test_queue_result_name,
            s3_bucket_name=self.test_bucket_name,
            dynamodb_artifact_table_name=self.
            test_dynamodb_artifact_table_name,
            dynamodb_stage_run_table_name=self.test_dynamodb_stage_run_name,
            loop=loop)

        server = RemoteSQSServer(
            aws_profile=self.test_profile,
            aws_region=self.test_region,
            s3_bucket_name=self.test_bucket_name,
            task_queue_name=self.test_queue_task_name,
            result_queue_name=self.test_queue_result_name,
            dynamodb_artifact_table_name=self.
            test_dynamodb_artifact_table_name,
            dynamodb_stage_run_table_name=self.test_dynamodb_stage_run_name,
            loop=loop)

        # Create task. Its input will be itself because that's just great.
        pf = PipelineStageFactory()
        stage = pf.create_pipeline_stage(self.stage_config)
        input_artifacts = []
        for art in stage.yield_artifacts():
            input_artifacts.append(art)
        executor.create_task(stage, input_artifacts)

        # Save input artifacts so they're available for the remote server
        executor._backend.save_artifact(input_artifacts[0])

        # Run our local RemoteExecutor and the remote RemoteSQSServer
        # for 10 seconds.
        async def timeout():
            await asyncio.sleep(10.0)
            for task in asyncio.Task.all_tasks():
                task.cancel()
            raise CancelledError

        try:
            loop.run_until_complete(
                asyncio.wait([
                    executor._process_queue(),
                    server._process_tasks(),
                    server._executor_server._listen_to_queue(),
                    timeout()
                ]))
        except CancelledError:
            print('CancelledError raised: closing event loop.')

        # Load our remotely generated artifact(s) and ensure they
        # have the correct payload.
        arts = executor._backend.find_pipeline_stage_run_artifacts(
            self.stage_config, Artifact.dependency_hash(input_artifacts))

        loaded = []
        for art in arts:
            loaded.append(executor._backend.load_artifact(art))

        self.assertEqual(1, len(loaded))
        self.assertEqual(loaded[0].item.payload['param_a'],
                         "string parameter value")
Exemplo n.º 11
0
 def __init__(self):
     self._stage_factory = PipelineStageFactory()
     self._loader = PipelineConfigLoader()