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.