Validate swift params for swift type function creation
Check the swift related params before sending request to Swift. Change-Id: I29866eeb95f8b6e465d781ed02d2d499413dff54 Story: 2003482 Task: 24882changes/54/597354/2
parent
5f7ba972b6
commit
ffbd3ba111
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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…
Reference in New Issue