Add image metadef resource type association commands
'create', 'list', 'delete' Change-Id: I2c860427b0b2693076cfe57841f0e512ad1f6388
This commit is contained in:
parent
b740f2f6bd
commit
276dbb6f56
@ -28,7 +28,7 @@ md-namespace-import,,Import a metadata definitions namespace from file or standa
|
|||||||
md-namespace-list,image metadef namespace list,List metadata definitions namespaces.
|
md-namespace-list,image metadef namespace list,List metadata definitions namespaces.
|
||||||
md-namespace-objects-delete,,Delete all metadata definitions objects inside a specific namespace.
|
md-namespace-objects-delete,,Delete all metadata definitions objects inside a specific namespace.
|
||||||
md-namespace-properties-delete,,Delete all metadata definitions property inside a specific namespace.
|
md-namespace-properties-delete,,Delete all metadata definitions property inside a specific namespace.
|
||||||
md-namespace-resource-type-list,image metadef resource type list,List resource types associated to specific namespace.
|
md-namespace-resource-type-list,image metadef resource type association list,List resource types associated to specific namespace.
|
||||||
md-namespace-show,image metadef namespace show,Describe a specific metadata definitions namespace.
|
md-namespace-show,image metadef namespace show,Describe a specific metadata definitions namespace.
|
||||||
md-namespace-tags-delete,,Delete all metadata definitions tags inside a specific namespace.
|
md-namespace-tags-delete,,Delete all metadata definitions tags inside a specific namespace.
|
||||||
md-namespace-update,,Update an existing metadata definitions namespace.
|
md-namespace-update,,Update an existing metadata definitions namespace.
|
||||||
@ -43,9 +43,9 @@ md-property-delete,image metadef property delete,Delete a specific metadata defi
|
|||||||
md-property-list,image metadef property list,List metadata definitions properties inside a specific namespace.
|
md-property-list,image metadef property list,List metadata definitions properties inside a specific namespace.
|
||||||
md-property-show,image metadef property show,Describe a specific metadata definitions property inside a namespace.
|
md-property-show,image metadef property show,Describe a specific metadata definitions property inside a namespace.
|
||||||
md-property-update,image metadef property set,Update metadata definitions property inside a namespace.
|
md-property-update,image metadef property set,Update metadata definitions property inside a namespace.
|
||||||
md-resource-type-associate,,Associate resource type with a metadata definitions namespace.
|
md-resource-type-associate,image metadef resource type association create,Associate resource type with a metadata definitions namespace.
|
||||||
md-resource-type-deassociate,,Deassociate resource type with a metadata definitions namespace.
|
md-resource-type-deassociate,image metadef resource type association delete,Deassociate resource type with a metadata definitions namespace.
|
||||||
md-resource-type-list,,List available resource type names.
|
md-resource-type-list,image metadef resource type list,List available resource type names.
|
||||||
md-tag-create,,Add a new metadata definitions tag inside a namespace.
|
md-tag-create,,Add a new metadata definitions tag inside a namespace.
|
||||||
md-tag-create-multiple,,Create new metadata definitions tags inside a namespace.
|
md-tag-create-multiple,,Create new metadata definitions tags inside a namespace.
|
||||||
md-tag-delete,,Delete a specific metadata definitions tag inside a namespace.
|
md-tag-delete,,Delete a specific metadata definitions tag inside a namespace.
|
||||||
|
|
189
openstackclient/image/v2/metadef_resource_type_association.py
Normal file
189
openstackclient/image/v2/metadef_resource_type_association.py
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# 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 logging
|
||||||
|
|
||||||
|
from osc_lib.command import command
|
||||||
|
from osc_lib import exceptions
|
||||||
|
from osc_lib import utils
|
||||||
|
|
||||||
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_columns(item):
|
||||||
|
column_map = {}
|
||||||
|
hidden_columns = ['location']
|
||||||
|
return utils.get_osc_show_columns_for_sdk_resource(
|
||||||
|
item, column_map, hidden_columns
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMetadefResourceTypeAssociation(command.ShowOne):
|
||||||
|
_description = _("Create metadef resource type association")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"namespace",
|
||||||
|
metavar="<namespace>",
|
||||||
|
help=_(
|
||||||
|
"The name of the namespace you want to create the "
|
||||||
|
"resource type association in"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"name",
|
||||||
|
metavar="<name>",
|
||||||
|
help=_("A name of the new resource type"),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--properties-target",
|
||||||
|
metavar="<properties_target>",
|
||||||
|
help=_(
|
||||||
|
"Some resource types allow more than one "
|
||||||
|
"key/value pair per instance."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
image_client = self.app.client_manager.image
|
||||||
|
kwargs = {}
|
||||||
|
|
||||||
|
kwargs['namespace'] = parsed_args.namespace
|
||||||
|
kwargs['name'] = parsed_args.name
|
||||||
|
|
||||||
|
if parsed_args.properties_target:
|
||||||
|
kwargs['properties_target'] = parsed_args.properties_target
|
||||||
|
|
||||||
|
obj = image_client.create_metadef_resource_type_association(
|
||||||
|
parsed_args.namespace, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
display_columns, columns = _get_columns(obj)
|
||||||
|
data = utils.get_item_properties(obj, columns, formatters={})
|
||||||
|
|
||||||
|
return (display_columns, data)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteMetadefResourceTypeAssociation(command.Command):
|
||||||
|
_description = _("Delete metadef resource type association")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"metadef_namespace",
|
||||||
|
metavar="<metadef_namespace>",
|
||||||
|
help=_("The name of the namespace whose details you want to see"),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"name",
|
||||||
|
metavar="<name>",
|
||||||
|
nargs="+",
|
||||||
|
help=_(
|
||||||
|
"The name of the resource type(s) (repeat option to delete"
|
||||||
|
"multiple metadef resource type associations)"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--force",
|
||||||
|
dest='force',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help=_(
|
||||||
|
"Force delete the resource type association if the"
|
||||||
|
"namespace is protected"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
image_client = self.app.client_manager.image
|
||||||
|
|
||||||
|
result = 0
|
||||||
|
for resource_type in parsed_args.name:
|
||||||
|
try:
|
||||||
|
metadef_namespace = image_client.get_metadef_namespace(
|
||||||
|
parsed_args.metadef_namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
kwargs = {}
|
||||||
|
is_initially_protected = (
|
||||||
|
True if metadef_namespace.is_protected else False
|
||||||
|
)
|
||||||
|
if is_initially_protected and parsed_args.force:
|
||||||
|
kwargs['is_protected'] = False
|
||||||
|
|
||||||
|
image_client.update_metadef_namespace(
|
||||||
|
metadef_namespace.namespace, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
image_client.delete_metadef_resource_type_association(
|
||||||
|
resource_type, metadef_namespace, ignore_missing=False
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
if is_initially_protected:
|
||||||
|
kwargs['is_protected'] = True
|
||||||
|
image_client.update_metadef_namespace(
|
||||||
|
metadef_namespace.namespace, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result += 1
|
||||||
|
LOG.error(
|
||||||
|
_(
|
||||||
|
"Failed to delete resource type with name or "
|
||||||
|
"ID '%(resource_type)s': %(e)s"
|
||||||
|
),
|
||||||
|
{'resource_type': resource_type, 'e': e},
|
||||||
|
)
|
||||||
|
|
||||||
|
if result > 0:
|
||||||
|
total = len(parsed_args.metadef_namespace)
|
||||||
|
msg = _(
|
||||||
|
"%(result)s of %(total)s resource type failed to delete."
|
||||||
|
) % {'result': result, 'total': total}
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class ListMetadefResourceTypeAssociations(command.Lister):
|
||||||
|
_description = _("List metadef resource type associations")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"metadef_namespace",
|
||||||
|
metavar="<metadef_namespace>",
|
||||||
|
help=_("The name of the namespace whose details you want to see"),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
image_client = self.app.client_manager.image
|
||||||
|
data = image_client.metadef_resource_type_associations(
|
||||||
|
parsed_args.metadef_namespace,
|
||||||
|
)
|
||||||
|
columns = ['Name']
|
||||||
|
column_headers = columns
|
||||||
|
return (
|
||||||
|
column_headers,
|
||||||
|
(
|
||||||
|
utils.get_item_properties(
|
||||||
|
s,
|
||||||
|
columns,
|
||||||
|
)
|
||||||
|
for s in data
|
||||||
|
),
|
||||||
|
)
|
@ -381,3 +381,44 @@ def create_one_metadef_object(attrs=None):
|
|||||||
# Overwrite default attributes if there are some attributes set
|
# Overwrite default attributes if there are some attributes set
|
||||||
metadef_objects_list.update(attrs)
|
metadef_objects_list.update(attrs)
|
||||||
return metadef_object.MetadefObject(**metadef_objects_list)
|
return metadef_object.MetadefObject(**metadef_objects_list)
|
||||||
|
|
||||||
|
|
||||||
|
def create_one_resource_type_association(attrs=None):
|
||||||
|
"""Create a fake MetadefResourceTypeAssociation.
|
||||||
|
|
||||||
|
:param attrs: A dictionary with all attributes of
|
||||||
|
metadef_resource_type_association member
|
||||||
|
:type attrs: dict
|
||||||
|
:return: A fake MetadefResourceTypeAssociation object
|
||||||
|
:rtype: A `metadef_resource_type_association.
|
||||||
|
MetadefResourceTypeAssociation`
|
||||||
|
"""
|
||||||
|
attrs = attrs or {}
|
||||||
|
|
||||||
|
metadef_resource_type_association_info = {
|
||||||
|
'namespace_name': 'OS::Compute::Quota',
|
||||||
|
'name': 'OS::Nova::Flavor',
|
||||||
|
}
|
||||||
|
|
||||||
|
metadef_resource_type_association_info.update(attrs)
|
||||||
|
return metadef_resource_type.MetadefResourceTypeAssociation(
|
||||||
|
**metadef_resource_type_association_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_resource_type_associations(attrs=None, count=2):
|
||||||
|
"""Create mutiple fake resource type associations/
|
||||||
|
|
||||||
|
:param attrs: A dictionary with all attributes of
|
||||||
|
metadef_resource_type_association member
|
||||||
|
:type attrs: dict
|
||||||
|
:return: A list of fake MetadefResourceTypeAssociation objects
|
||||||
|
:rtype: list
|
||||||
|
"""
|
||||||
|
resource_type_associations = []
|
||||||
|
for n in range(0, count):
|
||||||
|
resource_type_associations.append(
|
||||||
|
create_one_resource_type_association(attrs)
|
||||||
|
)
|
||||||
|
|
||||||
|
return resource_type_associations
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
# 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 openstackclient.image.v2 import metadef_resource_type_association
|
||||||
|
from openstackclient.tests.unit.image.v2 import fakes as resource_type_fakes
|
||||||
|
|
||||||
|
|
||||||
|
class TestMetadefResourceTypeAssociationCreate(
|
||||||
|
resource_type_fakes.TestImagev2
|
||||||
|
):
|
||||||
|
resource_type_association = (
|
||||||
|
resource_type_fakes.create_one_resource_type_association()
|
||||||
|
)
|
||||||
|
|
||||||
|
columns = (
|
||||||
|
'created_at',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'prefix',
|
||||||
|
'properties_target',
|
||||||
|
'updated_at',
|
||||||
|
)
|
||||||
|
|
||||||
|
data = (
|
||||||
|
resource_type_association.created_at,
|
||||||
|
resource_type_association.id,
|
||||||
|
resource_type_association.name,
|
||||||
|
resource_type_association.prefix,
|
||||||
|
resource_type_association.properties_target,
|
||||||
|
resource_type_association.updated_at,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.image_client.create_metadef_resource_type_association.return_value = (
|
||||||
|
self.resource_type_association
|
||||||
|
)
|
||||||
|
self.cmd = metadef_resource_type_association.CreateMetadefResourceTypeAssociation(
|
||||||
|
self.app, None
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_resource_type_association_create(self):
|
||||||
|
arglist = [
|
||||||
|
self.resource_type_association.namespace_name,
|
||||||
|
self.resource_type_association.name,
|
||||||
|
]
|
||||||
|
|
||||||
|
verifylist = []
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMetadefResourceTypeAssociationDelete(
|
||||||
|
resource_type_fakes.TestImagev2
|
||||||
|
):
|
||||||
|
resource_type_association = (
|
||||||
|
resource_type_fakes.create_one_resource_type_association()
|
||||||
|
)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.image_client.delete_metadef_resource_type_association.return_value = (
|
||||||
|
self.resource_type_association
|
||||||
|
)
|
||||||
|
self.cmd = metadef_resource_type_association.DeleteMetadefResourceTypeAssociation(
|
||||||
|
self.app, None
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_resource_type_association_delete(self):
|
||||||
|
arglist = [
|
||||||
|
self.resource_type_association.namespace_name,
|
||||||
|
self.resource_type_association.name,
|
||||||
|
]
|
||||||
|
|
||||||
|
verifylist = []
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMetadefResourceTypeAssociationList(resource_type_fakes.TestImagev2):
|
||||||
|
resource_type_associations = (
|
||||||
|
resource_type_fakes.create_resource_type_associations()
|
||||||
|
)
|
||||||
|
|
||||||
|
columns = ['Name']
|
||||||
|
|
||||||
|
datalist = [
|
||||||
|
(resource_type_association.name,)
|
||||||
|
for resource_type_association in resource_type_associations
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.image_client.metadef_resource_type_associations.side_effect = [
|
||||||
|
self.resource_type_associations,
|
||||||
|
[],
|
||||||
|
]
|
||||||
|
|
||||||
|
self.cmd = metadef_resource_type_association.ListMetadefResourceTypeAssociations(
|
||||||
|
self.app, None
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_resource_type_association_list(self):
|
||||||
|
arglist = [
|
||||||
|
self.resource_type_associations[0].namespace_name,
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, [])
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertCountEqual(self.datalist, data)
|
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added ``image metadef resource type association list``
|
||||||
|
to list resource type associations for the image service.
|
||||||
|
This is equivalent to the
|
||||||
|
``md-namespace-resource-type-list`` command in glance.
|
||||||
|
- |
|
||||||
|
Added ``image metadef resource type association create``
|
||||||
|
to create a resource type association for the image service.
|
||||||
|
This is equivalent to the
|
||||||
|
``md-resource-type-associate`` command in glance.
|
||||||
|
- |
|
||||||
|
Added ``image metadef resource type association delete``
|
||||||
|
to delete a resource type association for the image service.
|
||||||
|
This is equivalent to the
|
||||||
|
``md-resource-type-deassociate`` command in glance.
|
@ -411,6 +411,9 @@ openstack.image.v2 =
|
|||||||
image_metadef_property_show = openstackclient.image.v2.metadef_properties:ShowMetadefProperty
|
image_metadef_property_show = openstackclient.image.v2.metadef_properties:ShowMetadefProperty
|
||||||
|
|
||||||
image_metadef_resource_type_list = openstackclient.image.v2.metadef_resource_types:ListMetadefResourceTypes
|
image_metadef_resource_type_list = openstackclient.image.v2.metadef_resource_types:ListMetadefResourceTypes
|
||||||
|
image_metadef_resource_type_association_create = openstackclient.image.v2.metadef_resource_type_association:CreateMetadefResourceTypeAssociation
|
||||||
|
image_metadef_resource_type_association_delete = openstackclient.image.v2.metadef_resource_type_association:DeleteMetadefResourceTypeAssociation
|
||||||
|
image_metadef_resource_type_association_list = openstackclient.image.v2.metadef_resource_type_association:ListMetadefResourceTypeAssociations
|
||||||
|
|
||||||
cached_image_list = openstackclient.image.v2.cache:ListCachedImage
|
cached_image_list = openstackclient.image.v2.cache:ListCachedImage
|
||||||
cached_image_queue = openstackclient.image.v2.cache:QueueCachedImage
|
cached_image_queue = openstackclient.image.v2.cache:QueueCachedImage
|
||||||
|
Loading…
Reference in New Issue
Block a user