예제 #1
0
def GenerateServiceIdentity(project, service):
    """Generate a service identity.

  Args:
    project: The project to generate a service identity for.
    service: The service to generate a service identity for.

  Raises:
    exceptions.GenerateServiceIdentityPermissionDeniedException: when generating
    service identity fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    A dict with the email and uniqueId of the generated service identity.
  """
    client = _GetClientInstance(version=_V1BETA1_VERSION)
    messages = client.MESSAGES_MODULE

    request = messages.ServiceusageServicesGenerateServiceIdentityRequest(
        parent=_PROJECT_SERVICE_RESOURCE % (project, service))
    try:
        op = client.services.GenerateServiceIdentity(request)
        response = encoding.MessageToDict(op.response)
        # Only keep email and uniqueId from the response.
        return {k: response[k] for k in ('email', 'uniqueId')}
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.GenerateServiceIdentityPermissionDeniedException)
예제 #2
0
def ListConnections(project_number, service, network):
    """Make API call to list connections of a network for a specific service.

  Args:
    project_number: The number of the project for which to peer the service.
    service: The name of the service to peer with.
    network: The network in consumer project to peer with.

  Raises:
    exceptions.ListConnectionsPermissionDeniedException: when the list
    connections API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The list of connections.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # The API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesConnectionsListRequest(
        parent='services/' + service,
        network='projects/{0}/global/networks/{1}'.format(
            project_number, network))
    try:
        return client.services_connections.List(request).connections
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.ListConnectionsPermissionDeniedException)
예제 #3
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.
    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.
        exceptions.ReraiseError(
            e, exceptions.EnableServicePermissionDeniedException)
예제 #4
0
def DisableVpcServiceControls(project_number, service, network):
    """Make API call to disable VPC service controls for a specific service.

  Args:
    project_number: The number of the project which is peered with the service.
    service: The name of the service to disable VPC service controls for.
    network: The network in the consumer project peered with the service.

  Raises:
    exceptions.DisableVpcServiceControlsPermissionDeniedException: when the
    disable VPC service controls API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The result of the disable VPC service controls operation.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesDisableVpcServiceControlsRequest(
        disableVpcServiceControlsRequest=messages.
        DisableVpcServiceControlsRequest(
            consumerNetwork='projects/%s/global/networks/%s' %
            (project_number, network)),
        parent='services/' + service)
    try:
        return client.services.DisableVpcServiceControls(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.DisableVpcServiceControlsPermissionDeniedException)
예제 #5
0
def BatchEnableApiCall(project, services):
    """Make API call to batch enable services.

  Args:
    project: The project for which to enable the services.
    services: Iterable of identifiers of services to enable.

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

  Returns:
    The result of the operation
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    request = messages.ServiceusageServicesBatchEnableRequest(
        batchEnableServicesRequest=messages.BatchEnableServicesRequest(
            serviceIds=services),
        parent=_PROJECT_RESOURCE % project)
    try:
        return client.services.BatchEnable(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.EnableServicePermissionDeniedException)
예제 #6
0
def CreateConnection(project_number, service, network, ranges):
    """Make API call to create a connection a specific service.

  Args:
    project_number: The number of the project for which to peer the service.
    service: The name of the service to peer with.
    network: The network in consumer project to peer with.
    ranges: The names of IP CIDR ranges for peering service to use.

  Raises:
    exceptions.CreateConnectionsPermissionDeniedException: when the create
        connection API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The result of the create connection operation.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesConnectionsCreateRequest(
        parent='services/' + service,
        connection=messages.Connection(
            network='projects/%s/global/networks/%s' %
            (project_number, network),
            reservedPeeringRanges=ranges))
    try:
        return client.services_connections.Create(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.CreateConnectionsPermissionDeniedException)
예제 #7
0
def GenerateServiceIdentity(project, service):
    """Generate a service identity.

  Args:
    project: The project to generate a service identity for.
    service: The service to generate a service identity for.

  Raises:
    exceptions.GenerateServiceIdentityPermissionDeniedException: when generating
    service identity fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The email and uid of the generated service identity.
  """
    client = _GetClientInstance(version=_V1ALPHA_VERSION)
    messages = client.MESSAGES_MODULE

    request = messages.ServiceusageServicesGenerateIdentityRequest(
        parent=_PROJECT_SERVICE_RESOURCE % (project, service))
    try:
        op = client.services.GenerateIdentity(request)
        return _GetOperationResponseProperty(
            op, 'email'), _GetOperationResponseProperty(op, 'unique_id')
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.GenerateServiceIdentityPermissionDeniedException)
예제 #8
0
def UpdateConnection(project_number, service, network, ranges, force):
    """Make API call to update a connection to a specific service.

  Args:
    project_number: The number of the project for which to peer the service.
    service: The name of the service to peer with.
    network: The network in consumer project to peer with.
    ranges: The names of IP CIDR ranges for peering service to use.
    force: If true, update the connection even if the update can be destructive.

  Raises:
    exceptions.UpdateConnectionsPermissionDeniedException: when the update
        connection API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The result of the update connection operation.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesConnectionsPatchRequest(
        name='services/%s/connections/-' % service,
        connection=messages.Connection(network=NETWORK_URL_FORMAT %
                                       (project_number, network),
                                       reservedPeeringRanges=ranges),
        force=force)
    try:
        return client.services_connections.Patch(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.UpdateConnectionsPermissionDeniedException)
예제 #9
0
def GetService(project, service):
    """Get a service.

  Args:
    project: The project for which to get the service.
    service: The service to get.

  Raises:
    exceptions.GetServicePermissionDeniedException: when getting service fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The service configuration.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    request = messages.ServiceusageServicesGetRequest(
        name=_PROJECT_SERVICE_RESOURCE % (project, service))
    try:
        return client.services.Get(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(e,
                                exceptions.GetServicePermissionDeniedException)
예제 #10
0
def DeleteConnection(project_number, service, network):
    """Make API call to delete an existing connection to a specific service.

  Args:
    project_number: The number of the project which is peered to the service.
    service: The name of the service peered with.
    network: The network in consumer project peered with.

  Raises:
    exceptions.DeleteConnectionsPermissionDeniedException: when the delete
        connection API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The result of the delete connection operation.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesConnectionsDeleteConnectionRequest(
        name='services/%s/connections/-' % service,
        deleteConnectionRequest=messages.DeleteConnectionRequest(
            consumerNetwork=NETWORK_URL_FORMAT % (project_number, network)))
    try:
        return client.services_connections.DeleteConnection(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.DeleteConnectionsPermissionDeniedException)
예제 #11
0
def ListPeeredDnsDomains(project_number, service, network):
    """Make API call to list the peered DNS domains for a specific connection.

  Args:
    project_number: The number of the project which is peered with the service.
    service: The name of the service to list the peered DNS domains for.
    network: The network in the consumer project peered with the service.

  Raises:
    exceptions.ListPeeredDnsDomainsPermissionDeniedException: when the delete
    peered DNS domain API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
    service.

  Returns:
    The list of peered DNS domains.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesProjectsGlobalNetworksPeeredDnsDomainsListRequest(
        parent='services/%s/projects/%s/global/networks/%s' %
        (service, project_number, network))
    try:
        return client.services_projects_global_networks_peeredDnsDomains.List(
            request).peeredDnsDomains
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e,
            exceptions.ListPeeredDnsDomainsPermissionDeniedException,
        )
예제 #12
0
def PeerApiCall(project_number, service, network, reserved_ranges):
    """Make API call to peer a specific service.

  Args:
    project_number: The number of the project for which to peer the service.
    service: The name of the service to peer with.
    network: The network in consumer project to peer with.
    reserved_ranges: The IP CIDR ranges for peering service to use.

  Raises:
    exceptions.PeerServicePermissionDeniedException: when the peering API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
        service.

  Returns:
    The result of the peering operation
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    request = messages.ServicenetworkingServicesPeerRequest(
        name='services/' + service,
        peerSharedNetworkRequest=messages.PeerSharedNetworkRequest(
            network='projects/%s/global/networks/%s' %
            (project_number, network),
            reservedPeeringRange=reserved_ranges))
    try:
        return client.services.Peer(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.PeerServicePermissionDeniedException)
예제 #13
0
def EnableApiCall(project, service):
    """Make API call to enable a specific service.

  Args:
    project: The project for which to enable the service.
    service: The identifier of the service to enable, for example
      'serviceusage.googleapis.com'.

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

  Returns:
    The result of the operation
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    request = messages.ServiceusageServicesEnableRequest(
        name=_PROJECT_SERVICE_RESOURCE % (project, service))
    try:
        return client.services.Enable(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.EnableServicePermissionDeniedException)
예제 #14
0
def DisableApiCall(project, service, force=False):
    """Make API call to disable a specific service.

  Args:
    project: The project for which to enable the service.
    service: The identifier of the service to disable, for example
      'serviceusage.googleapis.com'.
    force: disable the service even if there are enabled services which depend
      on it. This also disables the services which depend on the service to be
      disabled.

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

  Returns:
    The result of the operation
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    check = messages.DisableServiceRequest.CheckIfServiceHasUsageValueValuesEnum.CHECK
    if force:
        check = messages.DisableServiceRequest.CheckIfServiceHasUsageValueValuesEnum.SKIP
    request = messages.ServiceusageServicesDisableRequest(
        name=_PROJECT_SERVICE_RESOURCE % (project, service),
        disableServiceRequest=messages.DisableServiceRequest(
            disableDependentServices=force,
            checkIfServiceHasUsage=check,
        ),
    )
    try:
        return client.services.Disable(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.EnableServicePermissionDeniedException)
    except apitools_exceptions.HttpBadRequestError as e:
        log.status.Print(
            'Provide the --force flag if you wish to force disable '
            'services.')
        exceptions.ReraiseError(e, exceptions.Error)
예제 #15
0
def UpdateQuotaOverrideCall(service,
                            consumer,
                            metric,
                            unit,
                            override_id,
                            dimensions,
                            value,
                            force=False):
  """Update a quota override.

  Args:
    service: The service to update a quota override for.
    consumer: The consumer to update a quota override for, e.g. "projects/123".
    metric: The quota metric name.
    unit: The unit of quota metric.
    override_id: The override ID.
    dimensions: The dimensions of the override in dictionary format. It can be
      None.
    value: The override integer value.
    force: Force override update even if the change results in a substantial
      decrease in available quota.

  Raises:
    exceptions.UpdateQuotaOverridePermissionDeniedException: when updating an
    override fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The quota override operation.
  """
  client = _GetClientInstance()
  messages = client.MESSAGES_MODULE

  parent = _GetMetricResourceName(service, consumer, metric, unit)
  name = _LIMIT_OVERRIDE_RESOURCE % (parent, override_id)
  dimensions_message = _GetDimensions(messages, dimensions)
  request = messages.ServiceconsumermanagementServicesConsumerQuotaMetricsLimitsProducerOverridesPatchRequest(
      name=name,
      v1Beta1QuotaOverride=messages.V1Beta1QuotaOverride(
          name=name,
          metric=metric,
          unit=unit,
          dimensions=dimensions_message,
          overrideValue=value,
      ),
      force=force,
  )
  try:
    return client.services_consumerQuotaMetrics_limits_producerOverrides.Patch(
        request)
  except (apitools_exceptions.HttpForbiddenError,
          apitools_exceptions.HttpNotFoundError) as e:
    exceptions.ReraiseError(
        e, exceptions.UpdateQuotaOverridePermissionDeniedException)
예제 #16
0
def UpdateQuotaOverrideCall(service,
                            consumer,
                            metric,
                            unit,
                            dimensions,
                            value,
                            force=False):
  """Update a quota override.

  Args:
    service: The service to update a quota override for.
    consumer: The consumer to update a quota override for, e.g. "projects/123".
    metric: The quota metric name.
    unit: The unit of quota metric.
    dimensions: The dimensions of the override in dictionary format. It can be
      None.
    value: The override integer value.
    force: Force override update even if the change results in a substantial
      decrease in available quota.

  Raises:
    exceptions.UpdateQuotaOverridePermissionDeniedException: when updating an
    override fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The quota override operation.
  """
  _ValidateConsumer(consumer)
  client = _GetClientInstance()
  messages = client.MESSAGES_MODULE

  dimensions_message = _GetDimensions(messages, dimensions)
  request = messages.ServiceconsumermanagementServicesConsumerQuotaMetricsImportProducerOverridesRequest(
      parent=_SERVICE_CONSUMER_RESOURCE % (service, consumer),
      v1Beta1ImportProducerOverridesRequest=messages
      .V1Beta1ImportProducerOverridesRequest(
          inlineSource=messages.V1Beta1OverrideInlineSource(
              overrides=[
                  messages.V1Beta1QuotaOverride(
                      metric=metric,
                      unit=unit,
                      overrideValue=value,
                      dimensions=dimensions_message)
              ],),
          force=force),
  )
  try:
    return client.services_consumerQuotaMetrics.ImportProducerOverrides(request)
  except (apitools_exceptions.HttpForbiddenError,
          apitools_exceptions.HttpNotFoundError) as e:
    exceptions.ReraiseError(
        e, exceptions.UpdateQuotaOverridePermissionDeniedException)
예제 #17
0
def DeleteQuotaOverrideCall(consumer,
                            service,
                            metric,
                            unit,
                            override_id,
                            force=False):
    """Delete a quota override.

  Args:
    consumer: The consumer to delete a quota override for, e.g. "projects/123".
    service: The service to delete a quota aoverride for.
    metric: The quota metric name.
    unit: The unit of quota metric.
    override_id: The override ID.
    force: Force override deletion even if the change results in a substantial
      decrease in available quota.

  Raises:
    exceptions.DeleteQuotaOverridePermissionDeniedException: when deleting an
    override fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The quota override operation.
  """
    _ValidateConsumer(consumer)
    client = _GetClientInstance(version=_V1BETA1_VERSION)
    messages = client.MESSAGES_MODULE

    parent = _GetMetricResourceName(consumer, service, metric, unit)
    name = _LIMIT_OVERRIDE_RESOURCE % (parent, override_id)
    request = messages.ServiceusageServicesConsumerQuotaMetricsLimitsConsumerOverridesDeleteRequest(
        name=name,
        force=force,
    )
    try:
        return client.services_consumerQuotaMetrics_limits_consumerOverrides.Delete(
            request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e, exceptions.DeleteQuotaOverridePermissionDeniedException)
예제 #18
0
def GetOperation(name):
    """Make API call to get an operation.

  Args:
    name: The name of operation.

  Raises:
    exceptions.OperationErrorException: when the getting operation API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The result of the operation
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE
    request = messages.ServiceusageOperationsGetRequest(name=name)
    try:
        return client.operations.Get(request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(e, exceptions.OperationErrorException)
예제 #19
0
def CreatePeeredDnsDomain(project_number, service, network, name, dns_suffix):
    """Make API call to create a peered DNS domain for a specific connection.

  Args:
    project_number: The number of the project which is peered with the service.
    service: The name of the service to create a peered DNS domain for.
    network: The network in the consumer project peered with the service.
    name: The name of the peered DNS domain.
    dns_suffix: The DNS domain name suffix of the peered DNS domain.

  Raises:
    exceptions.CreatePeeredDnsDomainPermissionDeniedException: when the create
    peered DNS domain API fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the peering
    service.

  Returns:
    The result of the create peered DNS domain operation.
  """
    client = _GetClientInstance()
    messages = client.MESSAGES_MODULE

    # the API only takes project number, so we cannot use resource parser.
    request = messages.ServicenetworkingServicesProjectsGlobalNetworksPeeredDnsDomainsCreateRequest(
        parent='services/%s/projects/%s/global/networks/%s' %
        (service, project_number, network),
        peeredDnsDomain=messages.PeeredDnsDomain(dnsSuffix=dns_suffix,
                                                 name=name),
    )
    try:
        return client.services_projects_global_networks_peeredDnsDomains.Create(
            request)
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        exceptions.ReraiseError(
            e,
            exceptions.CreatePeeredDnsDomainPermissionDeniedException,
        )
예제 #20
0
def ListServices(project, enabled, page_size, limit):
  """Make API call to list services.

  Args:
    project: The project for which to list services.
    enabled: List only enabled services.
    page_size: The page size to list.
    limit: The max number of services to display.

  Raises:
    exceptions.ListServicesPermissionDeniedException: when listing services
    fails.
    apitools_exceptions.HttpError: Another miscellaneous error with the service.

  Returns:
    The list of services
  """
  client = _GetClientInstance()
  messages = client.MESSAGES_MODULE

  if enabled:
    service_filter = 'state:ENABLED'
  else:
    service_filter = None
  request = messages.ServiceusageServicesListRequest(
      filter=service_filter, parent=_PROJECT_RESOURCE % project)
  try:
    return list_pager.YieldFromList(
        client.services,
        request,
        limit=limit,
        batch_size_attribute='pageSize',
        batch_size=page_size,
        field='services')
  except (apitools_exceptions.HttpForbiddenError,
          apitools_exceptions.HttpNotFoundError) as e:
    exceptions.ReraiseError(e,
                            exceptions.EnableServicePermissionDeniedException)
예제 #21
0
def IsServiceEnabled(project_id, service_name):
    """Return true if the service is enabled.

  Args:
    project_id: The ID of the project we want to query.
    service_name: The name of the service.

  Raises:
    exceptions.ListServicesPermissionDeniedException: if a 403 or 404
        error is returned by the List request.
    apitools_exceptions.HttpError: Another miscellaneous error with the listing
        service.

  Returns:
    True if the service is enabled, false otherwise.
  """

    client = services_util.GetClientInstance()

    # Get the list of enabled services.
    request = services_util.GetEnabledListRequest(project_id)
    try:
        for service in list_pager.YieldFromList(
                client.services,
                request,
                batch_size_attribute='pageSize',
                field='services'):
            # If the service is present in the list of enabled services, return
            # True, otherwise return False
            if service.serviceName.lower() == service_name.lower():
                return True
    except (apitools_exceptions.HttpForbiddenError,
            apitools_exceptions.HttpNotFoundError) as e:
        # TODO(b/36865980): When backend supports it, differentiate errors.
        exceptions.ReraiseError(
            e, exceptions.ListServicesPermissionDeniedException)
    return False