Support for Metadata Definitions Catalog API
API calls and shell commands added in this patch: - CRUD for metadefs namespaces; - CRUD for metadefs objects; - CRUD for metadefs properites; - CRD for metadefs resource types and resource type associations. Change-Id: I6d15f749038e8fd24fc651f0b314df5be7c673ef Implements: blueprint metadata-schema-catalog-support Co-Authored-By: Facundo Maldonado <facundo.n.maldonado@intel.com> Co-Authored-By: Michal Dulko <michal.dulko@intel.com> Co-Authored-By: Lakshmi N Sampath <lakshmi.sampath@hp.com> Co-Authored-By: Pawel Koniszewski <pawel.koniszewski@intel.com>
This commit is contained in:
committed by
Travis Tripp
parent
16077d91dd
commit
33dcea81b2
+38
-25
@@ -141,9 +141,9 @@ class ShellTest(utils.TestCase):
|
||||
self.assertEqual(kwargs['token'], 'mytoken')
|
||||
self.assertEqual(args[0], 'https://image:1234/v1')
|
||||
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schema')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schemas')
|
||||
def test_no_auth_with_token_and_image_url_with_v2(self,
|
||||
cache_schema):
|
||||
cache_schemas):
|
||||
with mock.patch('glanceclient.v2.client.Client') as v2_client:
|
||||
# test no authentication is required if both token and endpoint url
|
||||
# are specified
|
||||
@@ -181,14 +181,14 @@ class ShellTest(utils.TestCase):
|
||||
|
||||
@mock.patch('glanceclient.v2.client.Client')
|
||||
@mock.patch('keystoneclient.session.Session')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schema')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schemas')
|
||||
@mock.patch.object(keystoneclient.discover.Discover, 'url_for',
|
||||
side_effect=[keystone_client_fixtures.V2_URL, None])
|
||||
def test_auth_plugin_invocation_with_v2(self,
|
||||
v2_client,
|
||||
ks_session,
|
||||
url_for,
|
||||
cache_schema):
|
||||
cache_schemas):
|
||||
with mock.patch(self.auth_plugin) as mock_auth_plugin:
|
||||
args = '--os-image-api-version 2 image-list'
|
||||
glance_shell = openstack_shell.OpenStackImagesShell()
|
||||
@@ -211,12 +211,12 @@ class ShellTest(utils.TestCase):
|
||||
|
||||
@mock.patch('glanceclient.v2.client.Client')
|
||||
@mock.patch('keystoneclient.session.Session')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schema')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schemas')
|
||||
@mock.patch.object(keystoneclient.discover.Discover, 'url_for',
|
||||
side_effect=[keystone_client_fixtures.V2_URL,
|
||||
keystone_client_fixtures.V3_URL])
|
||||
def test_auth_plugin_invocation_with_unversioned_auth_url_with_v2(
|
||||
self, v2_client, ks_session, cache_schema, url_for):
|
||||
self, v2_client, ks_session, cache_schemas, url_for):
|
||||
with mock.patch(self.auth_plugin) as mock_auth_plugin:
|
||||
args = ('--os-auth-url %s --os-image-api-version 2 '
|
||||
'image-list') % (keystone_client_fixtures.BASE_URL)
|
||||
@@ -260,14 +260,14 @@ class ShellTestWithKeystoneV3Auth(ShellTest):
|
||||
|
||||
@mock.patch('glanceclient.v2.client.Client')
|
||||
@mock.patch('keystoneclient.session.Session')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schema')
|
||||
@mock.patch.object(openstack_shell.OpenStackImagesShell, '_cache_schemas')
|
||||
@mock.patch.object(keystoneclient.discover.Discover, 'url_for',
|
||||
side_effect=[None, keystone_client_fixtures.V3_URL])
|
||||
def test_auth_plugin_invocation_with_v2(self,
|
||||
v2_client,
|
||||
ks_session,
|
||||
url_for,
|
||||
cache_schema):
|
||||
cache_schemas):
|
||||
with mock.patch(self.auth_plugin) as mock_auth_plugin:
|
||||
args = '--os-image-api-version 2 image-list'
|
||||
glance_shell = openstack_shell.OpenStackImagesShell()
|
||||
@@ -292,7 +292,9 @@ class ShellCacheSchemaTest(utils.TestCase):
|
||||
self._mock_client_setup()
|
||||
self._mock_shell_setup()
|
||||
self.cache_dir = '/dir_for_cached_schema'
|
||||
self.cache_file = self.cache_dir + '/image_schema.json'
|
||||
self.cache_files = [self.cache_dir + '/image_schema.json',
|
||||
self.cache_dir + '/namespace_schema.json',
|
||||
self.cache_dir + '/resource_type_schema.json']
|
||||
|
||||
def tearDown(self):
|
||||
super(ShellCacheSchemaTest, self).tearDown()
|
||||
@@ -322,45 +324,56 @@ class ShellCacheSchemaTest(utils.TestCase):
|
||||
|
||||
@mock.patch('six.moves.builtins.open', new=mock.mock_open(), create=True)
|
||||
@mock.patch('os.path.exists', return_value=True)
|
||||
def test_cache_schema_gets_when_forced(self, exists_mock):
|
||||
def test_cache_schemas_gets_when_forced(self, exists_mock):
|
||||
options = {
|
||||
'get_schema': True
|
||||
}
|
||||
|
||||
self.shell._cache_schema(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
self.shell._cache_schemas(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
|
||||
self.assertEqual(4, open.mock_calls.__len__())
|
||||
self.assertEqual(mock.call(self.cache_file, 'w'), open.mock_calls[0])
|
||||
self.assertEqual(12, open.mock_calls.__len__())
|
||||
self.assertEqual(mock.call(self.cache_files[0], 'w'),
|
||||
open.mock_calls[0])
|
||||
self.assertEqual(mock.call(self.cache_files[1], 'w'),
|
||||
open.mock_calls[4])
|
||||
self.assertEqual(mock.call().write(json.dumps(self.schema_dict)),
|
||||
open.mock_calls[2])
|
||||
self.assertEqual(mock.call().write(json.dumps(self.schema_dict)),
|
||||
open.mock_calls[6])
|
||||
|
||||
@mock.patch('six.moves.builtins.open', new=mock.mock_open(), create=True)
|
||||
@mock.patch('os.path.exists', side_effect=[True, False])
|
||||
def test_cache_schema_gets_when_not_exists(self, exists_mock):
|
||||
@mock.patch('os.path.exists', side_effect=[True, False, False, False])
|
||||
def test_cache_schemas_gets_when_not_exists(self, exists_mock):
|
||||
options = {
|
||||
'get_schema': False
|
||||
}
|
||||
|
||||
self.shell._cache_schema(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
self.shell._cache_schemas(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
|
||||
self.assertEqual(4, open.mock_calls.__len__())
|
||||
self.assertEqual(mock.call(self.cache_file, 'w'), open.mock_calls[0])
|
||||
self.assertEqual(12, open.mock_calls.__len__())
|
||||
self.assertEqual(mock.call(self.cache_files[0], 'w'),
|
||||
open.mock_calls[0])
|
||||
self.assertEqual(mock.call(self.cache_files[1], 'w'),
|
||||
open.mock_calls[4])
|
||||
self.assertEqual(mock.call().write(json.dumps(self.schema_dict)),
|
||||
open.mock_calls[2])
|
||||
self.assertEqual(mock.call().write(json.dumps(self.schema_dict)),
|
||||
open.mock_calls[6])
|
||||
|
||||
@mock.patch('six.moves.builtins.open', new=mock.mock_open(), create=True)
|
||||
@mock.patch('os.path.exists', return_value=True)
|
||||
def test_cache_schema_leaves_when_present_not_forced(self, exists_mock):
|
||||
def test_cache_schemas_leaves_when_present_not_forced(self, exists_mock):
|
||||
options = {
|
||||
'get_schema': False
|
||||
}
|
||||
|
||||
self.shell._cache_schema(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
self.shell._cache_schemas(self._make_args(options),
|
||||
home_dir=self.cache_dir)
|
||||
|
||||
os.path.exists.assert_any_call(self.cache_dir)
|
||||
os.path.exists.assert_any_call(self.cache_file)
|
||||
self.assertEqual(2, exists_mock.call_count)
|
||||
os.path.exists.assert_any_call(self.cache_files[0])
|
||||
os.path.exists.assert_any_call(self.cache_files[1])
|
||||
self.assertEqual(4, exists_mock.call_count)
|
||||
self.assertEqual(0, open.mock_calls.__len__())
|
||||
|
||||
@@ -26,6 +26,14 @@ class ClientTest(testtools.TestCase):
|
||||
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()
|
||||
|
||||
@@ -0,0 +1,592 @@
|
||||
# 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
|
||||
|
||||
import warlock
|
||||
|
||||
from glanceclient.v2 import metadefs
|
||||
from tests import utils
|
||||
|
||||
NAMESPACE1 = 'Namespace1'
|
||||
NAMESPACE2 = 'Namespace2'
|
||||
NAMESPACE3 = 'Namespace3'
|
||||
NAMESPACE4 = 'Namespace4'
|
||||
NAMESPACE5 = 'Namespace5'
|
||||
NAMESPACE6 = 'Namespace6'
|
||||
NAMESPACE7 = 'Namespace7'
|
||||
NAMESPACE8 = 'Namespace8'
|
||||
NAMESPACENEW = 'NamespaceNew'
|
||||
RESOURCE_TYPE1 = 'ResourceType1'
|
||||
RESOURCE_TYPE2 = 'ResourceType2'
|
||||
OBJECT1 = 'Object1'
|
||||
PROPERTY1 = 'Property1'
|
||||
PROPERTY2 = 'Property2'
|
||||
|
||||
|
||||
def _get_namespace_fixture(ns_name, rt_name=RESOURCE_TYPE1, **kwargs):
|
||||
ns = {
|
||||
"display_name": "Flavor Quota",
|
||||
"description": "DESCRIPTION1",
|
||||
"self": "/v2/metadefs/namespaces/%s" % ns_name,
|
||||
"namespace": ns_name,
|
||||
"visibility": "public",
|
||||
"protected": True,
|
||||
"owner": "admin",
|
||||
"resource_types": [
|
||||
{
|
||||
"name": rt_name
|
||||
}
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespace",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
|
||||
ns.update(kwargs)
|
||||
|
||||
return ns
|
||||
|
||||
fixtures = {
|
||||
"/v2/metadefs/namespaces?limit=20": {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=20",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE1),
|
||||
_get_namespace_fixture(NAMESPACE2),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces"
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces?limit=1": {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=1",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE7),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces",
|
||||
"next": "/v2/metadefs/namespaces?marker=%s&limit=1"
|
||||
% NAMESPACE7,
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces?marker=%s&limit=1" % NAMESPACE7: {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=1",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE8),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces"
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces?limit=20&resource_types=%s" % RESOURCE_TYPE1: {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=20",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE3),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces"
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces?limit=20&resource_types="
|
||||
"%s%%2C%s" % (RESOURCE_TYPE1, RESOURCE_TYPE2): {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=20",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE4),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces"
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces?limit=20&visibility=private": {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"first": "/v2/metadefs/namespaces?limit=20",
|
||||
"namespaces": [
|
||||
_get_namespace_fixture(NAMESPACE5),
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespaces"
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces": {
|
||||
"POST": (
|
||||
{},
|
||||
{
|
||||
"display_name": "Flavor Quota",
|
||||
"description": "DESCRIPTION1",
|
||||
"self": "/v2/metadefs/namespaces/%s" % 'NamespaceNew',
|
||||
"namespace": 'NamespaceNew',
|
||||
"visibility": "public",
|
||||
"protected": True,
|
||||
"owner": "admin",
|
||||
"schema": "/v2/schemas/metadefs/namespace",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces/%s" % NAMESPACE1: {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"display_name": "Flavor Quota",
|
||||
"description": "DESCRIPTION1",
|
||||
"objects": [
|
||||
{
|
||||
"description": "DESCRIPTION2",
|
||||
"name": "OBJECT1",
|
||||
"self": "/v2/metadefs/namespaces/%s/objects/" %
|
||||
OBJECT1,
|
||||
"required": [],
|
||||
"properties": {
|
||||
PROPERTY1: {
|
||||
"type": "integer",
|
||||
"description": "DESCRIPTION3",
|
||||
"title": "Quota: CPU Shares"
|
||||
},
|
||||
PROPERTY2: {
|
||||
"minimum": 1000,
|
||||
"type": "integer",
|
||||
"description": "DESCRIPTION4",
|
||||
"maximum": 1000000,
|
||||
"title": "Quota: CPU Period"
|
||||
},
|
||||
},
|
||||
"schema": "/v2/schemas/metadefs/object"
|
||||
}
|
||||
],
|
||||
"self": "/v2/metadefs/namespaces/%s" % NAMESPACE1,
|
||||
"namespace": NAMESPACE1,
|
||||
"visibility": "public",
|
||||
"protected": True,
|
||||
"owner": "admin",
|
||||
"resource_types": [
|
||||
{
|
||||
"name": RESOURCE_TYPE1
|
||||
}
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespace",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
),
|
||||
"PUT": (
|
||||
{},
|
||||
{
|
||||
"display_name": "Flavor Quota",
|
||||
"description": "DESCRIPTION1",
|
||||
"objects": [
|
||||
{
|
||||
"description": "DESCRIPTION2",
|
||||
"name": "OBJECT1",
|
||||
"self": "/v2/metadefs/namespaces/%s/objects/" %
|
||||
OBJECT1,
|
||||
"required": [],
|
||||
"properties": {
|
||||
PROPERTY1: {
|
||||
"type": "integer",
|
||||
"description": "DESCRIPTION3",
|
||||
"title": "Quota: CPU Shares"
|
||||
},
|
||||
PROPERTY2: {
|
||||
"minimum": 1000,
|
||||
"type": "integer",
|
||||
"description": "DESCRIPTION4",
|
||||
"maximum": 1000000,
|
||||
"title": "Quota: CPU Period"
|
||||
},
|
||||
},
|
||||
"schema": "/v2/schemas/metadefs/object"
|
||||
}
|
||||
],
|
||||
"self": "/v2/metadefs/namespaces/%s" % NAMESPACENEW,
|
||||
"namespace": NAMESPACENEW,
|
||||
"visibility": "public",
|
||||
"protected": True,
|
||||
"owner": "admin",
|
||||
"resource_types": [
|
||||
{
|
||||
"name": RESOURCE_TYPE1
|
||||
}
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespace",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
),
|
||||
"DELETE": (
|
||||
{},
|
||||
{}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces/%s?resource_type=%s" % (NAMESPACE6,
|
||||
RESOURCE_TYPE1):
|
||||
{
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"display_name": "Flavor Quota",
|
||||
"description": "DESCRIPTION1",
|
||||
"objects": [],
|
||||
"self": "/v2/metadefs/namespaces/%s" % NAMESPACE1,
|
||||
"namespace": NAMESPACE6,
|
||||
"visibility": "public",
|
||||
"protected": True,
|
||||
"owner": "admin",
|
||||
"resource_types": [
|
||||
{
|
||||
"name": RESOURCE_TYPE1
|
||||
}
|
||||
],
|
||||
"schema": "/v2/schemas/metadefs/namespace",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
fake_namespace_schema = {
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Owner of the namespace.",
|
||||
"maxLength": 255
|
||||
},
|
||||
"resource_types": {
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"prefix": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata_type": {
|
||||
"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.controller = metadefs.NamespaceController(self.api,
|
||||
FakeNamespaceModel)
|
||||
|
||||
def test_list_namespaces(self):
|
||||
namespaces = list(self.controller.list())
|
||||
|
||||
self.assertEqual(len(namespaces), 2)
|
||||
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
||||
self.assertEqual(NAMESPACE2, namespaces[1]['namespace'])
|
||||
|
||||
def test_list_namespaces_paginate(self):
|
||||
namespaces = list(self.controller.list(page_size=1))
|
||||
|
||||
self.assertEqual(len(namespaces), 2)
|
||||
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
||||
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
||||
|
||||
def test_list_namespaces_with_one_resource_type_filter(self):
|
||||
namespaces = list(self.controller.list(
|
||||
filters={
|
||||
'resource_types': [RESOURCE_TYPE1]
|
||||
}
|
||||
))
|
||||
|
||||
self.assertEqual(len(namespaces), 1)
|
||||
self.assertEqual(NAMESPACE3, namespaces[0]['namespace'])
|
||||
|
||||
def test_list_namespaces_with_multiple_resource_types_filter(self):
|
||||
namespaces = list(self.controller.list(
|
||||
filters={
|
||||
'resource_types': [RESOURCE_TYPE1, RESOURCE_TYPE2]
|
||||
}
|
||||
))
|
||||
|
||||
self.assertEqual(len(namespaces), 1)
|
||||
self.assertEqual(NAMESPACE4, namespaces[0]['namespace'])
|
||||
|
||||
def test_list_namespaces_with_visibility_filter(self):
|
||||
namespaces = list(self.controller.list(
|
||||
filters={
|
||||
'visibility': 'private'
|
||||
}
|
||||
))
|
||||
|
||||
self.assertEqual(len(namespaces), 1)
|
||||
self.assertEqual(NAMESPACE5, namespaces[0]['namespace'])
|
||||
|
||||
def test_get_namespace(self):
|
||||
namespace = self.controller.get(NAMESPACE1)
|
||||
self.assertEqual(NAMESPACE1, namespace.namespace)
|
||||
self.assertTrue(namespace.protected)
|
||||
|
||||
def test_get_namespace_with_resource_type(self):
|
||||
namespace = self.controller.get(NAMESPACE6,
|
||||
resource_type=RESOURCE_TYPE1)
|
||||
self.assertEqual(NAMESPACE6, namespace.namespace)
|
||||
self.assertTrue(namespace.protected)
|
||||
|
||||
def test_create_namespace(self):
|
||||
properties = {
|
||||
'namespace': NAMESPACENEW
|
||||
}
|
||||
namespace = self.controller.create(**properties)
|
||||
|
||||
self.assertEqual(NAMESPACENEW, namespace.namespace)
|
||||
self.assertTrue(namespace.protected)
|
||||
|
||||
def test_create_namespace_invalid_data(self):
|
||||
properties = {}
|
||||
|
||||
self.assertRaises(TypeError, self.controller.create, **properties)
|
||||
|
||||
def test_create_namespace_invalid_property(self):
|
||||
properties = {'namespace': 'NewNamespace', 'protected': '123'}
|
||||
|
||||
self.assertRaises(TypeError, self.controller.create, **properties)
|
||||
|
||||
def test_update_namespace(self):
|
||||
properties = {'display_name': 'My Updated Name'}
|
||||
namespace = self.controller.update(NAMESPACE1, **properties)
|
||||
|
||||
self.assertEqual(NAMESPACE1, namespace.namespace)
|
||||
|
||||
def test_update_namespace_invalid_property(self):
|
||||
properties = {'protected': '123'}
|
||||
|
||||
self.assertRaises(TypeError, self.controller.update, NAMESPACE1,
|
||||
**properties)
|
||||
|
||||
def test_delete_namespace(self):
|
||||
self.controller.delete(NAMESPACE1)
|
||||
expect = [
|
||||
('DELETE',
|
||||
'/v2/metadefs/namespaces/%s' % NAMESPACE1,
|
||||
{},
|
||||
None)]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
@@ -0,0 +1,318 @@
|
||||
# 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 six
|
||||
import testtools
|
||||
|
||||
import warlock
|
||||
|
||||
from glanceclient.v2 import metadefs
|
||||
from tests import utils
|
||||
|
||||
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
|
||||
|
||||
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": (
|
||||
{},
|
||||
{}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fake_object_schema = {
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
"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)
|
||||
|
||||
def test_list_object(self):
|
||||
objects = list(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([PROPERTY1, PROPERTY2],
|
||||
list(six.iterkeys(obj.properties)))
|
||||
|
||||
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_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)
|
||||
@@ -0,0 +1,296 @@
|
||||
# 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
|
||||
|
||||
import warlock
|
||||
|
||||
from glanceclient.v2 import metadefs
|
||||
from tests import utils
|
||||
|
||||
NAMESPACE1 = 'Namespace1'
|
||||
PROPERTY1 = 'Property1'
|
||||
PROPERTY2 = 'Property2'
|
||||
PROPERTYNEW = 'PropertyNew'
|
||||
|
||||
fixtures = {
|
||||
"/v2/metadefs/namespaces/%s/properties" % NAMESPACE1: {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"properties": {
|
||||
PROPERTY1: {
|
||||
"default": "1",
|
||||
"type": "integer",
|
||||
"description": "Number of cores.",
|
||||
"title": "cores"
|
||||
},
|
||||
PROPERTY2: {
|
||||
"items": {
|
||||
"enum": [
|
||||
"Intel",
|
||||
"AMD"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Specifies the CPU manufacturer.",
|
||||
"title": "Vendor"
|
||||
},
|
||||
}
|
||||
}
|
||||
),
|
||||
"POST": (
|
||||
{},
|
||||
{
|
||||
"items": {
|
||||
"enum": [
|
||||
"Intel",
|
||||
"AMD"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "UPDATED_DESCRIPTION",
|
||||
"title": "Vendor",
|
||||
"name": PROPERTYNEW
|
||||
}
|
||||
),
|
||||
"DELETE": (
|
||||
{},
|
||||
{}
|
||||
)
|
||||
},
|
||||
"/v2/metadefs/namespaces/%s/properties/%s" % (NAMESPACE1, PROPERTY1): {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"items": {
|
||||
"enum": [
|
||||
"Intel",
|
||||
"AMD"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Specifies the CPU manufacturer.",
|
||||
"title": "Vendor"
|
||||
}
|
||||
),
|
||||
"PUT": (
|
||||
{},
|
||||
{
|
||||
"items": {
|
||||
"enum": [
|
||||
"Intel",
|
||||
"AMD"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "UPDATED_DESCRIPTION",
|
||||
"title": "Vendor"
|
||||
}
|
||||
),
|
||||
"DELETE": (
|
||||
{},
|
||||
{}
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
},
|
||||
"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.controller = metadefs.PropertyController(self.api,
|
||||
FakePropertyModel)
|
||||
|
||||
def test_list_property(self):
|
||||
properties = list(self.controller.list(NAMESPACE1))
|
||||
|
||||
actual = [prop.name for prop in properties]
|
||||
self.assertEqual([PROPERTY1, PROPERTY2], actual)
|
||||
|
||||
def test_get_property(self):
|
||||
prop = self.controller.get(NAMESPACE1, PROPERTY1)
|
||||
self.assertEqual(PROPERTY1, prop.name)
|
||||
|
||||
def test_create_property(self):
|
||||
properties = {
|
||||
'name': PROPERTYNEW,
|
||||
'title': 'TITLE',
|
||||
'type': 'string'
|
||||
}
|
||||
obj = self.controller.create(NAMESPACE1, **properties)
|
||||
self.assertEqual(PROPERTYNEW, obj.name)
|
||||
|
||||
def test_create_property_invalid_property(self):
|
||||
properties = {
|
||||
'namespace': NAMESPACE1
|
||||
}
|
||||
self.assertRaises(TypeError, self.controller.create, **properties)
|
||||
|
||||
def test_update_property(self):
|
||||
properties = {
|
||||
'description': 'UPDATED_DESCRIPTION'
|
||||
}
|
||||
prop = self.controller.update(NAMESPACE1, PROPERTY1, **properties)
|
||||
self.assertEqual(PROPERTY1, prop.name)
|
||||
|
||||
def test_update_property_invalid_property(self):
|
||||
properties = {
|
||||
'type': 'INVALID'
|
||||
}
|
||||
self.assertRaises(TypeError, self.controller.update, NAMESPACE1,
|
||||
PROPERTY1, **properties)
|
||||
|
||||
def test_delete_property(self):
|
||||
self.controller.delete(NAMESPACE1, PROPERTY1)
|
||||
expect = [
|
||||
('DELETE',
|
||||
'/v2/metadefs/namespaces/%s/properties/%s' % (NAMESPACE1,
|
||||
PROPERTY1),
|
||||
{},
|
||||
None)]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
|
||||
def test_delete_all_properties(self):
|
||||
self.controller.delete_all(NAMESPACE1)
|
||||
expect = [
|
||||
('DELETE',
|
||||
'/v2/metadefs/namespaces/%s/properties' % NAMESPACE1,
|
||||
{},
|
||||
None)]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
@@ -0,0 +1,176 @@
|
||||
# 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
|
||||
|
||||
import warlock
|
||||
|
||||
from glanceclient.v2 import metadefs
|
||||
from tests import utils
|
||||
|
||||
NAMESPACE1 = 'Namespace1'
|
||||
RESOURCE_TYPE1 = 'ResourceType1'
|
||||
RESOURCE_TYPE2 = 'ResourceType2'
|
||||
RESOURCE_TYPE3 = 'ResourceType3'
|
||||
RESOURCE_TYPE4 = 'ResourceType4'
|
||||
RESOURCE_TYPENEW = 'ResourceTypeNew'
|
||||
|
||||
|
||||
fixtures = {
|
||||
"/v2/metadefs/namespaces/%s/resource_types" % NAMESPACE1: {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"resource_type_associations": [
|
||||
{
|
||||
"name": RESOURCE_TYPE3,
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
},
|
||||
{
|
||||
"name": RESOURCE_TYPE4,
|
||||
"prefix": "PREFIX:",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
"POST": (
|
||||
{},
|
||||
{
|
||||
"name": RESOURCE_TYPENEW,
|
||||
"prefix": "PREFIX:",
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
),
|
||||
},
|
||||
"/v2/metadefs/namespaces/%s/resource_types/%s" % (NAMESPACE1,
|
||||
RESOURCE_TYPE1):
|
||||
{
|
||||
"DELETE": (
|
||||
{},
|
||||
{}
|
||||
),
|
||||
},
|
||||
"/v2/metadefs/resource_types": {
|
||||
"GET": (
|
||||
{},
|
||||
{
|
||||
"resource_types": [
|
||||
{
|
||||
"name": RESOURCE_TYPE1,
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
},
|
||||
{
|
||||
"name": RESOURCE_TYPE2,
|
||||
"created_at": "2014-08-14T09:07:06Z",
|
||||
"updated_at": "2014-08-14T09:07:06Z",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
},
|
||||
}
|
||||
}
|
||||
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.controller = metadefs.ResourceTypeController(self.api,
|
||||
FakeRTModel)
|
||||
|
||||
def test_list_resource_types(self):
|
||||
resource_types = list(self.controller.list())
|
||||
names = [rt.name for rt in resource_types]
|
||||
self.assertEqual([RESOURCE_TYPE1, RESOURCE_TYPE2], names)
|
||||
|
||||
def test_get_resource_types(self):
|
||||
resource_types = list(self.controller.get(NAMESPACE1))
|
||||
names = [rt.name for rt in resource_types]
|
||||
self.assertEqual([RESOURCE_TYPE3, RESOURCE_TYPE4], names)
|
||||
|
||||
def test_associate_resource_types(self):
|
||||
resource_types = self.controller.associate(NAMESPACE1,
|
||||
name=RESOURCE_TYPENEW)
|
||||
|
||||
self.assertEqual(RESOURCE_TYPENEW, resource_types['name'])
|
||||
|
||||
def test_associate_resource_types_invalid_property(self):
|
||||
longer = '1234' * 50
|
||||
properties = {'name': RESOURCE_TYPENEW, 'prefix': longer}
|
||||
self.assertRaises(TypeError, self.controller.associate, NAMESPACE1,
|
||||
**properties)
|
||||
|
||||
def test_deassociate_resource_types(self):
|
||||
self.controller.deassociate(NAMESPACE1, RESOURCE_TYPE1)
|
||||
expect = [
|
||||
('DELETE',
|
||||
'/v2/metadefs/namespaces/%s/resource_types/%s' % (NAMESPACE1,
|
||||
RESOURCE_TYPE1),
|
||||
{},
|
||||
None)]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
@@ -385,3 +385,502 @@ class ShellV2Test(testtools.TestCase):
|
||||
self.assert_exits_with_msg(func=test_shell.do_image_tag_delete,
|
||||
func_args=args,
|
||||
err_msg=msg)
|
||||
|
||||
def test_do_md_namespace_create(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'protected': True})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'create') as mocked_create:
|
||||
expect_namespace = {}
|
||||
expect_namespace['namespace'] = 'MyNamespace'
|
||||
expect_namespace['protected'] = True
|
||||
|
||||
mocked_create.return_value = expect_namespace
|
||||
|
||||
test_shell.do_md_namespace_create(self.gc, args)
|
||||
|
||||
mocked_create.assert_called_once_with(namespace='MyNamespace',
|
||||
protected=True)
|
||||
utils.print_dict.assert_called_once_with(expect_namespace)
|
||||
|
||||
def test_do_md_namespace_import(self):
|
||||
args = self._make_args({'file': 'test'})
|
||||
|
||||
expect_namespace = {}
|
||||
expect_namespace['namespace'] = 'MyNamespace'
|
||||
expect_namespace['protected'] = True
|
||||
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'create') as mocked_create:
|
||||
mock_read = mock.Mock(return_value=json.dumps(expect_namespace))
|
||||
mock_file = mock.Mock(read=mock_read)
|
||||
utils.get_data_file = mock.Mock(return_value=mock_file)
|
||||
mocked_create.return_value = expect_namespace
|
||||
|
||||
test_shell.do_md_namespace_import(self.gc, args)
|
||||
|
||||
mocked_create.assert_called_once_with(**expect_namespace)
|
||||
utils.print_dict.assert_called_once_with(expect_namespace)
|
||||
|
||||
def test_do_md_namespace_import_invalid_json(self):
|
||||
args = self._make_args({'file': 'test'})
|
||||
mock_read = mock.Mock(return_value='Invalid')
|
||||
mock_file = mock.Mock(read=mock_read)
|
||||
utils.get_data_file = mock.Mock(return_value=mock_file)
|
||||
|
||||
self.assertRaises(SystemExit, test_shell.do_md_namespace_import,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_namespace_import_no_input(self):
|
||||
args = self._make_args({'file': None})
|
||||
utils.get_data_file = mock.Mock(return_value=None)
|
||||
|
||||
self.assertRaises(SystemExit, test_shell.do_md_namespace_import,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_namespace_update(self):
|
||||
args = self._make_args({'id': 'MyNamespace',
|
||||
'protected': True})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'update') as mocked_update:
|
||||
expect_namespace = {}
|
||||
expect_namespace['namespace'] = 'MyNamespace'
|
||||
expect_namespace['protected'] = True
|
||||
|
||||
mocked_update.return_value = expect_namespace
|
||||
|
||||
test_shell.do_md_namespace_update(self.gc, args)
|
||||
|
||||
mocked_update.assert_called_once_with('MyNamespace',
|
||||
id='MyNamespace',
|
||||
protected=True)
|
||||
utils.print_dict.assert_called_once_with(expect_namespace)
|
||||
|
||||
def test_do_md_namespace_show(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'max_column_width': 80,
|
||||
'resource_type': None})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'get') as mocked_get:
|
||||
expect_namespace = {}
|
||||
expect_namespace['namespace'] = 'MyNamespace'
|
||||
|
||||
mocked_get.return_value = expect_namespace
|
||||
|
||||
test_shell.do_md_namespace_show(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace')
|
||||
utils.print_dict.assert_called_once_with(expect_namespace, 80)
|
||||
|
||||
def test_do_md_namespace_show_resource_type(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'max_column_width': 80,
|
||||
'resource_type': 'RESOURCE'})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'get') as mocked_get:
|
||||
expect_namespace = {}
|
||||
expect_namespace['namespace'] = 'MyNamespace'
|
||||
|
||||
mocked_get.return_value = expect_namespace
|
||||
|
||||
test_shell.do_md_namespace_show(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace',
|
||||
resource_type='RESOURCE')
|
||||
utils.print_dict.assert_called_once_with(expect_namespace, 80)
|
||||
|
||||
def test_do_md_namespace_list(self):
|
||||
args = self._make_args({'resource_type': None,
|
||||
'visibility': None,
|
||||
'page_size': None})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'list') as mocked_list:
|
||||
expect_namespaces = [{'namespace': 'MyNamespace'}]
|
||||
|
||||
mocked_list.return_value = expect_namespaces
|
||||
|
||||
test_shell.do_md_namespace_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with(filters={})
|
||||
utils.print_list.assert_called_once_with(expect_namespaces,
|
||||
['namespace'])
|
||||
|
||||
def test_do_md_namespace_list_page_size(self):
|
||||
args = self._make_args({'resource_type': None,
|
||||
'visibility': None,
|
||||
'page_size': 2})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'list') as mocked_list:
|
||||
expect_namespaces = [{'namespace': 'MyNamespace'}]
|
||||
|
||||
mocked_list.return_value = expect_namespaces
|
||||
|
||||
test_shell.do_md_namespace_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with(filters={}, page_size=2)
|
||||
utils.print_list.assert_called_once_with(expect_namespaces,
|
||||
['namespace'])
|
||||
|
||||
def test_do_md_namespace_list_one_filter(self):
|
||||
args = self._make_args({'resource_types': ['OS::Compute::Aggregate'],
|
||||
'visibility': None,
|
||||
'page_size': None})
|
||||
with mock.patch.object(self.gc.metadefs_namespace, 'list') as \
|
||||
mocked_list:
|
||||
expect_namespaces = [{'namespace': 'MyNamespace'}]
|
||||
|
||||
mocked_list.return_value = expect_namespaces
|
||||
|
||||
test_shell.do_md_namespace_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with(filters={
|
||||
'resource_types': ['OS::Compute::Aggregate']})
|
||||
utils.print_list.assert_called_once_with(expect_namespaces,
|
||||
['namespace'])
|
||||
|
||||
def test_do_md_namespace_list_all_filters(self):
|
||||
args = self._make_args({'resource_types': ['OS::Compute::Aggregate'],
|
||||
'visibility': 'public',
|
||||
'page_size': None})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'list') as mocked_list:
|
||||
expect_namespaces = [{'namespace': 'MyNamespace'}]
|
||||
|
||||
mocked_list.return_value = expect_namespaces
|
||||
|
||||
test_shell.do_md_namespace_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with(filters={
|
||||
'resource_types': ['OS::Compute::Aggregate'],
|
||||
'visibility': 'public'})
|
||||
utils.print_list.assert_called_once_with(expect_namespaces,
|
||||
['namespace'])
|
||||
|
||||
def test_do_md_namespace_list_unknown_filter(self):
|
||||
args = self._make_args({'resource_type': None,
|
||||
'visibility': None,
|
||||
'some_arg': 'some_value',
|
||||
'page_size': None})
|
||||
with mock.patch.object(self.gc.metadefs_namespace,
|
||||
'list') as mocked_list:
|
||||
expect_namespaces = [{'namespace': 'MyNamespace'}]
|
||||
|
||||
mocked_list.return_value = expect_namespaces
|
||||
|
||||
test_shell.do_md_namespace_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with(filters={})
|
||||
utils.print_list.assert_called_once_with(expect_namespaces,
|
||||
['namespace'])
|
||||
|
||||
def test_do_md_namespace_delete(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'content': False})
|
||||
with mock.patch.object(self.gc.metadefs_namespace, 'delete') as \
|
||||
mocked_delete:
|
||||
test_shell.do_md_namespace_delete(self.gc, args)
|
||||
|
||||
mocked_delete.assert_called_once_with('MyNamespace')
|
||||
|
||||
def test_do_md_resource_type_associate(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'name': 'MyResourceType',
|
||||
'prefix': 'PREFIX:'})
|
||||
with mock.patch.object(self.gc.metadefs_resource_type,
|
||||
'associate') as mocked_associate:
|
||||
expect_rt = {}
|
||||
expect_rt['namespace'] = 'MyNamespace'
|
||||
expect_rt['name'] = 'MyResourceType'
|
||||
expect_rt['prefix'] = 'PREFIX:'
|
||||
|
||||
mocked_associate.return_value = expect_rt
|
||||
|
||||
test_shell.do_md_resource_type_associate(self.gc, args)
|
||||
|
||||
mocked_associate.assert_called_once_with('MyNamespace',
|
||||
**expect_rt)
|
||||
utils.print_dict.assert_called_once_with(expect_rt)
|
||||
|
||||
def test_do_md_resource_type_deassociate(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'resource_type': 'MyResourceType'})
|
||||
with mock.patch.object(self.gc.metadefs_resource_type,
|
||||
'deassociate') as mocked_deassociate:
|
||||
test_shell.do_md_resource_type_deassociate(self.gc, args)
|
||||
|
||||
mocked_deassociate.assert_called_once_with('MyNamespace',
|
||||
'MyResourceType')
|
||||
|
||||
def test_do_md_resource_type_list(self):
|
||||
args = self._make_args({})
|
||||
with mock.patch.object(self.gc.metadefs_resource_type,
|
||||
'list') as mocked_list:
|
||||
expect_objects = ['MyResourceType1', 'MyResourceType2']
|
||||
|
||||
mocked_list.return_value = expect_objects
|
||||
|
||||
test_shell.do_md_resource_type_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once()
|
||||
|
||||
def test_do_md_namespace_resource_type_list(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace'})
|
||||
with mock.patch.object(self.gc.metadefs_resource_type,
|
||||
'get') as mocked_get:
|
||||
expect_objects = [{'namespace': 'MyNamespace',
|
||||
'object': 'MyObject'}]
|
||||
|
||||
mocked_get.return_value = expect_objects
|
||||
|
||||
test_shell.do_md_namespace_resource_type_list(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace')
|
||||
utils.print_list.assert_called_once_with(expect_objects,
|
||||
['name', 'prefix',
|
||||
'properties_target'])
|
||||
|
||||
def test_do_md_property_create(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'name': "MyProperty",
|
||||
'title': "Title",
|
||||
'schema': '{}'})
|
||||
with mock.patch.object(self.gc.metadefs_property,
|
||||
'create') as mocked_create:
|
||||
expect_property = {}
|
||||
expect_property['namespace'] = 'MyNamespace'
|
||||
expect_property['name'] = 'MyProperty'
|
||||
expect_property['title'] = 'Title'
|
||||
|
||||
mocked_create.return_value = expect_property
|
||||
|
||||
test_shell.do_md_property_create(self.gc, args)
|
||||
|
||||
mocked_create.assert_called_once_with('MyNamespace',
|
||||
name='MyProperty',
|
||||
title='Title')
|
||||
utils.print_dict.assert_called_once_with(expect_property)
|
||||
|
||||
def test_do_md_property_create_invalid_schema(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'name': "MyProperty",
|
||||
'title': "Title",
|
||||
'schema': 'Invalid'})
|
||||
self.assertRaises(SystemExit, test_shell.do_md_property_create,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_property_update(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'property': 'MyProperty',
|
||||
'name': 'NewName',
|
||||
'title': "Title",
|
||||
'schema': '{}'})
|
||||
with mock.patch.object(self.gc.metadefs_property,
|
||||
'update') as mocked_update:
|
||||
expect_property = {}
|
||||
expect_property['namespace'] = 'MyNamespace'
|
||||
expect_property['name'] = 'MyProperty'
|
||||
expect_property['title'] = 'Title'
|
||||
|
||||
mocked_update.return_value = expect_property
|
||||
|
||||
test_shell.do_md_property_update(self.gc, args)
|
||||
|
||||
mocked_update.assert_called_once_with('MyNamespace', 'MyProperty',
|
||||
name='NewName',
|
||||
title='Title')
|
||||
utils.print_dict.assert_called_once_with(expect_property)
|
||||
|
||||
def test_do_md_property_update_invalid_schema(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'property': 'MyProperty',
|
||||
'name': "MyObject",
|
||||
'title': "Title",
|
||||
'schema': 'Invalid'})
|
||||
self.assertRaises(SystemExit, test_shell.do_md_property_update,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_property_show(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'property': 'MyProperty',
|
||||
'max_column_width': 80})
|
||||
with mock.patch.object(self.gc.metadefs_property, 'get') as mocked_get:
|
||||
expect_property = {}
|
||||
expect_property['namespace'] = 'MyNamespace'
|
||||
expect_property['property'] = 'MyProperty'
|
||||
expect_property['title'] = 'Title'
|
||||
|
||||
mocked_get.return_value = expect_property
|
||||
|
||||
test_shell.do_md_property_show(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace', 'MyProperty')
|
||||
utils.print_dict.assert_called_once_with(expect_property, 80)
|
||||
|
||||
def test_do_md_property_delete(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'property': 'MyProperty'})
|
||||
with mock.patch.object(self.gc.metadefs_property,
|
||||
'delete') as mocked_delete:
|
||||
test_shell.do_md_property_delete(self.gc, args)
|
||||
|
||||
mocked_delete.assert_called_once_with('MyNamespace', 'MyProperty')
|
||||
|
||||
def test_do_md_namespace_property_delete(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace'})
|
||||
with mock.patch.object(self.gc.metadefs_property,
|
||||
'delete_all') as mocked_delete_all:
|
||||
test_shell.do_md_namespace_properties_delete(self.gc, args)
|
||||
|
||||
mocked_delete_all.assert_called_once_with('MyNamespace')
|
||||
|
||||
def test_do_md_property_list(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace'})
|
||||
with mock.patch.object(self.gc.metadefs_property,
|
||||
'list') as mocked_list:
|
||||
expect_objects = [{'namespace': 'MyNamespace',
|
||||
'property': 'MyProperty',
|
||||
'title': 'MyTitle'}]
|
||||
|
||||
mocked_list.return_value = expect_objects
|
||||
|
||||
test_shell.do_md_property_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with('MyNamespace')
|
||||
utils.print_list.assert_called_once_with(expect_objects,
|
||||
['name', 'title', 'type'])
|
||||
|
||||
def test_do_md_object_create(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'name': "MyObject",
|
||||
'schema': '{}'})
|
||||
with mock.patch.object(self.gc.metadefs_object,
|
||||
'create') as mocked_create:
|
||||
expect_object = {}
|
||||
expect_object['namespace'] = 'MyNamespace'
|
||||
expect_object['name'] = 'MyObject'
|
||||
|
||||
mocked_create.return_value = expect_object
|
||||
|
||||
test_shell.do_md_object_create(self.gc, args)
|
||||
|
||||
mocked_create.assert_called_once_with('MyNamespace',
|
||||
name='MyObject')
|
||||
utils.print_dict.assert_called_once_with(expect_object)
|
||||
|
||||
def test_do_md_object_create_invalid_schema(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'name': "MyObject",
|
||||
'schema': 'Invalid'})
|
||||
self.assertRaises(SystemExit, test_shell.do_md_object_create,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_object_update(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject',
|
||||
'name': 'NewName',
|
||||
'schema': '{}'})
|
||||
with mock.patch.object(self.gc.metadefs_object,
|
||||
'update') as mocked_update:
|
||||
expect_object = {}
|
||||
expect_object['namespace'] = 'MyNamespace'
|
||||
expect_object['name'] = 'MyObject'
|
||||
|
||||
mocked_update.return_value = expect_object
|
||||
|
||||
test_shell.do_md_object_update(self.gc, args)
|
||||
|
||||
mocked_update.assert_called_once_with('MyNamespace', 'MyObject',
|
||||
name='NewName')
|
||||
utils.print_dict.assert_called_once_with(expect_object)
|
||||
|
||||
def test_do_md_object_update_invalid_schema(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject',
|
||||
'name': "MyObject",
|
||||
'schema': 'Invalid'})
|
||||
self.assertRaises(SystemExit, test_shell.do_md_object_update,
|
||||
self.gc, args)
|
||||
|
||||
def test_do_md_object_show(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject',
|
||||
'max_column_width': 80})
|
||||
with mock.patch.object(self.gc.metadefs_object, 'get') as mocked_get:
|
||||
expect_object = {}
|
||||
expect_object['namespace'] = 'MyNamespace'
|
||||
expect_object['object'] = 'MyObject'
|
||||
|
||||
mocked_get.return_value = expect_object
|
||||
|
||||
test_shell.do_md_object_show(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace', 'MyObject')
|
||||
utils.print_dict.assert_called_once_with(expect_object, 80)
|
||||
|
||||
def test_do_md_object_property_show(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject',
|
||||
'property': 'MyProperty',
|
||||
'max_column_width': 80})
|
||||
with mock.patch.object(self.gc.metadefs_object, 'get') as mocked_get:
|
||||
expect_object = {'name': 'MyObject',
|
||||
'properties': {
|
||||
'MyProperty': {'type': 'string'}
|
||||
}}
|
||||
|
||||
mocked_get.return_value = expect_object
|
||||
|
||||
test_shell.do_md_object_property_show(self.gc, args)
|
||||
|
||||
mocked_get.assert_called_once_with('MyNamespace', 'MyObject')
|
||||
utils.print_dict.assert_called_once_with({'type': 'string',
|
||||
'name': 'MyProperty'},
|
||||
80)
|
||||
|
||||
def test_do_md_object_property_show_non_existing(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject',
|
||||
'property': 'MyProperty',
|
||||
'max_column_width': 80})
|
||||
with mock.patch.object(self.gc.metadefs_object, 'get') as mocked_get:
|
||||
expect_object = {'name': 'MyObject', 'properties': {}}
|
||||
mocked_get.return_value = expect_object
|
||||
|
||||
self.assertRaises(SystemExit,
|
||||
test_shell.do_md_object_property_show,
|
||||
self.gc, args)
|
||||
mocked_get.assert_called_once_with('MyNamespace', 'MyObject')
|
||||
|
||||
def test_do_md_object_delete(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace',
|
||||
'object': 'MyObject'})
|
||||
with mock.patch.object(self.gc.metadefs_object,
|
||||
'delete') as mocked_delete:
|
||||
test_shell.do_md_object_delete(self.gc, args)
|
||||
|
||||
mocked_delete.assert_called_once_with('MyNamespace', 'MyObject')
|
||||
|
||||
def test_do_md_namespace_objects_delete(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace'})
|
||||
with mock.patch.object(self.gc.metadefs_object,
|
||||
'delete_all') as mocked_delete_all:
|
||||
test_shell.do_md_namespace_objects_delete(self.gc, args)
|
||||
|
||||
mocked_delete_all.assert_called_once_with('MyNamespace')
|
||||
|
||||
def test_do_md_object_list(self):
|
||||
args = self._make_args({'namespace': 'MyNamespace'})
|
||||
with mock.patch.object(self.gc.metadefs_object, 'list') as mocked_list:
|
||||
expect_objects = [{'namespace': 'MyNamespace',
|
||||
'object': 'MyObject'}]
|
||||
|
||||
mocked_list.return_value = expect_objects
|
||||
|
||||
test_shell.do_md_object_list(self.gc, args)
|
||||
|
||||
mocked_list.assert_called_once_with('MyNamespace')
|
||||
utils.print_list.assert_called_once_with(
|
||||
expect_objects,
|
||||
['name', 'description'],
|
||||
field_settings={
|
||||
'description': {'align': 'l', 'max_width': 50}})
|
||||
|
||||
Reference in New Issue
Block a user