Remove all references to images v1

*Images v1 will soon be deprecated so the test code needs to  be removed
*Removed images v1 behaviors
*Removed images v1 client
*Removed images v1 models
*Removed images v1 metatests

Change-Id: If7279be4096c525780877d84a465930d0000341c
This commit is contained in:
Luke Wollney 2014-07-14 11:00:45 -05:00
parent 535be48912
commit 96b46e789c
12 changed files with 0 additions and 996 deletions

View File

@ -1,15 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

View File

@ -1,121 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import time
import cStringIO as StringIO
from cafe.engine.behaviors import BaseBehavior
from cloudcafe.auth.config import UserAuthConfig
from cloudcafe.auth.provider import AuthProvider
from cloudcafe.identity.v2_0.tenants_api.client import \
TenantsAPI_Client
from cloudcafe.images.common.types import ImageStatus
from cloudcafe.common.exceptions import \
TimeoutException, BuildErrorException
class ImagesV1Behaviors(BaseBehavior):
"""
@summary: Base Behaviors class for Images V1 API tests
"""
def __init__(self, images_client, images_config):
super(ImagesV1Behaviors, self).__init__()
self.config = images_config
self.client = images_client
access_data = AuthProvider().get_access_data()
self.tenants_client = TenantsAPI_Client(
UserAuthConfig().auth_endpoint,
access_data.token.id_,
'json', 'json')
def wait_for_image_status(self, image_id, desired_status,
interval_time=None, timeout=None):
"""Waits for a image to reach a desired status
@param image_id: The uuid of the image
@type image_id: String
@param desired_status: The desired final status of the image
@type desired_status: String
@param interval_time: The amount of time in seconds to wait
between polling
@type interval_time: Integer
@param interval_time: The amount of time in seconds to wait
before aborting
@type interval_time: Integer
@return: Response object containing response and the image
domain object
@rtype: requests.Response
"""
interval_time = interval_time or self.config.image_status_interval
timeout = timeout or self.config.snapshot_timeout
end_time = time.time() + timeout
while time.time() < end_time:
resp = self.client.retrieve_metadata(image_id)
image_id = resp.headers['x-image-meta-id']
image_status = resp.headers['x-image-meta-status']
if image_status == ImageStatus.ERROR:
raise BuildErrorException(
'Build failed. Image with uuid {0} entered ERROR status.'
.format(image_id))
if image_status == desired_status:
break
time.sleep(interval_time)
else:
raise TimeoutException(
"wait_for_image_status ran for {0} seconds and did not "
"observe the image achieving the {1} status.".format(
timeout, desired_status))
return resp
def create_remote_image(self, name, container_format, disk_format):
"""Create new remote image.
@return ID of the newly registered image
"""
name = 'New Remote Image {0}'.format(name)
response = self.client.add_image(
name,
None,
image_meta_container_format=container_format,
image_meta_disk_format=disk_format,
image_meta_is_public=True,
image_meta_location=self.config.remote_image)
return response.entity.id_
def create_standard_image(cls, name, container_format, disk_format, size):
"""Create new standard image.
@return ID of the newly registered image
"""
image_data = StringIO.StringIO('*' * size)
name = 'New Standard Image {0}'.format(name)
response = cls.client.add_image(
name,
image_data,
image_meta_container_format=container_format,
image_meta_disk_format=disk_format,
image_meta_is_public=True)
return response.entity.id_

View File

@ -1,183 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from cafe.engine.http.client import AutoMarshallingHTTPClient
from cloudcafe.images.v1.models.image import Image, ImageMinList
from cloudcafe.images.v1.models.member import MemberList
class ImagesClient(AutoMarshallingHTTPClient):
"""Client for Image API."""
def __init__(self, url, auth_token, serialize_format, deserialize_format):
"""
@param url: Base URL for the compute service
@type url: String
@param auth_token: Auth token to be used for all requests
@type auth_token: String
@param serialize_format: Format for serializing requests
@type serialize_format: String
@param deserialize_format: Format for de-serializing responses
@type deserialize_format: String
"""
super(ImagesClient, self).__init__(
serialize_format,
deserialize_format)
self.auth_token = auth_token
self.default_headers['X-Auth-Token'] = auth_token
self.default_headers['Content-Type'] = 'application/{0}'.format(
self.serialize_format)
self.default_headers['Accept'] = 'application/{0}'.format(
self.deserialize_format)
self.url = url
def list_images(self, requestslib_kwargs=None):
url = '{0}/images'.format(self.url)
return self.request('GET', url, response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def list_images_detail(self, parameters_list, requestslib_kwargs=None):
url = '{0}/images/detail'.format(self.url)
return self.request('GET', url, params=parameters_list,
response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def get_image(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}'.format(self.url, image_id)
return self.request('GET', url, response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def delete_image(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}'.format(self.url, image_id)
return self.request('DELETE', url, response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def filter_images_list(self, parameters_list, requestslib_kwargs=None):
url = '{0}/images'.format(self.url)
return self.request('GET', url, params=parameters_list,
response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def retrieve_metadata(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}'.format(self.url, image_id)
return self.request('HEAD',
url,
requestslib_kwargs=requestslib_kwargs)
def retrieve_raw_image_data(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}'.format(self.url, image_id)
return self.request('GET', url, requestslib_kwargs=requestslib_kwargs)
def add_image(self, image_name, image_data=None, headers=None,
image_meta_id=None, image_meta_store=None,
image_meta_disk_format=None,
image_meta_container_format=None, image_meta_size=None,
image_meta_checksum=None, image_meta_is_public=None,
image_meta_min_ram=None, image_meta_min_disk=None,
image_meta_owner=None, image_meta_property=None,
image_meta_location=None,
requestslib_kwargs=None):
headers = headers if headers else {}
if image_data:
headers['Content-Type'] = 'application/octet-stream'
headers['x-image-meta-name'] = image_name
headers['x-image-meta-id'] = image_meta_id
headers['x-image-meta-store'] = image_meta_store
headers['x-image-meta-disk-format'] = image_meta_disk_format
headers['x-image-meta-container-format'] = image_meta_container_format
headers['x-image-meta-size'] = image_meta_size
headers['x-image-meta-checksum'] = image_meta_checksum
headers['x-image-meta-is-public'] = image_meta_is_public
headers['x-image-meta-min-ram'] = image_meta_min_ram
headers['x-image-meta-min-disk'] = image_meta_min_disk
headers['x-image-meta-owner'] = image_meta_owner
headers['x-image-meta-location'] = image_meta_location
if image_meta_property:
for key, val in image_meta_property.items():
headers['x-image-meta-property-{0}'.format(key)] = val
url = '{0}/images'.format(self.url)
return self.request('POST', url, headers=headers, data=image_data,
response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def list_image_membership(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}/members'.format(self.url, image_id)
return self.request('GET', url,
response_entity_type=MemberList,
requestslib_kwargs=requestslib_kwargs)
def update_image(self, image_id, image_data=None, headers=None,
image_meta_name=None, image_meta_store=None,
image_meta_disk_format=None,
image_meta_container_format=None, image_meta_size=None,
image_meta_checksum=None, image_meta_is_public=None,
image_meta_min_ram=None, image_meta_min_disk=None,
image_meta_owner=None, image_meta_property=None,
image_meta_location=None,
requestslib_kwargs=None):
headers = headers if headers else {}
if image_data:
headers['Content-Type'] = 'application/octet-stream'
headers['x-image-meta-name'] = image_meta_name
headers['x-image-meta-store'] = image_meta_store
headers['x-image-meta-disk-format'] = image_meta_disk_format
headers['x-image-meta-container-format'] = image_meta_container_format
headers['x-image-meta-size'] = image_meta_size
headers['x-image-meta-checksum'] = image_meta_checksum
headers['x-image-meta-is-public'] = image_meta_is_public
headers['x-image-meta-min-ram'] = image_meta_min_ram
headers['x-image-meta-min-disk'] = image_meta_min_disk
headers['x-image-meta-owner'] = image_meta_owner
headers['x-image-meta-location'] = image_meta_location
if image_meta_property:
for key, val in image_meta_property.items():
headers['x-image-meta-property-{0}'.format(key)] = val
url = '{0}/images/{1}'.format(self.url, image_id)
return self.request('PUT', url, headers=headers,
data=image_data,
response_entity_type=Image,
requestslib_kwargs=requestslib_kwargs)
def list_shared_images(self, member_id, requestslib_kwargs=None):
url = '{0}/shared-images/{1}'.format(self.url, member_id)
return self.request('GET', url, response_entity_type=ImageMinList,
requestslib_kwargs=requestslib_kwargs)
def add_member_to_image(self, image_id, member_id,
requestslib_kwargs=None):
url = '{0}/images/{1}/members/{2}'.format(self.url, image_id,
member_id)
return self.request('PUT', url, requestslib_kwargs=requestslib_kwargs)
def delete_member_from_image(self, image_id, member_id,
requestslib_kwargs=None):
url = '{0}/images/{1}/members/{2}'.format(self.url, image_id,
member_id)
return self.request('DELETE', url,
requestslib_kwargs=requestslib_kwargs)
def replace_members_list(self, image_id, requestslib_kwargs=None):
url = '{0}/images/{1}/members'.format(self.url, image_id)
return self.request('PUT', url, requestslib_kwargs=requestslib_kwargs)

View File

@ -1,15 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

View File

@ -1,172 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from copy import deepcopy
from cafe.engine.models.base import AutoMarshallingModel
from cloudcafe.compute.common.equality_tools import EqualityTools
from datetime import datetime
import json
class Image(AutoMarshallingModel):
"""@Summary Complete model of an image"""
def __init__(self, id_=None, status=None, name=None, container_format=None,
disk_format=None, owner=None, checksum=None, min_ram=None,
min_disk=None, size=None, deleted=None, protected=None,
is_public=None, properties=None, created_at=None,
updated_at=None, deleted_at=None, members_list=None):
super(Image, self).__init__()
self.id_ = id_
self.status = status
self.name = name
self.deleted = deleted
self.container_format = container_format
self.created_at = created_at
self.disk_format = disk_format
self.updated_at = updated_at
self.owner = owner
self.protected = protected
self.min_ram = min_ram
self.checksum = checksum
self.min_disk = min_disk
self.is_public = is_public
self.deleted_at = deleted_at
self.properties = properties
self.size = size
self.members_list = members_list
def __eq__(self, other):
"""
@summary: Overrides the default equals
@param other: Image object to compare with
@type other: Image
@return: True if Image objects are equal, False otherwise
@rtype: bool
"""
return EqualityTools.are_objects_equal(self, other, '_log')
def __ne__(self, other):
"""
@summary: Overrides the default not-equals
@param other: Image object to compare with
@type other: Image
@return: True if Image objects are not equal, False otherwise
@rtype: bool
"""
return not self.__eq__(other)
def __repr__(self):
values = []
for prop in self.__dict__:
if prop in ['created_at', 'updated_at', 'deleted_at']:
date_property = self.__dict__[prop]
date_string = 'None' or \
date_property.strftime('%Y-%m-%dT%H:%M:%S')
values.append("{0}: {1}".format(prop, date_string))
else:
values.append("{0}: {1}".format(prop, self.__dict__[prop]))
return '[ {0} ]'.format(', '.join(values))
@classmethod
def _json_to_obj(cls, serialized_str):
serialized_str.replace('false', 'False')
serialized_str.replace('true', 'True')
json_dict = json.loads(serialized_str)
if 'images' in json_dict.keys():
images = []
for image in json_dict['images']:
images.append(cls._dict_to_obj(image))
return images
else:
image_str = json_dict['image']
return cls._dict_to_obj(image_str)
@classmethod
def _dict_to_obj(cls, json_dict):
"""@summary: Processing dates in converting string to date objects"""
json_dict = deepcopy(json_dict)
json_dict['id_'] = json_dict.pop('id')
for date_key in ['created_at', 'updated_at', 'deleted_at']:
if json_dict.get(date_key):
json_dict[date_key] = None or datetime.strptime(
json_dict[date_key],
'%Y-%m-%dT%H:%M:%S')
return Image(**json_dict)
@classmethod
def _xml_to_obj(cls, serialized_str):
"""Returns an instance of a Image based on the xml serialized_str
passed in.
"""
raise NotImplementedError("Glance does not serve XML-formatted \
resources.")
@classmethod
def _xml_ele_to_obj(cls, element):
raise NotImplementedError("Glance does not serve XML-formatted \
resources.")
def add_member(self, member):
members_list = self.members_list if self.members_list else []
members_list.append(member)
self.members_list = members_list
def delete_member(self, member_to_delete):
members_list = self.members_list if self.members_list else []
for member in self.members_list:
if member.member_id == member_to_delete.member_id:
members_list.remove(member_to_delete)
self.members_list = members_list
def replace_members_list(self, members_list):
self.members_list = members_list
class ImageMin(AutoMarshallingModel):
"""A mini Image model returned on certain calls to Images API """
def __init__(self, id_=None, can_share=None):
super(ImageMin, self).__init__()
self.id_ = id_
self.can_share = can_share
@classmethod
def _json_to_obj(cls, serialized_str):
json_dict = json.loads(serialized_str)
return cls._dict_to_obj(json_dict)
@classmethod
def _dict_to_obj(cls, json_dict):
return ImageMin(
id_=json_dict['image_id'],
can_share=json_dict['can_share'])
class ImageMinList(AutoMarshallingModel):
"""Model class that allows automarshalling of list of MinImage."""
@classmethod
def _json_to_obj(cls, serialized_str):
json_list = json.loads(serialized_str)
return [ImageMin._dict_to_obj(image_json) for image_json in
json_list['shared_images']]

View File

@ -1,31 +0,0 @@
import json
from cafe.engine.models.base import \
AutoMarshallingModel, AutoMarshallingListModel
class Member(AutoMarshallingModel):
def __init__(self, member_id=None, shared_images=None, can_share=None):
self.member_id = member_id
self.shared_images = shared_images
self.can_share = can_share
@classmethod
def _json_to_obj(cls, serialized_str):
json_dict = json.loads(serialized_str)
if 'members' in json_dict.keys():
members = []
members.extend([Member(**m) for m in json_dict['members']])
return members
else:
return Member(**json_dict)
class MemberList(AutoMarshallingListModel):
"""Represent a list of Members"""
@classmethod
def _json_to_obj(cls, serialized_str):
json_dict = json.loads(serialized_str)
return [Member(**m) for m in json_dict.get('members')]

View File

@ -1,15 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

View File

@ -1,297 +0,0 @@
import re
from cloudcafe.images.v1.client import ImagesClient
from httpretty import HTTPretty
GLANCE_API_SERVER_ENDPOINT = 'http://localhost:9292/v1'
class TestClient(object):
@classmethod
def setup_class(cls):
HTTPretty.enable()
cls.images_client = ImagesClient(
url=GLANCE_API_SERVER_ENDPOINT,
auth_token="36a04b4e71484ab9aacb1d0ac95733fc",
serialize_format="json",
deserialize_format="json"
)
cls.image_id = '1c675abd94f49cda114e12490b328d9'
cls.images_uri = '{0}/images'.format(GLANCE_API_SERVER_ENDPOINT)
cls.image_uri = '{0}/{1}'.format(cls.images_uri, cls.image_id)
@classmethod
def teardown_class(cls):
HTTPretty.disable()
def setup_method(self, method):
if method.__name__ is 'test_retrieve_image_metadata' or \
method.__name__ is 'test_retrieve_raw_image_data' or \
method.__name__ is 'test_update_image':
self.expected_headers = {
'x-image-meta-uri':
'{0}/images/1c675abd94f49cda114e12490b328d9'
.format(GLANCE_API_SERVER_ENDPOINT),
'x-image-meta-name': 'Ubuntu 10.04 Plain 5GB',
'x-image-meta-disk_format': 'vhd',
'x-image-meta-container_format': 'ovf',
'x-image-meta-size': '5368709120',
'x-image-meta-checksum': 'c2e5db72bd7fd153f53ede5da5a06de3',
'x-image-meta-created_at': '2010-02-03 09:34:01',
'x-image-meta-updated_at': '2010-02-03 09:34:01',
'x-image-meta-deleted_at': '',
'x-image-meta-status': 'available',
'x-image-meta-is_public': 'true',
'x-image-meta-min-ram': '256',
'x-image-meta-min-disk': '0',
'x-image-meta-owner': 'null',
'x-image-meta-property-distro': 'Ubuntu 10.04 LTS'
}
def test_list_available_images(self):
HTTPretty.register_uri(HTTPretty.GET, self.images_uri,
body=self._build_response_body(),
content_type="application/json")
actual_response = self.images_client.list_images()
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert HTTPretty.last_request.headers['Content-Type'] == \
'application/json'
assert HTTPretty.last_request.headers['Accept'] == 'application/json'
assert 200 == actual_response.status_code
assert self._build_response_body() == actual_response.content
assert self.images_uri == actual_response.url
def test_get_image(self):
HTTPretty.register_uri(HTTPretty.GET, self.image_uri,
body=self._build_response_body(),
content_type="application/json")
actual_response = self.images_client.get_image(image_id=self.image_id)
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert HTTPretty.last_request.headers['Content-Type'] == \
'application/json'
assert HTTPretty.last_request.headers['Accept'] == 'application/json'
assert 200 == actual_response.status_code
assert self._build_response_body() == actual_response.content
assert self.image_uri == actual_response.url
def test_filter_images_list(self):
filtering_parameters = {'name': 'precise', 'status': 'active',
'container_format': 'bare',
'disk_format': 'qcow2',
'min_disk': '0', 'size': '252116992'}
HTTPretty.register_uri(
HTTPretty.GET,
"{0}/images?status=active&name=precise&container_format=bare&\
disk_format=qcow2&min_disk=0&size=252116992"
.format(GLANCE_API_SERVER_ENDPOINT),
body=self._build_response_body(),
content_type="application/json")
actual_response = self.images_client.filter_images_list(
filtering_parameters)
request_querystring = HTTPretty.last_request.querystring
expected_request_querystring = self._get_querystring_data(
request_querystring)
assert expected_request_querystring == filtering_parameters
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert HTTPretty.last_request.headers['Content-Type'] == \
'application/json'
assert HTTPretty.last_request.headers['Accept'] == 'application/json'
assert 200 == actual_response.status_code
assert self._build_response_body() == actual_response.content
def test_add_image(self):
HTTPretty.register_uri(HTTPretty.POST, self.images_uri,
body='Adding New Image',
adding_headers={'x-image-meta-property-distro':
'Ubuntu 10.04 LTS'})
image_name = 'Ubuntu 10.04 Plain 5GB'
actual_response = self.images_client.add_image(image_name=image_name,
image_data=None)
assert 'x-image-meta-name' in \
HTTPretty.last_request.headers.keys()
assert 200 == actual_response.status_code
assert self.images_uri == actual_response.url
assert 'Adding New Image' == actual_response.content
assert 'x-image-meta-property-distro' in \
actual_response.__dict__['headers'].keys()
def test_retrieve_image_metadata(self):
url = '{0}/71c675ab-d94f-49cd-a114-e12490b328d9'.format(
self.images_uri)
HTTPretty.register_uri(HTTPretty.HEAD, url, body='Raw Image Data',
headers=self.expected_headers)
actual_response = self.images_client.retrieve_metadata(
'71c675ab-d94f-49cd-a114-e12490b328d9'
)
uri_regex = re.compile(
'{0}/[\w\d]{{8}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{12}}'
.format(self.images_uri)
)
assert re.match(uri_regex, actual_response.url) is not None
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert HTTPretty.last_request.headers['Content-Type'] == \
'application/json'
assert HTTPretty.last_request.headers['Accept'] == 'application/json'
assert 200 == actual_response.status_code
def test_retrieve_raw_image_data(self):
url = '{0}/71c675ab-d94f-49cd-a114-e12490b328d9'.format(
self.images_uri)
HTTPretty.register_uri(HTTPretty.GET, url, body='Raw Image Data',
headers=self.expected_headers)
actual_response = self.images_client.retrieve_raw_image_data(
'71c675ab-d94f-49cd-a114-e12490b328d9'
)
uri_regex = re.compile(
'{0}/[\w\d]{{8}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{12}}'
.format(self.images_uri)
)
assert re.match(uri_regex, actual_response.url) is not None
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert HTTPretty.last_request.headers['Content-Type'] == \
'application/json'
assert HTTPretty.last_request.headers['Accept'] == 'application/json'
assert 200 == actual_response.status_code
def test_list_image_memberships(self):
url = '{0}/members'.format(self.image_uri)
HTTPretty.register_uri(HTTPretty.GET,
url, body=self._build_list_image_membership())
actual_response = \
self.images_client.list_image_membership(self.image_id)
assert 200 == actual_response.status_code
assert url == actual_response.url
def _build_response_body(self):
return '{"images": '\
'[{"status": "active", '\
'"name": "precise", '\
'"deleted": false, '\
'"container_format": "bare", '\
'"created_at": "2013-04-29T19:32:56", '\
'"disk_format": "qcow2", '\
'"updated_at": "2013-04-29T19:32:56", '\
'"properties": {}, '\
'"min_disk": 0, '\
'"protected": false, '\
'"id": "46fd5b5c-b925-4316-a878-63cbbe7f0030", '\
'"checksum": null, '\
'"owner": "bd7531a57d3a47538fae1b89c169b293", '\
'"is_public": true, '\
'"deleted_at": null, '\
'"min_ram": "0", '\
'"size": "252116992"}]}'
def _get_querystring_data(self, querystring):
querystring_data = {}
for key in querystring:
querystring_data[key] = querystring[key][0] or \
int(querystring[key][0])
return querystring_data
def _build_list_image_membership(self):
"""@summary: Get the members_list attribute (image.members_list)
for an image with id=image_id"""
return {'members': 'members_list'}
def test_update_image(self):
url = '{0}/71c675ab-d94f-49cd-a114-e12490b328d9'.format(
self.images_uri)
HTTPretty.register_uri(HTTPretty.PUT, url, body='Updated Image',
headers=self.expected_headers)
actual_response = self.images_client.update_image(
'71c675ab-d94f-49cd-a114-e12490b328d9',
image_meta_is_public=False)
uri_regex = re.compile(
'{0}/[\w\d]{{8}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{4}}-[\w\d]{{12}}'
.format(self.images_uri)
)
assert re.match(uri_regex, actual_response.url) is not None
assert HTTPretty.last_request.headers['X-Auth-Token'] == \
'36a04b4e71484ab9aacb1d0ac95733fc'
assert 200 == actual_response.status_code
def test_list_shared_images(self):
member_id = ''
shared_images_url = '{0}/shared-images/{1}'.format(
GLANCE_API_SERVER_ENDPOINT,
member_id
)
HTTPretty.register_uri(HTTPretty.GET, shared_images_url,
body=self._build_list_shared_images())
actual_response = self.images_client.list_shared_images(member_id)
assert 200 == actual_response.status_code
assert shared_images_url == actual_response.url
def _build_list_shared_images(self):
"""@summary: Get the shared_images attribute (member.shared_attributes)
for a member with id=member_id"""
return {'shared_images': 'shared_images'}
def test_add_member_to_an_image(self):
member_id = ''
url = '{0}/members/{1}'.format(self.image_uri, member_id)
HTTPretty.register_uri(HTTPretty.PUT, url, body={})
actual_response = self.images_client.add_member_to_image(self.image_id,
member_id)
assert 200 == actual_response.status_code
assert url == actual_response.url
def test_remove_member_from_an_image(self):
member_id = ''
url = '{0}/members/{1}'.format(self.image_uri, member_id)
HTTPretty.register_uri(HTTPretty.DELETE, url, body={})
actual_response = \
self.images_client.delete_member_from_image(self.image_id,
member_id)
assert 200 == actual_response.status_code
assert url == actual_response.url
def test_replace_members_list_for_an_image(self):
url = '{0}/members'.format(self.image_uri)
HTTPretty.register_uri(HTTPretty.PUT, url,
body=self._build_members_list())
actual_response = \
self.images_client.replace_members_list(self.image_id)
assert 200 == actual_response.status_code
assert url == actual_response.url
def _build_members_list(self):
return {'memberships': 'new_members_list'}

View File

@ -1,8 +0,0 @@
{"image": {
"name": "cirros-0.3.1-x86_64-uec",
"container_format": "ami",
"disk_format": "ami",
"checksum": "f8a2eeee2dc65b3d9b6e63678955bd83",
"id": "48dd25eb-ada4-47e7-8b8c-9547c9263b52",
"size": 25165824
}}

View File

@ -1,26 +0,0 @@
{"images": [
{
"name": "cirros-0.3.1-x86_64-uec",
"container_format": "ami",
"disk_format": "ami",
"checksum": "f8a2eeee2dc65b3d9b6e63678955bd83",
"id": "48dd25eb-ada4-47e7-8b8c-9547c9263b52",
"size": 25165824
},
{
"name": "cirros-0.3.1-x86_64-uec-ramdisk",
"container_format": "ari",
"disk_format": "ari",
"checksum": "69c33642f44ca552ba4bb8b66ad97e85",
"id": "ba740a49-2b27-45a2-9fc6-d142b44698a9",
"size": 3714968
},
{
"name": "cirros-0.3.1-x86_64-uec-kernel",
"container_format": "aki",
"disk_format": "aki",
"checksum": "c352f4e7121c6eae958bc1570324f17e",
"id": "4057ba81-47da-406f-aa92-09bcb5b6ddcc",
"size": 4955792
}
]}

View File

@ -1,15 +0,0 @@
"""
Copyright 2013 Rackspace
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

View File

@ -1,98 +0,0 @@
import json
import os
from copy import deepcopy
from datetime import datetime
from cloudcafe.images.v1.models.image import Image
from cloudcafe.images.v1.models.member import Member
class TestImage(object):
"""@summary: Testing the behaviors of the image model..."""
@classmethod
def setup_class(cls):
cls.raw_image_str = open(os.path.join(
os.path.dirname(__file__), '../data/image.json')).read()
cls.raw_images_str = open(os.path.join(
os.path.dirname(__file__), '../data/images.json')).read()
cls._dict = json.loads(cls.raw_image_str).get('image')
cls.image_one = Image(
id_=cls._dict.get('id'),
name=cls._dict.get('name'),
container_format=cls._dict.get('container_format'),
checksum=cls._dict.get('checksum'),
size=cls._dict.get('size'),
disk_format=cls._dict.get('disk_format'))
cls.image_two = Image(
id_="c7dd539e-5077-49e8-bc4d-0359ba051122",
status="active",
name="precise",
deleted="False",
container_format="cirros",
created_at=datetime.today(),
disk_format="qcow2",
updated_at=datetime.today(),
owner="bd7531a57d3a47538fae1b89c169b293",
protected="False",
min_ram=0,
checksum="",
min_disk=0,
is_public="True",
deleted_at=datetime.today(),
properties={},
size=252116992)
def test_positive_equality_of_images(self):
assert self.image_one == deepcopy(self.image_one)
def test_negative_equality_of_images(self):
assert self.image_one != deepcopy(self.image_two)
def test_dict_to_obj(self):
assert Image._dict_to_obj(self._dict) == self.image_one
def test_json_to_obj(self):
assert Image._json_to_obj(self.raw_image_str) == self.image_one
def test_add_member_to_an_image(self):
member1 = Member(member_id='1')
self.image_one.add_member(member1)
assert len(self.image_one.members_list) == 1
assert member1 in self.image_one.members_list
def test_remove_member_from_an_image(self):
image = Image._dict_to_obj(self._dict)
member1 = Member(member_id='1')
member2 = Member(member_id='2')
image.add_member(member1)
image.add_member(member2)
assert len(image.members_list) == 2
image.delete_member(member1)
assert len(image.members_list) == 1
assert member1 not in image.members_list
assert member2 in image.members_list
def test_replace_members_list_for_an_image(self):
member1 = Member(member_id='1')
member2 = Member(member_id='2')
member3 = Member(member_id='3')
members_list = [member1, member2]
image = self.image_one
image.members_list = members_list
image.replace_members_list([member3])
assert len(image.members_list) == 1
assert member1 not in image.members_list
assert member2 not in image.members_list
assert member3 in image.members_list