Implement Update Plan for the OpenStack client

Change-Id: I47a052c5b66828faec5f6ddc788b0834cb276c3e
This commit is contained in:
Dougal Matthews 2015-04-30 12:57:36 +01:00
parent 83a1592a25
commit dd5036e26e
5 changed files with 232 additions and 5 deletions

View File

@ -15,6 +15,7 @@
from __future__ import print_function from __future__ import print_function
import sys
import uuid import uuid
from oslo_utils import importutils from oslo_utils import importutils
@ -116,7 +117,7 @@ def format_key_value(params):
yield name, value yield name, value
def format_attributes(params): def format_key_value_args(params):
"""Reformat CLI attributes into the structure expected by the API. """Reformat CLI attributes into the structure expected by the API.
The format expected by the API for attributes is a dictionary consisting The format expected by the API for attributes is a dictionary consisting
@ -135,3 +136,33 @@ def format_attributes(params):
attributes[key] = value attributes[key] = value
return attributes 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 # License for the specific language governing permissions and limitations
# under the License. # under the License.
from __future__ import print_function
import logging import logging
import sys
from cliff import command from cliff import command
from cliff import lister from cliff import lister
from cliff import show from cliff import show
from tuskarclient.common import utils
class CreateManagementPlan(show.ShowOne): class CreateManagementPlan(show.ShowOne):
"""Create a Management Plan.""" """Create a Management Plan."""
@ -103,11 +108,57 @@ class SetManagementPlan(show.ShowOne):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(SetManagementPlan, self).get_parser(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 return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % 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): class ShowManagementPlan(show.ShowOne):
"""Show a Management Plan.""" """Show a Management Plan."""

View File

@ -96,3 +96,59 @@ class FindResourceTest(test_utils.TestCase):
utils.find_resource, utils.find_resource,
self.manager, self.manager,
'My Overcloud 2') '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() super(TestSetManagementPlan, self).setUp()
self.cmd = plan.SetManagementPlan(self.app, None) self.cmd = plan.SetManagementPlan(self.app, None)
def test_update_plan(self): def test_update_plan_nothing(self):
arglist = [] arglist = ['UUID1', ]
verifylist = [] 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) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args) 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): class TestShowManagementPlan(TestPlans):

View File

@ -232,7 +232,7 @@ def do_plan_update(tuskar, args, outfile=sys.stdout):
parameters = [{'name': pair[0], 'value': pair[1]} parameters = [{'name': pair[0], 'value': pair[1]}
for pair for pair
in utils.format_attributes(parameters).items()] in utils.format_key_value_args(parameters).items()]
return tuskar.plans.patch(args.plan_uuid, parameters) return tuskar.plans.patch(args.plan_uuid, parameters)