Enable specified project_id in CLI commands
After we port to oslo-incubator.apiclient, the project_id can no
longer be specified for alarm-{,threhsold,combination}-{create,update}
and sample-create, this is because client.AuthPlugin registers a CLI
argument named --os-project-id which will shadow the project-id
argument.
Since os-project-id is used for Keystone V3 API, we should not
remove it from AuthPlugin, so this patch moves the dest of project_id
to {alarm,sample}_project_id, and adds a decorator to restore shadowed
project_id field when we call v2 client.
Change-Id: I0ce2416dccd61eb50584799e6df0b8c45d44cdda
Closes-Bug: #1393489
(cherry picked from commit 0c23c62cef)
			
			
This commit is contained in:
		 ZhiQiang Fan
					ZhiQiang Fan
				
			
				
					committed by
					
						 gordon chung
						gordon chung
					
				
			
			
				
	
			
			
			 gordon chung
						gordon chung
					
				
			
						parent
						
							1b346fb647
						
					
				
				
					commit
					40d7913cee
				
			| @@ -24,6 +24,7 @@ from testtools import matchers | ||||
|  | ||||
| from ceilometerclient import exc | ||||
| from ceilometerclient import shell as base_shell | ||||
| from ceilometerclient.tests import test_shell | ||||
| from ceilometerclient.tests import utils | ||||
| from ceilometerclient.v2 import alarms | ||||
| from ceilometerclient.v2 import events | ||||
| @@ -1119,3 +1120,56 @@ class ShellEventListCommandTest(utils.BaseTestCase): | ||||
| +--------------------------------------+-------------------------------\ | ||||
| +----------------------------+ | ||||
| ''', sys.stdout.getvalue()) | ||||
|  | ||||
|  | ||||
| class ShellShadowedArgsTest(test_shell.ShellTestBase): | ||||
|  | ||||
|     def _test_project_id_alarm(self, command, args, method): | ||||
|         self.make_env(test_shell.FAKE_V2_ENV) | ||||
|         cli_args = [ | ||||
|             '--os-project-id', '0ba30185ddf44834914a0b859d244c56', | ||||
|             '--debug', command, | ||||
|             '--project-id', 'the-project-id-i-want-to-set', | ||||
|             '--name', 'project-id-test'] + args | ||||
|         with mock.patch.object(alarms.AlarmManager, method) as mocked: | ||||
|             base_shell.main(cli_args) | ||||
|         args, kwargs = mocked.call_args | ||||
|         self.assertEqual('the-project-id-i-want-to-set', | ||||
|                          kwargs.get('project_id')) | ||||
|  | ||||
|     def test_project_id_threshold_alarm(self): | ||||
|         cli_args = ['--meter-name', 'cpu', '--threshold', '90'] | ||||
|         self._test_project_id_alarm('alarm-create', cli_args, 'create') | ||||
|         self._test_project_id_alarm('alarm-threshold-create', | ||||
|                                     cli_args, 'create') | ||||
|         cli_args += ['--alarm_id', '437b7ed0-3733-4054-a877-e9a297b8be85'] | ||||
|         self._test_project_id_alarm('alarm-update', cli_args, 'update') | ||||
|         self._test_project_id_alarm('alarm-threshold-update', | ||||
|                                     cli_args, 'update') | ||||
|  | ||||
|     def test_project_id_combination_alarm(self): | ||||
|         cli_args = ['--alarm_ids', 'fb16a05a-669d-414e-8bbe-93aa381df6a8', | ||||
|                     '--alarm_ids', 'b189bcca-0a7b-49a9-a244-a927ac291881'] | ||||
|         self._test_project_id_alarm('alarm-combination-create', | ||||
|                                     cli_args, 'create') | ||||
|         cli_args += ['--alarm_id', '437b7ed0-3733-4054-a877-e9a297b8be85'] | ||||
|         self._test_project_id_alarm('alarm-combination-update', | ||||
|                                     cli_args, 'update') | ||||
|  | ||||
|     @mock.patch.object(samples.OldSampleManager, 'create') | ||||
|     def test_project_id_sample_create(self, mocked): | ||||
|         self.make_env(test_shell.FAKE_V2_ENV) | ||||
|         cli_args = [ | ||||
|             '--os-project-id', '0ba30185ddf44834914a0b859d244c56', | ||||
|             '--debug', 'sample-create', | ||||
|             '--project-id', 'the-project-id-i-want-to-set', | ||||
|             '--resource-id', 'b666633d-9bb6-4e05-89c0-ee5a8752fb0b', | ||||
|             '--meter-name', 'cpu', | ||||
|             '--meter-type', 'cumulative', | ||||
|             '--meter-unit', 'ns', | ||||
|             '--sample-volume', '10086', | ||||
|         ] | ||||
|         base_shell.main(cli_args) | ||||
|         args, kwargs = mocked.call_args | ||||
|         self.assertEqual('the-project-id-i-want-to-set', | ||||
|                          kwargs.get('project_id')) | ||||
|   | ||||
| @@ -181,10 +181,22 @@ def do_sample_show(cc, args): | ||||
|     utils.print_dict(data, wrap=72) | ||||
|  | ||||
|  | ||||
| @utils.arg('--project-id', metavar='<PROJECT_ID>', | ||||
| def _restore_shadowed_arg(shadowed, observed): | ||||
|     def wrapper(func): | ||||
|         @functools.wraps(func) | ||||
|         def wrapped(cc, args): | ||||
|             v = getattr(args, observed, None) | ||||
|             setattr(args, shadowed, v) | ||||
|             return func(cc, args) | ||||
|         return wrapped | ||||
|     return wrapper | ||||
|  | ||||
|  | ||||
| @utils.arg('--project-id', metavar='<SAMPLE_PROJECT_ID>', | ||||
|            dest='sample_project_id', | ||||
|            help='Tenant to associate with sample ' | ||||
|                 '(only settable by admin users).') | ||||
| @utils.arg('--user-id', metavar='<USER_ID>', | ||||
| @utils.arg('--user-id', metavar='<SAMPLE_USER_ID>', | ||||
|            help='User to associate with sample ' | ||||
|                 '(only settable by admin users).') | ||||
| @utils.arg('-r', '--resource-id', metavar='<RESOURCE_ID>', required=True, | ||||
| @@ -202,12 +214,15 @@ def do_sample_show(cc, args): | ||||
|                 'key-value pairs e.g. {"key":"value"}.') | ||||
| @utils.arg('--timestamp', metavar='<TIMESTAMP>', | ||||
|            help='The sample timestamp.') | ||||
| @_restore_shadowed_arg('project_id', 'sample_project_id') | ||||
| def do_sample_create(cc, args={}): | ||||
|     """Create a sample.""" | ||||
|     arg_to_field_mapping = {'meter_name': 'counter_name', | ||||
|     arg_to_field_mapping = { | ||||
|         'meter_name': 'counter_name', | ||||
|         'meter_unit': 'counter_unit', | ||||
|         'meter_type': 'counter_type', | ||||
|                             'sample_volume': 'counter_volume'} | ||||
|         'sample_volume': 'counter_volume', | ||||
|     } | ||||
|     fields = {} | ||||
|     for var in vars(args).items(): | ||||
|         k, v = var[0], var[1] | ||||
| @@ -397,10 +412,11 @@ def common_alarm_arguments(create=False): | ||||
|     def _wrapper(func): | ||||
|         @utils.arg('--name', metavar='<NAME>', required=create, | ||||
|                    help='Name of the alarm (must be unique per tenant).') | ||||
|         @utils.arg('--project-id', metavar='<PROJECT_ID>', | ||||
|         @utils.arg('--project-id', metavar='<ALARM_PROJECT_ID>', | ||||
|                    dest='alarm_project_id', | ||||
|                    help='Tenant to associate with alarm ' | ||||
|                    '(only settable by admin users).') | ||||
|         @utils.arg('--user-id', metavar='<USER_ID>', | ||||
|         @utils.arg('--user-id', metavar='<ALARM_USER_ID>', | ||||
|                    help='User to associate with alarm ' | ||||
|                    '(only settable by admin users).') | ||||
|         @utils.arg('--description', metavar='<DESCRIPTION>', | ||||
| @@ -559,6 +575,7 @@ def common_alarm_gnocchi_resources_arguments(create=False): | ||||
|            default=False, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_create(cc, args={}): | ||||
|     """Create a new alarm (Deprecated). Use alarm-threshold-create instead.""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
| @@ -639,6 +656,7 @@ def do_alarm_gnocchi_aggregation_by_resources_threshold_create(cc, args={}): | ||||
|            default=False, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_threshold_create(cc, args={}): | ||||
|     """Create a new alarm based on computed statistics.""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
| @@ -665,6 +683,7 @@ def do_alarm_threshold_create(cc, args={}): | ||||
|            default=False, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_combination_create(cc, args={}): | ||||
|     """Create a new alarm based on state of other alarms.""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
| @@ -706,6 +725,7 @@ def do_alarm_combination_create(cc, args={}): | ||||
|            metavar='{True|False}', type=strutils.bool_from_string, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_update(cc, args={}): | ||||
|     """Update an existing alarm (Deprecated).""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
| @@ -757,6 +777,7 @@ def do_alarm_update(cc, args={}): | ||||
|            metavar='{True|False}', type=strutils.bool_from_string, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_threshold_update(cc, args={}): | ||||
|     """Update an existing alarm based on computed statistics.""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
| @@ -875,6 +896,7 @@ def do_alarm_gnocchi_aggregation_by_resources_threshold_update(cc, args={}): | ||||
|            metavar='{True|False}', type=strutils.bool_from_string, | ||||
|            help=('True if actions should be repeatedly notified ' | ||||
|                  'while alarm remains in target state.')) | ||||
| @_restore_shadowed_arg('project_id', 'alarm_project_id') | ||||
| def do_alarm_combination_update(cc, args={}): | ||||
|     """Update an existing alarm based on state of other alarms.""" | ||||
|     fields = dict(filter(lambda x: not (x[1] is None), vars(args).items())) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user