diff --git a/setup.cfg b/setup.cfg index eaa14df0..bc8f9a32 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,6 +36,9 @@ packages = taskflow [entry_points] +taskflow.jobboards = + zookeeper = taskflow.jobs.backends.impl_zookeeper:ZookeeperJobBoard + taskflow.persistence = dir = taskflow.persistence.backends.impl_dir:DirBackend file = taskflow.persistence.backends.impl_dir:DirBackend diff --git a/taskflow/jobs/backends/__init__.py b/taskflow/jobs/backends/__init__.py index da9e7d90..f9efc534 100644 --- a/taskflow/jobs/backends/__init__.py +++ b/taskflow/jobs/backends/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (C) 2013 Yahoo! Inc. All Rights Reserved. +# Copyright (C) 2014 Yahoo! Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -13,3 +13,33 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + +import logging + +import six +from stevedore import driver + +from taskflow import exceptions as exc + + +# NOTE(harlowja): this is the entrypoint namespace, not the module namespace. +BACKEND_NAMESPACE = 'taskflow.jobboards' + +LOG = logging.getLogger(__name__) + + +def fetch(name, conf, namespace=BACKEND_NAMESPACE, **kwargs): + # NOTE(harlowja): this allows simpler syntax. + if isinstance(conf, six.string_types): + conf = {'board': conf} + + board = conf['board'] + LOG.debug('Looking for %r jobboard driver in %r', board, namespace) + try: + mgr = driver.DriverManager(namespace, board, + invoke_on_load=True, + invoke_args=(name, conf), + invoke_kwds=kwargs) + return mgr.driver + except RuntimeError as e: + raise exc.NotFound("Could not find jobboard %s" % (board), e) diff --git a/taskflow/jobs/backends/impl_zookeeper.py b/taskflow/jobs/backends/impl_zookeeper.py index d635396d..96baadb2 100644 --- a/taskflow/jobs/backends/impl_zookeeper.py +++ b/taskflow/jobs/backends/impl_zookeeper.py @@ -144,8 +144,7 @@ class ZookeeperJob(base_job.Job): class ZookeeperJobBoard(jobboard.JobBoard): def __init__(self, name, conf, client=None): - super(ZookeeperJobBoard, self).__init__(name) - self._conf = conf + super(ZookeeperJobBoard, self).__init__(name, conf) if client is not None: self._client = client self._owned = False diff --git a/taskflow/jobs/jobboard.py b/taskflow/jobs/jobboard.py index 50af583e..c8f54e7c 100644 --- a/taskflow/jobs/jobboard.py +++ b/taskflow/jobs/jobboard.py @@ -28,8 +28,9 @@ class JobBoard(object): capabilities of the underlying jobboard implementation. """ - def __init__(self, name): + def __init__(self, name, conf): self._name = name + self._conf = conf @abc.abstractmethod def iterjobs(self, only_unclaimed=False): diff --git a/taskflow/tests/unit/jobs/test_entrypoint.py b/taskflow/tests/unit/jobs/test_entrypoint.py new file mode 100644 index 00000000..17dfa02e --- /dev/null +++ b/taskflow/tests/unit/jobs/test_entrypoint.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2014 Yahoo! Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import contextlib + +from zake import fake_client + +from taskflow.jobs import backends +from taskflow.jobs.backends import impl_zookeeper +from taskflow import test + + +class BackendFetchingTest(test.TestCase): + def test_zk_entry_point_text(self): + conf = 'zookeeper' + with contextlib.closing(backends.fetch('test', conf)) as be: + self.assertIsInstance(be, impl_zookeeper.ZookeeperJobBoard) + + def test_zk_entry_point(self): + conf = { + 'board': 'zookeeper', + } + with contextlib.closing(backends.fetch('test', conf)) as be: + self.assertIsInstance(be, impl_zookeeper.ZookeeperJobBoard) + + def test_zk_entry_point_existing_client(self): + existing_client = fake_client.FakeClient() + conf = { + 'board': 'zookeeper', + } + kwargs = { + 'client': existing_client, + } + with contextlib.closing(backends.fetch('test', conf, **kwargs)) as be: + self.assertIsInstance(be, impl_zookeeper.ZookeeperJobBoard) + self.assertIs(existing_client, be._client)