Powered by AppSignal & Oban Pro

Scoped DNSimple reads, optionally through a proxy

samples/discover.livemd

Scoped DNSimple reads, optionally through a proxy

This notebook is read-only. Start with DNSimple sandbox, whose account IDs and credentials are separate from production. It makes real requests only when you evaluate the read cells.

Setup

Create Livebook secrets with these names (Livebook exposes them as LB_... environment variables), or set the corresponding ordinary environment variables in the Livebook runtime:

Secret / ordinary environment variable Required Meaning
REQ_DNSIMPLE_PATH Yes Absolute path to your local checkout of this repository.
DNSIMPLE_TOKEN Yes, on each request Sandbox account or user token; never paste it into a code cell.
DNSIMPLE_ACCOUNT_ID Yes Your selected positive account ID, not a user ID.
DNSIMPLE_ZONE For record reads An existing zone selected by you.
DNSIMPLE_BASE_URL No Defaults to https://api.sandbox.dnsimple.com/v2; may point to a trusted HTTPS API-compatible reverse proxy, including /v2.

A reverse proxy receives your bearer token: use only infrastructure you trust. No account IDs, tokens, proxy hostnames, or local home-directory paths are embedded in this notebook.

repo_path =
  System.get_env("LB_REQ_DNSIMPLE_PATH") ||
    System.fetch_env!("REQ_DNSIMPLE_PATH")

Mix.install([
  {:req_dnsimple, path: repo_path}
])

After editing the local dependency, restart the Livebook runtime and evaluate setup with Mix.install(..., force: true) once to refresh compiled code and documentation.

Create an account-scoped client

Both account tokens and user tokens require the account ID here. Construction does not call DNSimple, discover an account, or evaluate the credential callback. The callback resolves a token for each request and may also return {:bearer, token}.

The result is still a Req.Request; Req.merge preserves its account scope. Do not display or inspect it, and do not call token_type(client) during setup because that helper evaluates dynamic credentials.

client =
  ReqDnsimple.new_client(
    fn ->
      System.get_env("LB_DNSIMPLE_TOKEN") ||
        System.fetch_env!("DNSIMPLE_TOKEN")
    end,
    account_id:
      System.get_env("LB_DNSIMPLE_ACCOUNT_ID") ||
        System.fetch_env!("DNSIMPLE_ACCOUNT_ID"),
    base_url:
      System.get_env("LB_DNSIMPLE_BASE_URL") ||
        System.get_env("DNSIMPLE_BASE_URL", "https://api.sandbox.dnsimple.com/v2"),
    retry: false
  )
  |> Req.merge(receive_timeout: 30_000)

:ok

Read zones with the existing bang helper

list_zones! returns a bare list and fetches just one page, with the same filter and pagination options as Zone.list!.

zones = ReqDnsimple.list_zones!(client, sort: [name: :asc], per_page: 20)
Enum.map(zones, & &1.name)

Choose a zone explicitly and read one record page

This does not select the first zone or first record. Supply DNSIMPLE_ZONE yourself. Record contents are deliberately not displayed.

zone =
  System.get_env("LB_DNSIMPLE_ZONE") ||
    System.fetch_env!("DNSIMPLE_ZONE")

filters = [type: "A", name_like: "www", sort: [name: :asc, id: :asc], per_page: 25]

{records, pagination} =
  ReqDnsimple.ZoneRecord.list_page(client, zone, filters ++ [page: 1])
  |> ReqDnsimple.unwrap!()

%{record_names: Enum.map(records, & &1.name), pagination: pagination}

Deliberately enumerate every matching page

list_all retains filters, sorting, and page size. It starts at page one and rejects a page: option. This cell can send multiple requests.

all_records =
  ReqDnsimple.ZoneRecord.list_all(client, zone, filters)
  |> ReqDnsimple.unwrap!()

%{matching_records: length(all_records)}

Discovery, multiple accounts, and safe mutations

If you do not know the account ID, use new_unscoped_client/1,2 followed by an explicit discovery request: account tokens use whoami/1 and the returned account ID; user tokens use Account.list/1 and your explicit account selection. Then use for_account/2. Never use a user identity's ID as an account ID. Re-scoping is immutable and local; DNSimple checks permissions on the request.

The sample index links runnable discovery, multiple-account, dynamic-credential, and filtered-record programs with their required inputs. Mutations are intentionally excluded from this notebook. The separate record lifecycle sample requires DNSIMPLE_ALLOW_MUTATIONS=true and your disposable DNSIMPLE_TEST_ZONE, recommends sandbox, and deletes only the record it just created.