Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,16 @@
)

import google.protobuf
from google.api_core import _feature_gating_helpers, _otel_helpers, gapic_v1
from google.api_core import client_options as client_options_lib
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1
from google.api_core import retry as retries
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.auth.transport import mtls # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.oauth2 import service_account # type: ignore

from google.cloud.secretmanager_v1 import gapic_version as package_version
from google.oauth2 import service_account # type: ignore

try:
OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
Expand All @@ -68,7 +67,6 @@
import google.protobuf.field_mask_pb2 as field_mask_pb2 # type: ignore
import google.protobuf.timestamp_pb2 as timestamp_pb2 # type: ignore
from google.cloud.location import locations_pb2 # type: ignore

from google.cloud.secretmanager_v1.services.secret_manager_service import pagers
from google.cloud.secretmanager_v1.types import resources, service

Expand Down Expand Up @@ -745,18 +743,31 @@ def __init__(
if isinstance(transport, str) or transport is None
else cast(Callable[..., SecretManagerServiceTransport], transport)
)
# Resolve interceptors for gRPC
interceptors = None
if transport_init is SecretManagerServiceGrpcTransport:
otel_interceptor = _otel_helpers.get_otel_grpc_interceptor(
self._client_options
)
if otel_interceptor:
interceptors = [otel_interceptor]

# initialize with the provided callable or the passed in class
self._transport = transport_init(
credentials=credentials,
credentials_file=self._client_options.credentials_file,
host=self._api_endpoint,
scopes=self._client_options.scopes,
client_cert_source_for_mtls=self._client_cert_source,
quota_project_id=self._client_options.quota_project_id,
client_info=client_info,
always_use_jwt_access=True,
api_audience=self._client_options.api_audience,
)
transport_kwargs = {
"credentials": credentials,
"credentials_file": self._client_options.credentials_file,
"host": self._api_endpoint,
"scopes": self._client_options.scopes,
"client_cert_source_for_mtls": self._client_cert_source,
"quota_project_id": self._client_options.quota_project_id,
"client_info": client_info,
"always_use_jwt_access": True,
"api_audience": self._client_options.api_audience,
}
if interceptors is not None:
transport_kwargs["interceptors"] = interceptors

self._transport = transport_init(**transport_kwargs)

if "async" not in str(self._transport):
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.cloud.location import locations_pb2 # type: ignore
from google.protobuf.json_format import MessageToJson

from google.cloud.secretmanager_v1.types import resources, service
from google.protobuf.json_format import MessageToJson

from .base import DEFAULT_CLIENT_INFO, SecretManagerServiceTransport

Expand Down Expand Up @@ -148,6 +147,7 @@ def __init__(
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
api_audience: Optional[str] = None,
interceptors: Optional[Sequence[object]] = None,
) -> None:
"""Instantiate the transport.

Expand Down Expand Up @@ -198,6 +198,9 @@ def __init__(
to the service that will be set when using certain 3rd party
authentication flows. Audience is typically a resource identifier.
If not set, the host value will be used as a default.
interceptors (Optional[Sequence[grpc.ClientInterceptor]]):
Additional interceptors to be injected into the gRPC channel pipeline.
These are executed in order.

Raises:
google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
Expand Down Expand Up @@ -274,6 +277,10 @@ def __init__(
],
)

if interceptors:
for i in interceptors:
self._grpc_channel = grpc.intercept_channel(self._grpc_channel, i)

self._interceptor = _LoggingClientInterceptor()
self._logged_channel = grpc.intercept_channel(
self._grpc_channel, self._interceptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,14 @@
from google.auth import credentials as ga_credentials
from google.auth.exceptions import MutualTLSChannelError
from google.cloud.location import locations_pb2
from google.oauth2 import service_account

from google.cloud.secretmanager_v1.services.secret_manager_service import (
SecretManagerServiceAsyncClient,
SecretManagerServiceClient,
pagers,
transports,
)
from google.cloud.secretmanager_v1.types import resources, service
from google.oauth2 import service_account

CRED_INFO_JSON = {
"credential_source": "/path/to/file",
Expand Down Expand Up @@ -770,6 +769,49 @@ def test_secret_manager_service_client_client_options(
)


def test_secret_manager_service_client_otel_interceptor_injection():
# Mock the helper to return a sentinel interceptor
mock_interceptor = mock.Mock()

with mock.patch(
"google.cloud.secretmanager_v1.services.secret_manager_service.client._otel_helpers.get_otel_grpc_interceptor"
) as mock_get_interceptor:
mock_get_interceptor.return_value = mock_interceptor

with mock.patch.object(
transports.SecretManagerServiceGrpcTransport, "__init__"
) as patched_transport_init:
patched_transport_init.return_value = None

client = SecretManagerServiceClient(transport="grpc")

mock_get_interceptor.assert_called_once()

called_kwargs = patched_transport_init.call_args.kwargs
assert "interceptors" in called_kwargs
assert called_kwargs["interceptors"] == [mock_interceptor]


def test_secret_manager_service_client_otel_interceptor_injection_disabled():
# The helper does not return an interceptor
with mock.patch(
"google.cloud.secretmanager_v1.services.secret_manager_service.client._otel_helpers.get_otel_grpc_interceptor"
) as mock_get_interceptor:
mock_get_interceptor.return_value = None

with mock.patch.object(
transports.SecretManagerServiceGrpcTransport, "__init__"
) as patched_transport_init:
patched_transport_init.return_value = None

client = SecretManagerServiceClient(transport="grpc")

mock_get_interceptor.assert_called_once()

called_kwargs = patched_transport_init.call_args.kwargs
assert "interceptors" not in called_kwargs


@pytest.mark.parametrize(
"client_class,transport_class,transport_name,use_client_cert_env",
[
Expand Down
Loading