1# -*- coding: utf-8 -*-
2# Copyright 2020 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import abc
17from typing import Awaitable, Callable, Dict, Optional, Sequence, Union
18import pkg_resources
19
20import google.auth  # type: ignore
21import google.api_core  # type: ignore
22from google.api_core import exceptions as core_exceptions  # type: ignore
23from google.api_core import gapic_v1  # type: ignore
24from google.api_core import retry as retries  # type: ignore
25from google.api_core import operations_v1  # type: ignore
26from google.auth import credentials as ga_credentials  # type: ignore
27from google.oauth2 import service_account  # type: ignore
28
29from google.cloud.datastore_admin_v1.types import datastore_admin
30from google.cloud.datastore_admin_v1.types import index
31from google.longrunning import operations_pb2  # type: ignore
32
33try:
34    DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
35        gapic_version=pkg_resources.get_distribution(
36            "google-cloud-datastore-admin",
37        ).version,
38    )
39except pkg_resources.DistributionNotFound:
40    DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
41
42
43class DatastoreAdminTransport(abc.ABC):
44    """Abstract transport class for DatastoreAdmin."""
45
46    AUTH_SCOPES = (
47        "https://www.googleapis.com/auth/cloud-platform",
48        "https://www.googleapis.com/auth/datastore",
49    )
50
51    DEFAULT_HOST: str = "datastore.googleapis.com"
52
53    def __init__(
54        self,
55        *,
56        host: str = DEFAULT_HOST,
57        credentials: ga_credentials.Credentials = None,
58        credentials_file: Optional[str] = None,
59        scopes: Optional[Sequence[str]] = None,
60        quota_project_id: Optional[str] = None,
61        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
62        always_use_jwt_access: Optional[bool] = False,
63        **kwargs,
64    ) -> None:
65        """Instantiate the transport.
66
67        Args:
68            host (Optional[str]):
69                 The hostname to connect to.
70            credentials (Optional[google.auth.credentials.Credentials]): The
71                authorization credentials to attach to requests. These
72                credentials identify the application to the service; if none
73                are specified, the client will attempt to ascertain the
74                credentials from the environment.
75            credentials_file (Optional[str]): A file with credentials that can
76                be loaded with :func:`google.auth.load_credentials_from_file`.
77                This argument is mutually exclusive with credentials.
78            scopes (Optional[Sequence[str]]): A list of scopes.
79            quota_project_id (Optional[str]): An optional project to use for billing
80                and quota.
81            client_info (google.api_core.gapic_v1.client_info.ClientInfo):
82                The client info used to send a user-agent string along with
83                API requests. If ``None``, then default info will be used.
84                Generally, you only need to set this if you're developing
85                your own client library.
86            always_use_jwt_access (Optional[bool]): Whether self signed JWT should
87                be used for service account credentials.
88        """
89        # Save the hostname. Default to port 443 (HTTPS) if none is specified.
90        if ":" not in host:
91            host += ":443"
92        self._host = host
93
94        scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES}
95
96        # Save the scopes.
97        self._scopes = scopes
98
99        # If no credentials are provided, then determine the appropriate
100        # defaults.
101        if credentials and credentials_file:
102            raise core_exceptions.DuplicateCredentialArgs(
103                "'credentials_file' and 'credentials' are mutually exclusive"
104            )
105
106        if credentials_file is not None:
107            credentials, _ = google.auth.load_credentials_from_file(
108                credentials_file, **scopes_kwargs, quota_project_id=quota_project_id
109            )
110
111        elif credentials is None:
112            credentials, _ = google.auth.default(
113                **scopes_kwargs, quota_project_id=quota_project_id
114            )
115
116        # If the credentials are service account credentials, then always try to use self signed JWT.
117        if (
118            always_use_jwt_access
119            and isinstance(credentials, service_account.Credentials)
120            and hasattr(service_account.Credentials, "with_always_use_jwt_access")
121        ):
122            credentials = credentials.with_always_use_jwt_access(True)
123
124        # Save the credentials.
125        self._credentials = credentials
126
127    def _prep_wrapped_messages(self, client_info):
128        # Precompute the wrapped methods.
129        self._wrapped_methods = {
130            self.export_entities: gapic_v1.method.wrap_method(
131                self.export_entities, default_timeout=60.0, client_info=client_info,
132            ),
133            self.import_entities: gapic_v1.method.wrap_method(
134                self.import_entities, default_timeout=60.0, client_info=client_info,
135            ),
136            self.create_index: gapic_v1.method.wrap_method(
137                self.create_index, default_timeout=60.0, client_info=client_info,
138            ),
139            self.delete_index: gapic_v1.method.wrap_method(
140                self.delete_index, default_timeout=60.0, client_info=client_info,
141            ),
142            self.get_index: gapic_v1.method.wrap_method(
143                self.get_index,
144                default_retry=retries.Retry(
145                    initial=0.1,
146                    maximum=60.0,
147                    multiplier=1.3,
148                    predicate=retries.if_exception_type(
149                        core_exceptions.DeadlineExceeded,
150                        core_exceptions.ServiceUnavailable,
151                    ),
152                    deadline=60.0,
153                ),
154                default_timeout=60.0,
155                client_info=client_info,
156            ),
157            self.list_indexes: gapic_v1.method.wrap_method(
158                self.list_indexes,
159                default_retry=retries.Retry(
160                    initial=0.1,
161                    maximum=60.0,
162                    multiplier=1.3,
163                    predicate=retries.if_exception_type(
164                        core_exceptions.DeadlineExceeded,
165                        core_exceptions.ServiceUnavailable,
166                    ),
167                    deadline=60.0,
168                ),
169                default_timeout=60.0,
170                client_info=client_info,
171            ),
172        }
173
174    def close(self):
175        """Closes resources associated with the transport.
176
177       .. warning::
178            Only call this method if the transport is NOT shared
179            with other clients - this may cause errors in other clients!
180        """
181        raise NotImplementedError()
182
183    @property
184    def operations_client(self):
185        """Return the client designed to process long-running operations."""
186        raise NotImplementedError()
187
188    @property
189    def export_entities(
190        self,
191    ) -> Callable[
192        [datastore_admin.ExportEntitiesRequest],
193        Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]],
194    ]:
195        raise NotImplementedError()
196
197    @property
198    def import_entities(
199        self,
200    ) -> Callable[
201        [datastore_admin.ImportEntitiesRequest],
202        Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]],
203    ]:
204        raise NotImplementedError()
205
206    @property
207    def create_index(
208        self,
209    ) -> Callable[
210        [datastore_admin.CreateIndexRequest],
211        Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]],
212    ]:
213        raise NotImplementedError()
214
215    @property
216    def delete_index(
217        self,
218    ) -> Callable[
219        [datastore_admin.DeleteIndexRequest],
220        Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]],
221    ]:
222        raise NotImplementedError()
223
224    @property
225    def get_index(
226        self,
227    ) -> Callable[
228        [datastore_admin.GetIndexRequest], Union[index.Index, Awaitable[index.Index]]
229    ]:
230        raise NotImplementedError()
231
232    @property
233    def list_indexes(
234        self,
235    ) -> Callable[
236        [datastore_admin.ListIndexesRequest],
237        Union[
238            datastore_admin.ListIndexesResponse,
239            Awaitable[datastore_admin.ListIndexesResponse],
240        ],
241    ]:
242        raise NotImplementedError()
243
244
245__all__ = ("DatastoreAdminTransport",)
246