Change metadata service helper to work with any query parameters (#588)

Part of #579 

This helper is used with '?recursive=true' in one place, and can now be used by
IDTokenCredentials for requests with query parameters to the metadata identity
end-point.

This change will allow making requests to the token end-point with '?scopes=..'
query parameters.
diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py
index fe82141..94e4ffb 100644
--- a/google/auth/compute_engine/_metadata.py
+++ b/google/auth/compute_engine/_metadata.py
@@ -108,7 +108,9 @@
     return False
 
 
-def get(request, path, root=_METADATA_ROOT, recursive=False, retry_count=5):
+def get(
+    request, path, root=_METADATA_ROOT, params=None, recursive=False, retry_count=5
+):
     """Fetch a resource from the metadata server.
 
     Args:
@@ -117,6 +119,8 @@
         path (str): The resource to retrieve. For example,
             ``'instance/service-accounts/default'``.
         root (str): The full path to the metadata server root.
+        params (Optional[Mapping[str, str]]): A mapping of query parameter
+            keys to values.
         recursive (bool): Whether to do a recursive query of metadata. See
             https://cloud.google.com/compute/docs/metadata#aggcontents for more
             details.
@@ -133,7 +137,7 @@
             retrieving metadata.
     """
     base_url = urlparse.urljoin(root, path)
-    query_params = {}
+    query_params = {} if params is None else params
 
     if recursive:
         query_params["recursive"] = "true"
@@ -224,11 +228,10 @@
         google.auth.exceptions.TransportError: if an error occurred while
             retrieving metadata.
     """
-    return get(
-        request,
-        "instance/service-accounts/{0}/".format(service_account),
-        recursive=True,
-    )
+    path = "instance/service-accounts/{0}/".format(service_account)
+    # See https://cloud.google.com/compute/docs/metadata#aggcontents
+    # for more on the use of 'recursive'.
+    return get(request, path, params={"recursive": "true"})
 
 
 def get_service_account_token(request, service_account="default"):
diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py
index b7fca18..8a41ffc 100644
--- a/google/auth/compute_engine/credentials.py
+++ b/google/auth/compute_engine/credentials.py
@@ -323,12 +323,9 @@
             ValueError: If extracting expiry from the obtained ID token fails.
         """
         try:
-            id_token = _metadata.get(
-                request,
-                "instance/service-accounts/default/identity?audience={}&format=full".format(
-                    self._target_audience
-                ),
-            )
+            path = "instance/service-accounts/default/identity"
+            params = {"audience": self._target_audience, "format": "full"}
+            id_token = _metadata.get(request, path, params=params)
         except exceptions.TransportError as caught_exc:
             new_exc = exceptions.RefreshError(caught_exc)
             six.raise_from(new_exc, caught_exc)
diff --git a/tests/compute_engine/test__metadata.py b/tests/compute_engine/test__metadata.py
index d9b039a..d053372 100644
--- a/tests/compute_engine/test__metadata.py
+++ b/tests/compute_engine/test__metadata.py
@@ -155,6 +155,49 @@
     assert result == data
 
 
+def test_get_success_params():
+    data = "foobar"
+    request = make_request(data, headers={"content-type": "text/plain"})
+    params = {"recursive": "true"}
+
+    result = _metadata.get(request, PATH, params=params)
+
+    request.assert_called_once_with(
+        method="GET",
+        url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
+        headers=_metadata._METADATA_HEADERS,
+    )
+    assert result == data
+
+
+def test_get_success_recursive_and_params():
+    data = "foobar"
+    request = make_request(data, headers={"content-type": "text/plain"})
+    params = {"recursive": "false"}
+    result = _metadata.get(request, PATH, recursive=True, params=params)
+
+    request.assert_called_once_with(
+        method="GET",
+        url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
+        headers=_metadata._METADATA_HEADERS,
+    )
+    assert result == data
+
+
+def test_get_success_recursive():
+    data = "foobar"
+    request = make_request(data, headers={"content-type": "text/plain"})
+
+    result = _metadata.get(request, PATH, recursive=True)
+
+    request.assert_called_once_with(
+        method="GET",
+        url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
+        headers=_metadata._METADATA_HEADERS,
+    )
+    assert result == data
+
+
 def test_get_success_custom_root_new_variable():
     request = make_request("{}", headers={"content-type": "application/json"})