def Run(self, args): """Run 'service-management access add'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the access API call. Raises: HttpException: An http error response was received while executing api request. ToolException: An error such as specifying a label that doesn't exist or a principal that is already a member of the service or visibility label. """ request = (self.services_messages. ServicemanagementServicesGetAccessPolicyRequest( serviceName=args.service)) if not services_util.ValidateEmailString(args.principal): raise exceptions.ToolException('Invalid email string') try: access_policy = self.services_client.services.GetAccessPolicy( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # Fill in the serviceName field if GetAccessPolicy didn't do so for us. if not access_policy.serviceName: access_policy.serviceName = args.service # Fill in the accessList field if GetAccessPolicy didn't do so for us. if not access_policy.accessList: access_policy.accessList = self.services_messages.ServiceAccessList( ) principal_string = self._BuildPrincipalString(args.principal, args.type) if args.label: # If a visibility label is provided, try to add the principal to it. self._AddPrincipalToLabel(principal_string, args.service, args.label, access_policy) else: # Otherwise, try to add principal to the service access policy directly. self._AddPrincipalToService(principal_string, args.service, access_policy) # Send updated access policy to backend try: return self.services_client.services.UpdateAccessPolicy( access_policy) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management operations describe'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the operations.Get API call. Raises: HttpException: An http error response was received while executing api request. """ # If a user includes the leading "operations/", just strip it off if args.operation.startswith(OPTIONAL_PREFIX_TO_STRIP): args.operation = args.operation[len(OPTIONAL_PREFIX_TO_STRIP):] request = self.services_messages.ServicemanagementOperationsGetRequest( operationsId=args.operation, ) try: result = self.services_client.operations.Get(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) if not args.full: log.warn('Response portion of Operation redacted. ' 'Use --full to see the whole Operation.\n') result.response = None # Set async to True because we don't need to wait for the operation # to complete to check the status of it. return services_util.ProcessOperationResult(result, async=True)
def Run(self, args): """Run 'service-management api-keys create'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the api-keys API call. Raises: HttpException: An http error response was received while executing api request. """ # Verify Android command-line arguments, if applicable if args.type == 'android': self._VerifyAndroidPackageArgs(args) # Construct the Create API Key request object request = self._ConstructApiKeyRequest(self.project, args) try: return self.apikeys_client.projects_apiKeys.Create(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management describe-consumer-settings'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the request name for better readability get_request = (self.services_messages. ServicemanagementServicesProjectSettingsGetRequest) views = services_util.GetCallerViews() request = get_request(serviceName=args.service, consumerProjectId=args.consumer_project, view=views.get(args.view)) try: return self.services_client.services_projectSettings.Get(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management list'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The list of managed services for this project. Raises: HttpException: An http error response was received while executing api request. """ # Default mode is --enabled, so if no flags were specified, # turn on the args.enabled flag. if not (args.enabled or args.available or args.produced): args.enabled = True validated_project = self._GetValidatedProject(args.project) if args.enabled: request = self._GetEnabledListRequest(validated_project) elif args.available: request = self._GetAvailableListRequest(validated_project) elif args.produced: request = self._GetProducedListRequest(validated_project) # TODO(user): Implement pagination and --limit try: response = self.services_client.services.List(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return response.services or []
def Run(self, args): """Run 'service-management convert-config'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the ConvertConfig API call. Raises: HttpException: An http error response was received while executing api request. """ try: with open(args.swagger_file) as f: swagger = self.services_messages.File( contents=f.read(), path=args.swagger_file, ) except IOError: raise exceptions.ToolException.FromCurrent( 'Cannot open {f} file'.format(f=args.swagger_file)) # TODO(user): Add support for swagger file references later # This requires the API to support multiple files first. b/23353397 swagger_spec = self.services_messages.SwaggerSpec( swaggerFiles=[swagger]) request = self.services_messages.ConvertConfigRequest( swaggerSpec=swagger_spec, ) try: converted_config = self.services_client.v1.ConvertConfig(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) diagnostics = converted_config.diagnostics if diagnostics: kind = self.services_messages.Diagnostic.KindValueValuesEnum for diagnostic in diagnostics: logger = log.error if diagnostic.kind == kind.ERROR else log.warning logger('{l}: {m}'.format(l=diagnostic.location, m=diagnostic.message)) service = converted_config.serviceConfig if service: if args.output_file: try: with open(args.output_file, 'w') as out: out.write(encoding.MessageToJson(service)) except IOError: raise exceptions.ToolException.FromCurrent( 'Cannot open output file \'{f}\''.format( f=args.output_file)) else: return service
def Run(self, args): """Run 'service-management describe'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the Get API call. Raises: HttpException: An http error response was received while executing api request. """ request = self.services_messages.ServicemanagementServicesGetRequest( serviceName=args.service, ) try: return self.services_client.services.Get(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management disable'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the patch request name for better readability patch_request = (self.services_messages. ServicemanagementServicesProjectSettingsPatchRequest) usage_settings = self.services_messages.UsageSettings( consumerEnableStatus=( self.services_messages.UsageSettings. ConsumerEnableStatusValueValuesEnum.DISABLED)) project_settings = self.services_messages.ProjectSettings( usageSettings=usage_settings) request = patch_request( serviceName=args.service, consumerProjectId=args.consumer_project, projectSettings=project_settings, updateMask='usage_settings.consumer_enable_status') try: # TODO(user): Add support for Operation completion, and --async flag result = self.services_client.services_projectSettings.Patch( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result)
def Run(self, args): """Run 'service-management api-keys revert'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the keys API call. Raises: HttpException: An http error response was received while executing api request. """ # Construct the Revert API Key request object request = self.apikeys_messages.ApikeysProjectsApiKeysRevertRequest( projectId=self.project, keyId=args.key) try: return self.apikeys_client.projects_apiKeys.Revert(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management access check'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the access API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the query request name for better readability query_request = (self.services_messages .ServicemanagementServicesAccessPolicyQueryRequest) request = query_request(serviceName=args.service, userEmail=args.principal) try: return self.services_client.services_accessPolicy.Query(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error))
def Run(self, args): """Run 'service-management delete'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the Delete API call (or None if cancelled). Raises: HttpException: An http error response was received while executing api request. """ # If the user doesn't specify --force, prompt with a warning before # continuing. if not args.force: continue_prompt_response = console_io.PromptContinue( message='Are you sure? This will permanently delete the service ' 'configuration and all of the associated consumer ' 'information. This CANNOT be undone!', prompt_string='Continue anyway', default=True, throw_if_unattended=True) if not continue_prompt_response: return request = self.services_messages.ServicemanagementServicesDeleteRequest( serviceName=args.service, ) try: result = self.services_client.services.Delete(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result)
def Run(self, args): """Run 'service-management add-visibility-label'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the request names for better readability get_request = (self.services_messages. ServicemanagementServicesProjectSettingsGetRequest) patch_request = (self.services_messages. ServicemanagementServicesProjectSettingsPatchRequest) # TODO(user): change this to a conditional update once the service # supports it. Until then... # # 1. Get the current labels request = get_request( serviceName=args.service, consumerProjectId=args.consumer_project, view=get_request.ViewValueValuesEnum.PRODUCER_VIEW, ) try: response = self.services_client.services_projectSettings.Get( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # 2. Add the new label to the current labels visibility_labels = [args.label] if (response.visibilitySettings and response.visibilitySettings.visibilityLabels): visibility_labels.extend( response.visibilitySettings.visibilityLabels) visibility_settings = self.services_messages.VisibilitySettings( visibilityLabels=visibility_labels) project_settings = self.services_messages.ProjectSettings( visibilitySettings=visibility_settings, ) request = patch_request( serviceName=args.service, consumerProjectId=args.consumer_project, projectSettings=project_settings, updateMask='visibility_settings.visibility_labels') try: # TODO(user): Add support for Operation completion, and --async flag result = self.services_client.services_projectSettings.Patch( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result, args. async)
def Run(self, args): """Run 'service-management deploy'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the Update API call. Raises: HttpException: An http error response was received while executing api request. """ with open(args.service_config_file, 'r') as f: config_contents = f.read() # Try to load the file as JSON. If that fails, try YAML. service_config_dict = services_util.LoadJsonOrYaml(config_contents) if not service_config_dict: raise exceptions.BadFileException( 'Could not read JSON or YAML from service config file %s.' % args.service_config_file) # Check if the provided file is a swagger spec that needs to be converted # to Google Service Configuration if 'swagger' in service_config_dict: swagger_file = self.services_messages.File( contents=config_contents, path=os.path.basename(args.service_config_file)) # TODO(user): Add support for swagger file references later # This requires the API to support multiple files first. b/23353397 swagger_spec = self.services_messages.SwaggerSpec( swaggerFiles=[swagger_file]) request = self.services_messages.ConvertConfigRequest( swaggerSpec=swagger_spec, ) try: response = self.services_client.v1.ConvertConfig(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) diagnostics = response.diagnostics if diagnostics: kind = self.services_messages.Diagnostic.KindValueValuesEnum for diagnostic in diagnostics: logger = log.error if diagnostic.kind == kind.ERROR else log.warning logger('{l}: {m}'.format(l=diagnostic.location, m=diagnostic.message)) service_config = response.serviceConfig else: # If not Swagger, assume that we are dealing with Google Service Config service_config = encoding.JsonToMessage( self.services_messages.Service, config_contents) managed_service = self.services_messages.ManagedService( serviceConfig=service_config, serviceName=service_config.name) # Set the serviceConfig producerProjectId if it is not already set if not managed_service.serviceConfig.producerProjectId: managed_service.serviceConfig.producerProjectId = self.project request = self.services_messages.ServicemanagementServicesUpdateRequest( serviceName=managed_service.serviceName, managedService=managed_service, ) try: result = self.services_client.services.Update(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # Validate the response type to avoid surprise errors below services_util.RaiseIfResultNotTypeOf(result, self.services_messages.Operation) service_name = None config_id = None # Fish the serviceName and serviceConfig.id fields from the proto Any # that is returned in result.response for prop in result.response.additionalProperties: if prop.key == 'serviceName': service_name = prop.value.string_value elif prop.key == 'serviceConfig': for item in prop.value.object_value.properties: if item.key == 'id': config_id = item.value.string_value break if service_name and config_id: log.status.Print( ('\nService Configuration with version "{0}" uploaded ' 'for service "{1}"\n').format(config_id, service_name)) else: log.error('Failed to retrieve Service Name and ' 'Service Configuration Version') # Remove the response portion of the resulting operation since # it can be extremely large. result.response = None return services_util.ProcessOperationResult(result, args. async)
def Run(self, args): """Run 'service-management add-quota-override'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the name for better readability patch_request = (self.services_messages. ServicemanagementServicesProjectSettingsPatchRequest) # TODO(user): What happens when --quota-limit is not specified? # Should there be a default value? Should it be required? quota_override = self.services_messages.QuotaLimitOverride( limit=args.quota_limit) # Create a QuotaSettings object to store the added override if args.consumer: overrides = self.services_messages.QuotaSettings.ConsumerOverridesValue( ) overrides.additionalProperties.append( self.services_messages.QuotaSettings.ConsumerOverridesValue. AdditionalProperty(key=args.quota_limit_key, value=quota_override)) quota_settings = self.services_messages.QuotaSettings( consumerOverrides=overrides) elif args.producer: overrides = self.services_messages.QuotaSettings.ProducerOverridesValue( ) overrides.additionalProperties.append( self.services_messages.QuotaSettings.ProducerOverridesValue. AdditionalProperty(key=args.quota_limit_key, value=quota_override)) quota_settings = self.services_messages.QuotaSettings( producerOverrides=overrides) project_settings = self.services_messages.ProjectSettings( quotaSettings=quota_settings, ) update_mask = 'quota_settings.{0}_overrides[{1}]'.format( 'consumer' if args.consumer else 'producer', args.quota_limit_key) request = patch_request(serviceName=args.service, consumerProjectId=args.consumer_project, projectSettings=project_settings, updateMask=update_mask) try: # TODO(user): Add support for Operation completion, and --async flag result = self.services_client.services_projectSettings.Patch( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result)
def Run(self, args): """Run 'service-management remove-quota-override'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. """ # Shorten the request names for better readability get_request = (self.services_messages. ServicemanagementServicesProjectSettingsGetRequest) patch_request = (self.services_messages. ServicemanagementServicesProjectSettingsPatchRequest) views = services_util.GetCallerViews() # Get the current list of quota settings to see if the quota override # exists in the first place. request = get_request( serviceName=args.service, consumerProjectId=args.consumer_project, view=views.get(args.view), ) try: response = self.services_client.services_projectSettings.Get( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # Check to see if the quota override was present in the first place. override_present = False overrides = None if args.consumer: if response.quotaSettings and response.quotaSettings.consumerOverrides: overrides = response.quotaSettings.consumerOverrides else: overrides = (self.services_messages.QuotaSettings. ConsumerOverridesValue()) elif args.producer: if response.quotaSettings and response.quotaSettings.producerOverrides: overrides = response.quotaSettings.producerOverrides else: overrides = (self.services_messages.QuotaSettings. ProducerOverridesValue()) if overrides: for override in overrides.additionalProperties: if override.key == args.quota_limit_key: override_present = True break if not override_present: log.warn('No quota override found for "{0}"'.format( args.quota_limit_key)) return project_settings = self.services_messages.ProjectSettings( quotaSettings=self.services_messages.QuotaSettings(), ) update_mask = 'quota_settings.{0}_overrides[{1}]'.format( 'consumer' if args.consumer else 'producer', args.quota_limit_key) request = patch_request(serviceName=args.service, consumerProjectId=args.consumer_project, projectSettings=project_settings, updateMask=update_mask) try: # TODO(user): Add support for Operation completion, and --async flag result = self.services_client.services_projectSettings.Patch( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result)
def Run(self, args): """Run 'service-management remove-visibility-label'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the consumer settings API call. Raises: HttpException: An http error response was received while executing api request. ToolException: The label that was supposed to be removed is not currently set for the given service and consumer project. """ # Shorten the request names for better readability get_request = (self.services_messages. ServicemanagementServicesProjectSettingsGetRequest) patch_request = (self.services_messages. ServicemanagementServicesProjectSettingsPatchRequest) # TODO(user): change this to a conditional update once the service # supports it. Until then... # # 1. Get the current labels request = get_request( serviceName=args.service, consumerProjectId=args.consumer_project, view=get_request.ViewValueValuesEnum.PRODUCER_VIEW, ) try: response = self.services_client.services_projectSettings.Get( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # 2. Remove the provided label from the current labels if it exists visibility_labels = [] if (response.visibilitySettings and response.visibilitySettings.visibilityLabels): visibility_labels.extend( response.visibilitySettings.visibilityLabels) if args.label in visibility_labels: visibility_labels.remove(args.label) else: raise exceptions.ToolException(( 'Label {0} is not currently applied to service {1} for consumer ' 'project {2}').format(args.label, args.service, args.consumer_project)) visibility_settings = self.services_messages.VisibilitySettings( visibilityLabels=visibility_labels) project_settings = self.services_messages.ProjectSettings( visibilitySettings=visibility_settings, ) request = patch_request( serviceName=args.service, consumerProjectId=args.consumer_project, projectSettings=project_settings, updateMask='visibility_settings.visibility_labels') try: # TODO(user): Add support for Operation completion, and --async flag result = self.services_client.services_projectSettings.Patch( request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) return services_util.ProcessOperationResult(result)
def Run(self, args): """Run 'service-management deploy'. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: The response from the Update API call. Raises: HttpException: An http error response was received while executing api request. """ with open(args.service_config_file, 'r') as f: config_contents = f.read() # Try to load the file as JSON. If that fails, try YAML. service_config_dict = services_util.LoadJsonOrYaml(config_contents) if not service_config_dict: raise exceptions.BadFileException( 'Could not read JSON or YAML from service config file %s.' % args.service_config_file) # Check if the provided file is a swagger spec that needs to be converted # to Google Service Configuration if 'swagger' in service_config_dict: swagger_file = self.services_messages.File( contents=config_contents, path=args.service_config_file) # TODO(user): Add support for swagger file references later # This requires the API to support multiple files first. b/23353397 swagger_spec = self.services_messages.SwaggerSpec( swaggerFiles=[swagger_file]) request = self.services_messages.ConvertConfigRequest( swaggerSpec=swagger_spec, ) try: response = self.services_client.v1.ConvertConfig(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) diagnostics = response.diagnostics if diagnostics: kind = self.services_messages.Diagnostic.KindValueValuesEnum for diagnostic in diagnostics: logger = log.error if diagnostic.kind == kind.ERROR else log.warning logger('{l}: {m}'.format(l=diagnostic.location, m=diagnostic.message)) service_config = response.serviceConfig else: # If not Swagger, assume that we are dealing with Google Service Config service_config = encoding.JsonToMessage( self.services_messages.Service, config_contents) managed_service = self.services_messages.ManagedService( serviceConfig=service_config, serviceName=service_config.name) # Set the serviceConfig producerProjectId if it is not already set if not managed_service.serviceConfig.producerProjectId: managed_service.serviceConfig.producerProjectId = self.project request = self.services_messages.ServicemanagementServicesUpdateRequest( serviceName=managed_service.serviceName, managedService=managed_service, ) try: result = self.services_client.services.Update(request) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(services_util.GetError(error)) # Remove the response portion of the resulting operation since # it can be extremely large. result.response = None return services_util.ProcessOperationResult(result)