python-openstackclient 6.4.0__py3-none-any.whl → 6.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. openstackclient/common/availability_zone.py +4 -4
  2. openstackclient/compute/v2/server.py +173 -99
  3. openstackclient/identity/v3/mapping.py +25 -3
  4. openstackclient/identity/v3/policy.py +3 -1
  5. openstackclient/image/v2/image.py +37 -0
  6. openstackclient/image/v2/metadef_namespaces.py +25 -21
  7. openstackclient/image/v2/metadef_objects.py +26 -30
  8. openstackclient/image/v2/metadef_properties.py +60 -38
  9. openstackclient/network/v2/default_security_group_rule.py +23 -4
  10. openstackclient/network/v2/local_ip_association.py +1 -1
  11. openstackclient/network/v2/ndp_proxy.py +7 -3
  12. openstackclient/network/v2/network.py +2 -2
  13. openstackclient/network/v2/port.py +23 -7
  14. openstackclient/network/v2/subnet.py +1 -0
  15. openstackclient/tests/functional/base.py +7 -4
  16. openstackclient/tests/unit/compute/v2/test_server.py +72 -54
  17. openstackclient/tests/unit/identity/v3/test_mappings.py +9 -4
  18. openstackclient/tests/unit/identity/v3/test_trust.py +0 -2
  19. openstackclient/tests/unit/image/v1/fakes.py +1 -1
  20. openstackclient/tests/unit/image/v2/test_image.py +60 -0
  21. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +5 -19
  22. openstackclient/tests/unit/integ/cli/test_shell.py +0 -2
  23. openstackclient/tests/unit/network/v2/fakes.py +1 -0
  24. openstackclient/tests/unit/network/v2/test_network.py +33 -0
  25. openstackclient/tests/unit/network/v2/test_network_trunk.py +6 -8
  26. openstackclient/tests/unit/network/v2/test_port.py +60 -18
  27. openstackclient/tests/unit/network/v2/test_subnet.py +92 -0
  28. openstackclient/tests/unit/network/v2/test_subnet_pool.py +11 -13
  29. openstackclient/tests/unit/test_shell.py +1 -7
  30. openstackclient/tests/unit/utils.py +8 -1
  31. openstackclient/tests/unit/volume/v1/test_volume.py +4 -6
  32. openstackclient/tests/unit/volume/v2/test_volume.py +4 -6
  33. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +3 -5
  34. openstackclient/volume/v2/volume_type.py +3 -3
  35. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/AUTHORS +4 -0
  36. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/METADATA +3 -1
  37. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/RECORD +42 -43
  38. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/entry_points.txt +6 -5
  39. python_openstackclient-6.5.0.dist-info/pbr.json +1 -0
  40. openstackclient/tests/unit/common/test_parseractions.py +0 -233
  41. python_openstackclient-6.4.0.dist-info/pbr.json +0 -1
  42. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/LICENSE +0 -0
  43. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/WHEEL +0 -0
  44. {python_openstackclient-6.4.0.dist-info → python_openstackclient-6.5.0.dist-info}/top_level.txt +0 -0
@@ -992,6 +992,43 @@ class RemoveProjectImage(command.Command):
992
992
  image_client.remove_member(member=project_id, image=image.id)
993
993
 
994
994
 
995
+ class ShowProjectImage(command.ShowOne):
996
+ _description = _("Show a particular project associated with image")
997
+
998
+ def get_parser(self, prog_name):
999
+ parser = super().get_parser(prog_name)
1000
+ parser.add_argument(
1001
+ "image",
1002
+ metavar="<image>",
1003
+ help=_("Image (name or ID)"),
1004
+ )
1005
+ parser.add_argument(
1006
+ "member",
1007
+ metavar="<project>",
1008
+ help=_("Project to show (name or ID)"),
1009
+ )
1010
+ identity_common.add_project_domain_option_to_parser(parser)
1011
+ return parser
1012
+
1013
+ def take_action(self, parsed_args):
1014
+ image_client = self.app.client_manager.image
1015
+
1016
+ image = image_client.find_image(
1017
+ parsed_args.image,
1018
+ ignore_missing=False,
1019
+ )
1020
+
1021
+ obj = image_client.get_member(
1022
+ image=image.id,
1023
+ member=parsed_args.member,
1024
+ )
1025
+
1026
+ display_columns, columns = _get_member_columns(obj)
1027
+ data = utils.get_item_properties(obj, columns, formatters={})
1028
+
1029
+ return (display_columns, data)
1030
+
1031
+
995
1032
  class SaveImage(command.Command):
996
1033
  _description = _("Save an image locally")
997
1034
 
@@ -42,6 +42,7 @@ def _format_namespace(namespace):
42
42
  'owner',
43
43
  'protected',
44
44
  'schema',
45
+ 'updated_at',
45
46
  'visibility',
46
47
  ]
47
48
 
@@ -61,7 +62,7 @@ def _format_namespace(namespace):
61
62
  return info
62
63
 
63
64
 
64
- class CreateMetadefNameSpace(command.ShowOne):
65
+ class CreateMetadefNamespace(command.ShowOne):
65
66
  _description = _("Create a metadef namespace")
66
67
 
67
68
  def get_parser(self, prog_name):
@@ -130,20 +131,21 @@ class CreateMetadefNameSpace(command.ShowOne):
130
131
  kwargs['visibility'] = parsed_args.visibility
131
132
 
132
133
  data = image_client.create_metadef_namespace(**kwargs)
134
+ info = _format_namespace(data)
133
135
 
134
- return zip(*sorted(data.items()))
136
+ return zip(*sorted(info.items()))
135
137
 
136
138
 
137
- class DeleteMetadefNameSpace(command.Command):
139
+ class DeleteMetadefNamespace(command.Command):
138
140
  _description = _("Delete metadef namespace")
139
141
 
140
142
  def get_parser(self, prog_name):
141
143
  parser = super().get_parser(prog_name)
142
144
  parser.add_argument(
143
- "namespace_name",
144
- metavar="<namespace_name>",
145
+ "namespace",
146
+ metavar="<namespace>",
145
147
  nargs="+",
146
- help=_("An identifier (a name) for the namespace"),
148
+ help=_("Metadef namespace(s) to delete (name)"),
147
149
  )
148
150
  return parser
149
151
 
@@ -151,9 +153,9 @@ class DeleteMetadefNameSpace(command.Command):
151
153
  image_client = self.app.client_manager.image
152
154
 
153
155
  result = 0
154
- for i in parsed_args.namespace_name:
156
+ for ns in parsed_args.namespace:
155
157
  try:
156
- namespace = image_client.get_metadef_namespace(i)
158
+ namespace = image_client.get_metadef_namespace(ns)
157
159
  image_client.delete_metadef_namespace(namespace.id)
158
160
  except Exception as e:
159
161
  result += 1
@@ -162,18 +164,18 @@ class DeleteMetadefNameSpace(command.Command):
162
164
  "Failed to delete namespace with name or "
163
165
  "ID '%(namespace)s': %(e)s"
164
166
  ),
165
- {'namespace': i, 'e': e},
167
+ {'namespace': ns, 'e': e},
166
168
  )
167
169
 
168
170
  if result > 0:
169
- total = len(parsed_args.namespace_name)
171
+ total = len(parsed_args.namespace)
170
172
  msg = _(
171
173
  "%(result)s of %(total)s namespace failed " "to delete."
172
174
  ) % {'result': result, 'total': total}
173
175
  raise exceptions.CommandError(msg)
174
176
 
175
177
 
176
- class ListMetadefNameSpaces(command.Lister):
178
+ class ListMetadefNamespace(command.Lister):
177
179
  _description = _("List metadef namespaces")
178
180
 
179
181
  def get_parser(self, prog_name):
@@ -215,7 +217,7 @@ class ListMetadefNameSpaces(command.Lister):
215
217
  )
216
218
 
217
219
 
218
- class SetMetadefNameSpace(command.Command):
220
+ class SetMetadefNamespace(command.Command):
219
221
  _description = _("Set metadef namespace properties")
220
222
 
221
223
  def get_parser(self, prog_name):
@@ -223,7 +225,7 @@ class SetMetadefNameSpace(command.Command):
223
225
  parser.add_argument(
224
226
  "namespace",
225
227
  metavar="<namespace>",
226
- help=_("Namespace (name) for the namespace"),
228
+ help=_("Metadef namespace to modify (name)"),
227
229
  )
228
230
  parser.add_argument(
229
231
  "--display-name",
@@ -241,14 +243,16 @@ class SetMetadefNameSpace(command.Command):
241
243
  action="store_const",
242
244
  const="public",
243
245
  dest="visibility",
244
- help=_("Set namespace visibility 'public'"),
246
+ help=_("Metadef namespace is accessible to the public"),
245
247
  )
246
248
  visibility_group.add_argument(
247
249
  "--private",
248
250
  action="store_const",
249
251
  const="private",
250
252
  dest="visibility",
251
- help=_("Set namespace visibility 'private'"),
253
+ help=_(
254
+ "Metadef namespace is inaccessible to the public (default)"
255
+ ),
252
256
  )
253
257
  protected_group = parser.add_mutually_exclusive_group()
254
258
  protected_group.add_argument(
@@ -289,24 +293,24 @@ class SetMetadefNameSpace(command.Command):
289
293
  image_client.update_metadef_namespace(namespace, **kwargs)
290
294
 
291
295
 
292
- class ShowMetadefNameSpace(command.ShowOne):
296
+ class ShowMetadefNamespace(command.ShowOne):
293
297
  _description = _("Show a metadef namespace")
294
298
 
295
299
  def get_parser(self, prog_name):
296
300
  parser = super().get_parser(prog_name)
297
301
  parser.add_argument(
298
- "namespace_name",
299
- metavar="<namespace_name>",
300
- help=_("Namespace (name) for the namespace"),
302
+ "namespace",
303
+ metavar="<namespace>",
304
+ help=_("Metadef namespace to show (name)"),
301
305
  )
302
306
  return parser
303
307
 
304
308
  def take_action(self, parsed_args):
305
309
  image_client = self.app.client_manager.image
306
310
 
307
- namespace_name = parsed_args.namespace_name
311
+ namespace = parsed_args.namespace
308
312
 
309
- data = image_client.get_metadef_namespace(namespace_name)
313
+ data = image_client.get_metadef_namespace(namespace)
310
314
  info = _format_namespace(data)
311
315
 
312
316
  return zip(*sorted(info.items()))
@@ -55,7 +55,7 @@ class CreateMetadefObjects(command.ShowOne):
55
55
  parser.add_argument(
56
56
  "--namespace",
57
57
  metavar="<namespace>",
58
- help=_("Metadef namespace to create the metadef object in (name)"),
58
+ help=_("Metadef namespace to create the object in (name)"),
59
59
  )
60
60
  parser.add_argument(
61
61
  "name",
@@ -81,31 +81,29 @@ class CreateMetadefObjects(command.ShowOne):
81
81
 
82
82
 
83
83
  class ShowMetadefObjects(command.ShowOne):
84
- _description = _(
85
- "Describe a specific metadata definitions object inside a namespace"
86
- )
84
+ _description = _("Show a particular metadef object")
87
85
 
88
86
  def get_parser(self, prog_name):
89
87
  parser = super().get_parser(prog_name)
90
88
  parser.add_argument(
91
- "namespace_name",
92
- metavar="<namespace_name>",
93
- help=_("Namespace (name) for the namespace"),
89
+ "namespace",
90
+ metavar="<namespace>",
91
+ help=_("Metadef namespace of the object (name)"),
94
92
  )
95
93
  parser.add_argument(
96
- "object_name",
97
- metavar="<object_name>",
98
- help=_("Name of an object."),
94
+ "object",
95
+ metavar="<object>",
96
+ help=_("Metadef object to show"),
99
97
  )
100
98
  return parser
101
99
 
102
100
  def take_action(self, parsed_args):
103
101
  image_client = self.app.client_manager.image
104
102
 
105
- namespace_name = parsed_args.namespace_name
106
- object_name = parsed_args.object_name
103
+ namespace = parsed_args.namespace
104
+ object = parsed_args.object
107
105
 
108
- data = image_client.get_metadef_object(object_name, namespace_name)
106
+ data = image_client.get_metadef_object(object, namespace)
109
107
 
110
108
  fields, value = _format_object(data)
111
109
 
@@ -113,35 +111,33 @@ class ShowMetadefObjects(command.ShowOne):
113
111
 
114
112
 
115
113
  class DeleteMetadefObject(command.Command):
116
- _description = _(
117
- "Delete a specific metadata definitions object inside a namespace"
118
- )
114
+ _description = _("Delete metadata definitions object(s)")
119
115
 
120
116
  def get_parser(self, prog_name):
121
117
  parser = super().get_parser(prog_name)
122
118
  parser.add_argument(
123
- "namespace_name",
124
- metavar="<namespace_name>",
125
- help=_("Namespace (name) for the namespace"),
119
+ "namespace",
120
+ metavar="<namespace>",
121
+ help=_("Metadef namespace of the object (name)"),
126
122
  )
127
123
  parser.add_argument(
128
- "object_name",
129
- metavar="<object_name>",
124
+ "objects",
125
+ metavar="<object>",
130
126
  nargs="+",
131
- help=_("Name of an object."),
127
+ help=_("Metadef object(s) to delete (name)"),
132
128
  )
133
129
  return parser
134
130
 
135
131
  def take_action(self, parsed_args):
136
132
  image_client = self.app.client_manager.image
137
133
 
138
- namespace_name = parsed_args.namespace_name
134
+ namespace = parsed_args.namespace
139
135
 
140
136
  result = 0
141
- for i in parsed_args.object_name:
137
+ for obj in parsed_args.objects:
142
138
  try:
143
- object = image_client.get_metadef_object(i, namespace_name)
144
- image_client.delete_metadef_object(object, namespace_name)
139
+ object = image_client.get_metadef_object(obj, namespace)
140
+ image_client.delete_metadef_object(object, namespace)
145
141
  except Exception as e:
146
142
  result += 1
147
143
  LOG.error(
@@ -149,11 +145,11 @@ class DeleteMetadefObject(command.Command):
149
145
  "Failed to delete object with name or "
150
146
  "ID '%(object)s': %(e)s"
151
147
  ),
152
- {'object': i, 'e': e},
148
+ {'object': obj, 'e': e},
153
149
  )
154
150
 
155
151
  if result > 0:
156
- total = len(parsed_args.namespace_name)
152
+ total = len(parsed_args.namespace)
157
153
  msg = _("%(result)s of %(total)s object failed to delete.") % {
158
154
  'result': result,
159
155
  'total': total,
@@ -176,10 +172,10 @@ class ListMetadefObjects(command.Lister):
176
172
  def take_action(self, parsed_args):
177
173
  image_client = self.app.client_manager.image
178
174
 
179
- namespace_name = parsed_args.namespace
175
+ namespace = parsed_args.namespace
180
176
  columns = ['name', 'description']
181
177
 
182
- md_objects = list(image_client.metadef_objects(namespace_name))
178
+ md_objects = list(image_client.metadef_objects(namespace))
183
179
  column_headers = columns
184
180
  return (
185
181
  column_headers,
@@ -13,6 +13,7 @@
13
13
  # under the License.
14
14
 
15
15
  import json
16
+ import logging
16
17
 
17
18
  from osc_lib.command import command
18
19
  from osc_lib import exceptions
@@ -21,6 +22,9 @@ from osc_lib import utils
21
22
  from openstackclient.i18n import _
22
23
 
23
24
 
25
+ LOG = logging.getLogger(__name__)
26
+
27
+
24
28
  def _format_property(prop):
25
29
  prop = prop.to_dict(ignore_none=True, original_names=True)
26
30
  return {
@@ -76,7 +80,7 @@ class CreateMetadefProperty(command.ShowOne):
76
80
  help=_("Valid JSON schema of the property"),
77
81
  )
78
82
  parser.add_argument(
79
- "namespace_name",
83
+ "namespace",
80
84
  help=_("Name of namespace the property will belong."),
81
85
  )
82
86
  return parser
@@ -100,7 +104,7 @@ class CreateMetadefProperty(command.ShowOne):
100
104
  )
101
105
 
102
106
  data = image_client.create_metadef_property(
103
- parsed_args.namespace_name, **kwargs
107
+ parsed_args.namespace, **kwargs
104
108
  )
105
109
  info = _format_property(data)
106
110
 
@@ -108,41 +112,55 @@ class CreateMetadefProperty(command.ShowOne):
108
112
 
109
113
 
110
114
  class DeleteMetadefProperty(command.Command):
111
- _description = _("Delete a metadef property")
115
+ _description = _("Delete metadef propert(ies)")
112
116
 
113
117
  def get_parser(self, prog_name):
114
118
  parser = super().get_parser(prog_name)
115
119
  parser.add_argument(
116
- "namespace_name",
117
- help=_("An identifier (a name) for the namespace"),
120
+ "namespace",
121
+ metavar="<namespace>",
122
+ help=_("Metadef namespace of the property (name)"),
118
123
  )
119
124
  parser.add_argument(
120
- "property_name",
121
- help=_("Property to delete"),
125
+ "properties",
126
+ metavar="<property>",
127
+ nargs="+",
128
+ help=_("Metadef propert(ies) to delete (name)"),
122
129
  )
123
130
  return parser
124
131
 
125
132
  def take_action(self, parsed_args):
126
133
  image_client = self.app.client_manager.image
127
134
 
128
- try:
129
- image_client.delete_metadef_property(
130
- parsed_args.property_name,
131
- parsed_args.namespace_name,
132
- ignore_missing=False,
133
- )
134
- except Exception as e:
135
- raise exceptions.CommandError(
136
- _(
137
- "Failed to delete property with name or "
138
- "ID '%(property)s' from namespace '%(namespace)s': %(e)s"
135
+ result = 0
136
+ for prop in parsed_args.properties:
137
+ try:
138
+ image_client.delete_metadef_property(
139
+ prop,
140
+ parsed_args.namespace,
141
+ ignore_missing=False,
139
142
  )
140
- % {
141
- 'property': parsed_args.property_name,
142
- 'namespace': parsed_args.namespace_name,
143
- 'e': e,
144
- }
145
- )
143
+ except Exception as e:
144
+ result += 1
145
+ LOG.error(
146
+ _(
147
+ "Failed to delete property with name or ID "
148
+ "'%(property)s' from namespace '%(namespace)s': %(e)s"
149
+ ),
150
+ {
151
+ 'property': prop,
152
+ 'namespace': parsed_args.namespace,
153
+ 'e': e,
154
+ },
155
+ )
156
+
157
+ if result > 0:
158
+ total = len(parsed_args.namespace)
159
+ msg = _("%(result)s of %(total)s properties failed to delete.") % {
160
+ 'result': result,
161
+ 'total': total,
162
+ }
163
+ raise exceptions.CommandError(msg)
146
164
 
147
165
 
148
166
  class ListMetadefProperties(command.Lister):
@@ -151,15 +169,15 @@ class ListMetadefProperties(command.Lister):
151
169
  def get_parser(self, prog_name):
152
170
  parser = super().get_parser(prog_name)
153
171
  parser.add_argument(
154
- "namespace_name",
155
- metavar="<namespace_name>",
172
+ "namespace",
173
+ metavar="<namespace>",
156
174
  help=_("An identifier (a name) for the namespace"),
157
175
  )
158
176
  return parser
159
177
 
160
178
  def take_action(self, parsed_args):
161
179
  image_client = self.app.client_manager.image
162
- props = image_client.metadef_properties(parsed_args.namespace_name)
180
+ props = image_client.metadef_properties(parsed_args.namespace)
163
181
  columns = ['name', 'title', 'type']
164
182
  return (
165
183
  columns,
@@ -195,11 +213,11 @@ class SetMetadefProperty(command.Command):
195
213
  help=_("Valid JSON schema of the property"),
196
214
  )
197
215
  parser.add_argument(
198
- "namespace_name",
216
+ "namespace",
199
217
  help=_("Namespace of the namespace to which the property belongs"),
200
218
  )
201
219
  parser.add_argument(
202
- "property_name",
220
+ "property",
203
221
  help=_("Property to update"),
204
222
  )
205
223
  return parser
@@ -211,7 +229,8 @@ class SetMetadefProperty(command.Command):
211
229
  # update_metadef_property(), otherwise the attributes that are not
212
230
  # listed will be reset.
213
231
  data = image_client.get_metadef_property(
214
- parsed_args.property_name, parsed_args.namespace_name
232
+ parsed_args.property,
233
+ parsed_args.namespace,
215
234
  )
216
235
  kwargs = _format_property(data)
217
236
  for key in ['name', 'title', 'type']:
@@ -231,23 +250,25 @@ class SetMetadefProperty(command.Command):
231
250
  )
232
251
 
233
252
  image_client.update_metadef_property(
234
- parsed_args.property_name, parsed_args.namespace_name, **kwargs
253
+ parsed_args.property,
254
+ parsed_args.namespace,
255
+ **kwargs,
235
256
  )
236
257
 
237
258
 
238
259
  class ShowMetadefProperty(command.ShowOne):
239
- _description = _("Describe a specific property from a namespace")
260
+ _description = _("Show a particular metadef property")
240
261
 
241
262
  def get_parser(self, prog_name):
242
263
  parser = super().get_parser(prog_name)
243
264
  parser.add_argument(
244
- "namespace_name",
245
- metavar="<namespace_name>",
246
- help=_("Namespace (name) for the namespace"),
265
+ "namespace",
266
+ metavar="<namespace>",
267
+ help=_("Metadef namespace of the property (name)"),
247
268
  )
248
269
  parser.add_argument(
249
- "property_name",
250
- metavar="<property_name>",
270
+ "property",
271
+ metavar="<property>",
251
272
  help=_("Property to show"),
252
273
  )
253
274
  return parser
@@ -255,7 +276,8 @@ class ShowMetadefProperty(command.ShowOne):
255
276
  def take_action(self, parsed_args):
256
277
  image_client = self.app.client_manager.image
257
278
  data = image_client.get_metadef_property(
258
- parsed_args.property_name, parsed_args.namespace_name
279
+ parsed_args.property,
280
+ parsed_args.namespace,
259
281
  )
260
282
  info = _format_property(data)
261
283
 
@@ -38,7 +38,12 @@ def _get_columns(item):
38
38
  class CreateDefaultSecurityGroupRule(
39
39
  command.ShowOne, common.NeutronCommandWithExtraArgs
40
40
  ):
41
- _description = _("Create a new default security group rule")
41
+ """Add a new security group rule to the default security group template.
42
+
43
+ These rules will be applied to the default security groups created for any
44
+ new project. They will not be applied to any existing default security
45
+ groups.
46
+ """
42
47
 
43
48
  def get_parser(self, prog_name):
44
49
  parser = super().get_parser(prog_name)
@@ -225,7 +230,12 @@ class CreateDefaultSecurityGroupRule(
225
230
 
226
231
 
227
232
  class DeleteDefaultSecurityGroupRule(command.Command):
228
- _description = _("Delete default security group rule(s)")
233
+ """Remove security group rule(s) from the default security group template.
234
+
235
+ These rules will not longer be applied to the default security groups
236
+ created for any new project. They will not be removed from any existing
237
+ default security groups.
238
+ """
229
239
 
230
240
  def get_parser(self, prog_name):
231
241
  parser = super().get_parser(prog_name)
@@ -265,7 +275,12 @@ class DeleteDefaultSecurityGroupRule(command.Command):
265
275
 
266
276
 
267
277
  class ListDefaultSecurityGroupRule(command.Lister):
268
- _description = _("List default security group rules")
278
+ """List security group rules used for new default security groups.
279
+
280
+ This shows the rules that will be added to any new default security groups
281
+ created. These rules may differ for the rules present on existing default
282
+ security groups.
283
+ """
269
284
 
270
285
  def _format_network_security_group_rule(self, rule):
271
286
  """Transform the SDK DefaultSecurityGroupRule object to a dict
@@ -373,7 +388,11 @@ class ListDefaultSecurityGroupRule(command.Lister):
373
388
 
374
389
 
375
390
  class ShowDefaultSecurityGroupRule(command.ShowOne):
376
- _description = _("Display default security group rule details")
391
+ """Show a security group rule used for new default security groups.
392
+
393
+ This shows a rule that will be added to any new default security groups
394
+ created. This rule may not be present on existing default security groups.
395
+ """
377
396
 
378
397
  def get_parser(self, prog_name):
379
398
  parser = super().get_parser(prog_name)
@@ -124,7 +124,7 @@ class DeleteLocalIPAssociation(command.Command):
124
124
  "fixed port "
125
125
  "name or ID '%(fixed_port_id)s': %(e)s"
126
126
  ),
127
- {'fixed port ID': fixed_port_id, 'e': e},
127
+ {'fixed_port_id': fixed_port_id, 'e': e},
128
128
  )
129
129
 
130
130
  if result > 0:
@@ -129,7 +129,7 @@ class DeleteNDPProxy(command.Command):
129
129
  if result > 0:
130
130
  total = len(parsed_args.ndp_proxy)
131
131
  msg = _(
132
- "%(result)s of %(total)s NDP Proxy failed " "to delete."
132
+ "%(result)s of %(total)s NDP proxies failed " "to delete."
133
133
  ) % {'result': result, 'total': total}
134
134
  raise exceptions.CommandError(msg)
135
135
 
@@ -142,12 +142,16 @@ class ListNDPProxy(command.Lister):
142
142
  parser.add_argument(
143
143
  '--router',
144
144
  metavar='<router>',
145
- help=_("List only NDP proxies belong to this router (name or ID)"),
145
+ help=_(
146
+ "List only NDP proxies belonging to this router (name or ID)"
147
+ ),
146
148
  )
147
149
  parser.add_argument(
148
150
  '--port',
149
151
  metavar='<port>',
150
- help=_("List only NDP proxies assocate to this port (name or ID)"),
152
+ help=_(
153
+ "List only NDP proxies associated to this port (name or ID)"
154
+ ),
151
155
  )
152
156
  parser.add_argument(
153
157
  '--ip-address',
@@ -107,7 +107,7 @@ def _get_attrs_network(client_manager, parsed_args):
107
107
  attrs['availability_zone_hints'] = parsed_args.availability_zone_hints
108
108
 
109
109
  # set description
110
- if parsed_args.description:
110
+ if parsed_args.description is not None:
111
111
  attrs['description'] = parsed_args.description
112
112
 
113
113
  # set mtu
@@ -139,7 +139,7 @@ def _get_attrs_network(client_manager, parsed_args):
139
139
  if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
140
140
  attrs['qos_policy_id'] = None
141
141
  # Update DNS network options
142
- if parsed_args.dns_domain:
142
+ if parsed_args.dns_domain is not None:
143
143
  attrs['dns_domain'] = parsed_args.dns_domain
144
144
  return attrs
145
145