Merge "Support "--no" option in aggregate set"
This commit is contained in:
commit
15069ef50e
@ -116,6 +116,7 @@ Set aggregate properties
|
|||||||
[--name <new-name>]
|
[--name <new-name>]
|
||||||
[--zone <availability-zone>]
|
[--zone <availability-zone>]
|
||||||
[--property <key=value> [...] ]
|
[--property <key=value> [...] ]
|
||||||
|
[--no-property]
|
||||||
<aggregate>
|
<aggregate>
|
||||||
|
|
||||||
.. option:: --name <name>
|
.. option:: --name <name>
|
||||||
@ -131,6 +132,12 @@ Set aggregate properties
|
|||||||
Property to set on :ref:`\<aggregate\> <aggregate_set-aggregate>`
|
Property to set on :ref:`\<aggregate\> <aggregate_set-aggregate>`
|
||||||
(repeat option to set multiple properties)
|
(repeat option to set multiple properties)
|
||||||
|
|
||||||
|
.. option:: --no-property
|
||||||
|
|
||||||
|
Remove all properties from :ref:`\<aggregate\> <aggregate_set-aggregate>`
|
||||||
|
(specify both --property and --no-property to
|
||||||
|
overwrite the current properties)
|
||||||
|
|
||||||
.. _aggregate_set-aggregate:
|
.. _aggregate_set-aggregate:
|
||||||
.. describe:: <aggregate>
|
.. describe:: <aggregate>
|
||||||
|
|
||||||
|
@ -248,6 +248,14 @@ class SetAggregate(command.Command):
|
|||||||
help=_("Property to set on <aggregate> "
|
help=_("Property to set on <aggregate> "
|
||||||
"(repeat option to set multiple properties)")
|
"(repeat option to set multiple properties)")
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-property",
|
||||||
|
dest="no_property",
|
||||||
|
action="store_true",
|
||||||
|
help=_("Remove all properties from <aggregate> "
|
||||||
|
"(specify both --property and --no-property to "
|
||||||
|
"overwrite the current properties)"),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -269,10 +277,23 @@ class SetAggregate(command.Command):
|
|||||||
kwargs
|
kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set_property = {}
|
||||||
|
if parsed_args.no_property:
|
||||||
|
# NOTE(RuiChen): "availability_zone" is removed from response of
|
||||||
|
# aggregate show and create commands, don't see it
|
||||||
|
# anywhere, so pop it, avoid the unexpected server
|
||||||
|
# exception(can't unset the availability zone from
|
||||||
|
# aggregate metadata in nova).
|
||||||
|
set_property.update({key: None
|
||||||
|
for key in aggregate.metadata.keys()
|
||||||
|
if key != 'availability_zone'})
|
||||||
if parsed_args.property:
|
if parsed_args.property:
|
||||||
|
set_property.update(parsed_args.property)
|
||||||
|
|
||||||
|
if set_property:
|
||||||
compute_client.aggregates.set_metadata(
|
compute_client.aggregates.set_metadata(
|
||||||
aggregate,
|
aggregate,
|
||||||
parsed_args.property
|
set_property
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -326,7 +347,6 @@ class UnsetAggregate(command.Command):
|
|||||||
"--property",
|
"--property",
|
||||||
metavar="<key>",
|
metavar="<key>",
|
||||||
action='append',
|
action='append',
|
||||||
required=True,
|
|
||||||
help=_("Property to remove from aggregate "
|
help=_("Property to remove from aggregate "
|
||||||
"(repeat option to remove multiple properties)")
|
"(repeat option to remove multiple properties)")
|
||||||
)
|
)
|
||||||
@ -338,6 +358,9 @@ class UnsetAggregate(command.Command):
|
|||||||
compute_client.aggregates,
|
compute_client.aggregates,
|
||||||
parsed_args.aggregate)
|
parsed_args.aggregate)
|
||||||
|
|
||||||
unset_property = {key: None for key in parsed_args.property}
|
unset_property = {}
|
||||||
compute_client.aggregates.set_metadata(aggregate,
|
if parsed_args.property:
|
||||||
unset_property)
|
unset_property.update({key: None for key in parsed_args.property})
|
||||||
|
if unset_property:
|
||||||
|
compute_client.aggregates.set_metadata(aggregate,
|
||||||
|
unset_property)
|
||||||
|
@ -83,6 +83,7 @@ class FakeAggregate(object):
|
|||||||
"id": "aggregate-id-" + uuid.uuid4().hex,
|
"id": "aggregate-id-" + uuid.uuid4().hex,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"availability_zone": "ag_zone",
|
"availability_zone": "ag_zone",
|
||||||
|
"key1": "value1",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ from osc_lib import utils
|
|||||||
|
|
||||||
from openstackclient.compute.v2 import aggregate
|
from openstackclient.compute.v2 import aggregate
|
||||||
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
|
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
|
||||||
from openstackclient.tests.unit import utils as tests_utils
|
|
||||||
|
|
||||||
|
|
||||||
class TestAggregate(compute_fakes.TestComputev2):
|
class TestAggregate(compute_fakes.TestComputev2):
|
||||||
@ -235,7 +234,8 @@ class TestAggregateList(TestAggregate):
|
|||||||
TestAggregate.fake_ag.id,
|
TestAggregate.fake_ag.id,
|
||||||
TestAggregate.fake_ag.name,
|
TestAggregate.fake_ag.name,
|
||||||
TestAggregate.fake_ag.availability_zone,
|
TestAggregate.fake_ag.availability_zone,
|
||||||
{},
|
{key: value for key, value in TestAggregate.fake_ag.metadata.items()
|
||||||
|
if key != 'availability_zone'},
|
||||||
), )
|
), )
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -371,6 +371,62 @@ class TestAggregateSet(TestAggregate):
|
|||||||
self.fake_ag, parsed_args.property)
|
self.fake_ag, parsed_args.property)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_aggregate_set_with_no_property_and_property(self):
|
||||||
|
arglist = [
|
||||||
|
'--no-property',
|
||||||
|
'--property', 'key2=value2',
|
||||||
|
'ag1',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('no_property', True),
|
||||||
|
('property', {'key2': 'value2'}),
|
||||||
|
('aggregate', 'ag1'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.aggregate_mock.get.assert_called_once_with(parsed_args.aggregate)
|
||||||
|
self.assertNotCalled(self.aggregate_mock.update)
|
||||||
|
self.aggregate_mock.set_metadata.assert_called_once_with(
|
||||||
|
self.fake_ag, {'key1': None, 'key2': 'value2'})
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_aggregate_set_with_no_property(self):
|
||||||
|
arglist = [
|
||||||
|
'--no-property',
|
||||||
|
'ag1',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('no_property', True),
|
||||||
|
('aggregate', 'ag1'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.aggregate_mock.get.assert_called_once_with(parsed_args.aggregate)
|
||||||
|
self.assertNotCalled(self.aggregate_mock.update)
|
||||||
|
self.aggregate_mock.set_metadata.assert_called_once_with(
|
||||||
|
self.fake_ag, {'key1': None})
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_aggregate_set_with_zone_and_no_property(self):
|
||||||
|
arglist = [
|
||||||
|
'--zone', 'new_zone',
|
||||||
|
'--no-property',
|
||||||
|
'ag1',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('zone', 'new_zone'),
|
||||||
|
('no_property', True),
|
||||||
|
('aggregate', 'ag1'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.aggregate_mock.get.assert_called_once_with(parsed_args.aggregate)
|
||||||
|
self.aggregate_mock.update.assert_called_once_with(
|
||||||
|
self.fake_ag, {'availability_zone': parsed_args.zone})
|
||||||
|
self.aggregate_mock.set_metadata.assert_called_once_with(
|
||||||
|
self.fake_ag, {'key1': None})
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
|
||||||
class TestAggregateShow(TestAggregate):
|
class TestAggregateShow(TestAggregate):
|
||||||
|
|
||||||
@ -387,7 +443,10 @@ class TestAggregateShow(TestAggregate):
|
|||||||
TestAggregate.fake_ag.hosts,
|
TestAggregate.fake_ag.hosts,
|
||||||
TestAggregate.fake_ag.id,
|
TestAggregate.fake_ag.id,
|
||||||
TestAggregate.fake_ag.name,
|
TestAggregate.fake_ag.name,
|
||||||
'',
|
utils.format_dict(
|
||||||
|
{key: value
|
||||||
|
for key, value in TestAggregate.fake_ag.metadata.items()
|
||||||
|
if key != 'availability_zone'}),
|
||||||
)
|
)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -435,13 +494,32 @@ class TestAggregateUnset(TestAggregate):
|
|||||||
self.fake_ag, {'unset_key': None})
|
self.fake_ag, {'unset_key': None})
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
def test_aggregate_unset_no_property(self):
|
def test_aggregate_unset_multiple_properties(self):
|
||||||
|
arglist = [
|
||||||
|
'--property', 'unset_key1',
|
||||||
|
'--property', 'unset_key2',
|
||||||
|
'ag1',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('property', ['unset_key1', 'unset_key2']),
|
||||||
|
('aggregate', 'ag1'),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.aggregate_mock.set_metadata.assert_called_once_with(
|
||||||
|
self.fake_ag, {'unset_key1': None, 'unset_key2': None})
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_aggregate_unset_no_option(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
'ag1',
|
'ag1',
|
||||||
]
|
]
|
||||||
verifylist = None
|
verifylist = [
|
||||||
self.assertRaises(tests_utils.ParserException,
|
('property', None),
|
||||||
self.check_parser,
|
('aggregate', 'ag1'),
|
||||||
self.cmd,
|
]
|
||||||
arglist,
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
verifylist)
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.assertNotCalled(self.aggregate_mock.set_metadata)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``--no-property`` option in ``aggregate set``.
|
||||||
|
Supporting ``--no-property`` option will apply user a convenience way to
|
||||||
|
clean all properties of aggregate in a short command.
|
||||||
|
[Blueprint `support-no-property-in-aggregate <https://blueprints.launchpad.net/python-openstackclient/+spec/support-no-property-in-aggregate>`_]
|
Loading…
x
Reference in New Issue
Block a user