示例#1
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).
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        # Prompt with a warning before continuing.
        console_io.PromptContinue(
            message=
            'Are you sure? This will set the service configuration to be '
            'deleted, along with all of the associated consumer '
            'information. Note: This does not immediately delete the '
            'service configuration or data and can be undone using the '
            'undelete command for 30 days. Only after 30 days will the '
            'service be purged from the system.',
            prompt_string='Continue anyway',
            default=True,
            throw_if_unattended=True,
            cancel_on_no=True)

        service = arg_parsers.GetServiceNameFromArg(args.service)

        request = messages.ServicemanagementServicesDeleteRequest(
            serviceName=service, )

        operation = client.services.Delete(request)

        return services_util.ProcessOperationResult(operation, args. async)
示例#2
0
def EnableServiceApiCall(project_id, service_name):
    """Make API call to enable a specific API.

  Args:
    project_id: The ID of the project for which to enable the service.
    service_name: The name of the service to enable on the project.

  Raises:
    services_util.EnableServicePermissionDeniedException: when enabling the API
        fails.
    api_lib_exceptions.HttpException: Another miscellaneous error with the
        enabling service.

  Returns:
    The result of the Enable operation
  """

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))

    try:
        return client.services.Enable(request)
    except exceptions.HttpError as e:
        if e.status_code in [403, 404]:
            # TODO(b/36865980): When backend supports it, differentiate errors.
            msg = json.loads(e.content).get('error', {}).get('message', '')
            raise services_util.EnableServicePermissionDeniedException(msg)
        else:
            raise api_lib_exceptions.HttpException(e)
    def Run(self, args):
        """Run 'service-management remove-iam-policy-binding'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the access API call.

    Raises:
      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.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()
        request = messages.ServicemanagementServicesGetIamPolicyRequest(
            servicesId=args.service)

        policy = client.services.GetIamPolicy(request)

        iam_util.RemoveBindingFromIamPolicy(policy, args.member, args.role)

        # Send updated access policy to backend
        request = messages.ServicemanagementServicesSetIamPolicyRequest(
            servicesId=args.service,
            setIamPolicyRequest=messages.SetIamPolicyRequest(policy=policy))
        return client.services.SetIamPolicy(request)
def EnableServiceApiCall(project_id, service_name):
    """Make API call to enable a specific API.

  Args:
    project_id: The ID of the project for which to enable the service.
    service_name: The name of the service to enable on the project.

  Raises:
    exceptions.EnableServicePermissionDeniedException: when enabling the API
        fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the enabling
        service.

  Returns:
    The result of the Enable operation
  """

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))

    try:
        return client.services.Enable(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        # TODO(b/36865980): When backend supports it, differentiate errors.
        _ReraiseError(e, exceptions.EnableServicePermissionDeniedException)
  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.
    """
    messages = services_util.GetMessagesModule()
    client = services_util.GetClientInstance()

    # 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 = messages.ServicemanagementOperationsGetRequest(
        operationsId=args.operation,)

    operation = client.operations.Get(request)

    if (sys.getsizeof(str(operation.response)) > MAX_RESPONSE_BYTES and
        not args.full):
      log.warn('Response portion of operation resource redacted. '
               'Use --full to see the whole Operation.\n')
      operation.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.GetProcessedOperationResult(operation, async=True)
示例#6
0
  def Run(self, args):
    """Run 'service-management configs list'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the List API call.
    """
    messages = services_util.GetMessagesModule()
    client = services_util.GetClientInstance()

    service = arg_parsers.GetServiceNameFromArg(args.service)

    request = messages.ServicemanagementServicesConfigsListRequest(
        serviceName=service)

    return list_pager.YieldFromList(
        client.services_configs,
        request,
        limit=args.limit,
        batch_size_attribute='pageSize',
        batch_size=args.page_size,
        field='serviceConfigs')
    def Run(self, args):
        """Run 'service-management check-access'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the access API call.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()
        all_iam_permissions = [
            'servicemanagement.services.get',
            'servicemanagement.services.getProjectSettings',
            'servicemanagement.services.delete',
            'servicemanagement.services.update',
            'servicemanagement.services.use',
            'servicemanagement.services.updateProjectSettings',
            'servicemanagement.services.check',
            'servicemanagement.services.report',
            'servicemanagement.services.setIamPolicy',
            'servicemanagement.services.getIamPolicy',
        ]

        # Shorten the query request name for better readability
        query_request = messages.ServicemanagementServicesTestIamPermissionsRequest

        request = query_request(
            servicesId=args.service,
            testIamPermissionsRequest=messages.TestIamPermissionsRequest(
                permissions=all_iam_permissions))

        return client.services.TestIamPermissions(request)
示例#8
0
    def Run(self, args):
        """Run 'service-management check-access'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the access API call.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()
        all_iam_permissions = services_util.ALL_IAM_PERMISSIONS

        # Shorten the query request name for better readability
        query_request = messages.ServicemanagementServicesTestIamPermissionsRequest

        service = arg_parsers.GetServiceNameFromArg(args.service)

        request = query_request(
            servicesId=service,
            testIamPermissionsRequest=messages.TestIamPermissionsRequest(
                permissions=all_iam_permissions))

        return client.services.TestIamPermissions(request)
示例#9
0
def EnableServiceApiCall(project_id, service_name):
    """Make API call to enable a specific API.

  Args:
    project_id: The ID of the project for which to enable the service.
    service_name: The name of the service to enable on the project.

  Raises:
    exceptions.EnableServicePermissionDeniedException: when enabling the API
        fails.
    api_lib_exceptions.HttpException: Another miscellaneous error with the
        enabling service.

  Returns:
    The result of the Enable operation
  """

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))

    try:
        return client.services.Enable(request)
    except apitools_exceptions.HttpError as e:
        _HandleStatusCode(e, exceptions.EnableServicePermissionDeniedException)
  def Run(self, args):
    """Run 'service-management operations list'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The list of operations for this project.
    """
    messages = services_util.GetMessagesModule()
    client = services_util.GetClientInstance()
    service = arg_parsers.GetServiceNameFromArg(args.service)

    msg_filter = 'serviceName="{0}"'.format(service)
    if args.filter:
      msg_filter += ' AND ({0})'.format(args.filter)
      args.filter = None  # We don't want Display() to handle the filter.

    msg = messages.ServicemanagementOperationsListRequest(filter=msg_filter)

    return list_pager.YieldFromList(
        client.operations,
        msg,
        limit=args.limit,
        batch_size_attribute='pageSize',
        batch_size=args.page_size,
        field='operations')
    def _GetConfig(self, service, config_id):
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        request = messages.ServicemanagementServicesConfigsGetRequest(
            serviceName=service, configId=config_id)
        return client.services_configs.Get(request)
示例#12
0
 def MakeConfigFile(self, file_contents, filename, file_type):
     messages = services_util.GetMessagesModule()
     return messages.ConfigFile(
         fileContents=file_contents,
         filePath=os.path.basename(filename),
         fileType=file_type,
     )
示例#13
0
    def _GetLatestVersionConfig(self, service):
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()
        request = messages.ServicemanagementServicesGetRequest(
            serviceName=service, expand='service_config')
        service_result = client.services.Get(request)

        # Return the service config from the service result
        return service_result.serviceConfig
示例#14
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:
      IOError: An IOError is returned if the input file cannot be read, or
          the output file cannot be written to.
    """
        log.warn('This command is deprecated and will be removed soon.')

        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        # TODO(b/36057355): Add support for swagger file references later
        # This requires the API to support multiple files first. b/23353397
        try:
            with open(args.open_api_file) as f:
                open_api_spec = messages.OpenApiSpec(openApiFiles=[
                    messages.ConfigFile(filePath=os.path.basename(
                        args.open_api_file),
                                        contents=f.read())
                ])
        except IOError:
            raise calliope_exceptions.NewErrorFromCurrentException(
                exceptions.FileOpenError,
                'Cannot open {f} file'.format(f=args.open_api_file))

        request = messages.ConvertConfigRequest(openApiSpec=open_api_spec)

        converted_config = client.v1.ConvertConfig(request)
        diagnostics = converted_config.diagnostics
        if diagnostics:
            kind = 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 calliope_exceptions.NewErrorFromCurrentException(
                        exceptions.FileOpenError,
                        'Cannot open output file \'{f}\''.format(
                            f=args.output_file))
            else:
                return service
示例#15
0
def EnableServiceApiCall(project_id, service_name):
    """Make API call to enable a specific API."""

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))
    return client.services.Enable(request)
示例#16
0
  def MakeConfigFileMessage(self, file_contents, filename, file_type):
    """Constructs a ConfigFile message from a config file.

    Args:
      file_contents: The contents of the config file.
      filename: The full path to the config file.
      file_type: FileTypeValueValuesEnum describing the type of config file.

    Returns:
      The constructed ConfigFile message.
    """

    messages = services_util.GetMessagesModule()
    return messages.ConfigFile(
        fileContents=file_contents,
        filePath=os.path.basename(filename),
        fileType=file_type,)
    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.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        request = messages.ServicemanagementServicesGetRequest(
            serviceName=args.service, )

        return client.services.Get(request)
示例#18
0
    def Run(self, args):
        """Run 'service-management undelete'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the Undelete API call (or None if cancelled).
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()
        request = messages.ServicemanagementServicesUndeleteRequest(
            serviceName=args.service, )

        operation = client.services.Undelete(request)

        return services_util.ProcessOperationResult(operation, args. async)
示例#19
0
def EnableServiceApiCall(project_id, service_name):
    """Make API call to enable a specific API.

  Args:
    project_id: The ID of the project for which to enable the service.
    service_name: The name of the service to enable on the project.

  Returns:
    The result of the Enable operation
  """

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))
    return client.services.Enable(request)
示例#20
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.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        project = properties.VALUES.core.project.Get(required=True)
        request = messages.ServicemanagementServicesDisableRequest(
            serviceName=args.service,
            disableServiceRequest=messages.DisableServiceRequest(
                consumerId='project:' + project))
        operation = client.services.Disable(request)
        return services_util.ProcessOperationResult(operation, args. async)
    def Run(self, args):
        """Run 'service-management add-iam-policy-binding'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      The response from the access API call.

    Raises:
      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.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        service = arg_parsers.GetServiceNameFromArg(args.service)

        request = messages.ServicemanagementServicesGetIamPolicyRequest(
            servicesId=service)

        try:
            policy = client.services.GetIamPolicy(request)
        except apitools_exceptions.HttpError as error:
            # If the error is a 404, no IAM policy exists, so just create a blank one.
            exc = exceptions.HttpException(error)
            if exc.payload.status_code == 404:
                policy = messages.Policy()
            else:
                raise

        iam_util.AddBindingToIamPolicy(messages.Binding, policy, args.member,
                                       args.role)

        # Send updated access policy to backend
        request = messages.ServicemanagementServicesSetIamPolicyRequest(
            servicesId=service,
            setIamPolicyRequest=(messages.SetIamPolicyRequest(policy=policy)))
        return client.services.SetIamPolicy(request)
示例#22
0
    def Run(self, args):
        """Run 'service-management operations wait'.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      If successful, the response from the operations.Get API call.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        operation_id = arg_parsers.GetOperationIdFromArg(args.operation)

        request = messages.ServicemanagementOperationsGetRequest(
            operationsId=operation_id, )

        operation = client.operations.Get(request)

        return services_util.ProcessOperationResult(operation, async=False)
示例#23
0
    def Run(self, args):
        """Run 'service-management get-iam-policy'.

    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.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        request = messages.ServicemanagementServicesGetIamPolicyRequest(
            servicesId=args.service)

        return client.services.GetIamPolicy(request)
示例#24
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:
      SwaggerUploadException: if the provided service configuration files are
          rejected by the Service Management API.

      BadFileExceptionn: if the provided service configuration files are
          invalid or cannot be read.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        file_types = messages.ConfigFile.FileTypeValueValuesEnum
        self.service_name = self.service_version = config_contents = None
        config_files = []

        for service_config_file in args.service_config_file:
            config_contents = None
            try:
                with open(service_config_file, 'r') as f:
                    config_contents = f.read()
            except IOError as ex:
                raise calliope_exceptions.BadFileException(
                    'Could not open service config file [{0}]: {1}'.format(
                        service_config_file, ex))

            if self.FilenameMatchesExtension(service_config_file,
                                             ['.json', '.yaml', '.yml']):
                # 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 calliope_exceptions.BadFileException(
                        'Could not read JSON or YAML from service config file '
                        '[{0}].'.format(service_config_file))

                if 'swagger' in service_config_dict:
                    if not self.service_name:
                        self.service_name = service_config_dict.get(
                            'host', None)

                    # Always use YAML for Open API because JSON is a subset of YAML.
                    config_files.append(
                        self.MakeConfigFile(config_contents,
                                            service_config_file,
                                            file_types.OPEN_API_YAML))
                elif service_config_dict.get('type') == 'google.api.Service':
                    self.service_name = service_config_dict.get('name')

                    config_files.append(
                        self.MakeConfigFile(config_contents,
                                            service_config_file,
                                            file_types.SERVICE_CONFIG_YAML))
                elif 'name' in service_config_dict:
                    # This is a special case. If we have been provided a Google Service
                    # Configuration file which has a service 'name' field, but no 'type'
                    # field, we have to assume that this is a normalized service config,
                    # and can be uploaded via the CreateServiceConfig API. Therefore,
                    # we can short circute the process here.
                    if len(args.service_config_file) > 1:
                        raise calliope_exceptions.BadFileException((
                            'Ambiguous input. Found normalized service configuration in '
                            'file [{0}], but received multiple input files. To upload '
                            'normalized service config, please provide it separately from '
                            'other input files to avoid ambiguity.'
                        ).format(service_config_file))

                    self.service_name = service_config_dict.get('name', None)
                    config_files = []
                    break
                else:
                    raise calliope_exceptions.BadFileException((
                        'Unable to parse Open API, or Google Service Configuration '
                        'specification from {0}').format(service_config_file))

            elif self.FilenameMatchesExtension(service_config_file,
                                               ['.pb', '.descriptor']):
                config_files.append(
                    self.MakeConfigFile(config_contents, service_config_file,
                                        file_types.FILE_DESCRIPTOR_SET_PROTO))
            else:
                raise calliope_exceptions.BadFileException((
                    'Could not determine the content type of file [{0}]. Supported '
                    'extensions are .json .yaml .yml .pb. and .descriptor'
                ).format(service_config_file))

        # Check to see if the Endpoints meta service needs to be enabled.
        enable_api.EnableServiceIfDisabled(
            properties.VALUES.core.project.Get(required=True),
            services_util.GetEndpointsServiceName(), args. async)
        # Check if we need to create the service.
        services_util.CreateServiceIfNew(
            self.service_name,
            properties.VALUES.core.project.Get(required=True))

        if config_files:
            self.service_config_id = services_util.PushMultipleServiceConfigFiles(
                self.service_name, config_files, args. async)
        else:
            self.service_config_id = services_util.PushNormalizedGoogleServiceConfig(
                self.service_name,
                properties.VALUES.core.project.Get(required=True),
                config_contents)

        if not self.service_config_id:
            raise calliope_exceptions.ToolException(
                'Failed to retrieve Service Configuration Id.')

        # Create a Rollout for the new service configuration
        percentages = messages.TrafficPercentStrategy.PercentagesValue()
        percentages.additionalProperties.append(
            (messages.TrafficPercentStrategy.PercentagesValue.
             AdditionalProperty(key=self.service_config_id, value=100.0)))
        traffic_percent_strategy = messages.TrafficPercentStrategy(
            percentages=percentages)
        rollout = messages.Rollout(
            serviceName=self.service_name,
            trafficPercentStrategy=traffic_percent_strategy,
        )
        rollout_operation = client.services_rollouts.Create(rollout)
        services_util.ProcessOperationResult(rollout_operation, args. async)

        # Check to see if the service is already enabled
        enable_api.EnableServiceIfDisabled(
            properties.VALUES.core.project.Get(required=True),
            self.service_name, args. async)
示例#25
0
    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    request = messages.ServicemanagementServicesEnableRequest(
        serviceName=service_name,
        enableServiceRequest=messages.EnableServiceRequest(
            consumerId='project:' + project_id))
    return client.services.Enable(request)


@http_error_handler.HandleHttpErrors
def EnableServiceIfDisabled(project_id, service_name, async=False):
    """Check to see if the service is enabled, and if it is not, do so."""

    client = services_util.GetClientInstance()
    messages = services_util.GetMessagesModule()

    # Check to see if the service is already enabled
    request = messages.ServicemanagementServicesProjectSettingsGetRequest(
        serviceName=service_name,
        consumerProjectId=project_id,
        view=services_util.GetCallerViews().get('CONSUMER'))

    project_settings_result = client.services_projectSettings.Get(request)
    enabled = messages.UsageSettings.ConsumerEnableStatusValueValuesEnum.ENABLED

    # If the service is not yet enabled, enable it
    if (not project_settings_result.usageSettings
            or project_settings_result.usageSettings.consumerEnableStatus !=
            enabled):
        log.status.Print('Enabling service {0} on project {1}...'.format(
示例#26
0
 def services_messages(self):
     return services_util.GetMessagesModule()
示例#27
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:
      BadFileExceptionn: if the provided service configuration files are
          invalid or cannot be read.
    """
        messages = services_util.GetMessagesModule()
        client = services_util.GetClientInstance()

        file_types = messages.ConfigFile.FileTypeValueValuesEnum
        self.service_name = self.service_version = config_contents = None
        config_files = []

        self.validate_only = args.validate_only

        # If we're not doing a validate-only run, we don't want to output the
        # resource directly unless the user specifically requests it using the
        # --format flag. The Epilog will show useful information after deployment
        # is complete.
        if not self.validate_only and not args.IsSpecified('format'):
            args.format = 'none'

        for service_config_file in args.service_config_file:
            config_contents = services_util.ReadServiceConfigFile(
                service_config_file)

            if services_util.FilenameMatchesExtension(
                    service_config_file, ['.json', '.yaml', '.yml']):
                # 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 calliope_exceptions.BadFileException(
                        'Could not read JSON or YAML from service config file '
                        '[{0}].'.format(service_config_file))

                if 'swagger' in service_config_dict:
                    if 'host' not in service_config_dict:
                        raise calliope_exceptions.BadFileException((
                            'Malformed input. Found Swagger service config in file [{}], '
                            'but no host was specified. Add a host specification to the '
                            'config file.').format(service_config_file))
                    if not self.service_name and service_config_dict.get(
                            'host'):
                        self.service_name = service_config_dict.get('host')

                    # Always use YAML for Open API because JSON is a subset of YAML.
                    config_files.append(
                        self.MakeConfigFileMessage(config_contents,
                                                   service_config_file,
                                                   file_types.OPEN_API_YAML))
                elif service_config_dict.get('type') == 'google.api.Service':
                    if not self.service_name and service_config_dict.get(
                            'name'):
                        self.service_name = service_config_dict.get('name')

                    config_files.append(
                        self.MakeConfigFileMessage(
                            config_contents, service_config_file,
                            file_types.SERVICE_CONFIG_YAML))
                elif 'name' in service_config_dict:
                    # This is a special case. If we have been provided a Google Service
                    # Configuration file which has a service 'name' field, but no 'type'
                    # field, we have to assume that this is a normalized service config,
                    # and can be uploaded via the CreateServiceConfig API. Therefore,
                    # we can short circute the process here.
                    if len(args.service_config_file) > 1:
                        raise calliope_exceptions.BadFileException((
                            'Ambiguous input. Found normalized service configuration in '
                            'file [{0}], but received multiple input files. To upload '
                            'normalized service config, please provide it separately from '
                            'other input files to avoid ambiguity.'
                        ).format(service_config_file))

                    # If this is a validate-only run, abort now, since this is not
                    # supported in the ServiceConfigs.Create API
                    if self.validate_only:
                        raise exceptions.InvalidFlagError(
                            'The --validate-only flag is not supported when using '
                            'normalized service configs as input.')

                    self.service_name = service_config_dict.get('name')
                    config_files = []
                    break
                else:
                    raise calliope_exceptions.BadFileException((
                        'Unable to parse Open API, or Google Service Configuration '
                        'specification from {0}').format(service_config_file))

            elif services_util.IsProtoDescriptor(service_config_file):
                config_files.append(
                    self.MakeConfigFileMessage(
                        config_contents, service_config_file,
                        file_types.FILE_DESCRIPTOR_SET_PROTO))
            else:
                raise calliope_exceptions.BadFileException((
                    'Could not determine the content type of file [{0}]. Supported '
                    'extensions are .json .yaml .yml .pb. and .descriptor'
                ).format(service_config_file))

        # Check to see if the Endpoints meta service needs to be enabled.
        enable_api.EnableServiceIfDisabled(
            properties.VALUES.core.project.Get(required=True),
            services_util.GetEndpointsServiceName(), args. async)
        # Check if we need to create the service.
        services_util.CreateServiceIfNew(
            self.service_name,
            properties.VALUES.core.project.Get(required=True))

        if config_files:
            push_config_result = services_util.PushMultipleServiceConfigFiles(
                self.service_name,
                config_files,
                args. async,
                validate_only=self.validate_only)
            self.service_config_id = (
                services_util.GetServiceConfigIdFromSubmitConfigSourceResponse(
                    push_config_result))
        else:
            push_config_result = services_util.PushNormalizedGoogleServiceConfig(
                self.service_name,
                properties.VALUES.core.project.Get(required=True),
                config_contents)
            self.service_config_id = push_config_result.id

        if not self.service_config_id:
            raise exceptions.InvalidConditionError(
                'Failed to retrieve Service Configuration Id.')

        # Run the Push Advisor to see if we need to warn the user of any
        # potentially hazardous changes to the service configuration.
        if self.CheckPushAdvisor(args.force):
            return None

        # Create a Rollout for the new service configuration
        if not self.validate_only:
            percentages = messages.TrafficPercentStrategy.PercentagesValue()
            percentages.additionalProperties.append(
                (messages.TrafficPercentStrategy.PercentagesValue.
                 AdditionalProperty(key=self.service_config_id, value=100.0)))
            traffic_percent_strategy = messages.TrafficPercentStrategy(
                percentages=percentages)
            rollout = messages.Rollout(
                serviceName=self.service_name,
                trafficPercentStrategy=traffic_percent_strategy,
            )
            rollout_operation = client.services_rollouts.Create(rollout)
            services_util.ProcessOperationResult(rollout_operation,
                                                 args. async)

            # Check to see if the service is already enabled
            enable_api.EnableServiceIfDisabled(
                properties.VALUES.core.project.Get(required=True),
                self.service_name, args. async)

        return push_config_result