diff --git a/qinling/api/controllers/v1/function.py b/qinling/api/controllers/v1/function.py index 5aa6549f..a80b351a 100644 --- a/qinling/api/controllers/v1/function.py +++ b/qinling/api/controllers/v1/function.py @@ -281,6 +281,10 @@ class FunctionsController(rest.RestController): raise exc.NotAllowedException( 'The function is still associated with webhook(s).' ) + if len(func_db.aliases) > 0: + raise exc.NotAllowedException( + 'The function is still associated with function alias(es).' + ) # Even admin user can not delete other project's function because # the trust associated can only be removed by function owner. diff --git a/qinling/api/controllers/v1/function_version.py b/qinling/api/controllers/v1/function_version.py index 25847d28..a4077366 100644 --- a/qinling/api/controllers/v1/function_version.py +++ b/qinling/api/controllers/v1/function_version.py @@ -243,7 +243,17 @@ class FunctionVersionsController(rest.RestController): ) if len(version_webhook) > 0: raise exc.NotAllowedException( - 'The function versioin is still associated with webhook.' + 'The function version is still associated with webhook.' + ) + + filters = rest_utils.get_filters( + function_id=version_db.function_id, + function_version=version_db.version_number + ) + version_aliases = db_api.get_function_aliases(**filters) + if len(version_aliases) > 0: + raise exc.NotAllowedException( + 'The function version is still associated with alias.' ) # Delete resources for function version diff --git a/qinling/db/sqlalchemy/models.py b/qinling/db/sqlalchemy/models.py index d7764532..a7f2d7d1 100644 --- a/qinling/db/sqlalchemy/models.py +++ b/qinling/db/sqlalchemy/models.py @@ -164,3 +164,7 @@ Function.versions = relationship( lazy='select', cascade="all, delete-orphan" ) +Function.aliases = relationship( + "FunctionAlias", + uselist=True +) diff --git a/qinling/tests/unit/api/controllers/v1/test_function.py b/qinling/tests/unit/api/controllers/v1/test_function.py index a3c70dba..9966b43d 100644 --- a/qinling/tests/unit/api/controllers/v1/test_function.py +++ b/qinling/tests/unit/api/controllers/v1/test_function.py @@ -377,6 +377,23 @@ class TestFunctionController(base.APITest): self.assertEqual(403, resp.status_int) + def test_delete_with_alias(self): + db_func = self.create_function(runtime_id=self.runtime_id) + func_id = db_func.id + name = self.rand_name(name="alias", prefix=self.prefix) + body = { + 'function_id': func_id, + 'name': name + } + db_api.create_function_alias(**body) + + resp = self.app.delete( + '/v1/functions/%s' % func_id, + expect_errors=True + ) + + self.assertEqual(403, resp.status_int) + @mock.patch('qinling.rpc.EngineClient.scaleup_function') def test_scale_up(self, scaleup_function_mock): db_func = self.create_function(runtime_id=self.runtime_id) diff --git a/qinling/tests/unit/api/controllers/v1/test_function_version.py b/qinling/tests/unit/api/controllers/v1/test_function_version.py index 048920f9..337c2db5 100644 --- a/qinling/tests/unit/api/controllers/v1/test_function_version.py +++ b/qinling/tests/unit/api/controllers/v1/test_function_version.py @@ -190,6 +190,24 @@ class TestFunctionVersionController(base.APITest): self.assertEqual(403, resp.status_int) + def test_delete_with_alias(self): + db_api.increase_function_version(self.func_id, 0, + description="version 1") + name = self.rand_name(name="alias", prefix=self.prefix) + body = { + 'function_id': self.func_id, + 'function_version': 1, + 'name': name + } + db_api.create_function_alias(**body) + + resp = self.app.delete( + '/v1/functions/%s/versions/1' % self.func_id, + expect_errors=True + ) + + self.assertEqual(403, resp.status_int) + @mock.patch('qinling.rpc.EngineClient.scaleup_function') def test_scale_up(self, scaleup_function_mock): db_api.increase_function_version(self.func_id, 0)