Skip to content
This repository was archived by the owner on Mar 6, 2026. It is now read-only.

Commit b33b802

Browse files
craigcitroJon Wayne Parrott
authored andcommitted
Allow customizing the GCE metadata service address via an env var. (#148)
The goal here is to make it possible for a user of a binary that depends on this library (eg the google cloud SDK) to be able to customize where it looks for the GCE metadata service. (An adventurous user can already customize the GCE metadata service location via the existing global vars in this library.)
1 parent 0c09c73 commit b33b802

3 files changed

Lines changed: 58 additions & 2 deletions

File tree

google/auth/compute_engine/_metadata.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@
2626
from six.moves.urllib import parse as urlparse
2727

2828
from google.auth import _helpers
29+
from google.auth import environment_vars
2930
from google.auth import exceptions
3031

3132
_LOGGER = logging.getLogger(__name__)
3233

33-
_METADATA_ROOT = 'http://metadata.google.internal/computeMetadata/v1/'
34+
_METADATA_ROOT = 'http://{}/computeMetadata/v1/'.format(
35+
os.getenv(environment_vars.GCE_METADATA_ROOT, 'metadata.google.internal'))
3436

3537
# This is used to ping the metadata server, it avoids the cost of a DNS
3638
# lookup.
37-
_METADATA_IP_ROOT = 'http://169.254.169.254'
39+
_METADATA_IP_ROOT = 'http://{}'.format(
40+
os.getenv(environment_vars.GCE_METADATA_IP, '169.254.169.254'))
3841
_METADATA_FLAVOR_HEADER = 'metadata-flavor'
3942
_METADATA_FLAVOR_VALUE = 'Google'
4043
_METADATA_HEADERS = {_METADATA_FLAVOR_HEADER: _METADATA_FLAVOR_VALUE}

google/auth/environment_vars.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@
3737
CLOUD_SDK_CONFIG_DIR = 'CLOUDSDK_CONFIG'
3838
"""Environment variable defines the location of Google Cloud SDK's config
3939
files."""
40+
41+
# These two variables allow for customization of the addresses used when
42+
# contacting the GCE metadata service.
43+
GCE_METADATA_ROOT = 'GCE_METADATA_ROOT'
44+
"""Environment variable providing an alternate hostname or host:port to be
45+
used for GCE metadata requests."""
46+
47+
GCE_METADATA_IP = 'GCE_METADATA_IP'
48+
"""Environment variable providing an alternate ip:port to be used for ip-only
49+
GCE metadata requests."""

tests/compute_engine/test__metadata.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414

1515
import datetime
1616
import json
17+
import os
1718

1819
import mock
1920
import pytest
2021
from six.moves import http_client
22+
from six.moves import reload_module
2123

2224
from google.auth import _helpers
25+
from google.auth import environment_vars
2326
from google.auth import exceptions
2427
from google.auth.compute_engine import _metadata
2528

@@ -67,6 +70,26 @@ def test_ping_failure_connection_failed(mock_request):
6770
assert not _metadata.ping(request_mock)
6871

6972

73+
def test_ping_success_custom_root(mock_request):
74+
request_mock = mock_request('', headers=_metadata._METADATA_HEADERS)
75+
76+
fake_ip = '1.2.3.4'
77+
os.environ[environment_vars.GCE_METADATA_IP] = fake_ip
78+
reload_module(_metadata)
79+
80+
try:
81+
assert _metadata.ping(request_mock)
82+
finally:
83+
del os.environ[environment_vars.GCE_METADATA_IP]
84+
reload_module(_metadata)
85+
86+
request_mock.assert_called_once_with(
87+
method='GET',
88+
url='http://' + fake_ip,
89+
headers=_metadata._METADATA_HEADERS,
90+
timeout=_metadata._METADATA_DEFAULT_TIMEOUT)
91+
92+
7093
def test_get_success_json(mock_request):
7194
key, value = 'foo', 'bar'
7295

@@ -96,6 +119,26 @@ def test_get_success_text(mock_request):
96119
assert result == data
97120

98121

122+
def test_get_success_custom_root(mock_request):
123+
request_mock = mock_request(
124+
'{}', headers={'content-type': 'application/json'})
125+
126+
fake_root = 'another.metadata.service'
127+
os.environ[environment_vars.GCE_METADATA_ROOT] = fake_root
128+
reload_module(_metadata)
129+
130+
try:
131+
_metadata.get(request_mock, PATH)
132+
finally:
133+
del os.environ[environment_vars.GCE_METADATA_ROOT]
134+
reload_module(_metadata)
135+
136+
request_mock.assert_called_once_with(
137+
method='GET',
138+
url='http://{}/computeMetadata/v1/{}'.format(fake_root, PATH),
139+
headers=_metadata._METADATA_HEADERS)
140+
141+
99142
def test_get_failure(mock_request):
100143
request_mock = mock_request(
101144
'Metadata error', status=http_client.NOT_FOUND)

0 commit comments

Comments
 (0)