diff --git a/heatclient/osc/v1/resource.py b/heatclient/osc/v1/resource.py index 7c12c756..7f9d1b2d 100644 --- a/heatclient/osc/v1/resource.py +++ b/heatclient/osc/v1/resource.py @@ -249,3 +249,51 @@ def _resource_signal(heat_client, args): 'not found.') % {'stack': args.stack, 'resource': args.resource}) + + +class ResourceMarkUnhealthy(command.Command): + """Set resource's health.""" + + log = logging.getLogger(__name__ + ".ResourceMarkUnhealthy") + + def get_parser(self, prog_name): + parser = super(ResourceMarkUnhealthy, self).get_parser(prog_name) + parser.add_argument( + 'stack', + metavar='', + help=_('Name or ID of stack the resource belongs to') + ) + parser.add_argument( + 'resource', + metavar='', + help=_('Name of the resource') + ) + parser.add_argument( + 'reason', + default="", + nargs='?', + help=_('Reason for state change') + ) + parser.add_argument( + '--reset', + default=False, + action="store_true", + help=_('Set the resource as healthy') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + heat_client = self.app.client_manager.orchestration + fields = {'stack_id': parsed_args.stack, + 'resource_name': parsed_args.resource, + 'mark_unhealthy': not parsed_args.reset, + 'resource_status_reason': parsed_args.reason} + try: + heat_client.resources.mark_unhealthy(**fields) + except heat_exc.HTTPNotFound: + raise exc.CommandError(_('Stack or resource not found: ' + '%(id)s %(resource)s') % + {'id': parsed_args.stack, + 'resource': parsed_args.resource}) diff --git a/heatclient/tests/unit/osc/v1/test_resource.py b/heatclient/tests/unit/osc/v1/test_resource.py index 1807942a..337d284c 100644 --- a/heatclient/tests/unit/osc/v1/test_resource.py +++ b/heatclient/tests/unit/osc/v1/test_resource.py @@ -322,3 +322,43 @@ class TestResourceSignal(TestResource): 'stack_id': 'my_stack', 'resource_name': 'my_resource' }) + + +class TestResourceMarkUnhealthy(TestResource): + def setUp(self): + super(TestResourceMarkUnhealthy, self).setUp() + self.cmd = resource.ResourceMarkUnhealthy(self.app, None) + self.resource_client.mark_unhealthy = mock.Mock() + + def test_resource_mark_unhealthy(self): + arglist = ['my_stack', 'my_resource', 'reason'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.resource_client.mark_unhealthy.assert_called_with(**{ + "stack_id": "my_stack", + "resource_name": "my_resource", + "mark_unhealthy": True, + "resource_status_reason": "reason" + }) + + def test_resource_mark_unhealthy_reset(self): + arglist = ['my_stack', 'my_resource', '--reset'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.resource_client.mark_unhealthy.assert_called_with(**{ + "stack_id": "my_stack", + "resource_name": "my_resource", + "mark_unhealthy": False, + "resource_status_reason": "" + }) + + def test_resource_mark_unhealthy_not_found(self): + arglist = ['my_stack', 'my_resource', '--reset'] + self.resource_client.mark_unhealthy.side_effect = ( + heat_exc.HTTPNotFound) + parsed_args = self.check_parser(self.cmd, arglist, []) + + error = self.assertRaises(exc.CommandError, + self.cmd.take_action, parsed_args) + self.assertEqual('Stack or resource not found: my_stack my_resource', + str(error)) diff --git a/setup.cfg b/setup.cfg index 367af4bb..4d2d7de0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,7 @@ openstack.orchestration.v1 = stack_output_list = heatclient.osc.v1.stack:OutputListStack stack_output_show = heatclient.osc.v1.stack:OutputShowStack stack_resource_list = heatclient.osc.v1.resource:ResourceList + stack_resource_mark_unhealthy = heatclient.osc.v1.resource:ResourceMarkUnhealthy stack_resource_metadata = heatclient.osc.v1.resource:ResourceMetadata stack_resource_show = heatclient.osc.v1.resource:ResourceShow stack_resource_signal = heatclient.osc.v1.resource:ResourceSignal