Example #1
0
    def sink_update(self, project, sink_name, filter_, destination):
        """API call:  update a sink resource.

        :type project: str
        :param project: ID of the project containing the sink.

        :type sink_name: str
        :param sink_name: the name of the sink

        :type filter_: str
        :param filter_: the advanced logs filter expression defining the
                        entries exported by the sink.

        :type destination: str
        :param destination: destination URI for the entries exported by
                            the sink.

        :rtype: dict
        :returns: The sink object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/sinks/%s' % (project, sink_name)
        sink_pb = LogSink(name=path, filter=filter_, destination=destination)
        try:
            self._gax_api.update_sink(path, sink_pb, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return MessageToDict(sink_pb)
Example #2
0
    def subscription_modify_ack_deadline(self, subscription_path, ack_ids,
                                         ack_deadline):
        """API call:  update ack deadline for retrieved messages

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyAckDeadline

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type ack_ids: list of string
        :param ack_ids: ack IDs of messages being acknowledged

        :type ack_deadline: int
        :param ack_deadline: the deadline (in seconds) by which messages pulled
                            from the back-end must be acknowledged.
        """
        try:
            self._gax_api.modify_ack_deadline(
                subscription_path, ack_ids, ack_deadline)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #3
0
    def metric_update(self, project, metric_name, filter_, description):
        """API call:  update a metric resource.

        :type project: str
        :param project: ID of the project containing the metric.

        :type metric_name: str
        :param metric_name: the name of the metric

        :type filter_: str
        :param filter_: the advanced logs filter expression defining the
                        entries exported by the metric.

        :type description: str
        :param description: description of the metric.

        :rtype: dict
        :returns: The metric object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        metric_pb = LogMetric(name=path, filter=filter_,
                              description=description)
        try:
            self._gax_api.update_log_metric(path, metric_pb, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return MessageToDict(metric_pb)
Example #4
0
    def metric_create(self, project, metric_name, filter_, description):
        """API call:  create a metric resource.

        See:
        https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/create

        :type project: str
        :param project: ID of the project in which to create the metric.

        :type metric_name: str
        :param metric_name: the name of the metric

        :type filter_: str
        :param filter_: the advanced logs filter expression defining the
                        entries exported by the metric.

        :type description: str
        :param description: description of the metric.
        """
        options = None
        parent = 'projects/%s' % (project,)
        metric_pb = LogMetric(name=metric_name, filter=filter_,
                              description=description)
        try:
            self._gax_api.create_log_metric(parent, metric_pb, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                path = 'projects/%s/metrics/%s' % (project, metric_name)
                raise Conflict(path)
            raise
Example #5
0
    def sink_create(self, project, sink_name, filter_, destination):
        """API call:  create a sink resource.

        See:
        https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/create

        :type project: str
        :param project: ID of the project in which to create the sink.

        :type sink_name: str
        :param sink_name: the name of the sink

        :type filter_: str
        :param filter_: the advanced logs filter expression defining the
                        entries exported by the sink.

        :type destination: str
        :param destination: destination URI for the entries exported by
                            the sink.
        """
        options = None
        parent = 'projects/%s' % (project,)
        sink_pb = LogSink(name=sink_name, filter=filter_,
                          destination=destination)
        try:
            self._gax_api.create_sink(parent, sink_pb, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                path = 'projects/%s/sinks/%s' % (project, sink_name)
                raise Conflict(path)
            raise
Example #6
0
    def topic_list_subscriptions(self, topic_path, page_token=None):
        """API call:  list subscriptions bound to a topic

        See:
        https://cloud.google.com/pubsub/reference/rest/v1/projects.topics.subscriptions/list

        :type topic_path: string
        :param topic_path: fully-qualified path of the topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type page_token: string
        :param page_token: opaque marker for the next "page" of subscriptions.
                           If not passed, the API will return the first page
                           of subscriptions.

        :rtype: list of strings
        :returns: fully-qualified names of subscriptions for the supplied
                topic.
        :raises: :exc:`gcloud.exceptions.NotFound` if the topic does not
                    exist
        """
        options = _build_paging_options(page_token)
        try:
            response = self._gax_api.list_topic_subscriptions(
                topic_path, options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        subs = [{'topic': topic_path, 'name': subscription}
                for subscription in response.subscriptions]
        return subs, response.next_page_token
Example #7
0
    def topic_publish(self, topic_path, messages):
        """API call:  publish one or more messages to a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/publish

        :type topic_path: str
        :param topic_path: fully-qualified path of the topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type messages: list of dict
        :param messages: messages to be published.

        :rtype: list of string
        :returns: list of opaque IDs for published messages.
        :raises: :exc:`google.cloud.exceptions.NotFound` if the topic does not
                    exist
        """
        options = CallOptions(is_bundling=False)
        message_pbs = [_message_pb_from_mapping(message)
                       for message in messages]
        try:
            result = self._gax_api.publish(topic_path, message_pbs,
                                           options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        return result.message_ids
Example #8
0
    def subscription_pull(self, subscription_path, return_immediately=False,
                          max_messages=1):
        """API call:  retrieve messages for a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyPushConfig

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type return_immediately: bool
        :param return_immediately: if True, the back-end returns even if no
                                   messages are available;  if False, the API
                                   call blocks until one or more messages are
                                   available.

        :type max_messages: int
        :param max_messages: the maximum number of messages to return.

        :rtype: list of dict
        :returns:  the ``receivedMessages`` element of the response.
        """
        try:
            response_pb = self._gax_api.pull(
                subscription_path, max_messages,
                return_immediately=return_immediately)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
        return [_received_message_pb_to_mapping(rmpb)
                for rmpb in response_pb.received_messages]
Example #9
0
def _retry_on_unavailable(exc):
    """Retry only errors whose status code is 'UNAVAILABLE'.

    :type exc: :class:`~google.gax.errors.GaxError`
    :param exc: The exception that was caught.

    :rtype: bool
    :returns: Boolean indicating if the exception was UNAVAILABLE.
    """
    return exc_to_code(exc) == StatusCode.UNAVAILABLE
Example #10
0
    def topic_delete(self, topic_path):
        """API call:  delete a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create

        :type topic_path: str
        :param topic_path: fully-qualified path of the new topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.
        """
        try:
            self._gax_api.delete_topic(topic_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
Example #11
0
    def subscription_create(self, subscription_path, topic_path,
                            ack_deadline=None, push_endpoint=None):
        """API call:  create a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/create

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type topic_path: str
        :param topic_path: the fully-qualified path of the topic being
                           subscribed, in format
                           ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type ack_deadline: int
        :param ack_deadline:
            (Optional) the deadline (in seconds) by which messages pulled from
            the back-end must be acknowledged.

        :type push_endpoint: str
        :param push_endpoint:
            (Optional) URL to which messages will be pushed by the back-end.
            If not set, the application must pull messages.

        :rtype: dict
        :returns: ``Subscription`` resource returned from the API.
        """
        if push_endpoint is not None:
            push_config = PushConfig(push_endpoint=push_endpoint)
        else:
            push_config = None

        if ack_deadline is None:
            ack_deadline = 0

        try:
            sub_pb = self._gax_api.create_subscription(
                subscription_path, topic_path,
                push_config=push_config, ack_deadline_seconds=ack_deadline)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                raise Conflict(topic_path)
            raise
        return _subscription_pb_to_mapping(sub_pb)
Example #12
0
    def sink_delete(self, project, sink_name):
        """API call:  delete a sink resource.

        :type project: str
        :param project: ID of the project containing the sink.

        :type sink_name: str
        :param sink_name: the name of the sink
        """
        options = None
        path = 'projects/%s/sinks/%s' % (project, sink_name)
        try:
            self._gax_api.delete_sink(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
Example #13
0
    def subscription_delete(self, subscription_path):
        """API call:  delete a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/delete

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.
        """
        try:
            self._gax_api.delete_subscription(subscription_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #14
0
    def logger_delete(self, project, logger_name):
        """API call:  delete all entries in a logger via a DELETE request

        :type project: str
        :param project: ID of project containing the log entries to delete

        :type logger_name: str
        :param logger_name: name of logger containing the log entries to delete
        """
        options = None
        path = 'projects/%s/logs/%s' % (project, logger_name)
        try:
            self._gax_api.delete_log(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
Example #15
0
    def metric_delete(self, project, metric_name):
        """API call:  delete a metric resource.

        :type project: str
        :param project: ID of the project containing the metric.

        :type metric_name: str
        :param metric_name: the name of the metric
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        try:
            self._gax_api.delete_log_metric(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
Example #16
0
    def metric_get(self, project, metric_name):
        """API call:  retrieve a metric resource.

        :type project: string
        :param project: ID of the project containing the metric.

        :type metric_name: string
        :param metric_name: the name of the metric
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        try:
            metric_pb = self._gax_api.get_log_metric(path, options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return _log_metric_pb_to_mapping(metric_pb)
Example #17
0
    def sink_get(self, project, sink_name):
        """API call:  retrieve a sink resource.

        :type project: string
        :param project: ID of the project containing the sink.

        :type sink_name: string
        :param sink_name: the name of the sink
        """
        options = None
        path = 'projects/%s/sinks/%s' % (project, sink_name)
        try:
            sink_pb = self._gax_api.get_sink(path, options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return _log_sink_pb_to_mapping(sink_pb)
Example #18
0
    def topic_list_subscriptions(self, topic, page_size=0, page_token=None):
        """API call:  list subscriptions bound to a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics.subscriptions/list

        :type topic: :class:`~google.cloud.pubsub.topic.Topic`
        :param topic: The topic that owns the subscriptions.

        :type page_size: int
        :param page_size: maximum number of subscriptions to return, If not
                          passed, defaults to a value set by the API.

        :type page_token: str
        :param page_token: opaque marker for the next "page" of subscriptions.
                           If not passed, the API will return the first page
                           of subscriptions.

        :rtype: :class:`~google.cloud.iterator.Iterator`
        :returns: Iterator of
                  :class:`~google.cloud.pubsub.subscription.Subscription`
                  accessible to the current API.
        :raises: :exc:`~google.cloud.exceptions.NotFound` if the topic does
                  not exist.
        """
        if page_token is None:
            page_token = INITIAL_PAGE
        options = CallOptions(page_token=page_token)
        topic_path = topic.full_name
        try:
            page_iter = self._gax_api.list_topic_subscriptions(
                topic_path, page_size=page_size, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise

        iter_kwargs = {}
        if page_size:  # page_size can be 0 or explicit None.
            iter_kwargs['max_results'] = page_size
        iterator = GAXIterator(self._client, page_iter,
                               _item_to_subscription, **iter_kwargs)
        iterator.topic = topic
        return iterator
Example #19
0
    def subscription_acknowledge(self, subscription_path, ack_ids):
        """API call:  acknowledge retrieved messages

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyPushConfig

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type ack_ids: list of string
        :param ack_ids: ack IDs of messages being acknowledged
        """
        try:
            self._gax_api.acknowledge(subscription_path, ack_ids)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #20
0
    def subscription_get(self, subscription_path):
        """API call:  retrieve a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/get

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :rtype: dict
        :returns: ``Subscription`` resource returned from the API.
        """
        try:
            sub_pb = self._gax_api.get_subscription(subscription_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
        return _subscription_pb_to_mapping(sub_pb)
Example #21
0
    def exists(self):
        """Test whether this instance exists.

        See
        https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig

        :rtype: bool
        :returns: True if the instance exists, else false
        :raises GaxError:
            for errors other than ``NOT_FOUND`` returned from the call
        """
        api = self._client.instance_admin_api
        options = _options_with_prefix(self.name)

        try:
            api.get_instance(self.name, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                return False
            raise

        return True
Example #22
0
    def sink_get(self, project, sink_name):
        """API call:  retrieve a sink resource.

        :type project: string
        :param project: ID of the project containing the sink.

        :type sink_name: string
        :param sink_name: the name of the sink

        :rtype: dict
        :returns: The sink object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/sinks/%s' % (project, sink_name)
        try:
            sink_pb = self._gax_api.get_sink(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return _log_sink_pb_to_mapping(sink_pb)
Example #23
0
    def reload(self):
        """Reload this database.

        Refresh any configured schema into :attr:`ddl_statements`.

        See
        https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.GetDatabaseDDL

        :raises NotFound: if the database does not exist
        :raises GaxError:
            for errors other than ``NOT_FOUND`` returned from the call
        """
        api = self._instance._client.database_admin_api
        options = _options_with_prefix(self.name)

        try:
            response = api.get_database_ddl(self.name, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(self.name)
            raise
        self._ddl_statements = tuple(response.statements)
Example #24
0
    def subscription_pull(self,
                          subscription_path,
                          return_immediately=False,
                          max_messages=1):
        """API call:  retrieve messages for a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyPushConfig

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type return_immediately: bool
        :param return_immediately: if True, the back-end returns even if no
                                   messages are available;  if False, the API
                                   call blocks until one or more messages are
                                   available.

        :type max_messages: int
        :param max_messages: the maximum number of messages to return.

        :rtype: list of dict
        :returns:  the ``receivedMessages`` element of the response.
        """
        try:
            response_pb = self._gax_api.pull(
                subscription_path,
                max_messages,
                return_immediately=return_immediately)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
        return [
            _received_message_pb_to_mapping(rmpb)
            for rmpb in response_pb.received_messages
        ]
Example #25
0
    def topic_create(self, topic_path):
        """API call:  create a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create

        :type topic_path: str
        :param topic_path: fully-qualified path of the new topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :rtype: dict
        :returns: ``Topic`` resource returned from the API.
        :raises: :exc:`google.cloud.exceptions.Conflict` if the topic already
                    exists
        """
        try:
            topic_pb = self._gax_api.create_topic(topic_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                raise Conflict(topic_path)
            raise
        return {'name': topic_pb.name}
Example #26
0
    def metric_get(self, project, metric_name):
        """API call:  retrieve a metric resource.

        :type project: str
        :param project: ID of the project containing the metric.

        :type metric_name: str
        :param metric_name: the name of the metric

        :rtype: dict
        :returns: The metric object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        try:
            metric_pb = self._gax_api.get_log_metric(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return MessageToDict(metric_pb)
Example #27
0
    def topic_get(self, topic_path):
        """API call:  retrieve a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/get

        :type topic_path: str
        :param topic_path: fully-qualified path of the topic, in format
                        ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :rtype: dict
        :returns: ``Topic`` resource returned from the API.
        :raises: :exc:`google.cloud.exceptions.NotFound` if the topic does not
                    exist
        """
        try:
            topic_pb = self._gax_api.get_topic(topic_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        return {'name': topic_pb.name}
Example #28
0
    def topic_get(self, topic_path):
        """API call:  retrieve a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/get

        :type topic_path: str
        :param topic_path: fully-qualified path of the topic, in format
                        ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :rtype: dict
        :returns: ``Topic`` resource returned from the API.
        :raises: :exc:`google.cloud.exceptions.NotFound` if the topic does not
                    exist
        """
        try:
            topic_pb = self._gax_api.get_topic(topic_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        return {'name': topic_pb.name}
Example #29
0
    def topic_create(self, topic_path):
        """API call:  create a topic

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create

        :type topic_path: str
        :param topic_path: fully-qualified path of the new topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :rtype: dict
        :returns: ``Topic`` resource returned from the API.
        :raises: :exc:`google.cloud.exceptions.Conflict` if the topic already
                    exists
        """
        try:
            topic_pb = self._gax_api.create_topic(topic_path)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                raise Conflict(topic_path)
            raise
        return {'name': topic_pb.name}
Example #30
0
    def topic_list_subscriptions(self,
                                 topic_path,
                                 page_size=0,
                                 page_token=None):
        """API call:  list subscriptions bound to a topic

        See:
        https://cloud.google.com/pubsub/reference/rest/v1/projects.topics.subscriptions/list

        :type topic_path: string
        :param topic_path: fully-qualified path of the topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type page_size: int
        :param page_size: maximum number of subscriptions to return, If not
                          passed, defaults to a value set by the API.

        :type page_token: string
        :param page_token: opaque marker for the next "page" of subscriptions.
                           If not passed, the API will return the first page
                           of subscriptions.

        :rtype: list of strings
        :returns: fully-qualified names of subscriptions for the supplied
                topic.
        :raises: :exc:`gcloud.exceptions.NotFound` if the topic does not
                    exist
        """
        options = _build_paging_options(page_token)
        try:
            page_iter = self._gax_api.list_topic_subscriptions(
                topic_path, page_size=page_size, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        subs = page_iter.next()
        token = page_iter.page_token or None
        return subs, token
Example #31
0
    def metric_get(self, project, metric_name):
        """API call:  retrieve a metric resource.

        :type project: str
        :param project: ID of the project containing the metric.

        :type metric_name: str
        :param metric_name: the name of the metric

        :rtype: dict
        :returns: The metric object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        try:
            metric_pb = self._gax_api.get_log_metric(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        return MessageToDict(metric_pb)
    def test_db_run_in_transaction_twice_4181(self):
        retry = RetryInstanceState(_has_all_ddl)
        retry(self._db.reload)()

        with self._db.batch() as batch:
            batch.delete(COUNTERS_TABLE, self.ALL)

        def _unit_of_work(transaction, name):
            transaction.insert(COUNTERS_TABLE, COUNTERS_COLUMNS, [[name, 0]])

        self._db.run_in_transaction(_unit_of_work, name='id_1')

        with self.assertRaises(errors.RetryError) as expected:
            self._db.run_in_transaction(_unit_of_work, name='id_1')

        self.assertEqual(exc_to_code(expected.exception.cause),
                         StatusCode.ALREADY_EXISTS)

        self._db.run_in_transaction(_unit_of_work, name='id_2')

        with self._db.snapshot() as after:
            rows = list(after.read(COUNTERS_TABLE, COUNTERS_COLUMNS, self.ALL))
        self.assertEqual(len(rows), 2)
Example #33
0
    def exists(self):
        """Test for the existence of this session.

        See
        https://cloud.google.com/spanner/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.GetSession

        :rtype: bool
        :returns: True if the session exists on the back-end, else False.
        :raises GaxError:
            for errors other than ``NOT_FOUND`` returned from the call
        """
        if self._session_id is None:
            return False
        api = self._database.spanner_api
        options = _options_with_prefix(self._database.name)
        try:
            api.get_session(self.name, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                return False
            raise
        else:
            return True
Example #34
0
    def subscription_seek(self, subscription_path, time=None, snapshot=None):
        """API call:  seek a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/seek

        :type subscription_path: str
        :param subscription_path::
            the fully-qualified path of the subscription to affect, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type time: :class:`.timestamp_pb2.Timestamp`
        :param time: The time to seek to.

        :type snapshot: str
        :param snapshot: The snapshot to seek to.
        """
        try:
            self._gax_api.seek(subscription_path, time=time, snapshot=snapshot)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #35
0
    def topic_list_subscriptions(self, topic_path, page_size=0,
                                 page_token=None):
        """API call:  list subscriptions bound to a topic

        See:
        https://cloud.google.com/pubsub/reference/rest/v1/projects.topics.subscriptions/list

        :type topic_path: string
        :param topic_path: fully-qualified path of the topic, in format
                            ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type page_size: int
        :param page_size: maximum number of subscriptions to return, If not
                          passed, defaults to a value set by the API.

        :type page_token: string
        :param page_token: opaque marker for the next "page" of subscriptions.
                           If not passed, the API will return the first page
                           of subscriptions.

        :rtype: list of strings
        :returns: fully-qualified names of subscriptions for the supplied
                topic.
        :raises: :exc:`gcloud.exceptions.NotFound` if the topic does not
                    exist
        """
        options = _build_paging_options(page_token)
        try:
            page_iter = self._gax_api.list_topic_subscriptions(
                topic_path, page_size=page_size, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(topic_path)
            raise
        subs = page_iter.next()
        token = page_iter.page_token or None
        return subs, token
Example #36
0
    def metric_update(self, project, metric_name, filter_, description):
        """API call:  update a metric resource.

        :type project: str
        :param project: ID of the project containing the metric.

        :type metric_name: str
        :param metric_name: the name of the metric

        :type filter_: str
        :param filter_: the advanced logs filter expression defining the
                        entries exported by the metric.

        :type description: str
        :param description: description of the metric.

        :rtype: dict
        :returns: The metric object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/metrics/%s' % (project, metric_name)
        metric_pb = LogMetric(name=path,
                              filter=filter_,
                              description=description)
        try:
            metric_pb = self._gax_api.update_log_metric(path,
                                                        metric_pb,
                                                        options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        # NOTE: LogMetric message type does not have an ``Any`` field
        #       so `MessageToDict`` can safely be used.
        return MessageToDict(metric_pb)
Example #37
0
    def delete(self):
        """Mark an instance and all of its databases for permanent deletion.

        See
        https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance

        Immediately upon completion of the request:

        * Billing will cease for all of the instance's reserved resources.

        Soon afterward:

        * The instance and all databases within the instance will be deleteed.
          All data in the databases will be permanently deleted.
        """
        api = self._client.instance_admin_api
        options = _options_with_prefix(self.name)

        try:
            api.delete_instance(self.name, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(self.name)
            raise
Example #38
0
    def subscription_modify_push_config(self, subscription_path,
                                        push_endpoint):
        """API call:  update push config of a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyPushConfig

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type push_endpoint: str
        :param push_endpoint:
            (Optional) URL to which messages will be pushed by the back-end.
            If not set, the application must pull messages.
        """
        push_config = PushConfig(push_endpoint=push_endpoint)
        try:
            self._gax_api.modify_push_config(subscription_path, push_config)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #39
0
    def sink_get(self, project, sink_name):
        """API call:  retrieve a sink resource.

        :type project: str
        :param project: ID of the project containing the sink.

        :type sink_name: str
        :param sink_name: the name of the sink

        :rtype: dict
        :returns: The sink object returned from the API (converted from a
                  protobuf to a dictionary).
        """
        options = None
        path = 'projects/%s/sinks/%s' % (project, sink_name)
        try:
            sink_pb = self._gax_api.get_sink(path, options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(path)
            raise
        # NOTE: LogSink message type does not have an ``Any`` field
        #       so `MessageToDict`` can safely be used.
        return MessageToDict(sink_pb)
Example #40
0
    def update_ddl(self, ddl_statements):
        """Update DDL for this database.

        Apply any configured schema from :attr:`ddl_statements`.

        See
        https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase

        :rtype: :class:`google.cloud.future.operation.Operation`
        :returns: an operation instance
        """
        client = self._instance._client
        api = client.database_admin_api
        options = _options_with_prefix(self.name)

        try:
            future = api.update_database_ddl(
                self.name, ddl_statements, '', options=options)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(self.name)
            raise

        return future
Example #41
0
    def subscription_modify_push_config(self, subscription_path,
                                        push_endpoint):
        """API call:  update push config of a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/modifyPushConfig

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type push_endpoint: str
        :param push_endpoint:
            (Optional) URL to which messages will be pushed by the back-end.
            If not set, the application must pull messages.
        """
        push_config = PushConfig(push_endpoint=push_endpoint)
        try:
            self._gax_api.modify_push_config(subscription_path, push_config)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
                raise NotFound(subscription_path)
            raise
Example #42
0
 def test_exc_to_code(self):
     code = grpc.exc_to_code(TestErrors.MyError())
     self.assertEqual(code, grpc.StatusCode.UNKNOWN)
     self.assertEqual(code, grpc.STATUS_CODE_NAMES['UNKNOWN'])
     self.assertIsNone(grpc.exc_to_code(Exception))
     self.assertIsNone(grpc.exc_to_code(grpc.RpcError()))
Example #43
0
    def subscription_create(self,
                            subscription_path,
                            topic_path,
                            ack_deadline=None,
                            push_endpoint=None,
                            retain_acked_messages=None,
                            message_retention_duration=None):
        """API call:  create a subscription

        See:
        https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/create

        :type subscription_path: str
        :param subscription_path:
            the fully-qualified path of the new subscription, in format
            ``projects/<PROJECT>/subscriptions/<SUB_NAME>``.

        :type topic_path: str
        :param topic_path: the fully-qualified path of the topic being
                           subscribed, in format
                           ``projects/<PROJECT>/topics/<TOPIC_NAME>``.

        :type ack_deadline: int
        :param ack_deadline:
            (Optional) the deadline (in seconds) by which messages pulled from
            the back-end must be acknowledged.

        :type push_endpoint: str
        :param push_endpoint:
            (Optional) URL to which messages will be pushed by the back-end.
            If not set, the application must pull messages.

        :type retain_acked_messages: bool
        :param retain_acked_messages:
            (Optional) Whether to retain acked messages. If set, acked messages
            are retained in the subscription's backlog for a duration indicated
            by `message_retention_duration`.

        :type message_retention_duration: :class:`datetime.timedelta`
        :param message_retention_duration:
            (Optional) Whether to retain acked messages. If set, acked messages
            are retained in the subscription's backlog for a duration indicated
            by `message_retention_duration`. If unset, defaults to 7 days.

        :rtype: dict
        :returns: ``Subscription`` resource returned from the API.
        """
        if push_endpoint is not None:
            push_config = PushConfig(push_endpoint=push_endpoint)
        else:
            push_config = None

        if message_retention_duration is not None:
            message_retention_duration = _timedelta_to_duration_pb(
                message_retention_duration)

        try:
            sub_pb = self._gax_api.create_subscription(
                subscription_path,
                topic_path,
                push_config=push_config,
                ack_deadline_seconds=ack_deadline,
                retain_acked_messages=retain_acked_messages,
                message_retention_duration=message_retention_duration)
        except GaxError as exc:
            if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
                raise Conflict(topic_path)
            raise
        return MessageToDict(sub_pb)
def _unavailable(exc):
    return exc_to_code(exc) == StatusCode.UNAVAILABLE
Example #45
0
    def test_run_in_transaction_w_abort_w_retry_metadata_deadline(self):
        import datetime
        from google.gax.errors import GaxError
        from google.gax.grpc import exc_to_code
        from grpc import StatusCode
        from google.cloud.spanner_v1.proto.spanner_pb2 import CommitResponse
        from google.cloud.spanner_v1.proto.transaction_pb2 import (
            Transaction as TransactionPB)
        from google.cloud._helpers import UTC
        from google.cloud._helpers import _datetime_to_pb_timestamp
        from google.cloud.spanner_v1.transaction import Transaction
        from google.cloud.spanner_v1 import session as MUT
        from google.cloud._testing import _Monkey

        TABLE_NAME = 'citizens'
        COLUMNS = ['email', 'first_name', 'last_name', 'age']
        VALUES = [
            ['*****@*****.**', 'Phred', 'Phlyntstone', 32],
            ['*****@*****.**', 'Bharney', 'Rhubble', 31],
        ]
        TRANSACTION_ID = b'FACEDACE'
        RETRY_SECONDS = 1
        RETRY_NANOS = 3456
        transaction_pb = TransactionPB(id=TRANSACTION_ID)
        now = datetime.datetime.utcnow().replace(tzinfo=UTC)
        now_pb = _datetime_to_pb_timestamp(now)
        response = CommitResponse(commit_timestamp=now_pb)
        gax_api = _SpannerApi(
            _begin_transaction_response=transaction_pb,
            _commit_abort_count=1,
            _commit_abort_retry_seconds=RETRY_SECONDS,
            _commit_abort_retry_nanos=RETRY_NANOS,
            _commit_response=response,
        )
        database = _Database(self.DATABASE_NAME)
        database.spanner_api = gax_api
        session = self._make_one(database)
        session._session_id = 'DEADBEEF'

        called_with = []

        def unit_of_work(txn, *args, **kw):
            called_with.append((txn, args, kw))
            txn.insert(TABLE_NAME, COLUMNS, VALUES)

        time_module = _FauxTimeModule()

        with _Monkey(MUT, time=time_module):
            with self.assertRaises(GaxError) as exc:
                session.run_in_transaction(unit_of_work,
                                           'abc',
                                           some_arg='def',
                                           timeout_secs=0.01)

        self.assertEqual(exc_to_code(exc.exception.cause), StatusCode.ABORTED)
        self.assertIsNone(time_module._slept)
        self.assertEqual(len(called_with), 1)
        txn, args, kw = called_with[0]
        self.assertIsInstance(txn, Transaction)
        self.assertIsNone(txn.committed)
        self.assertEqual(args, ('abc', ))
        self.assertEqual(kw, {'some_arg': 'def'})
def test_update_document(client, cleanup):
    document_id = 'for-update' + unique_resource_id('-')
    document = client.document('made', document_id)
    # Add to clean-up before API request (in case ``create()`` fails).
    cleanup(document)

    # 0. Try to update before the document exists.
    with pytest.raises(NotFound) as exc_info:
        document.update({'not': 'there'})
    assert exc_info.value.message.startswith(MISSING_ENTITY)
    assert document_id in exc_info.value.message

    # 1. Try to update before the document exists (now with an option).
    option1 = client.write_option(create_if_missing=False)
    with pytest.raises(NotFound) as exc_info:
        document.update({'still': 'not-there'}, option=option1)
    assert exc_info.value.message.startswith(MISSING_ENTITY)
    assert document_id in exc_info.value.message

    # 2. Update and create the document (with an option).
    data = {
        'foo': {
            'bar': 'baz',
        },
        'scoop': {
            'barn': 981,
        },
        'other': True,
    }
    option2 = client.write_option(create_if_missing=True)
    write_result2 = document.update(data, option=option2)

    # 3. Send an update without a field path (no option).
    field_updates3 = {'foo': {'quux': 800}}
    write_result3 = document.update(field_updates3)
    assert_timestamp_less(write_result2.update_time, write_result3.update_time)
    snapshot3 = document.get()
    expected3 = {
        'foo': field_updates3['foo'],
        'scoop': data['scoop'],
        'other': data['other'],
    }
    assert snapshot3.to_dict() == expected3

    # 4. Send an update **with** a field path and a delete and a valid
    #    "last timestamp" option.
    field_updates4 = {
        'scoop.silo': None,
        'other': firestore.DELETE_FIELD,
    }
    option4 = client.write_option(last_update_time=snapshot3.update_time)
    write_result4 = document.update(field_updates4, option=option4)
    assert_timestamp_less(write_result3.update_time, write_result4.update_time)
    snapshot4 = document.get()
    expected4 = {
        'foo': field_updates3['foo'],
        'scoop': {
            'barn': data['scoop']['barn'],
            'silo': field_updates4['scoop.silo'],
        },
    }
    assert snapshot4.to_dict() == expected4

    # 5. Call ``update()`` with invalid (in the past) "last timestamp" option.
    assert_timestamp_less(option4._last_update_time, snapshot4.update_time)
    with pytest.raises(GaxError) as exc_info:
        document.update({'bad': 'time-past'}, option=option4)

    assert exc_to_code(exc_info.value.cause) == StatusCode.FAILED_PRECONDITION

    # 6. Call ``update()`` with invalid (in future) "last timestamp" option.
    timestamp_pb = timestamp_pb2.Timestamp(
        seconds=snapshot4.update_time.nanos + 3600,
        nanos=snapshot4.update_time.nanos,
    )
    option6 = client.write_option(last_update_time=timestamp_pb)
    with pytest.raises(GaxError) as exc_info:
        document.set({'bad': 'time-future'}, option=option6)

    assert exc_to_code(exc_info.value.cause) == StatusCode.FAILED_PRECONDITION
Example #47
0
 def test_exc_to_code(self):
     code = grpc.exc_to_code(TestErrors.MyError())
     self.assertEqual(code, grpc.StatusCode.UNKNOWN)
     self.assertEqual(code, grpc.STATUS_CODE_NAMES['UNKNOWN'])
     self.assertIsNone(grpc.exc_to_code(Exception))
     self.assertIsNone(grpc.exc_to_code(grpc.RpcError()))