Browse Source

Validate swift params for swift type function creation

Check the swift related params before sending request to Swift.

Change-Id: I29866eeb95f8b6e465d781ed02d2d499413dff54
Story: 2003482
Task: 24882
changes/54/597354/2
Lingxian Kong 3 years ago
parent
commit
ffbd3ba111
3 changed files with 134 additions and 13 deletions
  1. +41
    -11
      qinling/api/controllers/v1/function.py
  2. +91
    -0
      qinling/tests/unit/api/controllers/v1/test_function.py
  3. +2
    -2
      qinling/tests/unit/base.py

+ 41
- 11
qinling/api/controllers/v1/function.py View File

@ -201,8 +201,15 @@ class FunctionsController(rest.RestController):
data = kwargs['package'].file.read()
elif source == constants.SWIFT_FUNCTION:
swift_info = values['code'].get('swift', {})
self._check_swift(swift_info.get('container'),
swift_info.get('object'))
if not (swift_info.get('container') and swift_info.get('object')):
raise exc.InputException("Both container and object must be "
"provided for swift type function.")
self._check_swift(
swift_info.get('container'),
swift_info.get('object')
)
else:
create_trust = False
values['entry'] = None
@ -341,11 +348,15 @@ class FunctionsController(rest.RestController):
when function is updating.
"""
values = {}
for key in UPDATE_ALLOWED:
if kwargs.get(key) is not None:
if key == "code":
kwargs[key] = json.loads(kwargs[key])
values.update({key: kwargs[key]})
try:
for key in UPDATE_ALLOWED:
if kwargs.get(key) is not None:
if key == "code":
kwargs[key] = json.loads(kwargs[key])
values.update({key: kwargs[key]})
except Exception as e:
raise exc.InputException("Invalid input, %s" % str(e))
LOG.info('Update function %s, params: %s', id, values)
ctx = context.get_ctx()
@ -416,10 +427,29 @@ class FunctionsController(rest.RestController):
values.pop('package')
# Swift type function
if pre_source == constants.SWIFT_FUNCTION:
swift_info = values['code'].get('swift', {})
self._check_swift(swift_info.get('container'),
swift_info.get('object'))
if (pre_source == constants.SWIFT_FUNCTION and
"swift" in values.get('code', {})):
swift_info = values['code']["swift"]
if not (swift_info.get('container') or
swift_info.get('object')):
raise exc.InputException(
"Either container or object must be provided for "
"swift type function update."
)
new_swift_info = pre_func.code['swift']
new_swift_info.update(swift_info)
self._check_swift(
new_swift_info.get('container'),
new_swift_info.get('object')
)
values['code'] = {
"source": pre_source,
"swift": new_swift_info
}
# Delete allocated resources in orchestrator and etcd.
self.engine_client.delete_function(id)


+ 91
- 0
qinling/tests/unit/api/controllers/v1/test_function.py View File

@ -102,6 +102,25 @@ class TestFunctionController(base.APITest):
)
self._assertDictContainsSubset(resp.json, body)
def test_post_swift_not_enough_params(self):
body = {
'name': 'swift_function',
'code': json.dumps(
{
"source": "swift",
"swift": {"container": "fake-container"}
}
),
'runtime_id': self.runtime_id,
}
resp = self.app.post(
'/v1/functions',
params=body,
expect_errors=True
)
self.assertEqual(400, resp.status_int)
@mock.patch('qinling.utils.openstack.keystone.get_swiftclient')
@mock.patch('qinling.context.AuthHook.before')
def test_post_swift_size_exceed(self, mock_auth, mock_client):
@ -242,6 +261,78 @@ class TestFunctionController(base.APITest):
self.assertEqual(400, resp.status_int)
@mock.patch('qinling.rpc.EngineClient.delete_function')
@mock.patch('qinling.utils.etcd_util.delete_function')
@mock.patch('qinling.utils.openstack.swift.check_object')
@mock.patch('qinling.context.AuthHook.before')
def test_put_swift_function(self, mock_auth, mock_check, mock_etcd_delete,
mock_func_delete):
self.override_config('auth_enable', True, group='pecan')
mock_check.return_value = True
db_func = self.create_function(
runtime_id=self.runtime_id,
code={
"source": "swift",
"swift": {"container": "fake-container", "object": "fake-obj"}
}
)
body = {
'code': json.dumps(
{
"source": "swift",
"swift": {"object": "new-obj"}
}
),
}
resp = self.app.put_json('/v1/functions/%s' % db_func.id, body)
self.assertEqual(200, resp.status_int)
swift_info = {
'code': {
"source": "swift",
"swift": {"container": "fake-container", "object": "new-obj"}
}
}
self._assertDictContainsSubset(resp.json, swift_info)
@mock.patch('qinling.rpc.EngineClient.delete_function')
@mock.patch('qinling.utils.etcd_util.delete_function')
@mock.patch('qinling.utils.openstack.swift.check_object')
@mock.patch('qinling.context.AuthHook.before')
def test_put_swift_function_without_source(self, mock_auth, mock_check,
mock_etcd_delete,
mock_func_delete):
self.override_config('auth_enable', True, group='pecan')
mock_check.return_value = True
db_func = self.create_function(
runtime_id=self.runtime_id,
code={
"source": "swift",
"swift": {"container": "fake-container", "object": "fake-obj"}
}
)
body = {
'code': json.dumps(
{
"swift": {"object": "new-obj"}
}
),
}
resp = self.app.put_json('/v1/functions/%s' % db_func.id, body)
self.assertEqual(200, resp.status_int)
swift_info = {
'code': {
"source": "swift",
"swift": {"container": "fake-container", "object": "new-obj"}
}
}
self._assertDictContainsSubset(resp.json, swift_info)
def test_put_cpu_with_type_error(self):
db_func = self.create_function(runtime_id=self.runtime_id)


+ 2
- 2
qinling/tests/unit/base.py View File

@ -182,7 +182,7 @@ class DbTestCase(BaseTest):
return runtime
def create_function(self, runtime_id=None):
def create_function(self, runtime_id=None, code=None):
if not runtime_id:
runtime_id = self.create_runtime().id
@ -190,7 +190,7 @@ class DbTestCase(BaseTest):
{
'name': self.rand_name('function', prefix=self.prefix),
'runtime_id': runtime_id,
'code': {"source": "package", "md5sum": "fake_md5"},
'code': code or {"source": "package", "md5sum": "fake_md5"},
'entry': 'main.main',
# 'auth_enable' is disabled by default, we create runtime for
# default tenant.


Loading…
Cancel
Save