Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4efa7ac

Browse filesBrowse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Adds CLI support for glance md-tags"
2 parents 158bf88 + fef4f38 commit 4efa7ac
Copy full SHA for 4efa7ac

5 files changed

+202-12Lines changed: 202 additions & 12 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎doc/source/cli/data/glance.csv‎

Copy file name to clipboardExpand all lines: doc/source/cli/data/glance.csv
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ md-namespace-objects-delete,image metadef object delete,Delete all metadata defi
3030
md-namespace-properties-delete,image metadef property delete,Delete all metadata definitions property inside a specific namespace.
3131
md-namespace-resource-type-list,image metadef resource type association list,List resource types associated to specific namespace.
3232
md-namespace-show,image metadef namespace show,Describe a specific metadata definitions namespace.
33-
md-namespace-tags-delete,,Delete all metadata definitions tags inside a specific namespace.
33+
md-namespace-tags-delete,image metadef namespace unset --all,Delete all metadata definitions tags inside a specific namespace.
3434
md-namespace-update,,Update an existing metadata definitions namespace.
3535
md-object-create,image metadef object create,Create a new metadata definitions object inside a namespace.
3636
md-object-show,image metadef object show,Describe a specific metadata definitions object inside a namespace.
@@ -46,12 +46,12 @@ md-property-update,image metadef property set,Update metadata definitions proper
4646
md-resource-type-associate,image metadef resource type association create,Associate resource type with a metadata definitions namespace.
4747
md-resource-type-deassociate,image metadef resource type association delete,Deassociate resource type with a metadata definitions namespace.
4848
md-resource-type-list,image metadef resource type list,List available resource type names.
49-
md-tag-create,,Add a new metadata definitions tag inside a namespace.
49+
md-tag-create,image metadef namespace set --tag,Add a new metadata definitions tag inside a namespace.
5050
md-tag-create-multiple,,Create new metadata definitions tags inside a namespace.
51-
md-tag-delete,,Delete a specific metadata definitions tag inside a namespace.
52-
md-tag-list,,List metadata definitions tags inside a specific namespace.
53-
md-tag-show,,Describe a specific metadata definitions tag inside a namespace.
54-
md-tag-update,,Rename a metadata definitions tag inside a namespace.
51+
md-tag-delete,image metadef namespace unset --tag,Delete a specific metadata definitions tag inside a namespace.
52+
md-tag-list,image metadef namespace show,List metadata definitions tags inside a specific namespace.
53+
md-tag-show,image metadef namespace show,Describe a specific metadata definitions tag inside a namespace.
54+
md-tag-update,image metadef namespace set --tag,Rename a metadata definitions tag inside a namespace.
5555
member-create,image add project,Create member for a given image.
5656
member-delete,image remove project,Delete image member.
5757
member-get,image member get,Show details of an image member
Collapse file

‎openstackclient/image/v2/metadef_namespaces.py‎

Copy file name to clipboardExpand all lines: openstackclient/image/v2/metadef_namespaces.py
+85Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def _format_namespace(namespace: Any) -> dict[str, Any]:
4444
'namespace',
4545
'owner',
4646
'protected',
47+
'tags',
4748
'schema',
4849
'updated_at',
4950
'visibility',
@@ -278,6 +279,17 @@ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
278279
dest="is_protected",
279280
help=_("Allow metadef namespace to be deleted (default)"),
280281
)
282+
parser.add_argument(
283+
"--tag",
284+
metavar="<tag>",
285+
action='append',
286+
default=[],
287+
dest='tags',
288+
help=_(
289+
"Set a tag on this metadef namespace "
290+
"(repeat option to set multiple tags)"
291+
),
292+
)
281293
return parser
282294

283295
def take_action(self, parsed_args: argparse.Namespace) -> None:
@@ -301,6 +313,21 @@ def take_action(self, parsed_args: argparse.Namespace) -> None:
301313

302314
image_client.update_metadef_namespace(namespace, **kwargs)
303315

316+
errors = 0
317+
for tag in parsed_args.tags:
318+
try:
319+
image_client.add_tag_to_metadef_namespace(namespace, tag)
320+
except Exception:
321+
LOG.error(_("Tag set failed for tag %s"), tag)
322+
errors += 1
323+
324+
if errors > 0:
325+
msg = _("Failed to set %(errors)s of %(total)s tags.") % {
326+
'errors': errors,
327+
'total': len(parsed_args.tags),
328+
}
329+
raise exceptions.CommandError(msg)
330+
304331

305332
class ShowMetadefNamespace(command.ShowOne):
306333
_description = _("Show a metadef namespace")
@@ -326,3 +353,61 @@ def take_action(
326353

327354
col_headers, col_data = zip(*sorted(info.items()))
328355
return col_headers, col_data
356+
357+
358+
class UnsetMetadefNamespace(command.Command):
359+
_description = _("Unset metadef namespace tags")
360+
361+
def get_parser(self, prog_name):
362+
parser = super().get_parser(prog_name)
363+
parser.add_argument(
364+
"namespace",
365+
metavar="<namespace>",
366+
help=_("Metadef namespace to modify (name)"),
367+
)
368+
tag_group = parser.add_mutually_exclusive_group(required=True)
369+
tag_group.add_argument(
370+
"--tag",
371+
metavar="<tag>",
372+
action='append',
373+
default=[],
374+
dest='tags',
375+
help=_(
376+
"Unset a tag on this metadef namespace "
377+
"(repeat option to unset multiple tags)"
378+
),
379+
)
380+
tag_group.add_argument(
381+
"--all-tags",
382+
action="store_true",
383+
default=False,
384+
help=_("Unset all metadef tags"),
385+
)
386+
return parser
387+
388+
def take_action(self, parsed_args):
389+
image_client = self.app.client_manager.image
390+
391+
namespace = image_client.get_metadef_namespace(parsed_args.namespace)
392+
393+
errors = 0
394+
if parsed_args.all_tags:
395+
namespace = image_client.remove_tags_from_metadef_namespace(
396+
namespace
397+
)
398+
elif parsed_args.tags:
399+
for tag in parsed_args.tags:
400+
try:
401+
image_client.remove_tag_from_metadef_namespace(
402+
namespace, tag
403+
)
404+
except Exception:
405+
LOG.error(_("tag unset failed for tag %s"), tag)
406+
errors += 1
407+
408+
if errors > 0:
409+
msg = _("Failed to unset %(errors)s of %(total)s tags.") % {
410+
'errors': errors,
411+
'total': len(parsed_args.tags),
412+
}
413+
raise exceptions.CommandError(msg)
Collapse file

‎openstackclient/tests/unit/image/v2/test_metadef_namespaces.py‎

Copy file name to clipboardExpand all lines: openstackclient/tests/unit/image/v2/test_metadef_namespaces.py
+105-6Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
from unittest import mock
16+
1517
from openstackclient.image.v2 import metadef_namespaces
1618
from openstackclient.tests.unit.image.v2 import fakes as image_fakes
1719

@@ -24,13 +26,15 @@ class TestMetadefNamespaceCreate(image_fakes.TestImagev2):
2426
'display_name',
2527
'namespace',
2628
'owner',
29+
'tags',
2730
'visibility',
2831
)
2932
expected_data = (
3033
_metadef_namespace.created_at,
3134
_metadef_namespace.display_name,
3235
_metadef_namespace.namespace,
3336
_metadef_namespace.owner,
37+
_metadef_namespace.tags,
3438
_metadef_namespace.visibility,
3539
)
3640

@@ -114,21 +118,25 @@ def test_namespace_list_no_options(self):
114118

115119

116120
class TestMetadefNamespaceSet(image_fakes.TestImagev2):
117-
_metadef_namespace = image_fakes.create_one_metadef_namespace()
118-
119121
def setUp(self):
120122
super().setUp()
121123

124+
self.metadef_namespace = image_fakes.create_one_metadef_namespace()
125+
126+
self.image_client.get_metadef_namespace.return_value = (
127+
self.metadef_namespace
128+
)
122129
self.image_client.update_metadef_namespace.return_value = (
123-
self._metadef_namespace
130+
self.metadef_namespace
124131
)
132+
self.image_client.add_tag_to_metadef_namespace.return_value = None
133+
125134
self.cmd = metadef_namespaces.SetMetadefNamespace(self.app, None)
126-
self.datalist = self._metadef_namespace
127135

128136
def test_namespace_set_no_options(self):
129-
arglist = [self._metadef_namespace.namespace]
137+
arglist = [self.metadef_namespace.namespace]
130138
verifylist = [
131-
('namespace', self._metadef_namespace.namespace),
139+
('namespace', self.metadef_namespace.namespace),
132140
]
133141

134142
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -137,6 +145,95 @@ def test_namespace_set_no_options(self):
137145

138146
self.assertIsNone(result)
139147

148+
def test_namespace_set_tag(self):
149+
arglist = [
150+
self.metadef_namespace.namespace,
151+
'--tag',
152+
't1',
153+
'--tag',
154+
't2',
155+
]
156+
verifylist = [
157+
('namespace', self.metadef_namespace.namespace),
158+
('tags', ['t1', 't2']),
159+
]
160+
161+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
162+
163+
self.cmd.take_action(parsed_args)
164+
165+
self.image_client.add_tag_to_metadef_namespace.assert_has_calls(
166+
[
167+
mock.call(self.metadef_namespace.namespace, 't1'),
168+
mock.call(self.metadef_namespace.namespace, 't2'),
169+
]
170+
)
171+
172+
173+
class TestMetadefNamespaceUnset(image_fakes.TestImagev2):
174+
def setUp(self):
175+
super().setUp()
176+
177+
self.metadef_namespace = image_fakes.create_one_metadef_namespace(
178+
attrs={'tags': [{'name': 't1'}]}
179+
)
180+
181+
self.image_client.get_metadef_namespace.return_value = (
182+
self.metadef_namespace
183+
)
184+
self.image_client.update_metadef_namespace.return_value = (
185+
self.metadef_namespace
186+
)
187+
self.image_client.remove_tag_from_metadef_namespace.return_value = None
188+
self.image_client.remove_tags_from_metadef_namespace.return_value = (
189+
None
190+
)
191+
192+
self.cmd = metadef_namespaces.UnsetMetadefNamespace(self.app, None)
193+
194+
def test_namespace_unset_tag(self):
195+
arglist = [
196+
self.metadef_namespace.namespace,
197+
'--tag',
198+
't1',
199+
'--tag',
200+
't2',
201+
]
202+
verifylist = [
203+
('namespace', self.metadef_namespace.namespace),
204+
('tags', ['t1', 't2']),
205+
]
206+
207+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
208+
209+
self.cmd.take_action(parsed_args)
210+
211+
self.image_client.remove_tag_from_metadef_namespace.assert_has_calls(
212+
[
213+
mock.call(self.metadef_namespace, 't1'),
214+
mock.call(self.metadef_namespace, 't2'),
215+
]
216+
)
217+
self.image_client.remove_tags_from_metadef_namespace.assert_not_called()
218+
219+
def test_namespace_unset_all_tag(self):
220+
arglist = [
221+
self.metadef_namespace.namespace,
222+
'--all-tags',
223+
]
224+
verifylist = [
225+
('namespace', self.metadef_namespace.namespace),
226+
]
227+
228+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
229+
230+
self.cmd.take_action(parsed_args)
231+
232+
self.image_client.remove_tags_from_metadef_namespace.assert_called_once_with(
233+
self.metadef_namespace
234+
)
235+
self.image_client.remove_tag_from_metadef_namespace.assert_not_called()
236+
140237

141238
class TestMetadefNamespaceShow(image_fakes.TestImagev2):
142239
_metadef_namespace = image_fakes.create_one_metadef_namespace()
@@ -146,13 +243,15 @@ class TestMetadefNamespaceShow(image_fakes.TestImagev2):
146243
'display_name',
147244
'namespace',
148245
'owner',
246+
'tags',
149247
'visibility',
150248
)
151249
expected_data = (
152250
_metadef_namespace.created_at,
153251
_metadef_namespace.display_name,
154252
_metadef_namespace.namespace,
155253
_metadef_namespace.owner,
254+
_metadef_namespace.tags,
156255
_metadef_namespace.visibility,
157256
)
158257

Collapse file

‎pyproject.toml‎

Copy file name to clipboardExpand all lines: pyproject.toml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ image_metadef_namespace_delete = "openstackclient.image.v2.metadef_namespaces:De
359359
image_metadef_namespace_list = "openstackclient.image.v2.metadef_namespaces:ListMetadefNamespace"
360360
image_metadef_namespace_set = "openstackclient.image.v2.metadef_namespaces:SetMetadefNamespace"
361361
image_metadef_namespace_show = "openstackclient.image.v2.metadef_namespaces:ShowMetadefNamespace"
362+
image_metadef_namespace_unset = "openstackclient.image.v2.metadef_namespaces:UnsetMetadefNamespace"
362363
image_metadef_object_create = "openstackclient.image.v2.metadef_objects:CreateMetadefObjects"
363364
image_metadef_object_show = "openstackclient.image.v2.metadef_objects:ShowMetadefObjects"
364365
image_metadef_object_list = "openstackclient.image.v2.metadef_objects:ListMetadefObjects"
Collapse file
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- |
4+
Add support for metadef-tags associated to namespace for adding, updating,
5+
removing a tag.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.