Implement Update Plan for the OpenStack client
Change-Id: I47a052c5b66828faec5f6ddc788b0834cb276c3e
This commit is contained in:
parent
83a1592a25
commit
dd5036e26e
@ -15,6 +15,7 @@
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
from oslo_utils import importutils
|
||||
@ -116,7 +117,7 @@ def format_key_value(params):
|
||||
yield name, value
|
||||
|
||||
|
||||
def format_attributes(params):
|
||||
def format_key_value_args(params):
|
||||
"""Reformat CLI attributes into the structure expected by the API.
|
||||
|
||||
The format expected by the API for attributes is a dictionary consisting
|
||||
@ -135,3 +136,33 @@ def format_attributes(params):
|
||||
attributes[key] = value
|
||||
|
||||
return attributes
|
||||
|
||||
|
||||
def parameters_args_to_patch(parameters):
|
||||
"""Create a list of patch dicts to update the parameters in the API."""
|
||||
|
||||
return [{'name': pair[0], 'value': pair[1]}
|
||||
for pair in sorted(format_key_value_args(parameters).items())]
|
||||
|
||||
|
||||
def args_to_patch(flavors, roles, parameter):
|
||||
"""Create a list of dicts to update the given parameter in the API."""
|
||||
|
||||
role_flavors_dict = format_key_value_args(flavors)
|
||||
|
||||
roles = dict(("{0}-{1}".format(r.name, r.version), r) for r in roles)
|
||||
patch = []
|
||||
|
||||
for role_name, flavor in sorted(role_flavors_dict.items()):
|
||||
|
||||
if role_name in roles:
|
||||
patch.append({
|
||||
'name': "{0}::{1}".format(role_name, parameter),
|
||||
'value': flavor
|
||||
})
|
||||
else:
|
||||
print("ERROR: no roles were found in the Plan with the name {0}".
|
||||
format(role_name), file=sys.stderr)
|
||||
continue
|
||||
|
||||
return patch
|
||||
|
@ -10,12 +10,17 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from tuskarclient.common import utils
|
||||
|
||||
|
||||
class CreateManagementPlan(show.ShowOne):
|
||||
"""Create a Management Plan."""
|
||||
@ -103,11 +108,57 @@ class SetManagementPlan(show.ShowOne):
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(SetManagementPlan, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'plan_uuid',
|
||||
help="The UUID of the plan being updated."
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-P', '--parameter', dest='parameters', metavar='<KEY1=VALUE1>',
|
||||
help=('Set a parameter in the Plan. This can be specified '
|
||||
'multiple times.'),
|
||||
action='append'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-F', '--flavor', dest='flavors', metavar='<ROLE=FLAVOR>',
|
||||
help=('Set the flavor for a role in the Plan. This can be '
|
||||
'specified multiple times.'),
|
||||
action='append'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-S', '--scale', dest='scales', metavar='<ROLE=SCALE-COUNT>',
|
||||
help=('Set the Scale count for a role in the Plan. This can be '
|
||||
'specified multiple times.'),
|
||||
action='append'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
|
||||
client = self.app.client_manager.management
|
||||
|
||||
plan = client.plans.get(parsed_args.plan_uuid)
|
||||
roles = plan.roles
|
||||
|
||||
patch = []
|
||||
|
||||
patch.extend(utils.parameters_args_to_patch(parsed_args.parameters))
|
||||
patch.extend(utils.args_to_patch(parsed_args.flavors, roles, "Flavor"))
|
||||
patch.extend(utils.args_to_patch(parsed_args.scales, roles, "count"))
|
||||
|
||||
if len(patch) > 0:
|
||||
plan = client.plans.patch(parsed_args.plan_uuid, patch)
|
||||
else:
|
||||
print(("WARNING: No valid arguments passed. No update operation "
|
||||
"has been performed."), file=sys.stderr)
|
||||
|
||||
return self.dict2columns(plan.to_dict())
|
||||
|
||||
|
||||
class ShowManagementPlan(show.ShowOne):
|
||||
"""Show a Management Plan."""
|
||||
|
@ -96,3 +96,59 @@ class FindResourceTest(test_utils.TestCase):
|
||||
utils.find_resource,
|
||||
self.manager,
|
||||
'My Overcloud 2')
|
||||
|
||||
|
||||
class ParseCLIArgsTest(test_utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ParseCLIArgsTest, self).setUp()
|
||||
|
||||
self.mock_role1 = mock.Mock()
|
||||
self.mock_role1.configure_mock(name="role1", version=1)
|
||||
|
||||
self.mock_role2 = mock.Mock()
|
||||
self.mock_role2.configure_mock(name="role2", version=2)
|
||||
|
||||
self.roles = [self.mock_role1, self.mock_role2]
|
||||
|
||||
def test_parameters_args_to_patch(self):
|
||||
|
||||
args = [
|
||||
"parameter1=value1",
|
||||
"parameter2=value2",
|
||||
]
|
||||
|
||||
result = utils.parameters_args_to_patch(args)
|
||||
|
||||
self.assertEqual([
|
||||
{'name': 'parameter1', 'value': 'value1'},
|
||||
{'name': 'parameter2', 'value': 'value2'},
|
||||
], result)
|
||||
|
||||
def test_flavors_args_to_patch(self):
|
||||
|
||||
args = [
|
||||
"role1-1=flavor1",
|
||||
"role2-2=flavor2",
|
||||
]
|
||||
|
||||
result = utils.args_to_patch(args, self.roles, "Flavor")
|
||||
|
||||
self.assertEqual([
|
||||
{'name': 'role1-1::Flavor', 'value': 'flavor1'},
|
||||
{'name': 'role2-2::Flavor', 'value': 'flavor2'}
|
||||
], result)
|
||||
|
||||
def test_scale_args_to_patch(self):
|
||||
|
||||
args = [
|
||||
"role1-1=1",
|
||||
"role2-2=2",
|
||||
]
|
||||
|
||||
result = utils.args_to_patch(args, self.roles, "count")
|
||||
|
||||
self.assertEqual([
|
||||
{'name': 'role1-1::count', 'value': '1'},
|
||||
{'name': 'role2-2::count', 'value': '2'}
|
||||
], result)
|
||||
|
@ -115,14 +115,103 @@ class TestSetManagementPlan(TestPlans):
|
||||
super(TestSetManagementPlan, self).setUp()
|
||||
self.cmd = plan.SetManagementPlan(self.app, None)
|
||||
|
||||
def test_update_plan(self):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
def test_update_plan_nothing(self):
|
||||
arglist = ['UUID1', ]
|
||||
verifylist = [
|
||||
('plan_uuid', "UUID1"),
|
||||
('parameters', None),
|
||||
('flavors', None),
|
||||
('scales', None),
|
||||
]
|
||||
|
||||
self.management_mock.plans.get.return_value = fakes.mock_plans[1]
|
||||
self.management_mock.plans.patch.return_value = fakes.mock_plans[1]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.management_mock.plans.patch.assert_not_called()
|
||||
|
||||
def test_update_plan_parameters(self):
|
||||
arglist = ['UUID1', '-P', 'A=1', '-P', 'B=2']
|
||||
verifylist = [
|
||||
('plan_uuid', "UUID1"),
|
||||
('parameters', ['A=1', 'B=2']),
|
||||
('flavors', None),
|
||||
('scales', None),
|
||||
]
|
||||
|
||||
self.management_mock.plans.get.return_value = fakes.mock_plans[1]
|
||||
self.management_mock.plans.patch.return_value = fakes.mock_plans[1]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertEqual([
|
||||
('description', 'name', 'roles', 'uuid'),
|
||||
('Plan 2', 'Plan 2 Name', [], 'UUID2')
|
||||
], list(result))
|
||||
|
||||
self.management_mock.plans.patch.assert_called_with('UUID1', [
|
||||
{'value': '1', 'name': 'A'},
|
||||
{'value': '2', 'name': 'B'}
|
||||
])
|
||||
|
||||
def test_update_plan_flavors(self):
|
||||
arglist = ['UUID1', '-F', 'Role 1 Name-1=strawberry',
|
||||
'-F', 'Role 2 Name-2=cherry']
|
||||
verifylist = [
|
||||
('plan_uuid', "UUID1"),
|
||||
('parameters', None),
|
||||
('flavors', ['Role 1 Name-1=strawberry', 'Role 2 Name-2=cherry']),
|
||||
('scales', None),
|
||||
]
|
||||
|
||||
self.management_mock.plans.get.return_value = fakes.mock_plans[0]
|
||||
self.management_mock.plans.patch.return_value = fakes.mock_plans[1]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertEqual([
|
||||
('description', 'name', 'roles', 'uuid'),
|
||||
('Plan 2', 'Plan 2 Name', [], 'UUID2')
|
||||
], list(result))
|
||||
|
||||
self.management_mock.plans.patch.assert_called_with('UUID1', [
|
||||
{'value': 'strawberry', 'name': 'Role 1 Name-1::Flavor'},
|
||||
{'value': 'cherry', 'name': 'Role 2 Name-2::Flavor'}
|
||||
])
|
||||
|
||||
def test_update_plan_scale(self):
|
||||
arglist = ['UUID1', '-S', 'Role 1 Name-1=2', '-S', 'Role 2 Name-2=3']
|
||||
verifylist = [
|
||||
('plan_uuid', "UUID1"),
|
||||
('parameters', None),
|
||||
('flavors', None),
|
||||
('scales', ['Role 1 Name-1=2', 'Role 2 Name-2=3']),
|
||||
]
|
||||
|
||||
self.management_mock.plans.get.return_value = fakes.mock_plans[0]
|
||||
self.management_mock.plans.patch.return_value = fakes.mock_plans[1]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertEqual([
|
||||
('description', 'name', 'roles', 'uuid'),
|
||||
('Plan 2', 'Plan 2 Name', [], 'UUID2')
|
||||
], list(result))
|
||||
|
||||
self.management_mock.plans.patch.assert_called_with('UUID1', [
|
||||
{'value': '2', 'name': 'Role 1 Name-1::count'},
|
||||
{'value': '3', 'name': 'Role 2 Name-2::count'}
|
||||
])
|
||||
|
||||
|
||||
class TestShowManagementPlan(TestPlans):
|
||||
|
||||
|
@ -232,7 +232,7 @@ def do_plan_update(tuskar, args, outfile=sys.stdout):
|
||||
|
||||
parameters = [{'name': pair[0], 'value': pair[1]}
|
||||
for pair
|
||||
in utils.format_attributes(parameters).items()]
|
||||
in utils.format_key_value_args(parameters).items()]
|
||||
return tuskar.plans.patch(args.plan_uuid, parameters)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user