diff --git a/qinling/api/controllers/v1/resources.py b/qinling/api/controllers/v1/resources.py index 7918e610..d4fda7b7 100644 --- a/qinling/api/controllers/v1/resources.py +++ b/qinling/api/controllers/v1/resources.py @@ -346,6 +346,7 @@ class ScaleInfo(Resource): class Webhook(Resource): id = types.uuid function_id = types.uuid + function_version = wsme.wsattr(int, default=0) description = wtypes.text project_id = wsme.wsattr(wtypes.text, readonly=True) created_at = wsme.wsattr(wtypes.text, readonly=True) diff --git a/qinling/api/controllers/v1/webhook.py b/qinling/api/controllers/v1/webhook.py index 334e610f..85ba1486 100644 --- a/qinling/api/controllers/v1/webhook.py +++ b/qinling/api/controllers/v1/webhook.py @@ -35,7 +35,7 @@ from qinling.utils import rest_utils LOG = logging.getLogger(__name__) POST_REQUIRED = set(['function_id']) -UPDATE_ALLOWED = set(['function_id', 'description']) +UPDATE_ALLOWED = set(['function_id', 'function_version', 'description']) class WebhooksController(rest.RestController): @@ -113,6 +113,11 @@ class WebhooksController(rest.RestController): # Even admin user can not expose normal user's function db_api.get_function(params['function_id'], insecure=False) + + version = params.get('function_version', 0) + if version > 0: + db_api.get_function_version(params['function_id'], version) + webhook_d = db_api.create_webhook(params).to_dict() return resources.Webhook.from_dict( @@ -135,7 +140,7 @@ class WebhooksController(rest.RestController): def put(self, id, webhook): """Update webhook. - Currently, we only support update function_id. + Currently, only function_id and function_version are allowed to update. """ acl.enforce('webhook:update', context.get_ctx()) @@ -146,9 +151,17 @@ class WebhooksController(rest.RestController): LOG.info('Update %s %s, params: %s', self.type, id, values) - if 'function_id' in values: - # Even admin user can not expose normal user's function - db_api.get_function(values['function_id'], insecure=False) + # Even admin user can not expose normal user's function + webhook_db = db_api.get_webhook(id, insecure=False) + pre_function_id = webhook_db.function_id + pre_version = webhook_db.function_version + + new_function_id = values.get("function_id", pre_function_id) + new_version = values.get("function_version", pre_version) + + db_api.get_function(new_function_id, insecure=False) + if new_version > 0: + db_api.get_function_version(new_function_id, new_version) webhook = db_api.update_webhook(id, values).to_dict() return resources.Webhook.from_dict(self._add_webhook_url(id, webhook)) @@ -163,10 +176,11 @@ class WebhooksController(rest.RestController): function_db = webhook_db.function trust_id = function_db.trust_id project_id = function_db.project_id + version = webhook_db.function_version LOG.info( - 'Invoking function %s by webhook %s', - webhook_db.function_id, id + 'Invoking function %s(version %s) by webhook %s', + webhook_db.function_id, version, id ) # Setup user context @@ -175,6 +189,7 @@ class WebhooksController(rest.RestController): params = { 'function_id': webhook_db.function_id, + 'function_version': version, 'sync': False, 'input': json.dumps(kwargs), 'description': constants.EXECUTION_BY_WEBHOOK % id diff --git a/qinling/db/api.py b/qinling/db/api.py index a1021ae1..06d778ad 100644 --- a/qinling/db/api.py +++ b/qinling/db/api.py @@ -56,11 +56,12 @@ def transaction(): def delete_all(): """A helper function for testing.""" - delete_jobs(insecure=True) - delete_webhooks(insecure=True) - delete_executions(insecure=True) - delete_functions(insecure=True) - delete_runtimes(insecure=True) + with transaction(): + delete_jobs(insecure=True) + delete_webhooks(insecure=True) + delete_executions(insecure=True) + delete_functions(insecure=True) + delete_runtimes(insecure=True) def conditional_update(model, values, expected_values, **kwargs): diff --git a/qinling/tests/unit/api/controllers/v1/test_webhook.py b/qinling/tests/unit/api/controllers/v1/test_webhook.py index 543918f6..f39b48e7 100644 --- a/qinling/tests/unit/api/controllers/v1/test_webhook.py +++ b/qinling/tests/unit/api/controllers/v1/test_webhook.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from qinling.db import api as db_api from qinling.tests.unit.api import base @@ -65,3 +66,30 @@ class TestWebhookController(base.APITest): self.assertEqual(204, resp.status_int) resp = self.app.get('/v1/webhooks/%s' % webhook_id, expect_errors=True) self.assertEqual(404, resp.status_int) + + def test_post_with_version(self): + db_api.increase_function_version(self.func_id, 0) + + body = { + 'function_id': self.func_id, + 'function_version': 1, + 'description': 'webhook test' + } + resp = self.app.post_json('/v1/webhooks', body) + + self.assertEqual(201, resp.status_int) + self.assertEqual(1, resp.json.get("function_version")) + + def test_put_with_version(self): + db_api.increase_function_version(self.func_id, 0) + webhook = self.create_webhook(self.func_id) + + self.assertEqual(0, webhook.function_version) + + resp = self.app.put_json( + '/v1/webhooks/%s' % webhook.id, + {'function_version': 1} + ) + + self.assertEqual(200, resp.status_int) + self.assertEqual(1, resp.json.get("function_version"))