Skip to content

Instantly share code, notes, and snippets.

@doublenns
Last active December 15, 2021 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doublenns/7e3e4b72df4aaeccbeabf87ba767f44e to your computer and use it in GitHub Desktop.
Save doublenns/7e3e4b72df4aaeccbeabf87ba767f44e to your computer and use it in GitHub Desktop.
Get EC2's region from instance metadata using Python

The region in which an EC2 instance is located is exposed via EC2 Instance Metadata.

Part of instance metadata is Instance Identity Documents. Specifically, the instance-identity/document endpoint is a dynamic data category that contains instance attributes such as the instanceId, privateIp, instanceType. And most relevantly the instance's region.

We can query the instance identity document via the 169.254.169.254 link-local address. (This only works on EC2 instances):

[ec2-user ~]$ curl http://169.254.169.254/latest/dynamic/instance-identity/document
{
  "devpayProductCodes" : null,
  "marketplaceProductCodes" : null,
  "accountId" : "123456789012",
  "imageId" : "ami-0d5d9d301c853a04a",
  "availabilityZone" : "us-east-2c",
  "ramdiskId" : null,
  "kernelId" : null,
  "privateIp" : "10.10.130.176",
  "version" : "2017-09-30",
  "region" : "us-east-2",
  "pendingTime" : "2019-10-14T14:06:42Z",
  "architecture" : "x86_64",
  "billingProducts" : null,
  "instanceId" : "i-050a5175c97088b9b",
  "instanceType" : "t3.micro"
}

The response's JSON payload includes a region key which can be extracted. We can use the Python requests library to query the endpoint and then use requests's built-in .json method to deserialize the data for filtering. (The requests library is the de-facto standard for making HTTP requests in Python: requests - PyPI)

If requests isn't currently on the local system, it can be installed via pip:

pip install requests

A simple function to get an EC2 instance's region:

import requests

def get_instance_region():
    instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
    session = requests.Session()
    r = requests.get(instance_identity_url)
    response_json = r.json()
    region = response_json.get("region")
    return(region)

The region alone is filtered utilizing this function:

>>> region = get_instance_region()
>>> print(region)
us-east-2

We can also add some exception handling and an explicitly defined timeout to the function to handle situations where the metadata service isn't availabe, possibly because the local system isn't an EC2 instance. The final version of the function:

import requests
import sys
from requests.packages.urllib3 import Retry

def get_instance_region():
    instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
    session = requests.Session()
    retries = Retry(total=3, backoff_factor=0.3)
    metadata_adapter = requests.adapters.HTTPAdapter(max_retries=retries)
    session.mount("http://169.254.169.254/", metadata_adapter)
    try:
        r = requests.get(instance_identity_url, timeout=(2, 5))
    except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as err:
        print("Connection to AWS EC2 Metadata timed out: " + str(err.__class__.__name__))
        print("Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/)")
        sys.exit(1)
    response_json = r.json()
    region = response_json.get("region")
    return(region)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment