Skip to content

Commit

Permalink
Merge "Use the base Resource's JSON patch support in Image"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and openstack-gerrit committed Aug 20, 2018
2 parents 26cf0ba + 04f7af7 commit af01ae2
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 45 deletions.
3 changes: 1 addition & 2 deletions openstack/image/v2/_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ def update_image(self, image, **attrs):
:returns: The updated image
:rtype: :class:`~openstack.image.v2.image.Image`
"""
res = self._get_resource(_image.Image, image)
return res.commit(self, **attrs)
return self._update(_image.Image, image, **attrs)

def deactivate_image(self, image):
"""Deactivate an image
Expand Down
39 changes: 13 additions & 26 deletions openstack/image/v2/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@

import hashlib

import copy
import jsonpatch

from openstack import _log
from openstack import exceptions
from openstack.image import image_service
Expand All @@ -36,6 +33,7 @@ class Image(resource.Resource):
allow_delete = True
allow_list = True
commit_method = 'PATCH'
commit_jsonpatch = True

_query_mapping = resource.QueryParameters(
"name", "visibility",
Expand Down Expand Up @@ -117,12 +115,6 @@ class Image(resource.Resource):
#: when you set the show_image_direct_url option to true in the
#: Image service's configuration file.
direct_url = resource.Body('direct_url')
#: An image property.
path = resource.Body('path')
#: Value of image property used in add or replace operations expressed
#: in JSON notation. For example, you must enclose strings in quotation
#: marks, and you do not enclose numeric values in quotation marks.
value = resource.Body('value')
#: The URL to access the image file kept in external store.
url = resource.Body('url')
#: The location metadata.
Expand Down Expand Up @@ -297,21 +289,16 @@ def download(self, session, stream=False):

return resp.content

def commit(self, session, **attrs):
url = utils.urljoin(self.base_path, self.id)
headers = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
'Accept': ''
}
original = self.to_dict()

# Update values from **attrs so they can be passed to jsonpatch
new = copy.deepcopy(self.to_dict())
new.update(**attrs)
def _prepare_request(self, requires_id=None, prepend_key=False,
patch=False):
request = super(Image, self)._prepare_request(requires_id=requires_id,
prepend_key=prepend_key,
patch=patch)
if patch:
headers = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
'Accept': ''
}
request.headers.update(headers)

patch_string = jsonpatch.make_patch(original, new).to_string()
resp = session.patch(url,
data=patch_string,
headers=headers)
self._translate_response(resp, has_body=True)
return self
return request
28 changes: 11 additions & 17 deletions openstack/tests/unit/image/v2/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.

import json
import operator

from keystoneauth1 import adapter
Expand Down Expand Up @@ -45,8 +44,6 @@
'file': '15',
'locations': ['15', '16'],
'direct_url': '17',
'path': '18',
'value': '19',
'url': '20',
'metadata': {'21': '22'},
'architecture': '23',
Expand Down Expand Up @@ -142,8 +139,6 @@ def test_make_it(self):
self.assertEqual(EXAMPLE['file'], sot.file)
self.assertEqual(EXAMPLE['locations'], sot.locations)
self.assertEqual(EXAMPLE['direct_url'], sot.direct_url)
self.assertEqual(EXAMPLE['path'], sot.path)
self.assertEqual(EXAMPLE['value'], sot.value)
self.assertEqual(EXAMPLE['url'], sot.url)
self.assertEqual(EXAMPLE['metadata'], sot.metadata)
self.assertEqual(EXAMPLE['architecture'], sot.architecture)
Expand Down Expand Up @@ -312,7 +307,9 @@ def test_download_stream(self):
self.assertEqual(rv, resp)

def test_image_update(self):
sot = image.Image(**EXAMPLE)
values = EXAMPLE.copy()
del values['instance_uuid']
sot = image.Image(**values)
# Let the translate pass through, that portion is tested elsewhere
sot._translate_response = mock.Mock()

Expand All @@ -326,21 +323,18 @@ def test_image_update(self):
resp.status_code = 200
self.sess.patch.return_value = resp

value = ('[{"value": "fake_name", "op": "replace", "path": "/name"}, '
'{"value": "fake_value", "op": "add", '
'"path": "/new_property"}]')
fake_img = sot.to_dict()
fake_img['name'] = 'fake_name'
fake_img['new_property'] = 'fake_value'
value = [{"value": "fake_name", "op": "replace", "path": "/name"},
{"value": "fake_value", "op": "add",
"path": "/instance_uuid"}]

sot.commit(self.sess, **fake_img)
sot.name = 'fake_name'
sot.instance_uuid = 'fake_value'
sot.commit(self.sess)
url = 'images/' + IDENTIFIER
self.sess.patch.assert_called_once()
call = self.sess.patch.call_args
call_args, call_kwargs = call
self.assertEqual(url, call_args[0])
self.assertEqual(
sorted(json.loads(value), key=operator.itemgetter('value')),
sorted(
json.loads(call_kwargs['data']),
key=operator.itemgetter('value')))
sorted(value, key=operator.itemgetter('value')),
sorted(call_kwargs['json'], key=operator.itemgetter('value')))
5 changes: 5 additions & 0 deletions releasenotes/notes/image-update-76bd3bf24c1c1380.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
upgrade:
- |
When using the Image API, it is no longer possible to set arbitrary
properties, not known to the SDK, via ``image.update_image`` API.

0 comments on commit af01ae2

Please sign in to comment.