aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBu Sun Kim <8822365+busunkim96@users.noreply.github.com>2020-07-20 13:43:47 -0700
committerGitHub <noreply@github.com>2020-07-20 13:43:47 -0700
commite2d9a7b209b7dfab300dc848fabbae8f42a2ab19 (patch)
tree239526d467c4335829c1bdc0aecade4f4afb98f4
parent8595f620e7d8295b6a379d6fd7979af3bef717e2 (diff)
downloadpython-api-core-e2d9a7b209b7dfab300dc848fabbae8f42a2ab19.tar.gz
feat: allow quota project to be passed to create_channel (#58)
* feat: allow quota project to be passed to create_channel * chore: update test name * chore: lint and increase auth lib version * chore: fix lint * Update setup.py
-rw-r--r--google/api_core/grpc_helpers.py24
-rw-r--r--google/api_core/grpc_helpers_async.py13
-rw-r--r--setup.py2
-rw-r--r--tests/asyncio/test_grpc_helpers_async.py17
-rw-r--r--tests/unit/test_grpc_helpers.py23
5 files changed, 73 insertions, 6 deletions
diff --git a/google/api_core/grpc_helpers.py b/google/api_core/grpc_helpers.py
index 2203968..dfc8442 100644
--- a/google/api_core/grpc_helpers.py
+++ b/google/api_core/grpc_helpers.py
@@ -176,7 +176,12 @@ def wrap_errors(callable_):
return _wrap_unary_errors(callable_)
-def _create_composite_credentials(credentials=None, credentials_file=None, scopes=None, ssl_credentials=None):
+def _create_composite_credentials(
+ credentials=None,
+ credentials_file=None,
+ scopes=None,
+ ssl_credentials=None,
+ quota_project_id=None):
"""Create the composite credentials for secure channels.
Args:
@@ -191,6 +196,7 @@ def _create_composite_credentials(credentials=None, credentials_file=None, scope
are passed to :func:`google.auth.default`.
ssl_credentials (grpc.ChannelCredentials): Optional SSL channel
credentials. This can be used to specify different certificates.
+ quota_project_id (str): An optional project to use for billing and quota.
Returns:
grpc.ChannelCredentials: The composed channel credentials object.
@@ -210,6 +216,9 @@ def _create_composite_credentials(credentials=None, credentials_file=None, scope
else:
credentials, _ = google.auth.default(scopes=scopes)
+ if quota_project_id:
+ credentials = credentials.with_quota_project(quota_project_id)
+
request = google.auth.transport.requests.Request()
# Create the metadata plugin for inserting the authorization header.
@@ -229,7 +238,14 @@ def _create_composite_credentials(credentials=None, credentials_file=None, scope
)
-def create_channel(target, credentials=None, scopes=None, ssl_credentials=None, credentials_file=None, **kwargs):
+def create_channel(
+ target,
+ credentials=None,
+ scopes=None,
+ ssl_credentials=None,
+ credentials_file=None,
+ quota_project_id=None,
+ **kwargs):
"""Create a secure channel with credentials.
Args:
@@ -245,6 +261,7 @@ def create_channel(target, credentials=None, scopes=None, ssl_credentials=None,
credentials_file (str): A file with credentials that can be loaded with
:func:`google.auth.load_credentials_from_file`. This argument is
mutually exclusive with credentials.
+ quota_project_id (str): An optional project to use for billing and quota.
kwargs: Additional key-word args passed to
:func:`grpc_gcp.secure_channel` or :func:`grpc.secure_channel`.
@@ -259,7 +276,8 @@ def create_channel(target, credentials=None, scopes=None, ssl_credentials=None,
credentials=credentials,
credentials_file=credentials_file,
scopes=scopes,
- ssl_credentials=ssl_credentials
+ ssl_credentials=ssl_credentials,
+ quota_project_id=quota_project_id,
)
if HAS_GRPC_GCP:
diff --git a/google/api_core/grpc_helpers_async.py b/google/api_core/grpc_helpers_async.py
index 1dfe8b9..9a994e9 100644
--- a/google/api_core/grpc_helpers_async.py
+++ b/google/api_core/grpc_helpers_async.py
@@ -206,7 +206,14 @@ def wrap_errors(callable_):
return _wrap_stream_errors(callable_)
-def create_channel(target, credentials=None, scopes=None, ssl_credentials=None, credentials_file=None, **kwargs):
+def create_channel(
+ target,
+ credentials=None,
+ scopes=None,
+ ssl_credentials=None,
+ credentials_file=None,
+ quota_project_id=None,
+ **kwargs):
"""Create an AsyncIO secure channel with credentials.
Args:
@@ -222,6 +229,7 @@ def create_channel(target, credentials=None, scopes=None, ssl_credentials=None,
credentials_file (str): A file with credentials that can be loaded with
:func:`google.auth.load_credentials_from_file`. This argument is
mutually exclusive with credentials.
+ quota_project_id (str): An optional project to use for billing and quota.
kwargs: Additional key-word args passed to :func:`aio.secure_channel`.
Returns:
@@ -235,7 +243,8 @@ def create_channel(target, credentials=None, scopes=None, ssl_credentials=None,
credentials=credentials,
credentials_file=credentials_file,
scopes=scopes,
- ssl_credentials=ssl_credentials
+ ssl_credentials=ssl_credentials,
+ quota_project_id=quota_project_id,
)
return aio.secure_channel(target, composite_credentials, **kwargs)
diff --git a/setup.py b/setup.py
index efa4a12..6e82e54 100644
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,7 @@ release_status = "Development Status :: 5 - Production/Stable"
dependencies = [
"googleapis-common-protos >= 1.6.0, < 2.0dev",
"protobuf >= 3.12.0",
- "google-auth >= 1.18.0, < 2.0dev",
+ "google-auth >= 1.19.1, < 2.0dev",
"requests >= 2.18.0, < 3.0.0dev",
"setuptools >= 34.0.0",
"six >= 1.10.0",
diff --git a/tests/asyncio/test_grpc_helpers_async.py b/tests/asyncio/test_grpc_helpers_async.py
index d56c4c6..924a74c 100644
--- a/tests/asyncio/test_grpc_helpers_async.py
+++ b/tests/asyncio/test_grpc_helpers_async.py
@@ -365,6 +365,23 @@ def test_create_channel_explicit_scoped(grpc_secure_channel, composite_creds_cal
@mock.patch("grpc.composite_channel_credentials")
@mock.patch("grpc.experimental.aio.secure_channel")
+def test_create_channel_explicit_with_quota_project(grpc_secure_channel, composite_creds_call):
+ target = "example.com:443"
+ composite_creds = composite_creds_call.return_value
+
+ credentials = mock.create_autospec(google.auth.credentials.Credentials, instance=True)
+
+ channel = grpc_helpers_async.create_channel(
+ target, credentials=credentials, quota_project_id="project-foo"
+ )
+
+ credentials.with_quota_project.assert_called_once_with("project-foo")
+ assert channel is grpc_secure_channel.return_value
+ grpc_secure_channel.assert_called_once_with(target, composite_creds)
+
+
+@mock.patch("grpc.composite_channel_credentials")
+@mock.patch("grpc.experimental.aio.secure_channel")
@mock.patch(
"google.auth.load_credentials_from_file",
return_value=(mock.sentinel.credentials, mock.sentinel.project)
diff --git a/tests/unit/test_grpc_helpers.py b/tests/unit/test_grpc_helpers.py
index e2f3666..f8fed40 100644
--- a/tests/unit/test_grpc_helpers.py
+++ b/tests/unit/test_grpc_helpers.py
@@ -337,6 +337,29 @@ def test_create_channel_explicit_scoped(grpc_secure_channel, composite_creds_cal
@mock.patch("grpc.composite_channel_credentials")
@mock.patch("grpc.secure_channel")
+def test_create_channel_explicit_with_quota_project(grpc_secure_channel, composite_creds_call):
+ target = "example.com:443"
+ composite_creds = composite_creds_call.return_value
+
+ credentials = mock.create_autospec(google.auth.credentials.Credentials, instance=True)
+
+ channel = grpc_helpers.create_channel(
+ target,
+ credentials=credentials,
+ quota_project_id="project-foo"
+ )
+
+ credentials.with_quota_project.assert_called_once_with("project-foo")
+
+ assert channel is grpc_secure_channel.return_value
+ if grpc_helpers.HAS_GRPC_GCP:
+ grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
+ else:
+ grpc_secure_channel.assert_called_once_with(target, composite_creds)
+
+
+@mock.patch("grpc.composite_channel_credentials")
+@mock.patch("grpc.secure_channel")
@mock.patch(
"google.auth.load_credentials_from_file",
return_value=(mock.sentinel.credentials, mock.sentinel.project)