IMDS (imds v1.0.0)

Copy Markdown

Read instance metadata from a cloud provider through one interface.

Supported providers:

detect/1 probes the providers in the order of providers/0 and answers with the first one that passes a strict check. No other provider passes the check of a given provider, so the shared link-local address 169.254.169.254 is safe to probe. The module keeps no state between calls: every call probes again.

Options

All functions accept these options:

  • :provider - skip detection and use this provider; the value is a provider name or a provider module
  • :base_url - replace the base URL of the provider, used in tests
  • :timeout - timeout of a single request in milliseconds, default 5000; the probe requests of provider detection default to 1000
  • :req_options - options added to the Req request, for example [plug: {Req.Test, IMDS}] in a test
  • :aws_imds_v1_fallback - permit IMDSv1 when the token request fails, default true. Detection requires IMDSv2: on an instance with only IMDSv1, pass provider: :aws
  • :api_version - the Azure IMDS API version, default 2021-02-01

The environment variable INSTANCE_METADATA_PROVIDER sets the provider when the :provider option is absent. The variable holds the name of a provider, for example gce. A value that names no provider is an error.

Summary

Types

Normalized identity of the instance.

Identifier of a provider.

Reason of a failed operation.

Functions

Detect the provider of the current instance.

Same as detect/1, but raises IMDS.Error on failure.

Return the body of one metadata path as a binary.

Return the body of one metadata path, decoded as JSON.

Return the normalized identity of the instance.

Same as identity/1, but raises IMDS.Error on failure.

Return the provider identifiers in probe order.

Merge instance metadata to global logger metadata.

Types

identity()

@type identity() :: IMDS.Provider.identity()

Normalized identity of the instance.

option()

@type option() ::
  {:provider, provider() | module() | binary()}
  | {:base_url, binary()}
  | {:timeout, timeout()}
  | {:req_options, keyword()}
  | {:aws_imds_v1_fallback, boolean()}
  | {:api_version, binary()}

provider()

@type provider() :: IMDS.Provider.provider()

Identifier of a provider.

reason()

@type reason() :: IMDS.Provider.reason()

Reason of a failed operation.

Functions

detect(opts \\ [])

@spec detect([option()]) :: {:ok, provider()} | {:error, reason()}

Detect the provider of the current instance.

Probes the providers in the order of providers/0 and returns the first provider that passes its check. When the :provider option or the INSTANCE_METADATA_PROVIDER variable is set, returns that provider without a request.

Examples

iex> IMDS.detect(provider: :aws)
{:ok, :aws}

detect!(opts \\ [])

@spec detect!([option()]) :: provider()

Same as detect/1, but raises IMDS.Error on failure.

get(path, opts \\ [])

@spec get(binary(), [option()]) :: {:ok, binary()} | {:error, reason()}

Return the body of one metadata path as a binary.

The path is relative to the base URL of the provider and MUST start with /. Pass the provider name or a provider module.

Examples

IMDS.get("/computeMetadata/v1/instance/id", provider: :gce)

get_json(path, opts \\ [])

@spec get_json(binary(), [option()]) :: {:ok, term()} | {:error, reason()}

Return the body of one metadata path, decoded as JSON.

identity(opts \\ [])

@spec identity([option()]) :: {:ok, identity()} | {:error, reason()}

Return the normalized identity of the instance.

The identity map holds the provider name, the instance identifier, the instance type, the region, the zone or availability domain, the owner scope, and the raw document of the provider. A field that the provider does not report is nil.

The instance_type field holds the machine size descriptor. The scope_id field holds the owner scope of the instance:

  • :aws - the account ID
  • :gce - the project ID
  • :azure - the subscription ID
  • :oracle - the compartment OCID
  • :scaleway - the organization identifier
  • :openstack - the project ID
  • :akamai - the account EUUID
  • :hetzner, :digital_ocean, :vultr - always nil, because the service reports no owner scope

A successful result has this shape:

{:ok, %{
  provider: :aws,
  instance_id: "i-0123456789abcdef0",
  instance_type: "t3.micro",
  region: "eu-central-1",
  zone: "eu-central-1a",
  scope_id: "111122223333",
  raw: %{"accountId" => "111122223333"}
}}

Every provider module also accepts the :base_url and :req_options options, which the test suite uses.

identity!(opts \\ [])

@spec identity!([option()]) :: identity()

Same as identity/1, but raises IMDS.Error on failure.

The provider field of the error holds the name of the provider that failed, or nil when no provider was found.

providers()

@spec providers() :: [provider()]

Return the provider identifiers in probe order.

Examples

iex> IMDS.providers()
[
  :aws,
  :gce,
  :azure,
  :oracle,
  :hetzner,
  :scaleway,
  :openstack,
  :digital_ocean,
  :akamai,
  :vultr
]

set_global_logger_metadata(opts \\ [])

@spec set_global_logger_metadata([option()]) :: :ok | {:error, term()}

Merge instance metadata to global logger metadata.

It will not override already set keys. A field that the provider does not report is not merged.

:raw key is removed to not bloat logger metadata.

Accepts the same options as identity/1.