Merge "Fix nits found in node traits"

This commit is contained in:
Zuul 2018-01-30 20:38:55 +00:00 committed by Gerrit Code Review
commit 51a0b8143a
6 changed files with 43 additions and 21 deletions

View File

@ -826,6 +826,11 @@ class NodeTraitsController(rest.RestController):
notify.emit_end_notification(context, node, 'update',
chassis_uuid=chassis_uuid)
if not replace:
# For single traits, set the HTTP Location Header.
url_args = '/'.join((self.node_ident, 'traits', trait))
pecan.response.location = link.build_url('nodes', url_args)
@METRICS.timer('NodeTraitsController.delete')
@expose.expose(None, wtypes.text,
status_code=http_client.NO_CONTENT)

View File

@ -81,9 +81,9 @@ def _get_node_query_with_all():
:returns: a query object.
"""
return model_query(models.Node)\
.options(joinedload('tags'))\
.options(joinedload('traits'))
return (model_query(models.Node)
.options(joinedload('tags'))
.options(joinedload('traits')))
def model_query(model, *args, **kwargs):
@ -342,9 +342,6 @@ class Connection(api.Connection):
node = models.Node()
node.update(values)
# Set tags & traits to [] for new created node
node['tags'] = []
node['traits'] = []
with _session_for_write() as session:
try:
session.add(node)
@ -357,7 +354,13 @@ class Connection(api.Connection):
instance_uuid=values['instance_uuid'],
node=values['uuid'])
raise exception.NodeAlreadyExists(uuid=values['uuid'])
return node
# Set tags & traits to [] for new created node
# NOTE(mgoddard): We need to set the tags and traits fields in the
# session context, otherwise SQLAlchemy will try and fail to lazy
# load the attributes, resulting in an exception being raised.
node['tags'] = []
node['traits'] = []
return node
def get_node_by_id(self, node_id):
query = _get_node_query_with_all()

View File

@ -4363,6 +4363,7 @@ class TestTraits(test_api_base.BaseApiTest):
notify_args = mock_notify.call_args_list
self.assertEqual(traits, notify_args[0][0][1].traits.get_trait_names())
self.assertEqual(traits, notify_args[1][0][1].traits.get_trait_names())
self.assertIsNone(ret.location)
@mock.patch.object(rpcapi.ConductorAPI, 'add_node_traits')
@mock.patch.object(notification_utils, '_emit_api_notification')
@ -4391,6 +4392,7 @@ class TestTraits(test_api_base.BaseApiTest):
notify_args = mock_notify.call_args_list
self.assertEqual(traits, notify_args[0][0][1].traits.get_trait_names())
self.assertEqual(traits, notify_args[1][0][1].traits.get_trait_names())
self.assertIsNone(ret.location)
@mock.patch.object(rpcapi.ConductorAPI, 'add_node_traits')
@mock.patch.object(notification_utils, '_emit_api_notification')
@ -4414,6 +4416,7 @@ class TestTraits(test_api_base.BaseApiTest):
notify_args = mock_notify.call_args_list
self.assertEqual([], notify_args[0][0][1].traits.get_trait_names())
self.assertEqual([], notify_args[1][0][1].traits.get_trait_names())
self.assertIsNone(ret.location)
@mock.patch.object(rpcapi.ConductorAPI, 'add_node_traits')
@mock.patch.object(notification_utils, '_emit_api_notification')
@ -4480,6 +4483,11 @@ class TestTraits(test_api_base.BaseApiTest):
notify_args = mock_notify.call_args_list
self.assertEqual(traits, notify_args[0][0][1].traits.get_trait_names())
self.assertEqual(traits, notify_args[1][0][1].traits.get_trait_names())
# Check location header.
self.assertIsNotNone(ret.location)
expected_location = '/v1/nodes/%s/traits/CUSTOM_3' % self.node.name
self.assertEqual(expected_location,
urlparse.urlparse(ret.location).path)
@mock.patch.object(rpcapi.ConductorAPI, 'add_node_traits')
@mock.patch.object(notification_utils, '_emit_api_notification')
@ -4606,7 +4614,7 @@ class TestTraits(test_api_base.BaseApiTest):
self.assertEqual(traits, notify_args[0][0][1].traits.get_trait_names())
self.assertEqual(traits, notify_args[1][0][1].traits.get_trait_names())
def test_add_single_traits_fails_with_bad_version(self):
def test_add_single_trait_fails_with_bad_version(self):
ret = self.put_json('/nodes/%s/traits/CUSTOM_TRAIT1' % self.node.uuid,
{}, headers={api_base.Version.string: "1.36"},
expect_errors=True)

View File

@ -6943,23 +6943,23 @@ class NodeTraitsTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
self.service.add_node_traits(self.context, self.node.id,
self.traits[:1])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits[:1])
self.assertEqual(self.traits[:1], [trait.trait for trait in traits])
self.service.add_node_traits(self.context, self.node.id,
self.traits[1:])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits)
self.assertEqual(self.traits, [trait.trait for trait in traits])
def test_add_node_traits_replace(self):
self.service.add_node_traits(self.context, self.node.id,
self.traits[:1], replace=True)
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits[:1])
self.assertEqual(self.traits[:1], [trait.trait for trait in traits])
self.service.add_node_traits(self.context, self.node.id,
self.traits[1:], replace=True)
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits[1:])
self.assertEqual(self.traits[1:], [trait.trait for trait in traits])
def _test_add_node_traits_exception(self, expected_exc):
with mock.patch.object(objects.Trait, 'create') as mock_create:
@ -6970,7 +6970,7 @@ class NodeTraitsTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
# Compare true exception hidden by @messaging.expected_exceptions
self.assertEqual(expected_exc, exc.exc_info[0])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual(traits.objects, [])
self.assertEqual([], traits.objects)
def test_add_node_traits_invalid_parameter_value(self):
self._test_add_node_traits_exception(exception.InvalidParameterValue)
@ -6986,24 +6986,24 @@ class NodeTraitsTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
self.service.remove_node_traits(self.context, self.node.id,
self.traits[:1])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits[1:])
self.assertEqual(self.traits[1:], [trait.trait for trait in traits])
self.service.remove_node_traits(self.context, self.node.id,
self.traits[1:])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual(traits.objects, [])
self.assertEqual([], traits.objects)
def test_remove_node_traits_all(self):
objects.TraitList.create(self.context, self.node.id, self.traits)
self.service.remove_node_traits(self.context, self.node.id, None)
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual(traits.objects, [])
self.assertEqual([], traits.objects)
def test_remove_node_traits_empty(self):
objects.TraitList.create(self.context, self.node.id, self.traits)
self.service.remove_node_traits(self.context, self.node.id, [])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits)
self.assertEqual(self.traits, [trait.trait for trait in traits])
def _test_remove_node_traits_exception(self, expected_exc):
objects.TraitList.create(self.context, self.node.id, self.traits)
@ -7015,7 +7015,7 @@ class NodeTraitsTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
# Compare true exception hidden by @messaging.expected_exceptions
self.assertEqual(expected_exc, exc.exc_info[0])
traits = objects.TraitList.get_by_node_id(self.context, self.node.id)
self.assertEqual([trait.trait for trait in traits], self.traits)
self.assertEqual(self.traits, [trait.trait for trait in traits])
def test_remove_node_traits_node_locked(self):
self._test_remove_node_traits_exception(exception.NodeLocked)

View File

@ -31,7 +31,9 @@ from ironic.tests.unit.db import utils
class DbNodeTestCase(base.DbTestCase):
def test_create_node(self):
utils.create_test_node()
node = utils.create_test_node()
self.assertEqual([], node.tags)
self.assertEqual([], node.traits)
def test_create_node_with_tags(self):
self.assertRaises(exception.InvalidParameterValue,

View File

@ -42,9 +42,10 @@ class TestTraitObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
@mock.patch.object(dbapi.IMPL, 'set_node_traits', autospec=True)
def test_create_list(self, mock_set_traits):
traits = [self.fake_trait['trait']]
fake_trait2 = db_utils.get_test_node_trait(trait='CUSTOM_TRAIT2')
traits = [self.fake_trait['trait'], fake_trait2['trait']]
mock_set_traits.return_value = [self.fake_trait, self.fake_trait]
mock_set_traits.return_value = [self.fake_trait, fake_trait2]
result = objects.TraitList.create(self.context, self.node_id, traits)
@ -52,6 +53,9 @@ class TestTraitObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
self.assertEqual(self.context, result._context)
self.assertEqual(2, len(result))
self.assertEqual(self.fake_trait['node_id'], result[0].node_id)
self.assertEqual(self.fake_trait['trait'], result[0].trait)
self.assertEqual(fake_trait2['node_id'], result[1].node_id)
self.assertEqual(fake_trait2['trait'], result[1].trait)
@mock.patch.object(dbapi.IMPL, 'unset_node_traits', autospec=True)
def test_destroy_list(self, mock_unset_traits):