Merge "Handle multiple exceptions raised by jsonpatch"

This commit is contained in:
Jenkins 2014-02-06 07:17:42 +00:00 committed by Gerrit Code Review
commit 4f4b0c6c40
8 changed files with 38 additions and 15 deletions

View File

@ -31,7 +31,7 @@ from ironic.api.controllers.v1 import collection
from ironic.api.controllers.v1 import link
from ironic.api.controllers.v1 import node
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils
from ironic.api.controllers.v1 import utils as api_utils
from ironic.common import exception
from ironic import objects
from ironic.openstack.common import excutils
@ -130,8 +130,8 @@ class ChassisController(rest.RestController):
def _get_chassis_collection(self, marker, limit, sort_key, sort_dir,
expand=False, resource_url=None):
limit = utils.validate_limit(limit)
sort_dir = utils.validate_sort_dir(sort_dir)
limit = api_utils.validate_limit(limit)
sort_dir = api_utils.validate_sort_dir(sort_dir)
marker_obj = None
if marker:
marker_obj = objects.Chassis.get_by_uuid(pecan.request.context,
@ -213,9 +213,8 @@ class ChassisController(rest.RestController):
try:
chassis = Chassis(**jsonpatch.apply_patch(rpc_chassis.as_dict(),
jsonpatch.JsonPatch(patch)))
except jsonpatch.JsonPatchException as e:
LOG.exception(e)
raise wsme.exc.ClientSideError(_("Patching Error: %s") % e)
except api_utils.JSONPATCH_EXCEPTIONS as e:
raise exception.PatchError(patch=patch, reason=e)
# Update only the fields that have changed
for field in objects.Chassis.fields:

View File

@ -588,9 +588,8 @@ class NodesController(rest.RestController):
try:
node = Node(**jsonpatch.apply_patch(rpc_node.as_dict(),
jsonpatch.JsonPatch(patch)))
except jsonpatch.JsonPatchException as e:
LOG.exception(e)
raise wsme.exc.ClientSideError(_("Patching Error: %s") % e)
except api_utils.JSONPATCH_EXCEPTIONS as e:
raise exception.PatchError(patch=patch, reason=e)
# Update only the fields that have changed
for field in objects.Node.fields:

View File

@ -276,9 +276,8 @@ class PortsController(rest.RestController):
try:
port = Port(**jsonpatch.apply_patch(rpc_port.as_dict(),
jsonpatch.JsonPatch(patch)))
except jsonpatch.JsonPatchException as e:
LOG.exception(e)
raise wsme.exc.ClientSideError(_("Patching Error: %s") % e)
except api_utils.JSONPATCH_EXCEPTIONS as e:
raise exception.PatchError(patch=patch, reason=e)
# Update only the fields that have changed
for field in objects.Port.fields:

View File

@ -16,6 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import jsonpatch
import wsme
from oslo.config import cfg
@ -23,6 +24,11 @@ from oslo.config import cfg
CONF = cfg.CONF
JSONPATCH_EXCEPTIONS = (jsonpatch.JsonPatchException,
jsonpatch.JsonPointerException,
KeyError)
def validate_limit(limit):
if limit and limit < 0:
raise wsme.exc.ClientSideError(_("Limit must be positive"))

View File

@ -139,6 +139,10 @@ class InvalidStateRequested(Invalid):
message = _("Invalid state '%(state)s' requested for node %(node)s.")
class PatchError(Invalid):
message = _("Couldn't apply patch '%(patch)s'. Reason: %(reason)s")
class InstanceDeployFailure(IronicException):
message = _("Failed to deploy instance: %(reason)s")

View File

@ -234,6 +234,15 @@ class TestPatch(base.FunctionalTest):
self.assertEqual(result['uuid'], cdict['uuid'])
self.assertEqual(result['description'], cdict['description'])
def test_remove_non_existent_property_fail(self):
cdict = dbutils.get_test_chassis()
response = self.patch_json('/chassis/%s' % cdict['uuid'],
[{'path': '/extra/non-existent', 'op': 'remove'}],
expect_errors=True)
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.status_code, 400)
self.assertTrue(response.json['error_message'])
def test_add_singular(self):
cdict = dbutils.get_test_chassis()
response = self.patch_json('/chassis/%s' % cdict['uuid'],

View File

@ -433,13 +433,12 @@ class TestPatch(base.FunctionalTest):
self.mock_update_node.assert_called_once_with(
mock.ANY, mock.ANY, 'test-topic')
def test_remove_fail(self):
def test_remove_non_existent_property_fail(self):
response = self.patch_json('/nodes/%s' % self.node['uuid'],
[{'path': '/extra/non-existent', 'op': 'remove'}],
expect_errors=True)
self.assertEqual(response.content_type, 'application/json')
# FIXME(lucasagomes): It should return 400 instead of 500
self.assertEqual(response.status_code, 500)
self.assertEqual(response.status_code, 400)
self.assertTrue(response.json['error_message'])
def test_update_state_in_progress(self):

View File

@ -257,6 +257,14 @@ class TestPatch(base.FunctionalTest):
self.assertEqual(result['uuid'], pdict['uuid'])
self.assertEqual(result['address'], pdict['address'])
def test_remove_non_existent_property_fail(self):
response = self.patch_json('/ports/%s' % self.pdict['uuid'],
[{'path': '/extra/non-existent', 'op': 'remove'}],
expect_errors=True)
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.status_code, 400)
self.assertTrue(response.json['error_message'])
def test_remove_mandatory_field(self):
pdict = post_get_test_port(address="AA:BB:CC:DD:EE:FF",
uuid=utils.generate_uuid())