1# -*- coding: utf-8 -*-
2# Copyright 2022 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#
16from typing import Callable, Dict, Optional, Sequence, Tuple, Union
17import warnings
18
19from google.api_core import gapic_v1, grpc_helpers, operations_v1
20import google.auth # type: ignore
21from google.auth import credentials as ga_credentials # type: ignore
22from google.auth.transport.grpc import SslCredentials # type: ignore
23from google.longrunning import operations_pb2 # type: ignore
24import grpc # type: ignore
25
26from google.cloud.resourcemanager_v3.types import tag_holds
27
28from .base import DEFAULT_CLIENT_INFO, TagHoldsTransport
29
30
31class TagHoldsGrpcTransport(TagHoldsTransport):
32 """gRPC backend transport for TagHolds.
33
34 Allow users to create and manage TagHolds for TagValues.
35 TagHolds represent the use of a Tag Value that is not captured
36 by TagBindings but should still block TagValue deletion (such as
37 a reference in a policy condition). This service provides
38 isolated failure domains by cloud location so that TagHolds can
39 be managed in the same location as their usage.
40
41 This class defines the same methods as the primary client, so the
42 primary client can load the underlying transport implementation
43 and call it.
44
45 It sends protocol buffers over the wire using gRPC (which is built on
46 top of HTTP/2); the ``grpcio`` package must be installed.
47 """
48
49 _stubs: Dict[str, Callable]
50
51 def __init__(
52 self,
53 *,
54 host: str = "cloudresourcemanager.googleapis.com",
55 credentials: Optional[ga_credentials.Credentials] = None,
56 credentials_file: Optional[str] = None,
57 scopes: Optional[Sequence[str]] = None,
58 channel: Optional[grpc.Channel] = None,
59 api_mtls_endpoint: Optional[str] = None,
60 client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
61 ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
62 client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
63 quota_project_id: Optional[str] = None,
64 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
65 always_use_jwt_access: Optional[bool] = False,
66 api_audience: Optional[str] = None,
67 ) -> None:
68 """Instantiate the transport.
69
70 Args:
71 host (Optional[str]):
72 The hostname to connect to.
73 credentials (Optional[google.auth.credentials.Credentials]): The
74 authorization credentials to attach to requests. These
75 credentials identify the application to the service; if none
76 are specified, the client will attempt to ascertain the
77 credentials from the environment.
78 This argument is ignored if ``channel`` is provided.
79 credentials_file (Optional[str]): A file with credentials that can
80 be loaded with :func:`google.auth.load_credentials_from_file`.
81 This argument is ignored if ``channel`` is provided.
82 scopes (Optional(Sequence[str])): A list of scopes. This argument is
83 ignored if ``channel`` is provided.
84 channel (Optional[grpc.Channel]): A ``Channel`` instance through
85 which to make calls.
86 api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
87 If provided, it overrides the ``host`` argument and tries to create
88 a mutual TLS channel with client SSL credentials from
89 ``client_cert_source`` or application default SSL credentials.
90 client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
91 Deprecated. A callback to provide client SSL certificate bytes and
92 private key bytes, both in PEM format. It is ignored if
93 ``api_mtls_endpoint`` is None.
94 ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
95 for the grpc channel. It is ignored if ``channel`` is provided.
96 client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
97 A callback to provide client certificate bytes and private key bytes,
98 both in PEM format. It is used to configure a mutual TLS channel. It is
99 ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
100 quota_project_id (Optional[str]): An optional project to use for billing
101 and quota.
102 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
103 The client info used to send a user-agent string along with
104 API requests. If ``None``, then default info will be used.
105 Generally, you only need to set this if you're developing
106 your own client library.
107 always_use_jwt_access (Optional[bool]): Whether self signed JWT should
108 be used for service account credentials.
109
110 Raises:
111 google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
112 creation failed for any reason.
113 google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
114 and ``credentials_file`` are passed.
115 """
116 self._grpc_channel = None
117 self._ssl_channel_credentials = ssl_channel_credentials
118 self._stubs: Dict[str, Callable] = {}
119 self._operations_client: Optional[operations_v1.OperationsClient] = None
120
121 if api_mtls_endpoint:
122 warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
123 if client_cert_source:
124 warnings.warn("client_cert_source is deprecated", DeprecationWarning)
125
126 if channel:
127 # Ignore credentials if a channel was passed.
128 credentials = False
129 # If a channel was explicitly provided, set it.
130 self._grpc_channel = channel
131 self._ssl_channel_credentials = None
132
133 else:
134 if api_mtls_endpoint:
135 host = api_mtls_endpoint
136
137 # Create SSL credentials with client_cert_source or application
138 # default SSL credentials.
139 if client_cert_source:
140 cert, key = client_cert_source()
141 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
142 certificate_chain=cert, private_key=key
143 )
144 else:
145 self._ssl_channel_credentials = SslCredentials().ssl_credentials
146
147 else:
148 if client_cert_source_for_mtls and not ssl_channel_credentials:
149 cert, key = client_cert_source_for_mtls()
150 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
151 certificate_chain=cert, private_key=key
152 )
153
154 # The base transport sets the host, credentials and scopes
155 super().__init__(
156 host=host,
157 credentials=credentials,
158 credentials_file=credentials_file,
159 scopes=scopes,
160 quota_project_id=quota_project_id,
161 client_info=client_info,
162 always_use_jwt_access=always_use_jwt_access,
163 api_audience=api_audience,
164 )
165
166 if not self._grpc_channel:
167 self._grpc_channel = type(self).create_channel(
168 self._host,
169 # use the credentials which are saved
170 credentials=self._credentials,
171 # Set ``credentials_file`` to ``None`` here as
172 # the credentials that we saved earlier should be used.
173 credentials_file=None,
174 scopes=self._scopes,
175 ssl_credentials=self._ssl_channel_credentials,
176 quota_project_id=quota_project_id,
177 options=[
178 ("grpc.max_send_message_length", -1),
179 ("grpc.max_receive_message_length", -1),
180 ],
181 )
182
183 # Wrap messages. This must be done after self._grpc_channel exists
184 self._prep_wrapped_messages(client_info)
185
186 @classmethod
187 def create_channel(
188 cls,
189 host: str = "cloudresourcemanager.googleapis.com",
190 credentials: Optional[ga_credentials.Credentials] = None,
191 credentials_file: Optional[str] = None,
192 scopes: Optional[Sequence[str]] = None,
193 quota_project_id: Optional[str] = None,
194 **kwargs,
195 ) -> grpc.Channel:
196 """Create and return a gRPC channel object.
197 Args:
198 host (Optional[str]): The host for the channel to use.
199 credentials (Optional[~.Credentials]): The
200 authorization credentials to attach to requests. These
201 credentials identify this application to the service. If
202 none are specified, the client will attempt to ascertain
203 the credentials from the environment.
204 credentials_file (Optional[str]): A file with credentials that can
205 be loaded with :func:`google.auth.load_credentials_from_file`.
206 This argument is mutually exclusive with credentials.
207 scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
208 service. These are only used when credentials are not specified and
209 are passed to :func:`google.auth.default`.
210 quota_project_id (Optional[str]): An optional project to use for billing
211 and quota.
212 kwargs (Optional[dict]): Keyword arguments, which are passed to the
213 channel creation.
214 Returns:
215 grpc.Channel: A gRPC channel object.
216
217 Raises:
218 google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
219 and ``credentials_file`` are passed.
220 """
221
222 return grpc_helpers.create_channel(
223 host,
224 credentials=credentials,
225 credentials_file=credentials_file,
226 quota_project_id=quota_project_id,
227 default_scopes=cls.AUTH_SCOPES,
228 scopes=scopes,
229 default_host=cls.DEFAULT_HOST,
230 **kwargs,
231 )
232
233 @property
234 def grpc_channel(self) -> grpc.Channel:
235 """Return the channel designed to connect to this service."""
236 return self._grpc_channel
237
238 @property
239 def operations_client(self) -> operations_v1.OperationsClient:
240 """Create the client designed to process long-running operations.
241
242 This property caches on the instance; repeated calls return the same
243 client.
244 """
245 # Quick check: Only create a new client if we do not already have one.
246 if self._operations_client is None:
247 self._operations_client = operations_v1.OperationsClient(self.grpc_channel)
248
249 # Return the client from cache.
250 return self._operations_client
251
252 @property
253 def create_tag_hold(
254 self,
255 ) -> Callable[[tag_holds.CreateTagHoldRequest], operations_pb2.Operation]:
256 r"""Return a callable for the create tag hold method over gRPC.
257
258 Creates a TagHold. Returns ALREADY_EXISTS if a TagHold with the
259 same resource and origin exists under the same TagValue.
260
261 Returns:
262 Callable[[~.CreateTagHoldRequest],
263 ~.Operation]:
264 A function that, when called, will call the underlying RPC
265 on the server.
266 """
267 # Generate a "stub function" on-the-fly which will actually make
268 # the request.
269 # gRPC handles serialization and deserialization, so we just need
270 # to pass in the functions for each.
271 if "create_tag_hold" not in self._stubs:
272 self._stubs["create_tag_hold"] = self.grpc_channel.unary_unary(
273 "/google.cloud.resourcemanager.v3.TagHolds/CreateTagHold",
274 request_serializer=tag_holds.CreateTagHoldRequest.serialize,
275 response_deserializer=operations_pb2.Operation.FromString,
276 )
277 return self._stubs["create_tag_hold"]
278
279 @property
280 def delete_tag_hold(
281 self,
282 ) -> Callable[[tag_holds.DeleteTagHoldRequest], operations_pb2.Operation]:
283 r"""Return a callable for the delete tag hold method over gRPC.
284
285 Deletes a TagHold.
286
287 Returns:
288 Callable[[~.DeleteTagHoldRequest],
289 ~.Operation]:
290 A function that, when called, will call the underlying RPC
291 on the server.
292 """
293 # Generate a "stub function" on-the-fly which will actually make
294 # the request.
295 # gRPC handles serialization and deserialization, so we just need
296 # to pass in the functions for each.
297 if "delete_tag_hold" not in self._stubs:
298 self._stubs["delete_tag_hold"] = self.grpc_channel.unary_unary(
299 "/google.cloud.resourcemanager.v3.TagHolds/DeleteTagHold",
300 request_serializer=tag_holds.DeleteTagHoldRequest.serialize,
301 response_deserializer=operations_pb2.Operation.FromString,
302 )
303 return self._stubs["delete_tag_hold"]
304
305 @property
306 def list_tag_holds(
307 self,
308 ) -> Callable[[tag_holds.ListTagHoldsRequest], tag_holds.ListTagHoldsResponse]:
309 r"""Return a callable for the list tag holds method over gRPC.
310
311 Lists TagHolds under a TagValue.
312
313 Returns:
314 Callable[[~.ListTagHoldsRequest],
315 ~.ListTagHoldsResponse]:
316 A function that, when called, will call the underlying RPC
317 on the server.
318 """
319 # Generate a "stub function" on-the-fly which will actually make
320 # the request.
321 # gRPC handles serialization and deserialization, so we just need
322 # to pass in the functions for each.
323 if "list_tag_holds" not in self._stubs:
324 self._stubs["list_tag_holds"] = self.grpc_channel.unary_unary(
325 "/google.cloud.resourcemanager.v3.TagHolds/ListTagHolds",
326 request_serializer=tag_holds.ListTagHoldsRequest.serialize,
327 response_deserializer=tag_holds.ListTagHoldsResponse.deserialize,
328 )
329 return self._stubs["list_tag_holds"]
330
331 def close(self):
332 self.grpc_channel.close()
333
334 @property
335 def get_operation(
336 self,
337 ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]:
338 r"""Return a callable for the get_operation method over gRPC."""
339 # Generate a "stub function" on-the-fly which will actually make
340 # the request.
341 # gRPC handles serialization and deserialization, so we just need
342 # to pass in the functions for each.
343 if "get_operation" not in self._stubs:
344 self._stubs["get_operation"] = self.grpc_channel.unary_unary(
345 "/google.longrunning.Operations/GetOperation",
346 request_serializer=operations_pb2.GetOperationRequest.SerializeToString,
347 response_deserializer=operations_pb2.Operation.FromString,
348 )
349 return self._stubs["get_operation"]
350
351 @property
352 def kind(self) -> str:
353 return "grpc"
354
355
356__all__ = ("TagHoldsGrpcTransport",)