示例#1
0
    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))
示例#2
0
    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)
示例#3
0
  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))
示例#4
0
    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))
示例#5
0
    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 []
示例#6
0
    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
示例#7
0
    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))
示例#8
0
    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)
示例#9
0
    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))
示例#10
0
  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))
示例#11
0
    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)
示例#12
0
    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)
示例#13
0
    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)
示例#17
0
    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)