def testRunWithResponseAttribute(self): class Good(object): def __init__(self): self.b = 1 class Response(object): def __init__(self, a): self.a = a response = Response(Good()) self.Expect(response=response) d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) d.response.result_attribute = 'a' cli = self.MakeCLI(d) self.assertEqual( response.a, cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i'])) self.Expect(response=Response(None)) d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) d.response.result_attribute = 'a.b' cli = self.MakeCLI(d) self.assertEqual( None, cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']))
def testCommandData(self): c = yaml_command_schema.CommandData( 'describe', { 'help_text': {}, 'request': { 'collection': 'foo.instances' }, 'response': {}, 'arguments': { 'params': [] }, 'input': { 'confirmation_prompt': 'asdf' }, 'output': { 'format': 'yaml' } }) self.assertEqual(c.hidden, False) self.assertEqual(c.release_tracks, []) self.assertEqual(c.command_type, yaml_command_schema.CommandType.DESCRIBE) self.assertEqual(c.help_text, {}) self.assertEqual(c.request.collection, 'foo.instances') self.assertEqual(c.response.result_attribute, None) self.assertEqual(c.response.error, None) self.assertEqual(c.async_, None) self.assertEqual(c.arguments.params, []) self.assertEqual(c.input.confirmation_prompt, 'asdf') self.assertEqual(c.output.format, 'yaml') c = yaml_command_schema.CommandData( 'describe', { 'hidden': True, 'release_tracks': ['GA', 'BETA'], 'help_text': {}, 'request': { 'collection': 'foo.instances', 'parse_resource_into_request': False }, 'async': { 'collection': 'operations' }, 'arguments': { 'params': [] }, 'output': { 'format': 'yaml' } }) self.assertEqual(c.hidden, True) self.assertFalse(c.request.parse_resource_into_request) self.assertEqual( c.release_tracks, [calliope_base.ReleaseTrack.GA, calliope_base.ReleaseTrack.BETA]) self.assertEqual(c.async_.method, 'get')
def testRunWithResponseErrorHandler(self): class Good(object): c = 2 d = 3 class Error(object): code = 10 message = 'message' class Bad(object): error = Error class Response(object): a = 1 b = [Good, Bad] self.Expect(response=Response) d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) d.response = yaml_command_schema.Response({ 'error': { 'field': 'b.error', 'code': 'code', 'message': 'message' } }) cli = self.MakeCLI(d) with self.assertRaises(SystemExit): cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.AssertErrContains('Code: [10] Message: [message]')
def testRun(self): _, done_response = self.Expect() spec = {'name': 'operation', 'collection': 'compute.zoneOperations', 'attributes': [ {'parameter_name': 'zone', 'attribute_name': 'zone', 'help': 'the zone'}, {'parameter_name': 'operation', 'attribute_name': 'operation', 'help': 'the op'}]} data = { 'help_text': {'brief': 'brief help'}, 'request': {'collection': 'compute.zoneOperations'}, 'arguments': { 'resource': { 'help_text': 'help', 'spec': spec}}, 'async': {'collection': 'compute.zoneOperations', 'state': {'field': 'status', 'success_values': ['DONE']}} } d = yaml_command_schema.CommandData('wait', data) cli = self.MakeCLI(d) self.AssertArgs(cli, 'OPERATION', '--zone') result = cli.Execute( ['command', '--project', 'p', '--zone', 'z', 'operation-12345']) self.AssertErrContains( 'Waiting for operation [projects/p/zones/z/operations/operation-12345] ' 'to complete') self.AssertOutputEquals(""" id: '12345' name: operation-12345 selfLink: https://www.googleapis.com/compute/v1/projects/p/zones/z/operations/operation-12345 status: DONE """.lstrip('\n'), normalize_space=True) self.assertEqual(result, done_response)
def testCommandDataErrors(self): with self.assertRaisesRegex( util.InvalidSchemaError, 'Wait commands must include an async section.'): yaml_command_schema.CommandData( 'wait', {'help_text': {}, 'request': {'collection': 'foo.instances'}})
def testGlobalAttributes(self): d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) d.hidden = True d.release_tracks = [ calliope_base.ReleaseTrack.GA, calliope_base.ReleaseTrack.BETA ] cb = yaml_command_translator.CommandBuilder(d, ['abc', 'xyz', 'describe']) class TempCommand(calliope_base.Command): pass cb._ConfigureGlobalAttributes(TempCommand) self.assertEqual(TempCommand.IsHidden(), True) self.assertEqual( TempCommand.ValidReleaseTracks(), {calliope_base.ReleaseTrack.GA, calliope_base.ReleaseTrack.BETA}) self.assertEqual( TempCommand.detailed_help, { 'brief': 'brief help', 'API REFERENCE': 'This command uses the *foo/v1* API. The full ' 'documentation for this API can be found at: ' 'https://cloud.google.com/docs' })
def testRunNoOperationMethod(self): """Test for when the API doesn't return an LRO.""" running_response, _ = self.Expect(is_async=True) data = self.MakeCommandData() data['request']['method'] = 'setTags' data['arguments']['params'] = [{ 'api_field': 'tags.items', 'arg_name': 'tags', 'help_text': 'the tags' }] d = yaml_command_schema.CommandData('set-tags', data) cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone', '--tags') result = cli.Execute([ 'command', '--project', 'p', '--zone', 'z', 'i', '--tags', 'foo,bar' ]) self.AssertOutputEquals(""" id: '12345' name: operation-12345 selfLink: https://www.googleapis.com/compute/v1/projects/p/zones/z/operations/operation-12345 status: RUNNING """.lstrip('\n'), normalize_space=True) self.assertEqual(result, running_response)
def testRunNoOperationMethod(self): """Test for when the API doesn't return an LRO.""" self.mocked_client.projects_instances.Patch.Expect( request=(self.messages.SpannerProjectsInstancesPatchRequest( name='projects/p/instances/i', updateInstanceRequest=self.messages.UpdateInstanceRequest( instance=self.messages.Instance( nodeCount=2, displayName='aaaa'), fieldMask='displayName,nodeCount'))), response='new instance', enable_type_checking=False) data = self._MakeUpdateCommandData() data['request']['method'] = 'patch' data['arguments']['params'] = [{ 'api_field': 'updateInstanceRequest.instance.nodeCount', 'arg_name': 'nodes', 'help_text': 'the number of the nodes of the instance to update' }, { 'api_field': 'updateInstanceRequest.instance.displayName', 'arg_name': 'description', 'help_text': 'the description of the instance' }] d = yaml_command_schema.CommandData('update', data) d.request.method = 'patch' cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--nodes', '--description') result = cli.Execute([ 'command', 'i', '--project', 'p', '--nodes', '2', '--description', 'aaaa' ]) self.assertEqual(result, 'new instance') self.AssertErrContains('Updated instance [i].\n')
def testRunWithModifyRequestHooks(self): self.Expect(instance='iiiiiii') d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) modify_request_mock1 = mock.MagicMock() modify_request_mock2 = mock.MagicMock() def augment(unused_ref, unused_args, req): req.instance += 'iii' return req modify_request_mock1.side_effect = augment modify_request_mock2.side_effect = augment d.request.modify_request_hooks = [ modify_request_mock1, modify_request_mock2 ] cli = self.MakeCLI(d) result = cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.assertEqual(result, {'foo': 'bar'}) self.AssertOutputEquals('foo: bar\n') self.assertEqual( str(modify_request_mock1.call_args[0][0]), 'https://compute.googleapis.com/compute/v1/projects/p/zones/z/instances/i' ) self.assertEqual(modify_request_mock1.call_args[0][1].instance, 'i') self.assertEqual( str(modify_request_mock2.call_args[0][0]), 'https://compute.googleapis.com/compute/v1/projects/p/zones/z/instances/i' ) self.assertEqual(modify_request_mock2.call_args[0][1].instance, 'i')
def testRunWithResponseErrorHandler(self): command_data = yaml_command_schema.CommandData( 'get_iam_policy', self.MakeIAMCommandData(help_text='to get IAM policy of')) execute_params = ['command', '--project', 'p', '--region', 'r', 'i'] self.AssertErrorHandlingWithResponse(self.Expect, command_data, execute_params)
def testCreateWithLabels(self): running_response, _ = self.OperationResponses() labels_cls = self.messages.Instance.LabelsValue additional_property_cls = labels_cls.AdditionalProperty self.mocked_client.instances.Insert.Expect( self.messages.ComputeInstancesInsertRequest( instance=self.messages.Instance( name='i', labels=labels_cls(additionalProperties=[ additional_property_cls(key='k1', value='v1') ])), zone='z', project='p'), response=running_response) command_data = self.MakeCommandData( is_create=True, is_async='zoneOperations') command_data['arguments']['labels'] = {'api_field': 'instance.labels'} d = yaml_command_schema.CommandData('create', command_data) d.request.method = 'insert' d.async_.response_name_field = 'selfLink' d.async_.state.field = 'status' d.async_.state.success_values = ['DONE'] cli = self.MakeCLI(d) result = cli.Execute([ 'command', '--project', 'p', '--zone', 'z', 'i', '--async', '--labels', 'k1=v1' ]) self.AssertOutputEquals('') self.AssertErrContains('Create request issued for: [i]\n' 'Check operation [projects/p/zones/z/operations/' 'operation-12345] for status.') self.AssertErrNotContains('Created instance [i]') self.assertEqual(result, running_response)
def testRunDisableAutoFieldMask(self): self._ExpectUpdate(field_mask='', is_async=True) data = self._MakeUpdateCommandData() data['async'] = {'collection': 'spanner.projects.instances.operations'} data['request']['method'] = 'patch' data['arguments']['params'] = [{ 'api_field': 'updateInstanceRequest.instance.nodeCount', 'arg_name': 'nodes', 'help_text': 'the number of the nodes of the instance to update' }] data['update']['disable_auto_field_mask'] = True d = yaml_command_schema.CommandData('update', data) d.request.method = 'patch' d.async_.state.field = 'done' d.async_.state.success_values = [True] cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--nodes', '--async', '--no-async') cli.Execute(['command', 'i', '--project', 'p', '--async', '--nodes', '2']) self.AssertOutputEquals( """ done: false name: projects/p/instances/i/operations/o """.lstrip('\n'), normalize_space=True) self.AssertErrContains('Request issued for: [i]') self.AssertErrContains('Check operation [projects/p/instances/i/' 'operations/o] for status.') self.AssertErrContains('Updated instance [i].\n')
def testRunCreate(self): """Tests import create command execution when resource doesn't exist.""" self.SetUpMocking(is_insert=True) data = self.MakeCommandData() import_spec = { 'create_if_not_exists': True, 'create_request': { 'method': 'insert', 'api_version': 'alpha', }, 'create_async': None } data['import'] = import_spec d = yaml_command_schema.CommandData('import', data) d.request.api_version = 'alpha' d.request.method = 'update' d.import_.create_request.method = 'insert' self.AssertArgsAndExecute(d) self.AssertOutputContains( textwrap.dedent("""\ id: '12345' name: operation-12345 selfLink: https://compute.googleapis.com/compute/v1/projects/p/zones/z/operations/operation-12345 status: RUNNING """))
def testCreateAsync(self): """Tests asynchronous behavior for create import commands.""" self.SetUpMocking(is_insert=True, is_async=True) data = self.MakeCommandData(is_async='zoneOperations') import_spec = { 'create_if_not_exists': True, 'create_request': { 'method': 'insert', 'api_version': 'alpha', }, 'create_async': { 'collection': 'compute.zoneOperations', 'state': { 'field': 'status', 'success_values': ['DONE'] }, 'api_version': 'alpha', 'method': 'wait', 'response_name_field': 'selfLink' } } data['import'] = import_spec d = yaml_command_schema.CommandData('import', data) d.request.api_version = 'alpha' d.request.method = 'update' self.AssertArgsAndExecute(d, is_async=True) self.AssertOutputEquals('name: test\nzone: z\n')
def testRunAsync(self): running_response, _ = self.Expect(is_async=True) data = self.MakeCommandData(is_async='zoneOperations') data['request']['method'] = 'setTags' data['arguments']['params'] = [{ 'api_field': 'tags.items', 'arg_name': 'tags', 'help_text': 'the tags' }] d = yaml_command_schema.CommandData('set-tags', data) d.async_.request_issued_message = 'Test message: [{__name__}]' d.async_.response_name_field = 'selfLink' d.async_.state.field = 'status' d.async_.state.success_values = ['DONE'] cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone', '--async', '--no-async', '--tags') result = cli.Execute([ 'command', '--project', 'p', '--zone', 'z', 'i', '--async', '--tags', 'foo,bar' ]) self.AssertOutputEquals(""" id: '12345' name: operation-12345 selfLink: https://www.googleapis.com/compute/v1/projects/p/zones/z/operations/operation-12345 status: RUNNING """.lstrip('\n'), normalize_space=True) self.AssertErrContains( 'Test message: [i]\n' 'Check operation [projects/p/zones/z/operations/operation-12345] for ' 'status.') self.assertEqual(result, running_response)
def testRunSync(self): _, done_response = self.Expect() data = self.MakeCommandData(is_async='zoneOperations') data['request']['method'] = 'setTags' data['arguments']['params'] = [{ 'api_field': 'tags.items', 'arg_name': 'tags', 'help_text': 'the tags' }] d = yaml_command_schema.CommandData('set-tags', data) d.request.method = 'setTags' d.async_.response_name_field = 'selfLink' d.async_.state.field = 'status' d.async_.state.success_values = ['DONE'] cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone', '--async', '--no-async', '--tags') result = cli.Execute([ 'command', '--project', 'p', '--zone', 'z', 'i', '--tags', 'foo,bar' ]) self.AssertOutputEquals('foo: bar\n') self.AssertErrContains('Request issued for: [i]') self.AssertErrContains( 'Waiting for operation [projects/p/zones/z/operations/operation-12345] ' 'to complete') self.assertEqual(result, done_response)
def testWithParentResourceAsync(self): m = self.functions_messages expected_function = m.CloudFunction(name='myfunction') expected_result = encoding.DictToMessage( encoding.MessageToDict(expected_function), m.Operation.ResponseValue) running_response = m.Operation(name='operations/12345', done=False) done_response = m.Operation(name='operations/12345', done=True, response=expected_result) self.mocked_functions_client.projects_locations_functions.Create.Expect( m.CloudfunctionsProjectsLocationsFunctionsCreateRequest( location='projects/p/locations/l'), response=running_response) self.mocked_functions_client.operations.Get.Expect( m.CloudfunctionsOperationsGetRequest( name='operations/12345'), response=done_response) command_data = self.MakeCommandData( is_create=True, collection='cloudfunctions.projects.locations.functions') command_data['async'] = { 'collection': 'cloudfunctions.operations', 'extract_resource_result': False} command_data['arguments']['resource'] = { 'arg_name': 'location', 'help_text': 'group help', 'is_parent_resource': True, 'spec': { 'name': 'location', 'collection': 'cloudfunctions.projects.locations', 'attributes': [ {'parameter_name': 'projectsId', 'attribute_name': 'project', 'help': 'help1'}, {'parameter_name': 'locationsId', 'attribute_name': 'location', 'help': 'help2'}]}} d = yaml_command_schema.CommandData( 'create', command_data) d.request.method = 'create' d.request.display_resource_type = 'function' d.response.result_attribute = 'response' cli = self.MakeCLI(d) self.AssertArgs(cli, 'LOCATION', '--async', '--no-async') result = cli.Execute( ['command', '--project', 'p', 'l']) result_function = encoding.DictToMessage( encoding.MessageToDict(result), m.CloudFunction) self.assertEqual(expected_function, result_function) self.AssertErrContains('Create request issued') self.AssertErrContains('Created {} [{}].'.format( d.request.display_resource_type, expected_function.name)) self.AssertErrNotContains('issued for')
def testAdditionalArgsHook(self): d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) additional_args_mock = mock.MagicMock() side_effect = [calliope_base.Argument('--foo', help='Auxilio aliis.')] additional_args_mock.side_effect = lambda: side_effect d.arguments.additional_arguments_hook = additional_args_mock cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone', '--foo')
def testRun(self): self.Expect() d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone') result = cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.assertEqual(result, {'foo': 'bar'}) self.AssertOutputEquals('foo: bar\n')
def testRun(self): self.Expect() d = yaml_command_schema.CommandData('list', self.MakeCommandData(is_list=True)) d.output.format = 'table(name)' cli = self.MakeCLI(d) self.AssertArgs(cli, '--zone', '--filter', '--limit', '--page-size', '--sort-by') cli.Execute(['command', '--project', 'p', '--zone', 'z']) self.AssertOutputEquals('NAME\ninstance-1\ninstance-2\n')
def testRunWithResponseErrorHandler(self): command_data = yaml_command_schema.CommandData( 'add_iam_policy_binding', self.MakeIAMCommandData(help_text='to add IAM policy binding to')) execute_params = [ 'command', '--project', 'p', '--region', 'r', 'i', '--role', 'roles/viewer', '--member', 'user:[email protected]' ] self.AssertErrorHandlingWithResponse(self.Expect, command_data, execute_params)
def testRunWithOverrides(self): client = apis.GetClientClass('ml', 'v1') mocked_client = apitools_mock.Client(client) mocked_client.Mock() self.addCleanup(mocked_client.Unmock) messages = client.MESSAGES_MODULE policy = messages.GoogleIamV1Policy(bindings=[{ 'role': 'roles/owner', 'members': [ 'user:[email protected]', 'group:[email protected]', 'domain:google.com' ] }], etag=b'ACAB', version=0) self.StartObjectPatch(iam_util, 'ParsePolicyFileWithUpdateMask', return_value=(policy, 'bindings,etag,version')) set_iam_policy_request = messages.GoogleIamV1SetIamPolicyRequest( policy=policy, updateMask='bindings,etag,version') mocked_client.projects_models.SetIamPolicy.Expect( messages.MlProjectsModelsSetIamPolicyRequest( resource='projects/p/models/m', googleIamV1SetIamPolicyRequest=set_iam_policy_request), policy) command_data = yaml_command_schema.CommandData( 'set_iam_policy', self.MakeIAMCommandData(help_text='to set IAM policy to', another_collection=True)) command_data.iam = yaml_command_schema.IamData({ 'set_iam_policy_request_path': 'googleIamV1SetIamPolicyRequest', 'message_type_overrides': { 'policy': 'GoogleIamV1Policy', 'set_iam_policy_request': 'GoogleIamV1SetIamPolicyRequest' } }) cli = self.MakeCLI(command_data) self.AssertArgs(cli, 'MODEL', 'POLICY_FILE') result = cli.Execute(['command', '--project', 'p', 'm', 'myfile']) self.assertEqual(result, policy) self.AssertErrContains('Updated IAM policy for model [m].', normalize_space=True) self.AssertOutputEquals(""" bindings: - members: - user:[email protected] - group:[email protected] - domain:google.com role: roles/owner etag: QUNBQg== version: 0 """.lstrip('\n'), normalize_space=True)
def testAdditionalArgsHook(self): command_data = yaml_command_schema.CommandData( 'get_iam_policy', self.MakeIAMCommandData(help_text='to get IAM policy of')) additional_args_mock = mock.MagicMock() side_effect = [calliope_base.Argument('--foo', help='Auxilio aliis.')] additional_args_mock.side_effect = lambda: side_effect command_data.arguments.additional_arguments_hook = additional_args_mock cli = self.MakeCLI(command_data) self.AssertArgs(cli, 'REGISTRY', '--region', '--filter', '--sort-by', '--page-size', '--limit', '--foo')
def testUnknownCommandType(self): cb = yaml_command_translator.CommandBuilder( yaml_command_schema.CommandData('describe', self.MakeCommandData()), ['abc', 'xyz', 'describe']) cb.spec.command_type = 'bogus' with self.assertRaisesRegex( ValueError, r'Command \[abc xyz describe] unknown command type \[bogus]\.' ): cb.Generate()
def testRunDeprecatedRemoved(self): command = self.MakeCommandData() command['deprecate'] = { 'is_removed': True, } d = yaml_command_schema.CommandData('describe', command) cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone') with self.assertRaises(SystemExit): cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.AssertErrContains('This command has been removed.')
def testRunNoOperationMethod(self): """Test for when the API doesn't return an LRO.""" running_response, _ = self.Expect(is_async=True) d = yaml_command_schema.CommandData('delete', self.MakeCommandData()) cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone') self.WriteInput('y\n') result = cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.AssertOutputEquals('') self.AssertErrContains('You are about to delete instance [i]') self.AssertErrContains('Deleted instance [i]') self.assertEqual(result, running_response)
def testRunWithPrompt(self): self.Expect() d = yaml_command_schema.CommandData('describe', self.MakeCommandData()) d.input.confirmation_prompt = 'PROMPT!' cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone') self.WriteInput('y\n') result = cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.assertEqual(result, {'foo': 'bar'}) self.AssertOutputEquals('foo: bar\n') self.AssertErrEquals( '{"ux": "PROMPT_CONTINUE", "message": "PROMPT!"}\n')
def testRunNoOperationMethod(self): """Test for when the API doesn't return an LRO.""" running_response, _ = self.Expect(is_async=True) d = yaml_command_schema.CommandData( 'create', self.MakeCommandData(is_create=True)) d.request.method = 'insert' cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone') result = cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.AssertOutputEquals('') self.AssertErrContains('Created instance [i]') self.assertEqual(result, running_response)
def testRunNoDestination(self): """Tests command exporting to stdout.""" self.Expect() self.StartExportMocking() data = self.MakeCommandData('compute.instances') d = yaml_command_schema.CommandData('export', data) cli = self.MakeCLI(d) self.AssertArgs(cli, 'INSTANCE', '--zone', '--destination') cli.Execute(['command', '--project', 'p', '--zone', 'z', 'i']) self.AssertOutputEquals('name: test\n')
def ValidateBuild(self): try: # Implicitly ensures that all python hooks are valid. spec = yaml_command_schema.CommandData(self.path[-1], self.command_data) # The ensures that the api collection, version, and method are all valid. c = yaml_command_translator.CommandBuilder(spec, ['abc', 'xyz', 'list']) c.Generate() return c # pylint: disable=broad-except, We are just logging it here. except Exception as e: self.E('GLOBAL', 'Command loading failed: ' + str(e))