# Copyright 2012 OpenStack Foundation. # All Rights Reserved. # # 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 testtools from glanceclient.tests.unit.v2 import base from glanceclient.tests import utils from glanceclient.v2 import metadefs NAMESPACE1 = 'Namespace1' OBJECT1 = 'Object1' OBJECT2 = 'Object2' OBJECTNEW = 'ObjectNew' PROPERTY1 = 'Property1' PROPERTY2 = 'Property2' PROPERTY3 = 'Property3' PROPERTY4 = 'Property4' def _get_object_fixture(ns_name, obj_name, **kwargs): obj = { "description": "DESCRIPTION", "name": obj_name, "self": "/v2/metadefs/namespaces/%s/objects/%s" % (ns_name, obj_name), "required": [], "properties": { PROPERTY1: { "type": "integer", "description": "DESCRIPTION", "title": "Quota: CPU Shares" }, PROPERTY2: { "minimum": 1000, "type": "integer", "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", } obj.update(kwargs) return obj data_fixtures = { "/v2/metadefs/namespaces/%s/objects" % NAMESPACE1: { "GET": ( {}, { "objects": [ _get_object_fixture(NAMESPACE1, OBJECT1), _get_object_fixture(NAMESPACE1, OBJECT2) ], "schema": "v2/schemas/metadefs/objects" } ), "POST": ( {}, _get_object_fixture(NAMESPACE1, OBJECTNEW) ), "DELETE": ( {}, {} ) }, "/v2/metadefs/namespaces/%s/objects/%s" % (NAMESPACE1, OBJECT1): { "GET": ( {}, _get_object_fixture(NAMESPACE1, OBJECT1) ), "PUT": ( {}, _get_object_fixture(NAMESPACE1, OBJECT1) ), "DELETE": ( {}, {} ) } } 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": [ "name" ], "name": "object", "properties": { "created_at": { "type": "string", "readOnly": True, "description": "Date and time of object creation ", "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", "readOnly": True, "description": "Date and time of the last object " "modification", "format": "date-time" }, } } ) } } class TestObjectController(testtools.TestCase): def setUp(self): super(TestObjectController, self).setUp() self.api = utils.FakeAPI(data_fixtures) self.schema_api = utils.FakeSchemaAPI(schema_fixtures) self.controller = base.BaseController(self.api, self.schema_api, metadefs.ObjectController) def test_list_object(self): objects = self.controller.list(NAMESPACE1) actual = [obj.name for obj in objects] self.assertEqual([OBJECT1, OBJECT2], actual) def test_get_object(self): obj = self.controller.get(NAMESPACE1, OBJECT1) self.assertEqual(OBJECT1, obj.name) self.assertEqual(sorted([PROPERTY1, PROPERTY2]), sorted(list(obj.properties.keys()))) def test_create_object(self): properties = { 'name': OBJECTNEW, 'description': 'DESCRIPTION' } obj = self.controller.create(NAMESPACE1, **properties) self.assertEqual(OBJECTNEW, obj.name) def test_create_object_invalid_property(self): properties = { 'namespace': NAMESPACE1 } self.assertRaises(TypeError, self.controller.create, **properties) def test_update_object(self): properties = { 'description': 'UPDATED_DESCRIPTION' } obj = self.controller.update(NAMESPACE1, OBJECT1, **properties) self.assertEqual(OBJECT1, obj.name) def test_update_object_invalid_property(self): properties = { 'required': 'INVALID' } self.assertRaises(TypeError, self.controller.update, NAMESPACE1, OBJECT1, **properties) def test_update_object_disallowed_fields(self): properties = { 'description': 'UPDATED_DESCRIPTION' } self.controller.update(NAMESPACE1, OBJECT1, **properties) actual = self.api.calls # API makes three calls(GET, PUT, GET) for object update. # PUT has the request body in the list '''('PUT', '/v2/metadefs/namespaces/Namespace1/objects/Object1', {}, [('description', 'UPDATED_DESCRIPTION'), ('name', 'Object1'), ('properties', ...), ('required', [])])''' _disallowed_fields = ['self', 'schema', 'created_at', 'updated_at'] for key in actual[1][3]: self.assertNotIn(key, _disallowed_fields) def test_delete_object(self): self.controller.delete(NAMESPACE1, OBJECT1) expect = [ ('DELETE', '/v2/metadefs/namespaces/%s/objects/%s' % (NAMESPACE1, OBJECT1), {}, None)] self.assertEqual(expect, self.api.calls) def test_delete_all_objects(self): self.controller.delete_all(NAMESPACE1) expect = [ ('DELETE', '/v2/metadefs/namespaces/%s/objects' % NAMESPACE1, {}, None)] self.assertEqual(expect, self.api.calls)