diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-09-13 07:36:36 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-09-13 07:36:36 +0000 |
commit | a8f31ccfbfdaa1b47fd3ce245744f241d68531bc (patch) | |
tree | 71633f8049f5a0c8ea673bd7ff8aeeb1951a2a7e | |
parent | 128ea59beafa1829c1a8579f4f38ad9ea59f2d79 (diff) | |
parent | 97b1506bdbccea9fbfcac731cf8b7e0cadebcbab (diff) | |
download | python-glanceclient-a8f31ccfbfdaa1b47fd3ce245744f241d68531bc.tar.gz |
Merge "Fix v2 requests to non-bleeding edge servers"
-rw-r--r-- | glanceclient/common/utils.py | 18 | ||||
-rw-r--r-- | glanceclient/v2/client.py | 48 | ||||
-rw-r--r-- | glanceclient/v2/image_members.py | 14 | ||||
-rw-r--r-- | glanceclient/v2/image_tags.py | 14 | ||||
-rw-r--r-- | glanceclient/v2/images.py | 10 | ||||
-rw-r--r-- | glanceclient/v2/metadefs.py | 39 | ||||
-rw-r--r-- | tests/utils.py | 11 | ||||
-rw-r--r-- | tests/v2/test_client.py | 13 | ||||
-rw-r--r-- | tests/v2/test_images.py | 94 | ||||
-rw-r--r-- | tests/v2/test_members.py | 29 | ||||
-rw-r--r-- | tests/v2/test_metadefs_namespaces.py | 399 | ||||
-rw-r--r-- | tests/v2/test_metadefs_objects.py | 285 | ||||
-rw-r--r-- | tests/v2/test_metadefs_properties.py | 240 | ||||
-rw-r--r-- | tests/v2/test_metadefs_resource_types.py | 112 | ||||
-rw-r--r-- | tests/v2/test_tags.py | 21 |
15 files changed, 727 insertions, 620 deletions
diff --git a/glanceclient/common/utils.py b/glanceclient/common/utils.py index 9071065..d1a634e 100644 --- a/glanceclient/common/utils.py +++ b/glanceclient/common/utils.py @@ -21,6 +21,7 @@ import json import os import re import sys +import threading import uuid import six @@ -36,6 +37,8 @@ from glanceclient import exc from glanceclient.openstack.common import importutils from glanceclient.openstack.common import strutils +_memoized_property_lock = threading.Lock() + # Decorator for cli-args def arg(*args, **kwargs): @@ -367,3 +370,18 @@ def integrity_iter(iter, checksum): raise IOError(errno.EPIPE, 'Corrupt image download. Checksum was %s expected %s' % (md5sum, checksum)) + + +def memoized_property(fn): + attr_name = '_lazy_once_' + fn.__name__ + + @property + def _memoized_property(self): + if hasattr(self, attr_name): + return getattr(self, attr_name) + else: + with _memoized_property_lock: + if not hasattr(self, attr_name): + setattr(self, attr_name, fn(self)) + return getattr(self, attr_name) + return _memoized_property diff --git a/glanceclient/v2/client.py b/glanceclient/v2/client.py index ed80388..4aa2e83 100644 --- a/glanceclient/v2/client.py +++ b/glanceclient/v2/client.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import warlock from glanceclient.common import http from glanceclient.common import utils @@ -38,50 +37,21 @@ class Client(object): self.http_client = http.HTTPClient(utils.strip_version(endpoint), *args, **kwargs) self.schemas = schemas.Controller(self.http_client) - image_model = self._get_image_model() - self.images = images.Controller(self.http_client, - image_model) - self.image_tags = image_tags.Controller(self.http_client, image_model) + + self.images = images.Controller(self.http_client, self.schemas) + self.image_tags = image_tags.Controller(self.http_client, + self.schemas) self.image_members = image_members.Controller(self.http_client, - self._get_member_model()) + self.schemas) - resource_type_model = self._get_metadefs_resource_type_model() self.metadefs_resource_type = ( - metadefs.ResourceTypeController(self.http_client, - resource_type_model)) + metadefs.ResourceTypeController(self.http_client, self.schemas)) - property_model = self._get_metadefs_property_model() self.metadefs_property = ( - metadefs.PropertyController(self.http_client, property_model)) + metadefs.PropertyController(self.http_client, self.schemas)) - object_model = self._get_metadefs_object_model() self.metadefs_object = ( - metadefs.ObjectController(self.http_client, object_model)) + metadefs.ObjectController(self.http_client, self.schemas)) - namespace_model = self._get_metadefs_namespace_model() self.metadefs_namespace = ( - metadefs.NamespaceController(self.http_client, namespace_model)) - - def _get_image_model(self): - schema = self.schemas.get('image') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def _get_member_model(self): - schema = self.schemas.get('member') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def _get_metadefs_namespace_model(self): - schema = self.schemas.get('metadefs/namespace') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def _get_metadefs_resource_type_model(self): - schema = self.schemas.get('metadefs/resource_type') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def _get_metadefs_property_model(self): - schema = self.schemas.get('metadefs/property') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def _get_metadefs_object_model(self): - schema = self.schemas.get('metadefs/object') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) + metadefs.NamespaceController(self.http_client, self.schemas)) diff --git a/glanceclient/v2/image_members.py b/glanceclient/v2/image_members.py index dcf4ac2..cb6a829 100644 --- a/glanceclient/v2/image_members.py +++ b/glanceclient/v2/image_members.py @@ -13,11 +13,21 @@ # License for the specific language governing permissions and limitations # under the License. +import warlock + +from glanceclient.common import utils +from glanceclient.v2 import schemas + class Controller(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('member') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def list(self, image_id): url = '/v2/images/%s/members' % image_id diff --git a/glanceclient/v2/image_tags.py b/glanceclient/v2/image_tags.py index 5c03648..0f2f1bb 100644 --- a/glanceclient/v2/image_tags.py +++ b/glanceclient/v2/image_tags.py @@ -13,11 +13,21 @@ # License for the specific language governing permissions and limitations # under the License. +import warlock + +from glanceclient.common import utils +from glanceclient.v2 import schemas + class Controller(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('image') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def update(self, image_id, tag_value): """ diff --git a/glanceclient/v2/images.py b/glanceclient/v2/images.py index 1144e6f..6ec9250 100644 --- a/glanceclient/v2/images.py +++ b/glanceclient/v2/images.py @@ -21,14 +21,20 @@ import warlock from glanceclient.common import utils from glanceclient import exc from glanceclient.openstack.common import strutils +from glanceclient.v2 import schemas DEFAULT_PAGE_SIZE = 20 class Controller(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('image') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def list(self, **kwargs): """Retrieve a listing of Image objects diff --git a/glanceclient/v2/metadefs.py b/glanceclient/v2/metadefs.py index 0935764..3dc7efc 100644 --- a/glanceclient/v2/metadefs.py +++ b/glanceclient/v2/metadefs.py @@ -19,14 +19,20 @@ import warlock from glanceclient.common import utils from glanceclient.openstack.common import strutils +from glanceclient.v2 import schemas DEFAULT_PAGE_SIZE = 20 class NamespaceController(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('metadefs/namespace') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def create(self, **kwargs): """Create a namespace. @@ -75,7 +81,7 @@ class NamespaceController(object): url = '/v2/metadefs/namespaces/{0}{1}'.format(namespace, query_params) resp, body = self.http_client.get(url) - #NOTE(bcwaldon): remove 'self' for now until we have an elegant + # NOTE(bcwaldon): remove 'self' for now until we have an elegant # way to pass it into the model constructor without conflict body.pop('self', None) return self.model(**body) @@ -141,9 +147,14 @@ class NamespaceController(object): class ResourceTypeController(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('metadefs/resource_type') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def associate(self, namespace, **kwargs): """Associate a resource type with a namespace.""" @@ -184,9 +195,14 @@ class ResourceTypeController(object): class PropertyController(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('metadefs/property') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def create(self, namespace, **kwargs): """Create a property. @@ -259,9 +275,14 @@ class PropertyController(object): class ObjectController(object): - def __init__(self, http_client, model): + def __init__(self, http_client, schema_client): self.http_client = http_client - self.model = model + self.schema_client = schema_client + + @utils.memoized_property + def model(self): + schema = self.schema_client.get('metadefs/object') + return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) def create(self, namespace, **kwargs): """Create an object. diff --git a/tests/utils.py b/tests/utils.py index 0fa0e2e..8f8c255 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -18,6 +18,8 @@ import json import six import testtools +from glanceclient.v2.schemas import Schema + class FakeAPI(object): def __init__(self, fixtures): @@ -60,6 +62,15 @@ class FakeAPI(object): return self._request('HEAD', *args, **kwargs) +class FakeSchemaAPI(FakeAPI): + def __init__(cls, *args): + super(FakeSchemaAPI, cls).__init__(*args) + + def get(self, *args, **kwargs): + _, raw_schema = self._request('GET', *args, **kwargs) + return Schema(raw_schema) + + class RawRequest(object): def __init__(self, headers, body=None, version=1.0, status=200, reason="Ok"): diff --git a/tests/v2/test_client.py b/tests/v2/test_client.py index 1971bf5..f775f72 100644 --- a/tests/v2/test_client.py +++ b/tests/v2/test_client.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from mox3 import mox import testtools from glanceclient.v2 import client @@ -23,21 +22,9 @@ class ClientTest(testtools.TestCase): def setUp(self): super(ClientTest, self).setUp() - self.mock = mox.Mox() - self.mock.StubOutWithMock(client.Client, '_get_image_model') - self.mock.StubOutWithMock(client.Client, '_get_member_model') - self.mock.StubOutWithMock(client.Client, - '_get_metadefs_namespace_model') - self.mock.StubOutWithMock(client.Client, - '_get_metadefs_resource_type_model') - self.mock.StubOutWithMock(client.Client, - '_get_metadefs_property_model') - self.mock.StubOutWithMock(client.Client, - '_get_metadefs_object_model') def tearDown(self): super(ClientTest, self).tearDown() - self.mock.UnsetStubs() def test_endpoint(self): gc = client.Client("http://example.com") diff --git a/tests/v2/test_images.py b/tests/v2/test_images.py index d231a31..8e23a21 100644 --- a/tests/v2/test_images.py +++ b/tests/v2/test_images.py @@ -15,10 +15,9 @@ import errno import json -import testtools import six -import warlock +import testtools from glanceclient import exc from glanceclient.v2 import images @@ -39,7 +38,31 @@ _PUBLIC_ID = '857806e7-05b6-48e0-9d40-cb0e6fb727b9' _SHARED_ID = '331ac905-2a38-44c5-a83d-653db8f08313' _STATUS_REJECTED_ID = 'f3ea56ff-d7e4-4451-998c-1e3d33539c8e' -fixtures = { +data_fixtures = { + '/v2/schemas/image': { + 'GET': ( + {}, + { + 'name': 'image', + 'properties': { + 'id': {}, + 'name': {}, + 'locations': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'metadata': {'type': 'object'}, + 'url': {'type': 'string'}, + }, + 'required': ['url', 'metadata'], + }, + }, + }, + 'additionalProperties': {'type': 'string'} + }, + ), + }, '/v2/images?limit=%d' % images.DEFAULT_PAGE_SIZE: { 'GET': ( {}, @@ -325,36 +348,43 @@ fixtures = { } -fake_schema = { - 'name': 'image', - 'properties': { - 'id': {}, - 'name': {}, - 'locations': { - 'type': 'array', - 'items': { - 'type': 'object', +schema_fixtures = { + 'image': { + 'GET': ( + {}, + { + 'name': 'image', 'properties': { - 'metadata': {'type': 'object'}, - 'url': {'type': 'string'}, + 'id': {}, + 'name': {}, + 'locations': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'metadata': {'type': 'object'}, + 'url': {'type': 'string'}, + }, + 'required': ['url', 'metadata'], + } + } }, - 'required': ['url', 'metadata'], - }, - }, - }, - 'additionalProperties': {'type': 'string'} + 'additionalProperties': {'type': 'string'} + } + ) + } } -FakeModel = warlock.model_factory(fake_schema) class TestController(testtools.TestCase): def setUp(self): super(TestController, self).setUp() - self.api = utils.FakeAPI(fixtures) - self.controller = images.Controller(self.api, FakeModel) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) + self.controller = images.Controller(self.api, self.schema_api) def test_list_images(self): - #NOTE(bcwaldon): cast to list since the controller returns a generator + # NOTE(bcwaldon):cast to list since the controller returns a generator images = list(self.controller.list()) self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id) self.assertEqual('image-1', images[0].name) @@ -362,7 +392,7 @@ class TestController(testtools.TestCase): self.assertEqual('image-2', images[1].name) def test_list_images_paginated(self): - #NOTE(bcwaldon): cast to list since the controller returns a generator + # NOTE(bcwaldon):cast to list since the controller returns a generator images = list(self.controller.list(page_size=1)) self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id) self.assertEqual('image-1', images[0].name) @@ -571,7 +601,7 @@ class TestController(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) self.assertEqual(image_id, image.id) - #NOTE(bcwaldon): due to limitations of our fake api framework, the name + # NOTE(bcwaldon):due to limitations of our fake api framework, the name # will not actually change - yet in real life it will... self.assertEqual('image-1', image.name) @@ -590,7 +620,7 @@ class TestController(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) self.assertEqual(image_id, image.id) - #NOTE(bcwaldon): due to limitations of our fake api framework, the name + # NOTE(bcwaldon):due to limitations of our fake api framework, the name # will not actually change - yet in real life it will... self.assertEqual('image-1', image.name) @@ -609,7 +639,7 @@ class TestController(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) self.assertEqual(image_id, image.id) - #NOTE(bcwaldon): due to limitations of our fake api framework, the name + # NOTE(bcwaldon):due to limitations of our fake api framework, the name # will not actually change - yet in real life it will... self.assertEqual('image-3', image.name) @@ -622,8 +652,8 @@ class TestController(testtools.TestCase): expect_hdrs = { 'Content-Type': 'application/openstack-images-v2.1-json-patch', } - expect_body = '[{"path": "/barney", "value": "miller", ' \ - '"op": "replace"}]' + expect_body = ('[{"path": "/barney", "value": "miller", ' + '"op": "replace"}]') expect = [ ('GET', '/v2/images/%s' % image_id, {}, None), ('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body), @@ -631,7 +661,7 @@ class TestController(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) self.assertEqual(image_id, image.id) - #NOTE(bcwaldon): due to limitations of our fake api framework, the name + # NOTE(bcwaldon):due to limitations of our fake api framework, the name # will not actually change - yet in real life it will... self.assertEqual('image-3', image.name) @@ -652,7 +682,7 @@ class TestController(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) self.assertEqual(image_id, image.id) - #NOTE(bcwaldon): due to limitations of our fake api framework, the name + # NOTE(bcwaldon):due to limitations of our fake api framework, the name # will not actually change - yet in real life it will... self.assertEqual('image-3', image.name) @@ -741,7 +771,7 @@ class TestController(testtools.TestCase): image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8' new_loc = {'url': 'http://foo.com/', 'metadata': {'spam': 'ham'}} fixture_idx = '/v2/images/%s' % (image_id) - orig_locations = fixtures[fixture_idx]['GET'][1]['locations'] + orig_locations = data_fixtures[fixture_idx]['GET'][1]['locations'] loc_map = dict([(l['url'], l) for l in orig_locations]) loc_map[new_loc['url']] = new_loc mod_patch = [{'path': '/locations', 'op': 'replace', diff --git a/tests/v2/test_members.py b/tests/v2/test_members.py index 0b57b0c..744f3a6 100644 --- a/tests/v2/test_members.py +++ b/tests/v2/test_members.py @@ -15,8 +15,6 @@ import testtools -import warlock - from glanceclient.v2 import image_members from tests import utils @@ -25,7 +23,7 @@ IMAGE = '3a4560a1-e585-443e-9b39-553b46ec92d1' MEMBER = '11223344-5566-7788-9911-223344556677' -fixtures = { +data_fixtures = { '/v2/images/{image}/members'.format(image=IMAGE): { 'GET': ( {}, @@ -58,20 +56,31 @@ fixtures = { 'status': 'accepted' } ), - }, + } } - -fake_schema = {'name': 'member', 'properties': {'image_id': {}, - 'member_id': {}}} -FakeModel = warlock.model_factory(fake_schema) +schema_fixtures = { + 'member': { + 'GET': ( + {}, + { + 'name': 'member', + 'properties': { + 'image_id': {}, + 'member_id': {} + } + }, + ) + } +} class TestController(testtools.TestCase): def setUp(self): super(TestController, self).setUp() - self.api = utils.FakeAPI(fixtures) - self.controller = image_members.Controller(self.api, FakeModel) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) + self.controller = image_members.Controller(self.api, self.schema_api) def test_list_image_members(self): image_id = IMAGE diff --git a/tests/v2/test_metadefs_namespaces.py b/tests/v2/test_metadefs_namespaces.py index ebb78de..878658f 100644 --- a/tests/v2/test_metadefs_namespaces.py +++ b/tests/v2/test_metadefs_namespaces.py @@ -15,8 +15,6 @@ import testtools -import warlock - from glanceclient.v2 import metadefs from tests import utils @@ -59,7 +57,7 @@ def _get_namespace_fixture(ns_name, rt_name=RESOURCE_TYPE1, **kwargs): return ns -fixtures = { +data_fixtures = { "/v2/metadefs/namespaces?limit=20": { "GET": ( {}, @@ -271,230 +269,243 @@ fixtures = { "updated_at": "2014-08-14T09:07:06Z", } ), - }, + } } -fake_namespace_schema = { - "additionalProperties": False, - "definitions": { - "property": { - "additionalProperties": { - "required": [ - "title", - "type" - ], - "type": "object", - "properties": { - "additionalItems": { - "type": "boolean" +schema_fixtures = { + "metadefs/namespace": + { + "GET": ( + {}, + { + "additionalProperties": False, + "definitions": { + "property": { + "additionalProperties": { + "required": [ + "title", + "type" + ], + "type": "object", + "properties": { + "additionalItems": { + "type": "boolean" + }, + "enum": { + "type": "array" + }, + "description": { + "type": "string" + }, + "title": { + "type": "string" + }, + "default": {}, + "minLength": { + "$ref": "#/definitions/" + "positiveIntegerDefault0" + }, + "required": { + "$ref": "#/definitions/stringArray" + }, + "maximum": { + "type": "number" + }, + "minItems": { + "$ref": "#/definitions/" + "positiveIntegerDefault0" + }, + "readonly": { + "type": "boolean" + }, + "minimum": { + "type": "number" + }, + "maxItems": { + "$ref": "#/definitions/" + "positiveInteger" + }, + "maxLength": { + "$ref": "#/definitions/positiveInteger" + }, + "uniqueItems": { + "default": False, + "type": "boolean" + }, + "pattern": { + "type": "string", + "format": "regex" + }, + "items": { + "type": "object", + "properties": { + "enum": { + "type": "array" + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } + } + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } + } + }, + "type": "object" + }, + "positiveIntegerDefault0": { + "allOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "default": 0 + } + ] }, - "enum": { + "stringArray": { + "uniqueItems": True, + "items": { + "type": "string" + }, "type": "array" }, + "positiveInteger": { + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "namespace" + ], + "name": "namespace", + "properties": { "description": { - "type": "string" - }, - "title": { - "type": "string" - }, - "default": {}, - "minLength": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "required": { - "$ref": "#/definitions/stringArray" - }, - "maximum": { - "type": "number" - }, - "minItems": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "readonly": { - "type": "boolean" + "type": "string", + "description": "Provides a user friendly description " + "of the namespace.", + "maxLength": 500 }, - "minimum": { - "type": "number" + "updated_at": { + "type": "string", + "description": "Date and time of the last namespace " + "modification (READ-ONLY)", + "format": "date-time" }, - "maxItems": { - "$ref": "#/definitions/positiveInteger" + "visibility": { + "enum": [ + "public", + "private" + ], + "type": "string", + "description": "Scope of namespace accessibility." }, - "maxLength": { - "$ref": "#/definitions/positiveInteger" + "self": { + "type": "string" }, - "uniqueItems": { - "default": False, - "type": "boolean" + "objects": { + "items": { + "type": "object", + "properties": { + "properties": { + "$ref": "#/definitions/property" + }, + "required": { + "$ref": "#/definitions/stringArray" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + } + }, + "type": "array" }, - "pattern": { + "owner": { "type": "string", - "format": "regex" + "description": "Owner of the namespace.", + "maxLength": 255 }, - "items": { - "type": "object", - "properties": { - "enum": { - "type": "array" - }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" + "resource_types": { + "items": { + "type": "object", + "properties": { + "prefix": { + "type": "string" + }, + "name": { + "type": "string" + }, + "metadata_type": { + "type": "string" + } } - } + }, + "type": "array" }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" - } - } - }, - "type": "object" - }, - "positiveIntegerDefault0": { - "allOf": [ - { - "$ref": "#/definitions/positiveInteger" - }, - { - "default": 0 - } - ] - }, - "stringArray": { - "uniqueItems": True, - "items": { - "type": "string" - }, - "type": "array" - }, - "positiveInteger": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "namespace" - ], - "name": "namespace", - "properties": { - "description": { - "type": "string", - "description": "Provides a user friendly description of the " - "namespace.", - "maxLength": 500 - }, - "updated_at": { - "type": "string", - "description": "Date and time of the last namespace modification " - "(READ-ONLY)", - "format": "date-time" - }, - "visibility": { - "enum": [ - "public", - "private" - ], - "type": "string", - "description": "Scope of namespace accessibility." - }, - "self": { - "type": "string" - }, - "objects": { - "items": { - "type": "object", - "properties": { "properties": { "$ref": "#/definitions/property" }, - "required": { - "$ref": "#/definitions/stringArray" + "display_name": { + "type": "string", + "description": "The user friendly name for the " + "namespace. Used by UI if available.", + "maxLength": 80 }, - "name": { - "type": "string" + "created_at": { + "type": "string", + "description": "Date and time of namespace creation " + "(READ-ONLY)", + "format": "date-time" }, - "description": { - "type": "string" - } - } - }, - "type": "array" - }, - "owner": { - "type": "string", - "description": "Owner of the namespace.", - "maxLength": 255 - }, - "resource_types": { - "items": { - "type": "object", - "properties": { - "prefix": { - "type": "string" + "namespace": { + "type": "string", + "description": "The unique namespace text.", + "maxLength": 80 }, - "name": { - "type": "string" + "protected": { + "type": "boolean", + "description": "If true, namespace will not be " + "deletable." }, - "metadata_type": { + "schema": { "type": "string" } } - }, - "type": "array" - }, - "properties": { - "$ref": "#/definitions/property" - }, - "display_name": { - "type": "string", - "description": "The user friendly name for the namespace. Used by" - " UI if available.", - "maxLength": 80 - }, - "created_at": { - "type": "string", - "description": "Date and time of namespace creation (READ-ONLY)", - "format": "date-time" - }, - "namespace": { - "type": "string", - "description": "The unique namespace text.", - "maxLength": 80 - }, - "protected": { - "type": "boolean", - "description": "If true, namespace will not be deletable." - }, - "schema": { - "type": "string" - } + } + ), } } -FakeNamespaceModel = warlock.model_factory(fake_namespace_schema) class TestNamespaceController(testtools.TestCase): def setUp(self): super(TestNamespaceController, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) self.controller = metadefs.NamespaceController(self.api, - FakeNamespaceModel) + self.schema_api) def test_list_namespaces(self): namespaces = list(self.controller.list()) diff --git a/tests/v2/test_metadefs_objects.py b/tests/v2/test_metadefs_objects.py index 7c17e1e..ca2f8c8 100644 --- a/tests/v2/test_metadefs_objects.py +++ b/tests/v2/test_metadefs_objects.py @@ -16,8 +16,6 @@ import six import testtools -import warlock - from glanceclient.v2 import metadefs from tests import utils @@ -50,8 +48,7 @@ def _get_object_fixture(ns_name, obj_name, **kwargs): "description": "DESCRIPTION", "maximum": 1000000, "title": "Quota: CPU Period" - }, - }, + }}, "schema": "/v2/schemas/metadefs/object", "created_at": "2014-08-14T09:07:06Z", "updated_at": "2014-08-14T09:07:06Z", @@ -61,7 +58,7 @@ def _get_object_fixture(ns_name, obj_name, **kwargs): return obj -fixtures = { +data_fixtures = { "/v2/metadefs/namespaces/%s/objects" % NAMESPACE1: { "GET": ( {}, @@ -98,166 +95,174 @@ fixtures = { } } - -fake_object_schema = { - "additionalProperties": False, - "definitions": { - "property": { - "additionalProperties": { +schema_fixtures = { + "metadefs/object": { + "GET": ( + {}, + { + "additionalProperties": False, + "definitions": { + "property": { + "additionalProperties": { + "required": [ + "title", + "type" + ], + "type": "object", + "properties": { + "additionalItems": { + "type": "boolean" + }, + "enum": { + "type": "array" + }, + "description": { + "type": "string" + }, + "title": { + "type": "string" + }, + "default": {}, + "minLength": { + "$ref": "#/definitions/positiveInteger" + "Default0" + }, + "required": { + "$ref": "#/definitions/stringArray" + }, + "maximum": { + "type": "number" + }, + "minItems": { + "$ref": "#/definitions/positiveInteger" + "Default0" + }, + "readonly": { + "type": "boolean" + }, + "minimum": { + "type": "number" + }, + "maxItems": { + "$ref": "#/definitions/positiveInteger" + }, + "maxLength": { + "$ref": "#/definitions/positiveInteger" + }, + "uniqueItems": { + "default": False, + "type": "boolean" + }, + "pattern": { + "type": "string", + "format": "regex" + }, + "items": { + "type": "object", + "properties": { + "enum": { + "type": "array" + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } + } + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } + } + }, + "type": "object" + }, + "positiveIntegerDefault0": { + "allOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "default": 0 + } + ] + }, + "stringArray": { + "uniqueItems": True, + "items": { + "type": "string" + }, + "type": "array" + }, + "positiveInteger": { + "minimum": 0, + "type": "integer" + } + }, "required": [ - "title", - "type" + "name" ], - "type": "object", + "name": "object", "properties": { - "additionalItems": { - "type": "boolean" - }, - "enum": { - "type": "array" + "created_at": { + "type": "string", + "description": "Date and time of object creation " + "(READ-ONLY)", + "format": "date-time" }, "description": { "type": "string" }, - "title": { + "name": { "type": "string" }, - "default": {}, - "minLength": { - "$ref": "#/definitions/positiveIntegerDefault0" + "self": { + "type": "string" }, "required": { "$ref": "#/definitions/stringArray" }, - "maximum": { - "type": "number" - }, - "minItems": { - "$ref": "#/definitions/positiveIntegerDefault0" + "properties": { + "$ref": "#/definitions/property" }, - "readonly": { - "type": "boolean" - }, - "minimum": { - "type": "number" - }, - "maxItems": { - "$ref": "#/definitions/positiveInteger" - }, - "maxLength": { - "$ref": "#/definitions/positiveInteger" - }, - "uniqueItems": { - "default": False, - "type": "boolean" + "schema": { + "type": "string" }, - "pattern": { + "updated_at": { "type": "string", - "format": "regex" + "description": "Date and time of the last object " + "modification (READ-ONLY)", + "format": "date-time" }, - "items": { - "type": "object", - "properties": { - "enum": { - "type": "array" - }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" - } - } - }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" - } } - }, - "type": "object" - }, - "positiveIntegerDefault0": { - "allOf": [ - { - "$ref": "#/definitions/positiveInteger" - }, - { - "default": 0 - } - ] - }, - "stringArray": { - "uniqueItems": True, - "items": { - "type": "string" - }, - "type": "array" - }, - "positiveInteger": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "name" - ], - "name": "object", - "properties": { - "created_at": { - "type": "string", - "description": "Date and time of object creation (READ-ONLY)", - "format": "date-time" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "self": { - "type": "string" - }, - "required": { - "$ref": "#/definitions/stringArray" - }, - "properties": { - "$ref": "#/definitions/property" - }, - "schema": { - "type": "string" - }, - "updated_at": { - "type": "string", - "description": "Date and time of the last object modification " - "(READ-ONLY)", - "format": "date-time" - }, + } + ) } } -FakeObjectModel = warlock.model_factory(fake_object_schema) class TestObjectController(testtools.TestCase): def setUp(self): super(TestObjectController, self).setUp() - self.api = utils.FakeAPI(fixtures) - self.controller = metadefs.ObjectController(self.api, - FakeObjectModel) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) + self.controller = metadefs.ObjectController(self.api, self.schema_api) def test_list_object(self): objects = list(self.controller.list(NAMESPACE1)) diff --git a/tests/v2/test_metadefs_properties.py b/tests/v2/test_metadefs_properties.py index 23cc0fb..7c50f13 100644 --- a/tests/v2/test_metadefs_properties.py +++ b/tests/v2/test_metadefs_properties.py @@ -15,8 +15,6 @@ import testtools -import warlock - from glanceclient.v2 import metadefs from tests import utils @@ -25,7 +23,7 @@ PROPERTY1 = 'Property1' PROPERTY2 = 'Property2' PROPERTYNEW = 'PropertyNew' -fixtures = { +data_fixtures = { "/v2/metadefs/namespaces/%s/properties" % NAMESPACE1: { "GET": ( {}, @@ -108,134 +106,140 @@ fixtures = { {}, {} ) - }, + } } - -fake_property_schema = { - "additionalProperties": False, - "definitions": { - "positiveIntegerDefault0": { - "allOf": [ - { - "$ref": "#/definitions/positiveInteger" - }, - { - "default": 0 - } - ] - }, - "stringArray": { - "minItems": 1, - "items": { - "type": "string" - }, - "uniqueItems": True, - "type": "array" - }, - "positiveInteger": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "name", - "title", - "type" - ], - "name": "property", - "properties": { - "description": { - "type": "string" - }, - "minLength": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "enum": { - "type": "array" - }, - "minimum": { - "type": "number" - }, - "maxItems": { - "$ref": "#/definitions/positiveInteger" - }, - "maxLength": { - "$ref": "#/definitions/positiveInteger" - }, - "uniqueItems": { - "default": False, - "type": "boolean" - }, - "additionalItems": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "title": { - "type": "string" - }, - "default": {}, - "pattern": { - "type": "string", - "format": "regex" - }, - "required": { - "$ref": "#/definitions/stringArray" - }, - "maximum": { - "type": "number" - }, - "minItems": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "readonly": { - "type": "boolean" - }, - "items": { - "type": "object", - "properties": { - "enum": { - "type": "array" +schema_fixtures = { + "metadefs/property": { + "GET": ( + {}, + { + "additionalProperties": False, + "definitions": { + "positiveIntegerDefault0": { + "allOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "default": 0 + } + ] + }, + "stringArray": { + "minItems": 1, + "items": { + "type": "string" + }, + "uniqueItems": True, + "type": "array" + }, + "positiveInteger": { + "minimum": 0, + "type": "integer" + } }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" + "required": [ + "name", + "title", + "type" + ], + "name": "property", + "properties": { + "description": { + "type": "string" + }, + "minLength": { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + "enum": { + "type": "array" + }, + "minimum": { + "type": "number" + }, + "maxItems": { + "$ref": "#/definitions/positiveInteger" + }, + "maxLength": { + "$ref": "#/definitions/positiveInteger" + }, + "uniqueItems": { + "default": False, + "type": "boolean" + }, + "additionalItems": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "default": {}, + "pattern": { + "type": "string", + "format": "regex" + }, + "required": { + "$ref": "#/definitions/stringArray" + }, + "maximum": { + "type": "number" + }, + "minItems": { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + "readonly": { + "type": "boolean" + }, + "items": { + "type": "object", + "properties": { + "enum": { + "type": "array" + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } + } + }, + "type": { + "enum": [ + "array", + "boolean", + "integer", + "number", + "object", + "string", + "null" + ], + "type": "string" + } } } - }, - "type": { - "enum": [ - "array", - "boolean", - "integer", - "number", - "object", - "string", - "null" - ], - "type": "string" - } + ) } } -FakePropertyModel = warlock.model_factory(fake_property_schema) class TestPropertyController(testtools.TestCase): def setUp(self): super(TestPropertyController, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) self.controller = metadefs.PropertyController(self.api, - FakePropertyModel) + self.schema_api) def test_list_property(self): properties = list(self.controller.list(NAMESPACE1)) diff --git a/tests/v2/test_metadefs_resource_types.py b/tests/v2/test_metadefs_resource_types.py index 386464d..bcb4993 100644 --- a/tests/v2/test_metadefs_resource_types.py +++ b/tests/v2/test_metadefs_resource_types.py @@ -15,8 +15,6 @@ import testtools -import warlock - from glanceclient.v2 import metadefs from tests import utils @@ -28,7 +26,7 @@ RESOURCE_TYPE4 = 'ResourceType4' RESOURCE_TYPENEW = 'ResourceTypeNew' -fixtures = { +data_fixtures = { "/v2/metadefs/namespaces/%s/resource_types" % NAMESPACE1: { "GET": ( {}, @@ -84,64 +82,76 @@ fixtures = { ] } ) - }, + } } - -fake_resource_type_schema = { - "name": "resource_type", - "properties": { - "prefix": { - "type": "string", - "description": "Specifies the prefix to use for the given " - "resource type. Any properties in the namespace " - "should be prefixed with this prefix when being " - "applied to the specified resource type. Must " - "include prefix separator (e.g. a colon :).", - "maxLength": 80 - }, - "properties_target": { - "type": "string", - "description": "Some resource types allow more than one " - "key / value pair per instance. For example, " - "Cinder allows user and image metadata on volumes. " - "Only the image properties metadata is evaluated " - "by Nova (scheduling or drivers). This property " - "allows a namespace target to remove the " - "ambiguity.", - "maxLength": 80 - }, - "name": { - "type": "string", - "description": "Resource type names should be aligned with Heat " - "resource types whenever possible: http://docs." - "openstack.org/developer/heat/template_guide/" - "openstack.html", - "maxLength": 80 - }, - "created_at": { - "type": "string", - "description": "Date and time of resource type association" - " (READ-ONLY)", - "format": "date-time" - }, - "updated_at": { - "type": "string", - "description": "Date and time of the last resource type " - "association modification (READ-ONLY)", - "format": "date-time" - }, +schema_fixtures = { + "metadefs/resource_type": { + "GET": ( + {}, + { + "name": "resource_type", + "properties": { + "prefix": { + "type": "string", + "description": "Specifies the prefix to use for the " + "given resource type. Any properties " + "in the namespace should be prefixed " + "with this prefix when being applied " + "to the specified resource type. Must " + "include prefix separator (e.g. a " + "colon :).", + "maxLength": 80 + }, + "properties_target": { + "type": "string", + "description": "Some resource types allow more than " + "one key / value pair per instance. " + "For example, Cinder allows user and " + "image metadata on volumes. Only the " + "image properties metadata is " + "evaluated by Nova (scheduling or " + "drivers). This property allows a " + "namespace target to remove the " + "ambiguity.", + "maxLength": 80 + }, + "name": { + "type": "string", + "description": "Resource type names should be " + "aligned with Heat resource types " + "whenever possible: http://docs." + "openstack.org/developer/heat/" + "template_guide/openstack.html", + "maxLength": 80 + }, + "created_at": { + "type": "string", + "description": "Date and time of resource type " + "association (READ-ONLY)", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "description": "Date and time of the last resource " + "type association modification " + "(READ-ONLY)", + "format": "date-time" + }, + } + } + ) } } -FakeRTModel = warlock.model_factory(fake_resource_type_schema) class TestResoureTypeController(testtools.TestCase): def setUp(self): super(TestResoureTypeController, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) self.controller = metadefs.ResourceTypeController(self.api, - FakeRTModel) + self.schema_api) def test_list_resource_types(self): resource_types = list(self.controller.list()) diff --git a/tests/v2/test_tags.py b/tests/v2/test_tags.py index 83fc368..88ec2fe 100644 --- a/tests/v2/test_tags.py +++ b/tests/v2/test_tags.py @@ -14,7 +14,6 @@ # under the License. import testtools -import warlock from glanceclient.v2 import image_tags from tests import utils @@ -24,7 +23,7 @@ IMAGE = '3a4560a1-e585-443e-9b39-553b46ec92d1' TAG = 'tag01' -fixtures = { +data_fixtures = { '/v2/images/{image}/tags/{tag_value}'.format(image=IMAGE, tag_value=TAG): { 'DELETE': ( {}, @@ -37,19 +36,25 @@ fixtures = { 'tag_value': TAG } ), - }, + } } - -fake_schema = {'name': 'image', 'properties': {'image_id': {}, 'tags': {}}} -FakeModel = warlock.model_factory(fake_schema) +schema_fixtures = { + 'tag': { + 'GET': ( + {}, + {'name': 'image', 'properties': {'image_id': {}, 'tags': {}}} + ) + } +} class TestController(testtools.TestCase): def setUp(self): super(TestController, self).setUp() - self.api = utils.FakeAPI(fixtures) - self.controller = image_tags.Controller(self.api, FakeModel) + self.api = utils.FakeAPI(data_fixtures) + self.schema_api = utils.FakeSchemaAPI(schema_fixtures) + self.controller = image_tags.Controller(self.api, self.schema_api) def test_update_image_tag(self): image_id = IMAGE |