Skip to content

Commit 43cec26

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add "image metadef property create" command"
2 parents b6baa2e + d9c4c43 commit 43cec26

5 files changed

Lines changed: 166 additions & 27 deletions

File tree

doc/source/cli/data/glance.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ md-object-list,,List metadata definitions objects inside a specific namespace.
3838
md-object-property-show,,Describe a specific metadata definitions property inside an object.
3939
md-object-show,,Describe a specific metadata definitions object inside a namespace.
4040
md-object-update,,Update metadata definitions object inside a namespace.
41-
md-property-create,,Create a new metadata definitions property inside a namespace.
41+
md-property-create,image metadef property create,Create a new metadata definitions property inside a namespace.
4242
md-property-delete,,Delete a specific metadata definitions property inside a namespace.
4343
md-property-list,image metadef property list,List metadata definitions properties inside a specific namespace.
4444
md-property-show,image metadef property show,Describe a specific metadata definitions property inside a namespace.

openstackclient/image/v2/metadef_properties.py

Lines changed: 90 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,101 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
import json
16+
1517
from osc_lib.command import command
18+
from osc_lib import exceptions
1619
from osc_lib import utils
1720

1821
from openstackclient.i18n import _
1922

2023

24+
def _format_property(prop):
25+
prop = prop.to_dict(ignore_none=True, original_names=True)
26+
return {
27+
key: prop[key]
28+
for key in [
29+
'namespace_name',
30+
'name',
31+
'type',
32+
'title',
33+
'description',
34+
'operators',
35+
'default',
36+
'is_readonly',
37+
'minimum',
38+
'maximum',
39+
'enum',
40+
'pattern',
41+
'min_length',
42+
'max_length',
43+
'items',
44+
'require_unique_items',
45+
'min_items',
46+
'max_items',
47+
'allow_additional_items',
48+
]
49+
if key in prop
50+
}
51+
52+
53+
class CreateMetadefProperty(command.ShowOne):
54+
_description = _("Create a metadef property")
55+
56+
def get_parser(self, prog_name):
57+
parser = super().get_parser(prog_name)
58+
parser.add_argument(
59+
"--name",
60+
required=True,
61+
help=_("Internal name of the property"),
62+
)
63+
parser.add_argument(
64+
"--title",
65+
required=True,
66+
help=_("Property name displayed to the user"),
67+
)
68+
parser.add_argument(
69+
"--type",
70+
required=True,
71+
help=_("Property type"),
72+
)
73+
parser.add_argument(
74+
"--schema",
75+
required=True,
76+
help=_("Valid JSON schema of the property"),
77+
)
78+
parser.add_argument(
79+
"namespace_name",
80+
help=_("Name of namespace the property will belong."),
81+
)
82+
return parser
83+
84+
def take_action(self, parsed_args):
85+
image_client = self.app.client_manager.image
86+
87+
kwargs = {
88+
'name': parsed_args.name,
89+
'title': parsed_args.title,
90+
'type': parsed_args.type,
91+
}
92+
try:
93+
kwargs.update(json.loads(parsed_args.schema))
94+
except json.JSONDecodeError as e:
95+
raise exceptions.CommandError(
96+
_("Failed to load JSON schema: %(e)s")
97+
% {
98+
'e': e,
99+
}
100+
)
101+
102+
data = image_client.create_metadef_property(
103+
parsed_args.namespace_name, **kwargs
104+
)
105+
info = _format_property(data)
106+
107+
return zip(*sorted(info.items()))
108+
109+
21110
class ListMetadefProperties(command.Lister):
22111
_description = _("List metadef properties")
23112

@@ -68,31 +157,6 @@ def take_action(self, parsed_args):
68157
data = image_client.get_metadef_property(
69158
parsed_args.property_name, parsed_args.namespace_name
70159
)
71-
data = data.to_dict(ignore_none=True, original_names=True)
72-
info = {
73-
key: data[key]
74-
for key in [
75-
'namespace_name',
76-
'name',
77-
'type',
78-
'title',
79-
'description',
80-
'operators',
81-
'default',
82-
'is_readonly',
83-
'minimum',
84-
'maximum',
85-
'enum',
86-
'pattern',
87-
'min_length',
88-
'max_length',
89-
'items',
90-
'require_unique_items',
91-
'min_items',
92-
'max_items',
93-
'allow_additional_items',
94-
]
95-
if key in data
96-
}
160+
info = _format_property(data)
97161

98162
return zip(*sorted(info.items()))

openstackclient/tests/unit/image/v2/test_metadef_properties.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,77 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
from osc_lib import exceptions
16+
1517
from openstackclient.image.v2 import metadef_properties
1618
from openstackclient.tests.unit.image.v2 import fakes as image_fakes
19+
from openstackclient.tests.unit import utils as tests_utils
20+
21+
22+
class TestMetadefPropertyCreate(image_fakes.TestImagev2):
23+
_metadef_namespace = image_fakes.create_one_metadef_namespace()
24+
_metadef_property = image_fakes.create_one_metadef_property()
25+
expected_columns = (
26+
'name',
27+
'title',
28+
'type',
29+
)
30+
expected_data = (
31+
_metadef_property.name,
32+
_metadef_property.title,
33+
_metadef_property.type,
34+
)
35+
36+
def setUp(self):
37+
super().setUp()
38+
self.image_client.create_metadef_property.return_value = (
39+
self._metadef_property
40+
)
41+
self.cmd = metadef_properties.CreateMetadefProperty(self.app, None)
42+
43+
def test_metadef_property_create_missing_arguments(self):
44+
self.assertRaises(
45+
tests_utils.ParserException, self.check_parser, self.cmd, [], []
46+
)
47+
48+
def test_metadef_property_create(self):
49+
arglist = [
50+
'--name',
51+
'cpu_cores',
52+
'--schema',
53+
'{}',
54+
'--title',
55+
'vCPU Cores',
56+
'--type',
57+
'integer',
58+
self._metadef_namespace.namespace,
59+
]
60+
verifylist = []
61+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
62+
63+
columns, data = self.cmd.take_action(parsed_args)
64+
65+
self.assertEqual(self.expected_columns, columns)
66+
self.assertEqual(self.expected_data, data)
67+
68+
def test_metadef_property_create_invalid_schema(self):
69+
arglist = [
70+
'--name',
71+
'cpu_cores',
72+
'--schema',
73+
'{invalid}',
74+
'--title',
75+
'vCPU Cores',
76+
'--type',
77+
'integer',
78+
self._metadef_namespace.namespace,
79+
]
80+
verifylist = []
81+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
82+
83+
self.assertRaises(
84+
exceptions.CommandError, self.cmd.take_action, parsed_args
85+
)
1786

1887

1988
class TestMetadefPropertyList(image_fakes.TestImagev2):
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- |
4+
Add ``image metadef property create`` command to create a new
5+
metadef property inside a specific namespace.

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ openstack.image.v2 =
397397
image_metadef_namespace_set = openstackclient.image.v2.metadef_namespaces:SetMetadefNameSpace
398398
image_metadef_namespace_show = openstackclient.image.v2.metadef_namespaces:ShowMetadefNameSpace
399399

400+
image_metadef_property_create = openstackclient.image.v2.metadef_properties:CreateMetadefProperty
400401
image_metadef_property_list = openstackclient.image.v2.metadef_properties:ListMetadefProperties
401402
image_metadef_property_show = openstackclient.image.v2.metadef_properties:ShowMetadefProperty
402403

0 commit comments

Comments
 (0)