Repository: googleapis/google-auth-library-python

Issue:
Cloud SDK credentials should use the 'active' config not the 'default' config
Context: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2588



Discussion:

Resolving patch:
diff --git a/google/auth/_cloud_sdk.py b/google/auth/_cloud_sdk.py
--- a/google/auth/_cloud_sdk.py
+++ b/google/auth/_cloud_sdk.py
@@ -14,6 +14,7 @@
 
 """Helpers for reading the Google Cloud SDK's configuration."""
 
+import io
 import os
 
 import six
@@ -32,10 +33,6 @@
 # The name of the file in the Cloud SDK config that contains default
 # credentials.
 _CREDENTIALS_FILENAME = 'application_default_credentials.json'
-# The name of the file in the Cloud SDK config that contains the
-# active configuration.
-_ACTIVE_CONFIG_FILENAME = os.path.join(
-    'configurations', 'config_default')
 # The config section and key for the project ID in the cloud SDK config.
 _PROJECT_CONFIG_SECTION = 'core'
 _PROJECT_CONFIG_KEY = 'project'
@@ -83,6 +80,40 @@ def get_application_default_credentials_path():
     return os.path.join(config_path, _CREDENTIALS_FILENAME)
 
 
+def _get_active_config(config_path):
+    """Gets the active config for the Cloud SDK.
+
+    Args:
+        config_path (str): The Cloud SDK's config path.
+
+    Returns:
+        str: The active configuration name.
+    """
+    active_config_filename = os.path.join(config_path, 'active_config')
+
+    if not os.path.isfile(active_config_filename):
+        return 'default'
+
+    with io.open(active_config_filename, 'r', encoding='utf-8') as file_obj:
+        active_config_name = file_obj.read().strip()
+
+    return active_config_name
+
+
+def _get_config_file(config_path, config_name):
+    """Returns the full path to a configuration's config file.
+
+    Args:
+        config_path (str): The Cloud SDK's config path.
+        config_name (str): The configuration name.
+
+    Returns:
+        str: The config file path.
+    """
+    return os.path.join(
+        config_path, 'configurations', 'config_{}'.format(config_name))
+
+
 def get_project_id():
     """Gets the project ID from the Cloud SDK's configuration.
 
@@ -90,7 +121,8 @@ def get_project_id():
         Optional[str]: The project ID.
     """
     config_path = get_config_path()
-    config_file = os.path.join(config_path, _ACTIVE_CONFIG_FILENAME)
+    active_config = _get_active_config(config_path)
+    config_file = _get_config_file(config_path, active_config)
 
     if not os.path.isfile(config_file):
         return None


Test patch:
diff --git a/tests/test__cloud_sdk.py b/tests/test__cloud_sdk.py
--- a/tests/test__cloud_sdk.py
+++ b/tests/test__cloud_sdk.py
@@ -16,6 +16,7 @@
 import os
 
 import mock
+import py
 import pytest
 
 from google.auth import _cloud_sdk
@@ -41,15 +42,20 @@
 
 
 @pytest.fixture
-def config_file(tmpdir):
+def config_dir(tmpdir):
     config_dir = tmpdir.join(
         '.config', _cloud_sdk._CONFIG_DIRECTORY)
-    config_file = config_dir.join(
-        _cloud_sdk._ACTIVE_CONFIG_FILENAME)
 
     with CONFIG_PATH_PATCH as mock_get_config_dir:
         mock_get_config_dir.return_value = str(config_dir)
-        yield config_file
+        yield config_dir
+
+
+@pytest.fixture
+def config_file(config_dir):
+    config_file = py.path.local(_cloud_sdk._get_config_file(
+        str(config_dir), 'default'))
+    yield config_file
 
 
 def test_get_project_id(config_file):
@@ -75,6 +81,20 @@ def test_get_project_id_no_section(config_file):
     assert project_id is None
 
 
+def test_get_project_id_non_default_config(config_dir):
+    active_config = config_dir.join('active_config')
+    test_config = py.path.local(_cloud_sdk._get_config_file(
+        str(config_dir), 'test'))
+
+    # Create an active config file that points to the 'test' config.
+    active_config.write('test', ensure=True)
+    test_config.write(CLOUD_SDK_CONFIG_DATA, ensure=True)
+
+    project_id = _cloud_sdk.get_project_id()
+
+    assert project_id == 'example-project'
+
+
 @CONFIG_PATH_PATCH
 def test_get_application_default_credentials_path(mock_get_config_dir):
     config_path = 'config_path'