Fix self.fields on API Port object
All fields from objects.Port were being added to self.fields in the API Port object. Because of this, when someone would POST, there'd be an entry for {'id': None} in the dictionary passed to dbapi.create_port(). We should only set fields we're exposing. This also required fixing PATCH to not try to look at fields not set on the API Port object when mapping to objects.Port. Change-Id: I7f163d42d1298ce4ba62b1b7d637fb0a4e3409ce
This commit is contained in:
parent
c95bba10f5
commit
e0efab0b28
@ -87,12 +87,23 @@ class Port(base.APIBase):
|
||||
"A list containing a self link and associated port links"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = objects.Port.fields.keys()
|
||||
self.fields = []
|
||||
fields = list(objects.Port.fields.keys())
|
||||
# NOTE(lucasagomes): node_uuid is not part of objects.Port.fields
|
||||
# because it's an API-only attribute
|
||||
self.fields.append('node_uuid')
|
||||
for k in self.fields:
|
||||
setattr(self, k, kwargs.get(k))
|
||||
fields.append('node_uuid')
|
||||
for field in fields:
|
||||
# Skip fields we do not expose.
|
||||
if not hasattr(self, field):
|
||||
continue
|
||||
self.fields.append(field)
|
||||
setattr(self, field, kwargs.get(field))
|
||||
|
||||
# NOTE(lucasagomes): node_id is an attribute created on-the-fly
|
||||
# by _set_node_uuid(), it needs to be present in the fields so
|
||||
# that as_dict() will contain node_id field when converting it
|
||||
# before saving it in the database.
|
||||
self.fields.append('node_id')
|
||||
setattr(self, 'node_uuid', kwargs.get('node_id'))
|
||||
|
||||
@classmethod
|
||||
@ -307,8 +318,13 @@ class PortsController(rest.RestController):
|
||||
|
||||
# Update only the fields that have changed
|
||||
for field in objects.Port.fields:
|
||||
if rpc_port[field] != getattr(port, field):
|
||||
rpc_port[field] = getattr(port, field)
|
||||
try:
|
||||
patch_val = getattr(port, field)
|
||||
except AttributeError:
|
||||
# Ignore fields that aren't exposed in the API
|
||||
continue
|
||||
if rpc_port[field] != patch_val:
|
||||
rpc_port[field] = patch_val
|
||||
|
||||
rpc_node = objects.Node.get_by_id(pecan.request.context,
|
||||
rpc_port.node_id)
|
||||
|
@ -508,6 +508,17 @@ class TestPost(base.FunctionalTest):
|
||||
self.assertEqual(urlparse.urlparse(response.location).path,
|
||||
expected_location)
|
||||
|
||||
def test_create_port_doesnt_contain_id(self):
|
||||
with mock.patch.object(self.dbapi, 'create_port',
|
||||
wraps=self.dbapi.create_port) as cp_mock:
|
||||
pdict = post_get_test_port(extra={'foo': 123})
|
||||
self.post_json('/ports', pdict)
|
||||
result = self.get_json('/ports/%s' % pdict['uuid'])
|
||||
self.assertEqual(pdict['extra'], result['extra'])
|
||||
cp_mock.assert_called_once_with(mock.ANY)
|
||||
# Check that 'id' is not in first arg of positional args
|
||||
self.assertNotIn('id', cp_mock.call_args[0][0])
|
||||
|
||||
def test_create_port_generate_uuid(self):
|
||||
pdict = post_get_test_port()
|
||||
del pdict['uuid']
|
||||
|
Loading…
x
Reference in New Issue
Block a user