Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/next-release/bugfix-IMDS-51328.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "bugfix",
"category": "IMDS",
"description": "Fixes region resolution from IMDS in Local Zones by reading the region directly instead of deriving it from the availability zone."
}
6 changes: 2 additions & 4 deletions awscli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _create_fetcher(self):


class InstanceMetadataRegionFetcher(IMDSFetcher):
_URL_PATH = 'latest/meta-data/placement/availability-zone/'
_URL_PATH = 'latest/meta-data/placement/region'

def retrieve_region(self):
"""Get the current region from the instance metadata service.
Expand Down Expand Up @@ -204,9 +204,7 @@ def _get_region(self):
retry_func=self._default_retry,
token=token,
)
availability_zone = response.text
region = availability_zone[:-1]
return region
return response.text


def split_on_commas(value):
Expand Down
2 changes: 1 addition & 1 deletion scripts/new-change
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ You'll see this template::
Fill in the appropriate values, save and exit the editor.
Make sure to commit these changes as part of your pull request.

If, when your editor is open, you decide don't don't want to add a changelog
If, when your editor is open, you decide you don't want to add a changelog
entry, save an empty file and no entry will be generated.

You can then use the ``scripts/render-change`` to generate the
Expand Down
10 changes: 4 additions & 6 deletions tests/functional/test_clidriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ def test_imds_region_is_used_as_fallback_wo_v2_support(self):
# First response should be from the IMDS server for security token
# if server supports IMDSv1 only there will be no response for token
self.add_response(None)
# Then another response from the IMDS server for an availability
# zone.
self.add_response(b'us-mars-2a')
# Then another response from the IMDS server for the region.
self.add_response(b'us-mars-2')
# Once a region is fetched form the IMDS server we need to mock an
# XML response from ec2 so that the CLI driver doesn't throw an error
# during parsing.
Expand All @@ -84,9 +83,8 @@ def test_imds_region_is_used_as_fallback_with_v2_support(self):
# First response should be from the IMDS server for security token
# if server supports IMDSv2 it'll return token
self.add_response(b'token')
# Then another response from the IMDS server for an availability
# zone.
self.add_response(b'us-mars-2a')
# Then another response from the IMDS server for the region.
self.add_response(b'us-mars-2')
# Once a region is fetched form the IMDS server we need to mock an
# XML response from ec2 so that the CLI driver doesn't throw an error
# during parsing.
Expand Down
22 changes: 21 additions & 1 deletion tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def setUp(self):
self._send = self._urllib3_patch.start()
self._imds_responses = []
self._send.side_effect = self.get_imds_response
self._region = 'us-mars-1a'
self._region = 'us-mars-1'
self.environ = {}
self.environ_patch = mock.patch('os.environ', self.environ)
self.environ_patch.start()
Expand Down Expand Up @@ -473,6 +473,26 @@ def test_includes_user_agent_header(self):
headers = self._send.call_args[0][0].headers
self.assertEqual(headers['User-Agent'], user_agent)

def test_requests_region_from_placement_region(self):
self.add_imds_token_response()
self.add_get_region_imds_response()

InstanceMetadataRegionFetcher().retrieve_region()

url = self._send.call_args[0][0].url
self.assertTrue(url.endswith('latest/meta-data/placement/region'))

def test_local_zone_returns_parent_region(self):
# In a Local Zone the availability zone is e.g. us-east-1-atl-2a,
# so the region has to come from placement/region rather than
# being derived from the availability zone.
self.add_imds_token_response()
self.add_get_region_imds_response(region='us-east-1')

result = InstanceMetadataRegionFetcher().retrieve_region()

self.assertEqual(result, 'us-east-1')

def test_non_200_response_for_region_is_retried(self):
# Response for role name that have a non 200 status code should
# be retried.
Expand Down
Loading