Skip to content

Commit

Permalink
Tidy docs (#538)
Browse files Browse the repository at this point in the history
One line per sentence and other small fixes.
  • Loading branch information
adamchainz authored Oct 27, 2024
1 parent 960b48b commit 0cfffaa
Showing 1 changed file with 67 additions and 100 deletions.
167 changes: 67 additions & 100 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,17 @@ Python 3.9 to 3.13 supported.
Why?
====

``boto`` came with a utility function to retrieve the instance metadata as a
lazy loading dictionary, ``boto.utils.get_instance_metadata``, but this has not
been ported to ``boto3``, as per `this issue
<https://github.com/boto/boto3/issues/313>`_. I thought that rather than
building a new version inside ``boto3`` it would work well as a standalone
library.
``boto`` came with a utility function to retrieve the instance metadata as a lazy loading dictionary, ``boto.utils.get_instance_metadata``, but this has not been ported to ``boto3``, as per `this issue <https://github.com/boto/boto3/issues/313>`_.
I thought that rather than building a new version inside ``boto3`` it would work well as a standalone library.

Instance Metadata Service Version 2
===================================

In November 2019, AWS released
`version 2 <https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/>`__
of the instance metadata service. It's more secure against Server Side Request
Forgery (SSRF) attacks.
In November 2019, AWS released `version 2 <https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/>`__ of the instance metadata service.
It's more secure against Server Side Request Forgery (SSRF) attacks.

``ec2-metadata`` now uses it exclusively. You can therefore consider disabling
version 1, as per
`AWS' guide <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-transition-to-version-2>`__.
``ec2-metadata`` now uses it exclusively.
So, you may consider disabling version 1, as per `AWS' guide <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-transition-to-version-2>`__.

**Note:** Instance Metadata Service v2 has a default IP hop limit of 1.
This can mean that you can see ``requests.exceptions.ReadTimeout`` errors from within Docker containers.
Expand All @@ -88,39 +81,39 @@ API
-----------------------------

A container that represents the data available on the EC2 metadata service.
Attributes don't entirely correspond to the paths in the metadata service -
they have been 'cleaned up'. You may also want to refer to the `metadata
service docs
<https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html>`_
to understand the exact contents.
Attributes don't entirely correspond to the paths in the metadata service—they have been 'cleaned up'.
You may also want to refer to the `metadata service docs <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html>`_ to understand the exact contents.

There's a singleton instance of it at the name ``ec2_metadata`` which should
cover 90% of use cases. Use it like:
There's a singleton instance of it at the name ``ec2_metadata`` which should cover most use cases.
Use it like:

.. code-block:: python
from ec2_metadata import ec2_metadata
ec2_metadata.region
The ``session`` argument, if provided, should be an instance of
``requests.Session``, allowing you to customize the way requests are made.
The ``session`` argument, if provided, should be an instance of |requests.Session|__, allowing you to customize the way requests are made.

Most of the attributes are cached, except where noted below. This is because
they are mostly immutable, or at least require an instance stop to change.
However some cached attributes do represent things that can change without an
instance stop, but rarely do, such as network devices.
.. |requests.Session| replace:: ``requests.Session``
__ https://docs.python-requests.org/en/latest/user/advanced/

The caching is done with ``@cached_property``, so they cache on first access.
Most of the attributes are cached, except where noted below.
This is because they are mostly immutable, or at least require an instance stop to change.
However some cached attributes do represent things that can change without an instance stop, but rarely do, such as network devices.

The caching is done with |@cached_property|__, so they cache on first access.
If you want to clear the cache of one attribute you can just `del` it:

.. |@cached_property| replace:: ``@cached_property``
__ https://docs.python.org/3/library/functools.html#functools.cached_property

.. code-block:: python
del ec2_metadata.network_interfaces
To clear all, use the ``clear_all()`` method as per below.


``account_id: str``
~~~~~~~~~~~~~~~~~~~

Expand All @@ -135,6 +128,7 @@ The ID of the AMI used to launch the instance, for example ``'ami-123456'``.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Uncached.**

The target Auto Scaling lifecycle state that the instance is transitionioning to, or ``None`` if the instance is not in an autoscaling group.
See AWS docs page `Retrieve the target lifecycle state through instance metadata <https://docs.aws.amazon.com/autoscaling/ec2/userguide/retrieving-target-lifecycle-state-through-imds.html>`__.

Expand All @@ -147,8 +141,7 @@ The name of the current AZ, for example ``'eu-west-1a'``.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The unique, cross-account ID of the current AZ, for example ``'use1-az6'``.
See AWS docs page `AZ IDs for your AWS resources
<https://docs.aws.amazon.com/ram/latest/userguide/working-with-az-ids.html>`__.
See AWS docs page `AZ IDs for your AWS resources <https://docs.aws.amazon.com/ram/latest/userguide/working-with-az-ids.html>`__.

``ami_launch_index: int``
~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -158,21 +151,19 @@ The index of the instance in the launch request, zero-based, for example ``0``.
``ami_manifest_path: str``
~~~~~~~~~~~~~~~~~~~~~~~~~~

The path to the AMI manifest file in Amazon S3, or ``'(unknown)'`` on
EBS-backed AMI's.
The path to the AMI manifest file in Amazon S3, or ``'(unknown)'`` on EBS-backed AMI's.

``clear_all() -> None``
~~~~~~~~~~~~~~~~~~~~~~~

Clear all the cached attributes on the class, meaning their next access will
re-fetch the data from the metadata API. This includes clearing the token used
to authenticate with the service.
Clear all the cached attributes on the class, meaning their next access will re-fetch the data from the metadata API.
This includes clearing the token used to authenticate with the service.

``domain: str``
~~~~~~~~~~~~~~~

The domain for AWS resources for the region. For example, ``'amazonaws.com'`` for the
standard AWS regions and GovCloud (US), or ``'amazonaws.com.cn'`` for China.
The domain for AWS resources for the region.
For example: ``'amazonaws.com'`` for the standard AWS regions and GovCloud (US), or ``'amazonaws.com.cn'`` for China.

``iam_info: IamInfoDict | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -191,8 +182,7 @@ The dict has this type, based on what the metadata service returns:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A dictionary of data for the security credentials associated with the IAM role attached to the instance, or ``None`` if no role is attached.
See the `AWS docs section “Retrieve security credentials from instance metadata” <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials>`__
for details.
See the `AWS docs section “Retrieve security credentials from instance metadata” <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials>`__ for details.
The dict has this type, based on that document:

.. code-block:: python
Expand All @@ -209,10 +199,9 @@ The dict has this type, based on that document:
~~~~~~~~~~~~~~~~~~~~~~~~

**Uncached.**
A state that notifies if the instance will reboot in preparation
for bundling. See the `AWS docs section “Instance Metadata Categories”
<https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html>`_
for the valid values.

A state that notifies if the instance will reboot in preparation for bundling.
See the `AWS docs section “Instance Metadata Categories” <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html>`_ for the valid values.

``instance_id: str``
~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -252,14 +241,12 @@ The purchasing option of this instance, for example ``'on-demand'``.
``instance_profile_arn: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ARN of the IAM role/instance profile attached to the instance, taken from
``iam_info``, or ``None`` if no role is attached.
The ARN of the IAM role/instance profile attached to the instance, taken from ``iam_info``, or ``None`` if no role is attached.

``instance_profile_id: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ID of the IAM role/instance profile attached to the instance, taken from
``iam_info``, or ``None`` if no role is attached.
The ID of the IAM role/instance profile attached to the instance, taken from ``iam_info``, or ``None`` if no role is attached.


``instance_profile_name: str | None``
Expand All @@ -275,8 +262,7 @@ The current instance's type, for example ``'t2.nano'``.
``kernel_id: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~

The current instance's kernel ID, or ``None`` if it doesn't have one,
for example ``'aki-dc9ed9af'``.
The current instance's kernel ID, or ``None`` if it doesn't have one, for example ``'aki-dc9ed9af'``.

``mac : str``
~~~~~~~~~~~~~
Expand All @@ -286,22 +272,19 @@ The instance's MAC address, for example ``'0a:d2:ae:4d:f3:12'``.
``network_interfaces: dict[str, NetworkInterface]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A dictionary of mac address to ``NetworkInterface``, which represents the data
available on a network interface - see below. For example:
``{'01:23:45:67:89:ab': NetworkInterface('01:23:45:67:89:ab')}``
A dictionary of mac address to ``NetworkInterface``, which represents the data available on a network interface, documented below.
For example: ``{'01:23:45:67:89:ab': NetworkInterface('01:23:45:67:89:ab')}``

``partition: str``
~~~~~~~~~~~~~~~~~~

The AWS partition where the instance is running. For example, ``'aws'`` for the
standard AWS regions, ``'aws-us-gov'`` for GovCloud (US), or ``'aws-cn'``
for China.
The AWS partition where the instance is running.
For example: ``'aws'`` for the standard AWS regions, ``'aws-us-gov'`` for GovCloud (US), or ``'aws-cn'`` for China.

``private_hostname : str``
~~~~~~~~~~~~~~~~~~~~~~~~~~

The private IPv4 DNS hostname of the instance, for example
``'ip-172-30-0-0.eu-west-1.compute.internal'`` .
The private IPv4 DNS hostname of the instance, for example ``'ip-172-30-0-0.eu-west-1.compute.internal'`` .

``private_ipv4: str``
~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -311,14 +294,14 @@ The private IPv4 of the instance, for example ``'172.30.0.0'``.
``public_hostname : str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The public DNS hostname of the instance, or ``None`` if the instance is not
public, for example ``'ec2-1-2-3-4.compute-1.amazonaws.com'``.
The public DNS hostname of the instance, or ``None`` if the instance is not public.
For example: ``'ec2-1-2-3-4.compute-1.amazonaws.com'``.

``public_ipv4: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The public IPv4 address of the instance, or ``None`` if the instance is not
public, for example ``'1.2.3.4'``.
The public IPv4 address of the instance, or ``None`` if the instance is not public.
For example: ``'1.2.3.4'``.

``region: str``
~~~~~~~~~~~~~~~
Expand All @@ -328,8 +311,7 @@ The region the instance is running in, for example ``'eu-west-1'``.
``reservation_id: str``
~~~~~~~~~~~~~~~~~~~~~~~

The ID of the reservation used to launch the instance, for example
``'r-12345678901234567'``.
The ID of the reservation used to launch the instance, for example ``'r-12345678901234567'``.

``security_groups : list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -340,6 +322,7 @@ List of security groups by name, for example ``['ssh-access', 'custom-sg-1']``.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Uncached.**

An object describing an action about to happen to this spot instance.
Returns ``None`` if the instance is not spot, or not marked for termination.

Expand All @@ -363,8 +346,7 @@ This is indistinguishable from “no tags”, so beware that in that case, ``Ins
``user_data: bytes | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The raw user data assigned to the instance (not base64 encoded), or ``None`` if
there is none.
The raw user data assigned to the instance (not base64 encoded), or ``None`` if there is none.

``InstanceTags``
----------------
Expand All @@ -388,10 +370,8 @@ Because ``InstanceTags`` is cached, it won’t reflect such updates on Nitro ins
``NetworkInterface``
--------------------

Represents a single network interface, as retrieved from
``EC2Metadata.network_interfaces``. Again like ``EC2Metadata`` all its
attributes cache on first access, and can be cleared with ``del`` or
its ``clear_all()`` method.
Represents a single network interface, as retrieved from ``EC2Metadata.network_interfaces``.
Again like ``EC2Metadata`` all its attributes cache on first access, and can be cleared with ``del`` or its ``clear_all()`` method.

``device_number: int``
~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -406,15 +386,13 @@ The unique id used to identify the Elastic Network Interface, for example ``'eni
``ipv4_associations: dict[str, list[str]]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A dictionary mapping public IP addresses on the interface to the list of
private IP addresses associated with that public IP, for each public IP that is
associated with the interface, for example ``{'54.0.0.1': ['172.30.0.0']}``.
A dictionary mapping the interface’s public IP addresses on the interface to the list of private IP addresses associated with that public IP.
For example: ``{'54.0.0.1': ['172.30.0.0']}``.

``ipv6s: list[str]``
~~~~~~~~~~~~~~~~~~~~

The IPv6 addresses associated with the interface, for example
``['2001:db8:abcd:ef00::1234']``.
The IPv6 addresses associated with the interface, for example ``['2001:db8:abcd:ef00::1234']``.

``mac: str``
~~~~~~~~~~~~
Expand All @@ -424,26 +402,22 @@ The MAC address of the interface, for example ``'01:23:45:67:89:ab'``.
``owner_id: str``
~~~~~~~~~~~~~~~~~

The AWS Account ID of the owner of the network interface, for example
``'123456789012'``.
The AWS Account ID of the owner of the network interface, for example ``'123456789012'``.

``private_hostname: str``
~~~~~~~~~~~~~~~~~~~~~~~~~

The interface's local/private hostname, for example
``'ip-172-30-0-0.eu-west-1.compute.internal'``.
The interface's local/private hostname, for example ``'ip-172-30-0-0.eu-west-1.compute.internal'``.

``private_ipv4s: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The private IPv4 addresses associated with the interface, for example
``['172.30.0.0']``.
The private IPv4 addresses associated with the interface, for example ``['172.30.0.0']``.

``public_hostname: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The interface's public DNS (IPv4), for example
``'ec2-54-0-0-0.compute-1.amazonaws.com'``.
The interface's public DNS (IPv4), for example ``'ec2-54-0-0-0.compute-1.amazonaws.com'``.

``public_ipv4s: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -453,33 +427,28 @@ The Elastic IP addresses associated with the interface, for example ``['54.0.0.0
``security_groups: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The names of the security groups to which the network interface belongs, for example
``['ssh-access', 'custom-sg-1']``.
The names of the security groups to which the network interface belongs, for example ``['ssh-access', 'custom-sg-1']``.

``security_group_ids: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The names of the security groups to which the network interface belongs, for example
``['sg-12345678', 'sg-12345679']``.
The names of the security groups to which the network interface belongs, for example ``['sg-12345678', 'sg-12345679']``.

``subnet_id: str``
~~~~~~~~~~~~~~~~~~

The ID of the subnet in which the interface resides, for example
``'subnet-12345678'``.
The ID of the subnet in which the interface resides, for example ``'subnet-12345678'``.

``subnet_ipv4_cidr_block: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The IPv4 CIDR block of the subnet in which the interface resides, or ``None``
if there is none, for example ``'172.30.0.0/24'``.
The IPv4 CIDR block of the subnet in which the interface resides, or ``None`` if there is none, for example ``'172.30.0.0/24'``.

``subnet_ipv6_cidr_blocks: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The list of IPv6 CIDR blocks of the subnet in which the interface resides, for example
``['2001:db8:abcd:ef00::/64']``. If the subnet does not have any IPv6 CIDR
blocks or the instance isn't in a VPC, the list will be empty, for example ``[]``.
The list of IPv6 CIDR blocks of the subnet in which the interface resides, for example ``['2001:db8:abcd:ef00::/64']``.
If the subnet does not have any IPv6 CIDR blocks or the instance isn't in a VPC, the list will be empty, for example ``[]``.

``vpc_id: str``
~~~~~~~~~~~~~~~
Expand All @@ -489,18 +458,16 @@ The ID of the VPC in which the interface resides, for example ``'vpc-12345678'``
``vpc_ipv4_cidr_block: str | None``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The IPv4 CIDR block of the VPC, or ``None`` if the instance isn't in a VPC,
for example ``'172.30.0.0/16'``.
The IPv4 CIDR block of the VPC, or ``None`` if the instance isn't in a VPC, for example ``'172.30.0.0/16'``.

``vpc_ipv4_cidr_blocks: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The list of IPv4 CIDR blocks for example ``['172.30.0.0/16']``. If the interface
doesn’t have any such CIDR blocks, the list will be empty.
The list of IPv4 CIDR blocks for example ``['172.30.0.0/16']``.
If the interface doesn’t have any such CIDR blocks, the list will be empty.

``vpc_ipv6_cidr_blocks: list[str]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The list of IPv6 CIDR blocks of the VPC in which the interface resides, for example
``['2001:db8:abcd:ef00::/56']``. If the VPC does not have any IPv6 CIDR blocks
or the instance isn't in a VPC, the list will be empty, for example ``[]``.
The list of IPv6 CIDR blocks of the VPC in which the interface resides, for example ``['2001:db8:abcd:ef00::/56']``.
If the VPC does not have any IPv6 CIDR blocks or the instance isn't in a VPC, the list will be empty, for example ``[]``.

0 comments on commit 0cfffaa

Please sign in to comment.