Example #1
0
class TestEphemeral(EphemeralBuilderTestCase):
    """ Simple unit tests for the ephemeral builder around config management, starting and stopping
      jobs.
  """
    def setUp(self):
        super(TestEphemeral, self).setUp()

        unregister_component_callback = Mock()
        job_heartbeat_callback = Mock()

        @coroutine
        def job_complete_callback(*args, **kwargs):
            raise Return()

        self.manager = EphemeralBuilderManager(
            self._register_component,
            unregister_component_callback,
            job_heartbeat_callback,
            job_complete_callback,
            "127.0.0.1",
            30,
        )

    def tearDown(self):
        super(TestEphemeral, self).tearDown()
        self.manager.shutdown()

    def test_verify_executor_oldconfig(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        self.manager.initialize({
            "EXECUTOR":
            "test",
            "EXECUTOR_CONFIG":
            dict(MINIMUM_RETRY_THRESHOLD=42),
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Ensure that we have a single test executor.
        self.assertEqual(1, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)
        self.assertEqual("TestExecutor",
                         self.manager.registered_executors[0].name)

    def test_verify_executor_newconfig(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        self.manager.initialize({
            "EXECUTORS": [{
                "EXECUTOR": "test",
                "MINIMUM_RETRY_THRESHOLD": 42
            }],
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Ensure that we have a single test executor.
        self.assertEqual(1, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)

    def test_multiple_executors_samename(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        EphemeralBuilderManager.EXECUTORS["anotherexecutor"] = TestExecutor

        with self.assertRaises(Exception):
            self.manager.initialize({
                "EXECUTORS": [
                    {
                        "NAME": "primary",
                        "EXECUTOR": "test",
                        "MINIMUM_RETRY_THRESHOLD": 42
                    },
                    {
                        "NAME": "primary",
                        "EXECUTOR": "anotherexecutor",
                        "MINIMUM_RETRY_THRESHOLD": 24,
                    },
                ],
                "ORCHESTRATOR": {
                    "MEM_CONFIG": None
                },
            })

    def test_verify_multiple_executors(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        EphemeralBuilderManager.EXECUTORS["anotherexecutor"] = TestExecutor

        self.manager.initialize({
            "EXECUTORS": [
                {
                    "NAME": "primary",
                    "EXECUTOR": "test",
                    "MINIMUM_RETRY_THRESHOLD": 42
                },
                {
                    "NAME": "secondary",
                    "EXECUTOR": "anotherexecutor",
                    "MINIMUM_RETRY_THRESHOLD": 24,
                },
            ],
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Ensure that we have a two test executors.
        self.assertEqual(2, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)
        self.assertEqual(
            24, self.manager.registered_executors[1].minimum_retry_threshold)

    def test_skip_invalid_executor(self):
        self.manager.initialize({
            "EXECUTORS": [
                {
                    "EXECUTOR": "unknown",
                    "MINIMUM_RETRY_THRESHOLD": 42
                },
            ],
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        self.assertEqual(0, len(self.manager.registered_executors))

    @async_test
    def test_schedule_job_namespace_filter(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        self.manager.initialize({
            "EXECUTORS": [{
                "EXECUTOR": "test",
                "NAMESPACE_WHITELIST": ["something"],
            }],
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Try with a build job in an invalid namespace.
        build_job = self._create_build_job(namespace="somethingelse")
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        # Try with a valid namespace.
        build_job = self._create_build_job(namespace="something")
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

    @async_test
    def test_schedule_job_retries_filter(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor
        self.manager.initialize({
            "EXECUTORS": [{
                "EXECUTOR": "test",
                "MINIMUM_RETRY_THRESHOLD": 2,
            }],
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Try with a build job that has too few retries.
        build_job = self._create_build_job(retries=1)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        # Try with a valid job.
        build_job = self._create_build_job(retries=2)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

    @async_test
    def test_schedule_job_executor_fallback(self):
        EphemeralBuilderManager.EXECUTORS["primary"] = TestExecutor
        EphemeralBuilderManager.EXECUTORS["secondary"] = TestExecutor

        self.manager.initialize({
            "EXECUTORS": [
                {
                    "NAME": "primary",
                    "EXECUTOR": "primary",
                    "NAMESPACE_WHITELIST": ["something"],
                    "MINIMUM_RETRY_THRESHOLD": 3,
                },
                {
                    "NAME": "secondary",
                    "EXECUTOR": "secondary",
                    "MINIMUM_RETRY_THRESHOLD": 2,
                },
            ],
            "ALLOWED_WORKER_COUNT":
            5,
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Try a job not matching the primary's namespace filter. Should schedule on secondary.
        build_job = self._create_build_job(namespace="somethingelse")
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNotNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job not matching the primary's retry minimum. Should schedule on secondary.
        build_job = self._create_build_job(namespace="something", retries=2)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNotNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job matching the primary. Should schedule on the primary.
        build_job = self._create_build_job(namespace="something", retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.assertIsNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job not matching either's restrictions.
        build_job = self._create_build_job(namespace="somethingelse",
                                           retries=1)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

    @async_test
    def test_schedule_job_single_executor(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor

        self.manager.initialize({
            "EXECUTOR": "test",
            "EXECUTOR_CONFIG": {},
            "ALLOWED_WORKER_COUNT": 5,
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        build_job = self._create_build_job(namespace="something", retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.manager.registered_executors[0].job_started = None

        build_job = self._create_build_job(namespace="something", retries=0)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.manager.registered_executors[0].job_started = None

    @async_test
    def test_executor_exception(self):
        EphemeralBuilderManager.EXECUTORS["bad"] = BadExecutor

        self.manager.initialize({
            "EXECUTOR": "bad",
            "EXECUTOR_CONFIG": {},
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        build_job = self._create_build_job(namespace="something", retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

    @async_test
    def test_schedule_and_stop(self):
        EphemeralBuilderManager.EXECUTORS["test"] = TestExecutor

        self.manager.initialize({
            "EXECUTOR": "test",
            "EXECUTOR_CONFIG": {},
            "ORCHESTRATOR": {
                "MEM_CONFIG": None
            },
        })

        # Start the build job.
        build_job = self._create_build_job(namespace="something", retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        executor = self.manager.registered_executors[0]
        self.assertIsNotNone(executor.job_started)

        # Register the realm so the build information is added.
        yield From(
            self.manager._register_realm({
                "realm": str(uuid.uuid4()),
                "token": str(uuid.uuid4()),
                "execution_id": executor.job_started,
                "executor_name": "TestExecutor",
                "build_uuid": build_job.build_uuid,
                "job_queue_item": build_job.job_item,
            }))

        # Stop the build job.
        yield From(self.manager.kill_builder_executor(build_job.build_uuid))
        self.assertEqual(executor.job_stopped, executor.job_started)
Example #2
0
class TestEphemeral(EphemeralBuilderTestCase):
    """ Simple unit tests for the ephemeral builder around config management, starting and stopping
      jobs.
  """
    def setUp(self):
        super(TestEphemeral, self).setUp()

        unregister_component_callback = Mock()
        job_heartbeat_callback = Mock()

        @coroutine
        def job_complete_callback(*args, **kwargs):
            raise Return()

        self.manager = EphemeralBuilderManager(
            self._register_component,
            unregister_component_callback,
            job_heartbeat_callback,
            job_complete_callback,
            '127.0.0.1',
            30,
        )

    def tearDown(self):
        super(TestEphemeral, self).tearDown()
        self.manager.shutdown()

    def test_verify_executor_oldconfig(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        self.manager.initialize({
            'EXECUTOR':
            'test',
            'EXECUTOR_CONFIG':
            dict(MINIMUM_RETRY_THRESHOLD=42),
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Ensure that we have a single test executor.
        self.assertEqual(1, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)
        self.assertEqual('TestExecutor',
                         self.manager.registered_executors[0].name)

    def test_verify_executor_newconfig(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        self.manager.initialize({
            'EXECUTORS': [{
                'EXECUTOR': 'test',
                'MINIMUM_RETRY_THRESHOLD': 42
            }],
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Ensure that we have a single test executor.
        self.assertEqual(1, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)

    def test_multiple_executors_samename(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        EphemeralBuilderManager.EXECUTORS['anotherexecutor'] = TestExecutor

        with self.assertRaises(Exception):
            self.manager.initialize({
                'EXECUTORS': [
                    {
                        'NAME': 'primary',
                        'EXECUTOR': 'test',
                        'MINIMUM_RETRY_THRESHOLD': 42
                    },
                    {
                        'NAME': 'primary',
                        'EXECUTOR': 'anotherexecutor',
                        'MINIMUM_RETRY_THRESHOLD': 24
                    },
                ],
                'ORCHESTRATOR': {
                    'MEM_CONFIG': None
                },
            })

    def test_verify_multiple_executors(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        EphemeralBuilderManager.EXECUTORS['anotherexecutor'] = TestExecutor

        self.manager.initialize({
            'EXECUTORS': [
                {
                    'NAME': 'primary',
                    'EXECUTOR': 'test',
                    'MINIMUM_RETRY_THRESHOLD': 42
                },
                {
                    'NAME': 'secondary',
                    'EXECUTOR': 'anotherexecutor',
                    'MINIMUM_RETRY_THRESHOLD': 24
                },
            ],
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Ensure that we have a two test executors.
        self.assertEqual(2, len(self.manager.registered_executors))
        self.assertEqual(
            42, self.manager.registered_executors[0].minimum_retry_threshold)
        self.assertEqual(
            24, self.manager.registered_executors[1].minimum_retry_threshold)

    def test_skip_invalid_executor(self):
        self.manager.initialize({
            'EXECUTORS': [
                {
                    'EXECUTOR': 'unknown',
                    'MINIMUM_RETRY_THRESHOLD': 42
                },
            ],
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        self.assertEqual(0, len(self.manager.registered_executors))

    @async_test
    def test_schedule_job_namespace_filter(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        self.manager.initialize({
            'EXECUTORS': [{
                'EXECUTOR': 'test',
                'NAMESPACE_WHITELIST': ['something'],
            }],
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Try with a build job in an invalid namespace.
        build_job = self._create_build_job(namespace='somethingelse')
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        # Try with a valid namespace.
        build_job = self._create_build_job(namespace='something')
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

    @async_test
    def test_schedule_job_retries_filter(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor
        self.manager.initialize({
            'EXECUTORS': [{
                'EXECUTOR': 'test',
                'MINIMUM_RETRY_THRESHOLD': 2,
            }],
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Try with a build job that has too few retries.
        build_job = self._create_build_job(retries=1)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        # Try with a valid job.
        build_job = self._create_build_job(retries=2)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

    @async_test
    def test_schedule_job_executor_fallback(self):
        EphemeralBuilderManager.EXECUTORS['primary'] = TestExecutor
        EphemeralBuilderManager.EXECUTORS['secondary'] = TestExecutor

        self.manager.initialize({
            'EXECUTORS': [
                {
                    'NAME': 'primary',
                    'EXECUTOR': 'primary',
                    'NAMESPACE_WHITELIST': ['something'],
                    'MINIMUM_RETRY_THRESHOLD': 3,
                },
                {
                    'NAME': 'secondary',
                    'EXECUTOR': 'secondary',
                    'MINIMUM_RETRY_THRESHOLD': 2,
                },
            ],
            'ALLOWED_WORKER_COUNT':
            5,
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Try a job not matching the primary's namespace filter. Should schedule on secondary.
        build_job = self._create_build_job(namespace='somethingelse')
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNotNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job not matching the primary's retry minimum. Should schedule on secondary.
        build_job = self._create_build_job(namespace='something', retries=2)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNotNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job matching the primary. Should schedule on the primary.
        build_job = self._create_build_job(namespace='something', retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.assertIsNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

        # Try a job not matching either's restrictions.
        build_job = self._create_build_job(namespace='somethingelse',
                                           retries=1)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

        self.assertIsNone(self.manager.registered_executors[0].job_started)
        self.assertIsNone(self.manager.registered_executors[1].job_started)

        self.manager.registered_executors[0].job_started = None
        self.manager.registered_executors[1].job_started = None

    @async_test
    def test_schedule_job_single_executor(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor

        self.manager.initialize({
            'EXECUTOR': 'test',
            'EXECUTOR_CONFIG': {},
            'ALLOWED_WORKER_COUNT': 5,
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        build_job = self._create_build_job(namespace='something', retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.manager.registered_executors[0].job_started = None

        build_job = self._create_build_job(namespace='something', retries=0)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        self.assertIsNotNone(self.manager.registered_executors[0].job_started)
        self.manager.registered_executors[0].job_started = None

    @async_test
    def test_executor_exception(self):
        EphemeralBuilderManager.EXECUTORS['bad'] = BadExecutor

        self.manager.initialize({
            'EXECUTOR': 'bad',
            'EXECUTOR_CONFIG': {},
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        build_job = self._create_build_job(namespace='something', retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertFalse(result[0])

    @async_test
    def test_schedule_and_stop(self):
        EphemeralBuilderManager.EXECUTORS['test'] = TestExecutor

        self.manager.initialize({
            'EXECUTOR': 'test',
            'EXECUTOR_CONFIG': {},
            'ORCHESTRATOR': {
                'MEM_CONFIG': None
            },
        })

        # Start the build job.
        build_job = self._create_build_job(namespace='something', retries=3)
        result = yield From(self.manager.schedule(build_job))
        self.assertTrue(result[0])

        executor = self.manager.registered_executors[0]
        self.assertIsNotNone(executor.job_started)

        # Register the realm so the build information is added.
        yield From(
            self.manager._register_realm({
                'realm': str(uuid.uuid4()),
                'token': str(uuid.uuid4()),
                'execution_id': executor.job_started,
                'executor_name': 'TestExecutor',
                'build_uuid': build_job.build_uuid,
                'job_queue_item': build_job.job_item,
            }))

        # Stop the build job.
        yield From(self.manager.kill_builder_executor(build_job.build_uuid))
        self.assertEqual(executor.job_stopped, executor.job_started)