Add image metadef object operations
The Image Metadata Object operations are not support currently. In this patch, I added an operations of image metadata object. Co-authored-by: Hael Yoon <dbsgodl@naver.com> Co-authored-by: JaeSeong Shin <rornfl916@gmail.com> Co-authored-by: LEE SUN JAE <tjswo98sj06@gmail.com> Co-authored-by: Mridula Joshi <mrjoshi@redhat.com> Change-Id: Ie76804204878d5302beda4dfa93b898ec3f6f46a
This commit is contained in:
parent
14ee05f264
commit
c6aaae56ee
@ -67,6 +67,14 @@ Metadef Namespace Operations
|
||||
get_metadef_namespace, metadef_namespaces, update_metadef_namespace
|
||||
|
||||
|
||||
Metadef Object Operations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openstack.image.v2._proxy.Proxy
|
||||
:noindex:
|
||||
:members: create_metadef_object, delete_metadef_object,
|
||||
get_metadef_object, metadef_objects, update_metadef_object
|
||||
|
||||
Metadef Resource Type Operations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -18,6 +18,7 @@ Image v2 Resources
|
||||
v2/image
|
||||
v2/member
|
||||
v2/metadef_namespace
|
||||
v2/metadef_object
|
||||
v2/metadef_resource_type
|
||||
v2/metadef_schema
|
||||
v2/task
|
||||
|
13
doc/source/user/resources/image/v2/metadef_object.rst
Normal file
13
doc/source/user/resources/image/v2/metadef_object.rst
Normal file
@ -0,0 +1,13 @@
|
||||
openstack.image.v2.metadef_object
|
||||
==================================
|
||||
|
||||
.. automodule:: openstack.image.v2.metadef_object
|
||||
|
||||
The MetadefObject Class
|
||||
------------------------
|
||||
|
||||
The ``MetadefObject`` class inherits
|
||||
from :class:`~openstack.resource.Resource`.
|
||||
|
||||
.. autoclass:: openstack.image.v2.metadef_object.MetadefObject
|
||||
:members:
|
@ -19,6 +19,7 @@ from openstack.image.v2 import cache as _cache
|
||||
from openstack.image.v2 import image as _image
|
||||
from openstack.image.v2 import member as _member
|
||||
from openstack.image.v2 import metadef_namespace as _metadef_namespace
|
||||
from openstack.image.v2 import metadef_object as _metadef_object
|
||||
from openstack.image.v2 import metadef_resource_type as _metadef_resource_type
|
||||
from openstack.image.v2 import metadef_schema as _metadef_schema
|
||||
from openstack.image.v2 import schema as _schema
|
||||
@ -1205,6 +1206,117 @@ class Proxy(proxy.Proxy):
|
||||
**attrs,
|
||||
)
|
||||
|
||||
# ====== METADEF OBJECT ======
|
||||
def create_metadef_object(self, namespace, **attrs):
|
||||
"""Create a new object from namespace
|
||||
|
||||
:param namespace: The value can be either the name of a metadef
|
||||
namespace or a
|
||||
:class:`~openstack.image.v2.metadef_namespace.MetadefNamespace`
|
||||
instance.
|
||||
:param dict attrs: Keyword arguments which will be used to create
|
||||
a :class:`~openstack.image.v2.metadef_object.MetadefObject`,
|
||||
comprised of the properties on the Metadef object class.
|
||||
|
||||
:returns: A metadef namespace
|
||||
:rtype: :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
"""
|
||||
namespace_name = resource.Resource._get_id(namespace)
|
||||
return self._create(
|
||||
_metadef_object.MetadefObject,
|
||||
namespace_name=namespace_name,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
def get_metadef_object(self, metadef_object, namespace):
|
||||
"""Get a single metadef object
|
||||
|
||||
:param metadef_object: The value can be the ID of a metadef_object
|
||||
or a
|
||||
:class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
instance.
|
||||
:param namespace: The value can be either the name of a metadef
|
||||
namespace or a
|
||||
:class:`~openstack.image.v2.metadef_namespace.MetadefNamespace`
|
||||
instance.
|
||||
:returns: One :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
"""
|
||||
object_name = resource.Resource._get_id(metadef_object)
|
||||
namespace_name = resource.Resource._get_id(namespace)
|
||||
return self._get(
|
||||
_metadef_object.MetadefObject,
|
||||
namespace_name=namespace_name,
|
||||
name=object_name,
|
||||
)
|
||||
|
||||
def metadef_objects(self, namespace):
|
||||
"""Get metadef object list of the namespace
|
||||
|
||||
:param namespace: The value can be either the name of a metadef
|
||||
namespace or a
|
||||
:class:`~openstack.image.v2.metadef_namespace.MetadefNamespace`
|
||||
instance.
|
||||
|
||||
:returns: One :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
"""
|
||||
namespace_name = resource.Resource._get_id(namespace)
|
||||
return self._list(
|
||||
_metadef_object.MetadefObject,
|
||||
namespace_name=namespace_name,
|
||||
)
|
||||
|
||||
def update_metadef_object(self, metadef_object, namespace, **attrs):
|
||||
"""Update a single metadef object
|
||||
|
||||
:param metadef_object: The value can be the ID of a metadef_object or a
|
||||
:class:`~openstack.image.v2.metadef_object.MetadefObject` instance.
|
||||
:param namespace: The value can be either the name of a metadef
|
||||
namespace or a
|
||||
:class:`~openstack.image.v2.metadef_namespace.MetadefNamespace`
|
||||
instance.
|
||||
:param dict attrs: Keyword arguments which will be used to update
|
||||
a :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
|
||||
:returns: One :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
"""
|
||||
namespace_name = resource.Resource._get_id(namespace)
|
||||
return self._update(
|
||||
_metadef_object.MetadefObject,
|
||||
metadef_object,
|
||||
namespace_name=namespace_name,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
def delete_metadef_object(self, metadef_object, namespace, **attrs):
|
||||
"""Removes a single metadef object
|
||||
|
||||
:param metadef_object: The value can be the ID of a metadef_object or a
|
||||
:class:`~openstack.image.v2.metadef_object.MetadefObject` instance.
|
||||
:param namespace: The value can be either the name of a metadef
|
||||
namespace or a
|
||||
:class:`~openstack.image.v2.metadef_namespace.MetadefNamespace`
|
||||
instance.
|
||||
:param dict attrs: Keyword arguments which will be used to update
|
||||
a :class:`~openstack.image.v2.metadef_object.MetadefObject`
|
||||
|
||||
:returns: ``None``
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
"""
|
||||
namespace_name = resource.Resource._get_id(namespace)
|
||||
return self._delete(
|
||||
_metadef_object.MetadefObject,
|
||||
metadef_object,
|
||||
namespace_name=namespace_name,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
# ====== METADEF RESOURCE TYPES ======
|
||||
def metadef_resource_types(self, **query):
|
||||
"""Return a generator of metadef resource types
|
||||
@ -1213,7 +1325,7 @@ class Proxy(proxy.Proxy):
|
||||
:rtype:
|
||||
:class:`~openstack.image.v2.metadef_resource_type.MetadefResourceType`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
when no resource can be found.
|
||||
"""
|
||||
return self._list(_metadef_resource_type.MetadefResourceType, **query)
|
||||
|
||||
|
40
openstack/image/v2/metadef_object.py
Normal file
40
openstack/image/v2/metadef_object.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import resource
|
||||
|
||||
|
||||
class MetadefObject(resource.Resource):
|
||||
resources_key = 'objects'
|
||||
base_path = '/metadefs/namespaces/%(namespace_name)s/objects'
|
||||
|
||||
# capabilities
|
||||
allow_create = True
|
||||
allow_fetch = True
|
||||
allow_commit = True
|
||||
allow_delete = True
|
||||
allow_list = True
|
||||
|
||||
_query_mapping = resource.QueryParameters(
|
||||
"visibility",
|
||||
"resource_types",
|
||||
"sort_key",
|
||||
"sort_dir",
|
||||
)
|
||||
|
||||
created_at = resource.Body('created_at')
|
||||
description = resource.Body('description')
|
||||
name = resource.Body('name', alternate_id=True)
|
||||
namespace_name = resource.URI('namespace_name')
|
||||
properties = resource.Body('properties')
|
||||
required = resource.Body('required')
|
||||
updated_at = resource.Body('updated_at')
|
103
openstack/tests/functional/image/v2/test_metadef_object.py
Normal file
103
openstack/tests/functional/image/v2/test_metadef_object.py
Normal file
@ -0,0 +1,103 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.image.v2 import metadef_namespace as _metadef_namespace
|
||||
from openstack.image.v2 import metadef_object as _metadef_object
|
||||
from openstack.tests.functional.image.v2 import base
|
||||
|
||||
|
||||
class TestMetadefObject(base.BaseImageTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
# create namespace for object
|
||||
namespace = self.getUniqueString().split('.')[-1]
|
||||
self.metadef_namespace = self.conn.image.create_metadef_namespace(
|
||||
namespace=namespace,
|
||||
)
|
||||
self.assertIsInstance(
|
||||
self.metadef_namespace,
|
||||
_metadef_namespace.MetadefNamespace,
|
||||
)
|
||||
self.assertEqual(namespace, self.metadef_namespace.namespace)
|
||||
|
||||
# create object
|
||||
object = self.getUniqueString().split('.')[-1]
|
||||
self.metadef_object = self.conn.image.create_metadef_object(
|
||||
name=object,
|
||||
namespace=self.metadef_namespace,
|
||||
)
|
||||
self.assertIsInstance(
|
||||
self.metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
)
|
||||
self.assertEqual(object, self.metadef_object.name)
|
||||
|
||||
def tearDown(self):
|
||||
self.conn.image.delete_metadef_object(
|
||||
self.metadef_object,
|
||||
self.metadef_object.namespace_name,
|
||||
)
|
||||
self.conn.image.wait_for_delete(self.metadef_object)
|
||||
|
||||
self.conn.image.delete_metadef_namespace(self.metadef_namespace)
|
||||
self.conn.image.wait_for_delete(self.metadef_namespace)
|
||||
|
||||
super().tearDown()
|
||||
|
||||
def test_metadef_objects(self):
|
||||
# get
|
||||
metadef_object = self.conn.image.get_metadef_object(
|
||||
self.metadef_object.name,
|
||||
self.metadef_namespace,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.metadef_object.namespace_name,
|
||||
metadef_object.namespace_name,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.metadef_object.name,
|
||||
metadef_object.name,
|
||||
)
|
||||
|
||||
# list
|
||||
metadef_objects = list(
|
||||
self.conn.image.metadef_objects(self.metadef_object.namespace_name)
|
||||
)
|
||||
# there are a load of default metadef objects so we don't assert
|
||||
# that this is the *only* metadef objects present
|
||||
self.assertIn(
|
||||
self.metadef_object.name,
|
||||
{o.name for o in metadef_objects},
|
||||
)
|
||||
|
||||
# update
|
||||
metadef_object_new_name = 'New object name'
|
||||
metadef_object_new_description = 'New object description'
|
||||
metadef_object = self.conn.image.update_metadef_object(
|
||||
self.metadef_object.name,
|
||||
namespace=self.metadef_object.namespace_name,
|
||||
name=metadef_object_new_name,
|
||||
description=metadef_object_new_description,
|
||||
)
|
||||
self.assertIsInstance(
|
||||
metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
)
|
||||
self.assertEqual(
|
||||
metadef_object_new_name,
|
||||
metadef_object.name,
|
||||
)
|
||||
self.assertEqual(
|
||||
metadef_object_new_description,
|
||||
metadef_object.description,
|
||||
)
|
77
openstack/tests/unit/image/v2/test_metadef_object.py
Normal file
77
openstack/tests/unit/image/v2/test_metadef_object.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.image.v2 import metadef_object
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
EXAMPLE = {
|
||||
'created_at': '2014-09-19T18:20:56Z',
|
||||
'description': 'The CPU limits with control parameters.',
|
||||
'name': 'CPU Limits',
|
||||
'properties': {
|
||||
'quota:cpu_period': {
|
||||
'description': 'The enforcement interval',
|
||||
'maximum': 1000000,
|
||||
'minimum': 1000,
|
||||
'title': 'Quota: CPU Period',
|
||||
'type': 'integer',
|
||||
},
|
||||
'quota:cpu_quota': {
|
||||
'description': 'The maximum allowed bandwidth',
|
||||
'title': 'Quota: CPU Quota',
|
||||
'type': 'integer',
|
||||
},
|
||||
'quota:cpu_shares': {
|
||||
'description': 'The proportional weighted',
|
||||
'title': 'Quota: CPU Shares',
|
||||
'type': 'integer',
|
||||
},
|
||||
},
|
||||
'required': [],
|
||||
'schema': '/v2/schemas/metadefs/object',
|
||||
'updated_at': '2014-09-19T18:20:56Z',
|
||||
}
|
||||
|
||||
|
||||
class TestMetadefObject(base.TestCase):
|
||||
def test_basic(self):
|
||||
sot = metadef_object.MetadefObject()
|
||||
self.assertIsNone(sot.resource_key)
|
||||
self.assertEqual('objects', sot.resources_key)
|
||||
test_base_path = '/metadefs/namespaces/%(namespace_name)s/objects'
|
||||
self.assertEqual(test_base_path, sot.base_path)
|
||||
self.assertTrue(sot.allow_create)
|
||||
self.assertTrue(sot.allow_fetch)
|
||||
self.assertTrue(sot.allow_commit)
|
||||
self.assertTrue(sot.allow_delete)
|
||||
self.assertTrue(sot.allow_list)
|
||||
|
||||
def test_make_it(self):
|
||||
sot = metadef_object.MetadefObject(**EXAMPLE)
|
||||
self.assertEqual(EXAMPLE['created_at'], sot.created_at)
|
||||
self.assertEqual(EXAMPLE['description'], sot.description)
|
||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
||||
self.assertEqual(EXAMPLE['properties'], sot.properties)
|
||||
self.assertEqual(EXAMPLE['required'], sot.required)
|
||||
self.assertEqual(EXAMPLE['updated_at'], sot.updated_at)
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"limit": "limit",
|
||||
"marker": "marker",
|
||||
"visibility": "visibility",
|
||||
"resource_types": "resource_types",
|
||||
"sort_key": "sort_key",
|
||||
"sort_dir": "sort_dir",
|
||||
},
|
||||
sot._query_mapping._mapping,
|
||||
)
|
@ -21,6 +21,7 @@ from openstack.image.v2 import cache as _cache
|
||||
from openstack.image.v2 import image as _image
|
||||
from openstack.image.v2 import member as _member
|
||||
from openstack.image.v2 import metadef_namespace as _metadef_namespace
|
||||
from openstack.image.v2 import metadef_object as _metadef_object
|
||||
from openstack.image.v2 import metadef_resource_type as _metadef_resource_type
|
||||
from openstack.image.v2 import metadef_schema as _metadef_schema
|
||||
from openstack.image.v2 import schema as _schema
|
||||
@ -569,6 +570,53 @@ class TestMetadefNamespace(TestImageProxy):
|
||||
)
|
||||
|
||||
|
||||
class TestMetadefObject(TestImageProxy):
|
||||
def test_create_metadef_object(self):
|
||||
self.verify_create(
|
||||
self.proxy.create_metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
method_kwargs={"namespace": "test_namespace_name"},
|
||||
expected_kwargs={"namespace_name": "test_namespace_name"},
|
||||
)
|
||||
|
||||
def test_get_metadef_object(self):
|
||||
self.verify_get(
|
||||
self.proxy.get_metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
method_kwargs={"namespace": "test_namespace_name"},
|
||||
expected_kwargs={
|
||||
"namespace_name": "test_namespace_name",
|
||||
'name': 'resource_id',
|
||||
},
|
||||
expected_args=[],
|
||||
)
|
||||
|
||||
def test_metadef_objects(self):
|
||||
self.verify_list(
|
||||
self.proxy.metadef_objects,
|
||||
_metadef_object.MetadefObject,
|
||||
method_kwargs={"namespace": "test_namespace_name"},
|
||||
expected_kwargs={"namespace_name": "test_namespace_name"},
|
||||
)
|
||||
|
||||
def test_update_metadef_object(self):
|
||||
self.verify_update(
|
||||
self.proxy.update_metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
method_kwargs={"namespace": "test_namespace_name"},
|
||||
expected_kwargs={"namespace_name": "test_namespace_name"},
|
||||
)
|
||||
|
||||
def test_delete_metadef_object(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_metadef_object,
|
||||
_metadef_object.MetadefObject,
|
||||
False,
|
||||
method_kwargs={"namespace": "test_namespace_name"},
|
||||
expected_kwargs={"namespace_name": "test_namespace_name"},
|
||||
)
|
||||
|
||||
|
||||
class TestMetadefResourceType(TestImageProxy):
|
||||
def test_metadef_resource_types(self):
|
||||
self.verify_list(
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add support for Image Metadef objects.
|
Loading…
x
Reference in New Issue
Block a user