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:
Taehyun Park 2022-09-19 21:21:31 +09:00 committed by Stephen Finucane
parent 14ee05f264
commit c6aaae56ee
9 changed files with 407 additions and 1 deletions

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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

View 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:

View File

@ -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)

View 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')

View 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,
)

View 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,
)

View File

@ -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(

View File

@ -0,0 +1,4 @@
---
features:
- |
Add support for Image Metadef objects.