Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: avoid authentication when use emulator #328

Closed
wants to merge 4 commits into from

Conversation

HemangChothani
Copy link
Contributor

Fixes #324

@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Nov 28, 2020
@product-auto-label product-auto-label bot added the api: storage Issues related to the googleapis/python-storage API. label Nov 28, 2020
project = os.getenv("GCLOUD_PROJECT")
if project is None:
raise ValueError(
"For emulator pass `project` as a argument or set `GCLOUD_PROJECT` via environment variable"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"For emulator pass `project` as a argument or set `GCLOUD_PROJECT` via environment variable"
"To use the GCS emulator, pass 'project' as an argument "
"or set GCLOUD_PROJECT environment variable"

Comment on lines 222 to 232
def test_ctor_w_emulator_w_env_var_glcoud_project(self):
from google.cloud.storage._helpers import STORAGE_EMULATOR_ENV_VAR

HOST = "https://api.example.com"
PROJECT = "test"

with mock.patch("os.environ", {STORAGE_EMULATOR_ENV_VAR: HOST}):
with mock.patch("os.getenv", side_effect=[HOST, PROJECT]):
client = self._make_one()
self.assertEqual(client.project, PROJECT)
self.assertEqual(client._connection.API_BASE_URL, HOST)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test needs an assertion that the client's credentials is an instance of AnonymousCredentials.

Also, rather than patching os.getenv, this would be clearer if we just patched in the expected environment:

Suggested change
def test_ctor_w_emulator_w_env_var_glcoud_project(self):
from google.cloud.storage._helpers import STORAGE_EMULATOR_ENV_VAR
HOST = "https://api.example.com"
PROJECT = "test"
with mock.patch("os.environ", {STORAGE_EMULATOR_ENV_VAR: HOST}):
with mock.patch("os.getenv", side_effect=[HOST, PROJECT]):
client = self._make_one()
self.assertEqual(client.project, PROJECT)
self.assertEqual(client._connection.API_BASE_URL, HOST)
def test_ctor_w_emulator_w_env_var_glcoud_project(self):
from google.auth.credentials import AnonymousCredentials
from google.cloud.storage._helpers import STORAGE_EMULATOR_ENV_VAR
HOST = "https://api.example.com"
PROJECT = "test"
environ = {
STORAGE_EMULATOR_ENV_VAR: HOST,
"GCLOUD_PROJECT": PROJECT,
}
with mock.patch("os.environ", environ):
client = self._make_one()
self.assertEqual(client.project, PROJECT)
self.assertEqual(client._connection.API_BASE_URL, HOST)
self.assertIsInstance(client._credentials, AnonymousCredentials)

Comment on lines 234 to 246
def test_ctor_w_emulator_w_project_argument(self):
HOST = "https://api.example.com"
PROJECT = "test"

with mock.patch("os.getenv", side_effect=[HOST]):
client = self._make_one(project=PROJECT)
self.assertEqual(client.project, PROJECT)

def test_ctor_w_emulator_missing_project(self):
HOST = "https://api.example.com"
with mock.patch("os.getenv", side_effect=[HOST, None]):
with self.assertRaises(ValueError):
self._make_one()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to verify that the passed-in project overrides the one in the environment. Likewise for these tests, just patch os.environ:

Suggested change
def test_ctor_w_emulator_w_project_argument(self):
HOST = "https://api.example.com"
PROJECT = "test"
with mock.patch("os.getenv", side_effect=[HOST]):
client = self._make_one(project=PROJECT)
self.assertEqual(client.project, PROJECT)
def test_ctor_w_emulator_missing_project(self):
HOST = "https://api.example.com"
with mock.patch("os.getenv", side_effect=[HOST, None]):
with self.assertRaises(ValueError):
self._make_one()
def test_ctor_w_emulator_w_project_argument(self):
from google.auth.credentials import AnonymousCredentials
from google.cloud.storage._helpers import STORAGE_EMULATOR_ENV_VAR
HOST = "https://api.example.com"
PROJECT = "test"
ENVIRON_PROJECT = "environ-project"
environ = {
STORAGE_EMULATOR_ENV_VAR: HOST,
"GCLOUD_PROJECT": ENVIRON_PROJECT,
}
with mock.patch("os.environ", environ):
client = self._make_one(project=PROJECT)
self.assertEqual(client.project, PROJECT)
self.assertEqual(client._connection.API_BASE_URL, HOST)
self.assertIsInstance(client._credentials, AnonymousCredentials)
def test_ctor_w_emulator_missing_project(self):
from google.cloud.storage._helpers import STORAGE_EMULATOR_ENV_VAR
HOST = "https://api.example.com"
environ = {STORAGE_EMULATOR_ENV_VAR: HOST}
with mock.patch("os.environ", environ):
with self.assertRaises(ValueError):
self._make_one()

@@ -112,6 +114,15 @@ def __init__(
if project is _marker:
project = None

if os.getenv(STORAGE_EMULATOR_ENV_VAR) is not None:
credentials = AnonymousCredentials()
if project in [_marker, None]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is project validation necessary given the super class will fall back to the expected environment variables?

https://googleapis.dev/python/google-cloud-core/latest/client.html#google.cloud.client.ClientWithProject

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, when we are passing credentials as a keyword argument and if not passing project then it found the project in fall back but then throw an error about Default credential from here https://github.com/googleapis/google-auth-library-python/blob/bc92abbce5e0a5e7b5de8157e7772db84349a6cb/google/auth/_default.py#L356 when called a method google.auth.default() method because method unable to find credential from the given four options .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think i can remove this condition after merge of cloud-core-51 PR

@@ -112,6 +114,15 @@ def __init__(
if project is _marker:
project = None

if os.getenv(STORAGE_EMULATOR_ENV_VAR) is not None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to infer this from endpoint value in client_options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry didn't get the point, few questions regarding that

  • what if client_options didn't pass

  • which value use to compare with kw_args["api_endpoint"]? _DEFAULT_STORAGE_HOST which is https://storage.googleapis.com?

  • Right now first we call the super class of client with credentials and then iterate the client_options and _get_storage_host() for an api_endpoint, should we need to change that order?

@HemangChothani HemangChothani requested a review from a team December 3, 2020 11:34
@cojenco
Copy link
Contributor

cojenco commented Feb 10, 2022

Replaced by #679

@cojenco cojenco closed this Feb 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the googleapis/python-storage API. cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Avoid Authentication When Connecting to Storage Emulator
4 participants