summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-09-13 07:36:36 +0000
committerGerrit Code Review <review@openstack.org>2014-09-13 07:36:36 +0000
commita8f31ccfbfdaa1b47fd3ce245744f241d68531bc (patch)
tree71633f8049f5a0c8ea673bd7ff8aeeb1951a2a7e
parent128ea59beafa1829c1a8579f4f38ad9ea59f2d79 (diff)
parent97b1506bdbccea9fbfcac731cf8b7e0cadebcbab (diff)
downloadpython-glanceclient-a8f31ccfbfdaa1b47fd3ce245744f241d68531bc.tar.gz
Merge "Fix v2 requests to non-bleeding edge servers"
-rw-r--r--glanceclient/common/utils.py18
-rw-r--r--glanceclient/v2/client.py48
-rw-r--r--glanceclient/v2/image_members.py14
-rw-r--r--glanceclient/v2/image_tags.py14
-rw-r--r--glanceclient/v2/images.py10
-rw-r--r--glanceclient/v2/metadefs.py39
-rw-r--r--tests/utils.py11
-rw-r--r--tests/v2/test_client.py13
-rw-r--r--tests/v2/test_images.py94
-rw-r--r--tests/v2/test_members.py29
-rw-r--r--tests/v2/test_metadefs_namespaces.py399
-rw-r--r--tests/v2/test_metadefs_objects.py285
-rw-r--r--tests/v2/test_metadefs_properties.py240
-rw-r--r--tests/v2/test_metadefs_resource_types.py112
-rw-r--r--tests/v2/test_tags.py21
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