Skip to content

Commit 0e1c21b

Browse files
committed
feat(secretmanager): guard _observability import and update interceptor assertions
1 parent e73fdcb commit 0e1c21b

6 files changed

Lines changed: 48 additions & 14 deletions

File tree

packages/google-cloud-secret-manager/google/cloud/secretmanager_v1/services/secret_manager_service/client.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,21 @@
3535
)
3636

3737
import google.protobuf
38-
from google.api_core import _observability, gapic_v1
3938
from google.api_core import client_options as client_options_lib
4039
from google.api_core import exceptions as core_exceptions
40+
from google.api_core import gapic_v1
4141
from google.api_core import retry as retries
4242
from google.auth import credentials as ga_credentials # type: ignore
4343
from google.auth.exceptions import MutualTLSChannelError # type: ignore
4444
from google.auth.transport import mtls # type: ignore
4545
from google.oauth2 import service_account # type: ignore
4646

47+
try:
48+
# mypy: _observability was added in google-api-core 2.35.0; guard for older versions
49+
from google.api_core import _observability # type: ignore[attr-defined]
50+
except ImportError:
51+
_observability = None # type: ignore[assignment]
52+
4753
from google.cloud.secretmanager_v1 import gapic_version as package_version
4854
from google.cloud.secretmanager_v1._compat import (
4955
get_api_endpoint,
@@ -622,12 +628,18 @@ def __init__(
622628

623629
# When OpenTelemetry tracing is enabled, obtain the channel interceptor
624630
# and pass it to the transport.
625-
if transport_init is SecretManagerServiceGrpcTransport:
631+
if (
632+
transport_init is SecretManagerServiceGrpcTransport
633+
and _observability is not None
634+
):
626635
otel_interceptor = _observability.get_otel_interceptor(
627636
self._client_options
628637
)
629638
if otel_interceptor is not None:
630-
transport_kwargs["interceptors"] = [otel_interceptor]
639+
interceptors = transport_kwargs.get("interceptors", [])
640+
transport_kwargs["interceptors"] = [otel_interceptor] + list(
641+
interceptors
642+
)
631643

632644
self._transport = transport_init(**transport_kwargs)
633645

packages/google-cloud-secret-manager/google/cloud/secretmanager_v1/services/secret_manager_service/transports/grpc.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@
2727
import grpc # type: ignore
2828
import proto # type: ignore
2929
from google.api_core import gapic_v1, grpc_helpers
30-
from google.api_core.grpc_helpers import ClientInterceptor
30+
31+
try:
32+
# mypy: ClientInterceptor was added in google-api-core 2.35.0; guard for older versions
33+
from google.api_core.grpc_helpers import ClientInterceptor # type: ignore[attr-defined]
34+
except ImportError:
35+
ClientInterceptor = grpc.ClientInterceptor # type: ignore[misc,assignment]
3136
from google.auth import credentials as ga_credentials # type: ignore
3237
from google.auth.transport.grpc import SslCredentials # type: ignore
3338
from google.cloud.location import locations_pb2 # type: ignore
@@ -286,9 +291,9 @@ def __init__(
286291
],
287292
)
288293

289-
self._grpc_channel = grpc_helpers.apply_channel_interceptors(
290-
self._grpc_channel, interceptors
291-
)
294+
apply_interceptors = getattr(grpc_helpers, "apply_channel_interceptors", None)
295+
if apply_interceptors is not None:
296+
self._grpc_channel = apply_interceptors(self._grpc_channel, interceptors)
292297

293298
self._interceptor = _LoggingClientInterceptor()
294299
self._logged_channel = grpc.intercept_channel(

packages/google-cloud-secret-manager/noxfile.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@
7171
"pytest-asyncio",
7272
]
7373
UNIT_TEST_EXTERNAL_DEPENDENCIES: List[str] = []
74-
UNIT_TEST_LOCAL_DEPENDENCIES: List[str] = [
75-
"../google-api-core[tracing,testing]",
76-
]
74+
UNIT_TEST_LOCAL_DEPENDENCIES: List[str] = []
7775
UNIT_TEST_DEPENDENCIES: List[str] = []
7876
UNIT_TEST_EXTRAS: List[str] = []
7977
UNIT_TEST_EXTRAS_BY_PYTHON: Dict[str, List[str]] = {}

packages/google-cloud-secret-manager/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
release_status = "Development Status :: 5 - Production/Stable"
4545

4646
dependencies = [
47-
"google-api-core[grpc] >= 2.35.0, <3.0.0",
47+
"google-api-core[grpc] >= 2.28.0, <3.0.0",
4848
# Exclude incompatible versions of `google-auth`
4949
# See https://github.com/googleapis/google-cloud-python/issues/12364
5050
"google-auth >= 2.14.1, <3.0.0,!=2.24.0,!=2.25.0",

packages/google-cloud-secret-manager/testing/constraints-3.10.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# pinning their versions to their lower bounds.
55
# For example, if setup.py has "google-cloud-foo >= 1.14.0, < 2.0.0",
66
# then this file should have google-cloud-foo==1.14.0
7-
google-api-core==2.35.0
7+
google-api-core==2.28.0
88
google-auth==2.14.1
99
grpcio==1.59.0
1010
proto-plus==1.26.1

packages/google-cloud-secret-manager/tests/unit/gapic/secretmanager_v1/test_secret_manager_service.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ def test_secret_manager_service_client_otel_channel_injection_disabled():
507507
"""Proves that when OpenTelemetry tracing is disabled:
508508

509509
1. SecretManagerServiceClient checks for an OTel interceptor and receives None.
510-
2. No 'interceptors' argument is passed to the transport constructor.
510+
2. No OTel interceptor is added to the transport constructor kwargs.
511511
"""
512512
with (
513513
mock.patch(
@@ -522,7 +522,26 @@ def test_secret_manager_service_client_otel_channel_injection_disabled():
522522

523523
mock_get_interceptor.assert_called_once_with(client._client_options)
524524
called_kwargs = patched_transport_init.call_args.kwargs
525-
assert "interceptors" not in called_kwargs
525+
interceptors = called_kwargs.get("interceptors", [])
526+
assert not interceptors
527+
528+
529+
def test_secret_manager_service_client_observability_import_error():
530+
"""Proves that when _observability cannot be imported (older google-api-core),
531+
SecretManagerServiceClient instantiates gracefully without error.
532+
"""
533+
with (
534+
mock.patch(
535+
"google.cloud.secretmanager_v1.services.secret_manager_service.client._observability",
536+
None,
537+
),
538+
mock.patch.object(
539+
transports.SecretManagerServiceGrpcTransport, "__init__", return_value=None
540+
) as patched_transport_init,
541+
):
542+
SecretManagerServiceClient(transport="grpc")
543+
called_kwargs = patched_transport_init.call_args.kwargs
544+
assert not called_kwargs.get("interceptors", [])
526545

527546

528547
def test_secret_manager_service_grpc_transport_interceptors():

0 commit comments

Comments
 (0)