# `Ankusa.BlobStore.GCS.MetadataServer`
[🔗](https://github.com/jamescarr/ankusa/blob/ankusa-v0.7.0/packages/ankusa/lib/ankusa/blob_store/gcs/metadata_server.ex#L1)

Access tokens for `Ankusa.BlobStore.GCS` from the GCE/GKE metadata server: the
best credential for a service running on Google Cloud, with no key to store or
rotate (the node's service account, granted `roles/storage.objectAdmin` on the
bucket).

    {Ankusa.BlobStore.GCS,
     bucket: "ankusa-segments",
     token_provider: {Ankusa.BlobStore.GCS.MetadataServer, :token, []}}

The token comes from
`http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/<account>/token`
(the `Metadata-Flavor: Google` header is required; the address only answers
inside Google Cloud). It is cached node-wide until a minute before it expires, so
the adapter's per-request call is an ETS read, and refreshed on demand: a `401`
makes the adapter call `invalidate/1`, and its retry fetches a new token.

Arguments (a keyword list, the one optional argument of `token/1` and
`invalidate/1`):

  * `:service_account` — default `"default"`
  * `:endpoint` — default the metadata server's token URL (override in tests)
  * `:timeout_ms` — default `5_000`
  * `:req_options` — transport options, e.g. `plug:` for `Req.Test`

# `invalidate`

```elixir
@spec invalidate(keyword()) :: :ok
```

Drop the cached token: the next `token/1` fetches a new one.

# `token`

```elixir
@spec token(keyword()) :: {:ok, String.t()} | :error
```

`{:ok, bearer_token}`, or `:error` when the metadata server did not give one.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
