Merge "Implement Update Plan for the OpenStack client"

This commit is contained in:
Jenkins 2015-05-11 15:57:14 +00:00 committed by Gerrit Code Review
commit 0d94ef552f
5 changed files with 232 additions and 5 deletions

View File

@ -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

View File

@ -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."""

View File

@ -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)

View File

@ -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):

View File

@ -244,7 +244,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)