Repository: googleapis/python-containeranalysis

Issue:
Credentials to not propagate when using <Container analysis client>.get_grafeas_client()
Below is an example of the issue.
```
from google.cloud.devtools import containeranalysis_v1
from google.oauth2 import service_account

# path to service account json file
credentials_json_path = <path to your service account.json>

# Create credentials object
credentials = service_account.Credentials.from_service_account_file(credentials_json_path)

# Create a client for containeranalysis_v1
analysis_client = containeranalysis_v1.ContainerAnalysisClient(credentials=credentials)

 # The output is <google.oauth2.service_account.Credentials object> which is what we want
print(analysis_client.transport._credentials)

# Create a client for grafeas
grafeas_client = analysis_client.get_grafeas_client()

# Here the output is <google.oauth2.credentials.Credentials object> not <google.oauth2.service_account.Credentials object>
print(grafeas_client.transport._credentials) 
```

Comments:

Patch:
diff --git a/google/cloud/devtools/containeranalysis_v1/services/container_analysis/async_client.py b/google/cloud/devtools/containeranalysis_v1/services/container_analysis/async_client.py
index e876c37..82e9826 100644
--- a/google/cloud/devtools/containeranalysis_v1/services/container_analysis/async_client.py
+++ b/google/cloud/devtools/containeranalysis_v1/services/container_analysis/async_client.py
@@ -221,9 +221,14 @@ class ContainerAnalysisAsyncClient:
         )
 
     def get_grafeas_client(self) -> grafeas_v1.GrafeasClient:
-        transport = type(self).get_transport_class("grpc_asyncio")()
         grafeas_transport = grafeas_v1.services.grafeas.transports.GrafeasGrpcTransport(
-            host=transport._host, scopes=transport.AUTH_SCOPES
+            credentials=self.transport._credentials,
+            # Set ``credentials_file`` to ``None`` here as
+            # transport._credentials contains the credentials
+            # which are saved
+            credentials_file=None,
+            host=self.transport._host,
+            scopes=self.transport.AUTH_SCOPES,
         )
         return grafeas_v1.GrafeasClient(transport=grafeas_transport)
 
diff --git a/google/cloud/devtools/containeranalysis_v1/services/container_analysis/client.py b/google/cloud/devtools/containeranalysis_v1/services/container_analysis/client.py
index 83ec851..7884537 100644
--- a/google/cloud/devtools/containeranalysis_v1/services/container_analysis/client.py
+++ b/google/cloud/devtools/containeranalysis_v1/services/container_analysis/client.py
@@ -406,9 +406,14 @@ class ContainerAnalysisClient(metaclass=ContainerAnalysisClientMeta):
             )
 
     def get_grafeas_client(self) -> grafeas_v1.GrafeasClient:
-        transport = type(self).get_transport_class("grpc")()
         grafeas_transport = grafeas_v1.services.grafeas.transports.GrafeasGrpcTransport(
-            host=transport._host, scopes=transport.AUTH_SCOPES
+            credentials=self.transport._credentials,
+            # Set ``credentials_file`` to ``None`` here as
+            # transport._credentials contains the credentials
+            # which are saved
+            credentials_file=None,
+            host=self.transport._host,
+            scopes=self.transport.AUTH_SCOPES,
         )
         return grafeas_v1.GrafeasClient(transport=grafeas_transport)
 
diff --git a/owlbot.py b/owlbot.py
index de2bcf1..2815408 100644
--- a/owlbot.py
+++ b/owlbot.py
@@ -69,10 +69,14 @@ for library in s.get_staging_dirs(default_version):
         r'''\n\g<1>def get_grafeas_client(
             self
         ) -> grafeas_v1.GrafeasClient:
-            transport = type(self).get_transport_class("grpc")()
             grafeas_transport = grafeas_v1.services.grafeas.transports.GrafeasGrpcTransport(
-                host=transport._host,
-                scopes=transport.AUTH_SCOPES
+                credentials=self.transport._credentials,
+                # Set ``credentials_file`` to ``None`` here as
+                # transport._credentials contains the credentials
+                # which are saved
+                credentials_file=None,
+                host = self.transport._host,
+                scopes=self.transport.AUTH_SCOPES
             )
             return grafeas_v1.GrafeasClient(transport=grafeas_transport)
 
@@ -86,10 +90,14 @@ for library in s.get_staging_dirs(default_version):
         r'''\n\g<1>def get_grafeas_client(
             self
         ) -> grafeas_v1.GrafeasClient:
-            transport = type(self).get_transport_class("grpc_asyncio")()
             grafeas_transport = grafeas_v1.services.grafeas.transports.GrafeasGrpcTransport(
-                host=transport._host,
-                scopes=transport.AUTH_SCOPES
+                credentials=self.transport._credentials,
+                # Set ``credentials_file`` to ``None`` here as
+                # transport._credentials contains the credentials
+                # which are saved
+                credentials_file=None,
+                host = self.transport._host,
+                scopes=self.transport.AUTH_SCOPES
             )
             return grafeas_v1.GrafeasClient(transport=grafeas_transport)
 
@@ -97,6 +105,48 @@ for library in s.get_staging_dirs(default_version):
     \g<1>async def set_iam_policy(''',
     )
 
+    # Add test to ensure that credentials propagate to client.get_grafeas_client()
+    num_replacements = s.replace(library / "tests/**/test_container_analysis.py",
+        """create_channel.assert_called_with\(
+            "containeranalysis.googleapis.com:443",
+            credentials=file_creds,
+            credentials_file=None,
+            quota_project_id=None,
+            default_scopes=\(
+                'https://www.googleapis.com/auth/cloud-platform',
+\),
+            scopes=None,
+            default_host="containeranalysis.googleapis.com",
+            ssl_credentials=None,
+            options=\[
+                \("grpc.max_send_message_length", -1\),
+                \("grpc.max_receive_message_length", -1\),
+            \],
+        \)""",
+        """create_channel.assert_called_with(
+            "containeranalysis.googleapis.com:443",
+            credentials=file_creds,
+            credentials_file=None,
+            quota_project_id=None,
+            default_scopes=(
+                'https://www.googleapis.com/auth/cloud-platform',
+),
+            scopes=None,
+            default_host="containeranalysis.googleapis.com",
+            ssl_credentials=None,
+            options=[
+                ("grpc.max_send_message_length", -1),
+                ("grpc.max_receive_message_length", -1),
+            ],
+        )
+
+        # Also check client.get_grafeas_client() to make sure that the file credentials are used
+        assert file_creds == client.get_grafeas_client().transport._credentials
+        """
+    )
+
+    assert num_replacements == 1
+
     s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst"])
 
 s.remove_staging_dirs()


Test patch:
diff --git a/tests/unit/gapic/containeranalysis_v1/test_container_analysis.py b/tests/unit/gapic/containeranalysis_v1/test_container_analysis.py
index 8c6d80c..f660d72 100644
--- a/tests/unit/gapic/containeranalysis_v1/test_container_analysis.py
+++ b/tests/unit/gapic/containeranalysis_v1/test_container_analysis.py
@@ -650,6 +650,9 @@ def test_container_analysis_client_create_channel_credentials_file(
             ],
         )
 
+        # Also check client.get_grafeas_client() to make sure that the file credentials are used
+        assert file_creds == client.get_grafeas_client().transport._credentials
+
 
 @pytest.mark.parametrize("request_type", [iam_policy_pb2.SetIamPolicyRequest, dict,])
 def test_set_iam_policy(request_type, transport: str = "grpc"):