From a907b7dcf6d7b5013950e4f3457ce6a11ebb382c Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Wed, 23 Jun 2021 20:34:33 +0000
Subject: [PATCH] feat: add always_use_jwt_access (#80)

... chore: update gapic-generator-ruby to the latest commit chore: release gapic-generator-typescript 1.5.0

Committer: @miraleung
PiperOrigin-RevId: 380641501

Source-Link: https://github.com/googleapis/googleapis/commit/076f7e9f0b258bdb54338895d7251b202e8f0de3

Source-Link: https://github.com/googleapis/googleapis-gen/commit/27e4c88b4048e5f56508d4e1aa417d60a3380892
---
 .../dashboards_service/transports/base.py     |  40 +++----
 .../dashboards_service/transports/grpc.py     |   7 +-
 .../transports/grpc_asyncio.py                |   7 +-
 setup.py                                      |   2 +-
 testing/constraints-3.6.txt                   |   2 +-
 .../dashboard_v1/test_dashboards_service.py   | 109 +++---------------
 6 files changed, 39 insertions(+), 128 deletions(-)

diff --git a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/base.py b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/base.py
index 1363421..938b11c 100644
--- a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/base.py
+++ b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/base.py
@@ -24,6 +24,7 @@
 from google.api_core import gapic_v1  # type: ignore
 from google.api_core import retry as retries  # type: ignore
 from google.auth import credentials as ga_credentials  # type: ignore
+from google.oauth2 import service_account  # type: ignore
 
 from google.cloud.monitoring_dashboard_v1.types import dashboard
 from google.cloud.monitoring_dashboard_v1.types import dashboards_service
@@ -47,8 +48,6 @@
     except pkg_resources.DistributionNotFound:  # pragma: NO COVER
         _GOOGLE_AUTH_VERSION = None
 
-_API_CORE_VERSION = google.api_core.__version__
-
 
 class DashboardsServiceTransport(abc.ABC):
     """Abstract transport class for DashboardsService."""
@@ -71,6 +70,7 @@ def __init__(
         scopes: Optional[Sequence[str]] = None,
         quota_project_id: Optional[str] = None,
         client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+        always_use_jwt_access: Optional[bool] = False,
         **kwargs,
     ) -> None:
         """Instantiate the transport.
@@ -94,6 +94,8 @@ def __init__(
                 API requests. If ``None``, then default info will be used.
                 Generally, you only need to set this if you're developing
                 your own client library.
+            always_use_jwt_access (Optional[bool]): Whether self signed JWT should
+                be used for service account credentials.
         """
         # Save the hostname. Default to port 443 (HTTPS) if none is specified.
         if ":" not in host:
@@ -122,13 +124,20 @@ def __init__(
                 **scopes_kwargs, quota_project_id=quota_project_id
             )
 
+        # If the credentials is service account credentials, then always try to use self signed JWT.
+        if (
+            always_use_jwt_access
+            and isinstance(credentials, service_account.Credentials)
+            and hasattr(service_account.Credentials, "with_always_use_jwt_access")
+        ):
+            credentials = credentials.with_always_use_jwt_access(True)
+
         # Save the credentials.
         self._credentials = credentials
 
-    # TODO(busunkim): These two class methods are in the base transport
+    # TODO(busunkim): This method is in the base transport
     # to avoid duplicating code across the transport classes. These functions
-    # should be deleted once the minimum required versions of google-api-core
-    # and google-auth are increased.
+    # should be deleted once the minimum required versions of google-auth is increased.
 
     # TODO: Remove this function once google-auth >= 1.25.0 is required
     @classmethod
@@ -149,27 +158,6 @@ def _get_scopes_kwargs(
 
         return scopes_kwargs
 
-    # TODO: Remove this function once google-api-core >= 1.26.0 is required
-    @classmethod
-    def _get_self_signed_jwt_kwargs(
-        cls, host: str, scopes: Optional[Sequence[str]]
-    ) -> Dict[str, Union[Optional[Sequence[str]], str]]:
-        """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version"""
-
-        self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {}
-
-        if _API_CORE_VERSION and (
-            packaging.version.parse(_API_CORE_VERSION)
-            >= packaging.version.parse("1.26.0")
-        ):
-            self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES
-            self_signed_jwt_kwargs["scopes"] = scopes
-            self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST
-        else:
-            self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES
-
-        return self_signed_jwt_kwargs
-
     def _prep_wrapped_messages(self, client_info):
         # Precompute the wrapped methods.
         self._wrapped_methods = {
diff --git a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc.py b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc.py
index b5186b7..816e86f 100644
--- a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc.py
+++ b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc.py
@@ -152,6 +152,7 @@ def __init__(
             scopes=scopes,
             quota_project_id=quota_project_id,
             client_info=client_info,
+            always_use_jwt_access=True,
         )
 
         if not self._grpc_channel:
@@ -207,14 +208,14 @@ def create_channel(
               and ``credentials_file`` are passed.
         """
 
-        self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes)
-
         return grpc_helpers.create_channel(
             host,
             credentials=credentials,
             credentials_file=credentials_file,
             quota_project_id=quota_project_id,
-            **self_signed_jwt_kwargs,
+            default_scopes=cls.AUTH_SCOPES,
+            scopes=scopes,
+            default_host=cls.DEFAULT_HOST,
             **kwargs,
         )
 
diff --git a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc_asyncio.py b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc_asyncio.py
index 7c8551d..f04aa16 100644
--- a/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc_asyncio.py
+++ b/google/cloud/monitoring_dashboard_v1/services/dashboards_service/transports/grpc_asyncio.py
@@ -81,14 +81,14 @@ def create_channel(
             aio.Channel: A gRPC AsyncIO channel object.
         """
 
-        self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes)
-
         return grpc_helpers_async.create_channel(
             host,
             credentials=credentials,
             credentials_file=credentials_file,
             quota_project_id=quota_project_id,
-            **self_signed_jwt_kwargs,
+            default_scopes=cls.AUTH_SCOPES,
+            scopes=scopes,
+            default_host=cls.DEFAULT_HOST,
             **kwargs,
         )
 
@@ -198,6 +198,7 @@ def __init__(
             scopes=scopes,
             quota_project_id=quota_project_id,
             client_info=client_info,
+            always_use_jwt_access=True,
         )
 
         if not self._grpc_channel:
diff --git a/setup.py b/setup.py
index 0dbf1dc..f89d05a 100644
--- a/setup.py
+++ b/setup.py
@@ -25,7 +25,7 @@
 version = "2.1.0"
 release_status = "Development Status :: 5 - Production/Stable"
 dependencies = [
-    "google-api-core[grpc] >= 1.22.2, < 2.0.0dev",
+    "google-api-core[grpc] >= 1.26.0, <2.0.0dev",
     "proto-plus >= 0.4.0",
     "packaging >= 14.3",
 ]
diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt
index 4b0d32c..b237c54 100644
--- a/testing/constraints-3.6.txt
+++ b/testing/constraints-3.6.txt
@@ -5,7 +5,7 @@
 #
 # e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev",
 # Then this file should have foo==1.14.0
-google-api-core==1.22.2
+google-api-core==1.26.0
 proto-plus==0.4.0
 libcst==0.2.5
 packaging==14.3
diff --git a/tests/unit/gapic/dashboard_v1/test_dashboards_service.py b/tests/unit/gapic/dashboard_v1/test_dashboards_service.py
index 2b6c847..f799b11 100644
--- a/tests/unit/gapic/dashboard_v1/test_dashboards_service.py
+++ b/tests/unit/gapic/dashboard_v1/test_dashboards_service.py
@@ -39,9 +39,6 @@
 )
 from google.cloud.monitoring_dashboard_v1.services.dashboards_service import pagers
 from google.cloud.monitoring_dashboard_v1.services.dashboards_service import transports
-from google.cloud.monitoring_dashboard_v1.services.dashboards_service.transports.base import (
-    _API_CORE_VERSION,
-)
 from google.cloud.monitoring_dashboard_v1.services.dashboards_service.transports.base import (
     _GOOGLE_AUTH_VERSION,
 )
@@ -59,8 +56,9 @@
 import google.auth
 
 
-# TODO(busunkim): Once google-api-core >= 1.26.0 is required:
-# - Delete all the api-core and auth "less than" test cases
+# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively
+# through google-api-core:
+# - Delete the auth "less than" test cases
 # - Delete these pytest markers (Make the "greater than or equal to" tests the default).
 requires_google_auth_lt_1_25_0 = pytest.mark.skipif(
     packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"),
@@ -71,16 +69,6 @@
     reason="This test requires google-auth >= 1.25.0",
 )
 
-requires_api_core_lt_1_26_0 = pytest.mark.skipif(
-    packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"),
-    reason="This test requires google-api-core < 1.26.0",
-)
-
-requires_api_core_gte_1_26_0 = pytest.mark.skipif(
-    packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"),
-    reason="This test requires google-api-core >= 1.26.0",
-)
-
 
 def client_cert_source_callback():
     return b"cert bytes", b"key bytes"
@@ -144,6 +132,18 @@ def test_dashboards_service_client_from_service_account_info(client_class):
         assert client.transport._host == "monitoring.googleapis.com:443"
 
 
+@pytest.mark.parametrize(
+    "client_class", [DashboardsServiceClient, DashboardsServiceAsyncClient,]
+)
+def test_dashboards_service_client_service_account_always_use_jwt(client_class):
+    with mock.patch.object(
+        service_account.Credentials, "with_always_use_jwt_access", create=True
+    ) as use_jwt:
+        creds = service_account.Credentials(None, None, None)
+        client = client_class(credentials=creds)
+        use_jwt.assert_called_with(True)
+
+
 @pytest.mark.parametrize(
     "client_class", [DashboardsServiceClient, DashboardsServiceAsyncClient,]
 )
@@ -1611,7 +1611,6 @@ def test_dashboards_service_transport_auth_adc_old_google_auth(transport_class):
         (transports.DashboardsServiceGrpcAsyncIOTransport, grpc_helpers_async),
     ],
 )
-@requires_api_core_gte_1_26_0
 def test_dashboards_service_transport_create_channel(transport_class, grpc_helpers):
     # If credentials and host are not provided, the transport class should use
     # ADC credentials.
@@ -1645,84 +1644,6 @@ def test_dashboards_service_transport_create_channel(transport_class, grpc_helpe
         )
 
 
-@pytest.mark.parametrize(
-    "transport_class,grpc_helpers",
-    [
-        (transports.DashboardsServiceGrpcTransport, grpc_helpers),
-        (transports.DashboardsServiceGrpcAsyncIOTransport, grpc_helpers_async),
-    ],
-)
-@requires_api_core_lt_1_26_0
-def test_dashboards_service_transport_create_channel_old_api_core(
-    transport_class, grpc_helpers
-):
-    # If credentials and host are not provided, the transport class should use
-    # ADC credentials.
-    with mock.patch.object(
-        google.auth, "default", autospec=True
-    ) as adc, mock.patch.object(
-        grpc_helpers, "create_channel", autospec=True
-    ) as create_channel:
-        creds = ga_credentials.AnonymousCredentials()
-        adc.return_value = (creds, None)
-        transport_class(quota_project_id="octopus")
-
-        create_channel.assert_called_with(
-            "monitoring.googleapis.com:443",
-            credentials=creds,
-            credentials_file=None,
-            quota_project_id="octopus",
-            scopes=(
-                "https://www.googleapis.com/auth/cloud-platform",
-                "https://www.googleapis.com/auth/monitoring",
-                "https://www.googleapis.com/auth/monitoring.read",
-                "https://www.googleapis.com/auth/monitoring.write",
-            ),
-            ssl_credentials=None,
-            options=[
-                ("grpc.max_send_message_length", -1),
-                ("grpc.max_receive_message_length", -1),
-            ],
-        )
-
-
-@pytest.mark.parametrize(
-    "transport_class,grpc_helpers",
-    [
-        (transports.DashboardsServiceGrpcTransport, grpc_helpers),
-        (transports.DashboardsServiceGrpcAsyncIOTransport, grpc_helpers_async),
-    ],
-)
-@requires_api_core_lt_1_26_0
-def test_dashboards_service_transport_create_channel_user_scopes(
-    transport_class, grpc_helpers
-):
-    # If credentials and host are not provided, the transport class should use
-    # ADC credentials.
-    with mock.patch.object(
-        google.auth, "default", autospec=True
-    ) as adc, mock.patch.object(
-        grpc_helpers, "create_channel", autospec=True
-    ) as create_channel:
-        creds = ga_credentials.AnonymousCredentials()
-        adc.return_value = (creds, None)
-
-        transport_class(quota_project_id="octopus", scopes=["1", "2"])
-
-        create_channel.assert_called_with(
-            "monitoring.googleapis.com:443",
-            credentials=creds,
-            credentials_file=None,
-            quota_project_id="octopus",
-            scopes=["1", "2"],
-            ssl_credentials=None,
-            options=[
-                ("grpc.max_send_message_length", -1),
-                ("grpc.max_receive_message_length", -1),
-            ],
-        )
-
-
 @pytest.mark.parametrize(
     "transport_class",
     [