diff --git a/qinling/api/controllers/v1/job.py b/qinling/api/controllers/v1/job.py index 60ff4a91..d1613416 100644 --- a/qinling/api/controllers/v1/job.py +++ b/qinling/api/controllers/v1/job.py @@ -35,7 +35,6 @@ from qinling.utils import rest_utils LOG = logging.getLogger(__name__) CONF = cfg.CONF -POST_REQUIRED = set(['function_id']) UPDATE_ALLOWED = set(['name', 'function_input', 'status', 'pattern', 'next_execution_time']) @@ -52,9 +51,9 @@ class JobsController(rest.RestController): def post(self, job): """Creates a new job.""" params = job.to_dict() - if not POST_REQUIRED.issubset(set(params.keys())): + if not (params.get("function_id") or params.get("function_alias")): raise exc.InputException( - 'Required param is missing. Required: %s' % POST_REQUIRED + 'Either function_alias or function_id must be provided.' ) # Check the input params. @@ -62,6 +61,14 @@ class JobsController(rest.RestController): LOG.info("Creating %s, params: %s", self.type, params) version = params.get('function_version', 0) + # if function_alias provided + function_alias = params.get('function_alias') + if function_alias: + alias_db = db_api.get_function_alias(function_alias) + function_id = alias_db.function_id + version = alias_db.function_version + params.update({'function_id': function_id, + 'version': version}) with db_api.transaction(): db_api.get_function(params['function_id']) diff --git a/qinling/api/controllers/v1/resources.py b/qinling/api/controllers/v1/resources.py index 49a39809..2c60353f 100644 --- a/qinling/api/controllers/v1/resources.py +++ b/qinling/api/controllers/v1/resources.py @@ -336,6 +336,7 @@ class Job(Resource): id = types.uuid name = wtypes.text function_id = types.uuid + function_alias = wtypes.text function_version = wsme.wsattr(int, default=0) function_input = wtypes.text status = wtypes.text diff --git a/qinling/tests/unit/api/controllers/v1/test_job.py b/qinling/tests/unit/api/controllers/v1/test_job.py index 4d89ebb7..96e9937f 100644 --- a/qinling/tests/unit/api/controllers/v1/test_job.py +++ b/qinling/tests/unit/api/controllers/v1/test_job.py @@ -56,6 +56,38 @@ class TestJobController(base.APITest): self.assertEqual(201, resp.status_int) self.assertEqual(1, resp.json.get('function_version')) + def test_post_with_alias(self): + db_api.increase_function_version(self.function_id, 0, + description="version 1") + name = self.rand_name(name="alias", prefix=self.prefix) + body = { + 'function_id': self.function_id, + 'function_version': 1, + 'name': name + } + db_api.create_function_alias(**body) + + job_body = { + 'name': self.rand_name('job', prefix=self.prefix), + 'first_execution_time': str( + datetime.utcnow() + timedelta(hours=1)), + 'function_alias': name + } + + resp = self.app.post_json('/v1/jobs', job_body) + + self.assertEqual(201, resp.status_int) + self.assertEqual(1, resp.json.get('function_version')) + + def test_post_without_required_params(self): + resp = self.app.post( + '/v1/jobs', + params={}, + expect_errors=True + ) + + self.assertEqual(400, resp.status_int) + def test_post_pattern(self): body = { 'name': self.rand_name('job', prefix=self.prefix), diff --git a/qinling_tempest_plugin/services/qinling_client.py b/qinling_tempest_plugin/services/qinling_client.py index c1eefc27..567e6ac8 100644 --- a/qinling_tempest_plugin/services/qinling_client.py +++ b/qinling_tempest_plugin/services/qinling_client.py @@ -174,8 +174,23 @@ class QinlingClient(client_base.QinlingClientBase): resp, body = self.post_json('webhooks', req_body) return resp, body - def create_job(self, function_id, version=0, first_execution_time=None): - req_body = {"function_id": function_id, "function_version": version} + def create_job(self, function_id=None, function_alias=None, version=0, + first_execution_time=None): + """Create job. + + function_alias takes precedence over function_id. + """ + if function_alias: + req_body = {'function_alias': function_alias} + elif function_id: + req_body = { + 'function_id': function_id, + 'function_version': version + } + else: + raise Exception("Either function_alias or function_id must be " + "provided.") + if not first_execution_time: first_execution_time = str( datetime.utcnow() + timedelta(hours=1) diff --git a/qinling_tempest_plugin/tests/api/test_jobs.py b/qinling_tempest_plugin/tests/api/test_jobs.py index 0dd44d1b..83bdd117 100644 --- a/qinling_tempest_plugin/tests/api/test_jobs.py +++ b/qinling_tempest_plugin/tests/api/test_jobs.py @@ -66,3 +66,29 @@ class JobsTest(base.BaseQinlingTest): resp, body = self.client.get_execution_log(exec_id) self.assertEqual(200, resp.status) self.assertIn('Hello, World', body) + + @decorators.idempotent_id('2ff6b90b-0432-44ec-8698-eed1c7fb7f04') + def test_create_with_function_alias(self): + version = self.create_function_version(self.function_id) + function_alias = self.create_function_alias(self.function_id, version) + # first_execution_time is at least 1 min ahead of current time. + first_execution_time = str(datetime.utcnow() + timedelta(seconds=90)) + job_id = self.create_job(function_alias=function_alias, + first_execution_time=first_execution_time) + + # Wait for job to be finished + self.wait_job_done(job_id) + + resp, body = self.client.get_resources( + 'executions', + {'description': 'has:%s' % job_id} + ) + self.assertEqual(200, resp.status) + self.assertEqual(1, len(body['executions'])) + + exec_id = body['executions'][0]['id'] + self.wait_execution_success(exec_id) + + resp, body = self.client.get_execution_log(exec_id) + self.assertEqual(200, resp.status) + self.assertIn('Hello, World', body) diff --git a/qinling_tempest_plugin/tests/base.py b/qinling_tempest_plugin/tests/base.py index e76fa23d..a95db597 100644 --- a/qinling_tempest_plugin/tests/base.py +++ b/qinling_tempest_plugin/tests/base.py @@ -182,15 +182,21 @@ class BaseQinlingTest(test.BaseTestCase): return webhook_id, body['webhook_url'] - def create_job(self, function_id=None, version=0, + def create_job(self, function_id=None, function_alias=None, version=0, first_execution_time=None): - if not function_id: - function_id = self.create_function() - resp, body = self.client.create_job( - function_id, - version=version, - first_execution_time=first_execution_time - ) + if function_alias: + resp, body = self.client.create_job( + function_alias=function_alias, + first_execution_time=first_execution_time + ) + else: + if not function_id: + function_id = self.create_function() + resp, body = self.client.create_job( + function_id, + version=version, + first_execution_time=first_execution_time + ) self.assertEqual(201, resp.status) job_id = body['id']