DNS Service

The DNS service: zones and records, in any cloud provider’s DNS.

The platform uses DNSService, through smarter.apps.infrastructure.services.infrastructure .dns, and the provider’s DNS is an implementation of it, e.g. Route53DNSService.

A provider implements only the primitives, the abstract _ methods. The operations that the platform needs, e.g. DNSService.create_domain_a_record(), are built on them here, once, along with their signals, so that they behave the same in every cloud.

Zones and records are DNSZone and DNSRecord, whatever the provider’s own representation. Names never have a trailing dot.

class smarter.apps.infrastructure.services.dns.DNSRecord(name, type, ttl=None, values=<factory>, alias=None)[source]

Bases: object

A DNS record set: the values of one name and type.

__init__(name, type, ttl=None, values=<factory>, alias=None)
alias: dict[str, Any] | None = None

A provider-specific alias target, e.g. an AWS load balancer, in place of values.

name: str

The record’s name, e.g. api.example.com.

same_target(other)[source]

Whether two records point at the same values, or the same alias.

Return type:

bool

ttl: int | None = None

Seconds.

None for an alias record.

type: str

The record’s type, e.g. A, CNAME, NS or TXT.

values: list[str]

The record’s values, e.g. IP addresses.

class smarter.apps.infrastructure.services.dns.DNSService(provider_name, *args, **kwargs)[source]

Bases: InfrastructureService

The DNS service of a cloud provider.

Parameters:

provider_name (str) – The name of the provider, e.g. aws.

billable_zones: bool = True

Whether the provider bills for zones, e.g. AWS Route53 bills each hosted zone monthly.

create_domain_a_record(hostname, api_host_domain, zone_id=None)[source]

Point a host at the same target as a parent domain, by copying the parent’s A record.

e.g. an LLMClient’s host, example.3141-5926-5359.api.smarter.sh, points at the load balancer of api.smarter.sh.

Parameters:
  • hostname (str) – The host, e.g. example.3141-5926-5359.api.smarter.sh.

  • api_host_domain (str) – The parent domain whose A record is copied, e.g. api.smarter.sh. The record is created in its zone, unless zone_id is given.

  • zone_id (Optional[str]) – The zone in which to create the record, e.g. a custom domain’s.

Return type:

tuple[DNSRecord, bool]

Returns:

The record, and whether it was created.

Raises:

DNSZoneNotFound – If the parent domain has no A record.

delete_record(zone_id, name, record_type)[source]

Delete a record.

Parameters:
  • zone_id (str) – The provider’s id of the zone.

  • name (str) – The record’s name.

  • record_type (str) – The record’s type.

Return type:

bool

Returns:

True if the record was deleted, False if it did not exist.

delete_zone(domain)[source]

Delete the zone of a domain, and all of its records.

This cannot be undone.

Parameters:

domain (str) – The zone’s domain.

Return type:

bool

Returns:

True if the zone was deleted, False if it did not exist.

property environment_api_domain: str

The environment’s API domain, as it exists in DNS, e.g. local.api.example.com.

In the local environment, smarter_settings.environment_api_domain is a localhost domain, which DNS cannot serve, so this is its proxy domain.

error_class

alias of DNSServiceError

get_environment_a_record(domain=None)[source]

Return the A record of a domain, in its own zone: by default, the environment’s domain.

The A record of a Smarter environment’s domain points at its load balancer. The platform copies it to the hosts that it serves, e.g. each LLMClient’s.

Parameters:

domain (Optional[str]) – The domain, by default smarter_settings.environment_platform_domain.

Return type:

Optional[DNSRecord]

Returns:

The A record, or None if the domain has no zone or no A record.

get_name_servers(zone_id)[source]

Return the name servers of a zone, e.g. for a customer to delegate their domain to.

Parameters:

zone_id (str) – The provider’s id of the zone.

Return type:

list[str]

Returns:

The name servers, without trailing dots.

Raises:

DNSZoneNotFound – If the zone does not exist.

get_or_create_record(zone_id, name, record_type, ttl=600, values=None, alias=None)[source]

Return a record, and create it, or update its values, if it does not match.

Parameters:
  • zone_id (str) – The provider’s id of the zone.

  • name (str) – The record’s name.

  • record_type (str) – The record’s type.

  • ttl (Optional[int]) – Seconds. Ignored for an alias record.

  • values (Optional[list[str]]) – The record’s values, e.g. IP addresses.

  • alias (Optional[dict[str, Any]]) – A provider-specific alias target, in place of values.

Return type:

tuple[DNSRecord, bool]

Returns:

The record, and whether it was created, rather than found or updated.

Raises:

DNSRecordTimeout – If the record does not appear in the zone in time.

get_or_create_zone(domain)[source]

Return the zone of a domain, and create it if it does not exist.

A new zone is billable in most clouds, so it is announced with billable_resource_creating and billable_resource_created.

Parameters:

domain (str) – The zone’s domain, e.g. example.com.

Return type:

tuple[DNSZone, bool]

Returns:

The zone, and whether it was created.

get_record(zone_id, name, record_type)[source]

Return a record of a zone.

Parameters:
  • zone_id (str) – The provider’s id of the zone.

  • name (str) – The record’s name, e.g. api.example.com.

  • record_type (str) – The record’s type, e.g. A.

Return type:

Optional[DNSRecord]

Returns:

The record, or None if it does not exist.

get_zone(domain)[source]

Return the zone of a domain.

Parameters:

domain (str) – The zone’s domain, e.g. example.com.

Return type:

Optional[DNSZone]

Returns:

The zone, or None if it does not exist.

get_zone_by_id(zone_id)[source]

Return a zone by its id.

Parameters:

zone_id (str) – The provider’s id of the zone.

Return type:

Optional[DNSZone]

Returns:

The zone, with its name servers, or None if it does not exist.

list_records(zone_id)[source]

Return a zone’s records.

Return type:

list[DNSRecord]

record_wait_attempts: int = 10

How many times to look for a new record, before DNSRecordTimeout.

record_wait_seconds: float = 15

Seconds between the attempts.

resolve_domain(domain)[source]

Validate a domain, and replace a local environment’s API domain with its proxy domain.

Parameters:

domain (str) – A domain, e.g. example.api.localhost:9357.

Return type:

str

Returns:

The domain as it exists in DNS.

Raises:

SmarterValueError – If the domain is invalid, or is a local host.

resolve_record_name(name)[source]

Resolve a record’s name, as resolve_domain() does, but without validating it as a host name.

Record names may contain labels that host names may not, e.g. _acme-challenge.example.com.

Return type:

str

service_name: str = 'dns'

The name of the service in signals and logs, see InfrastructureServiceNames.

class smarter.apps.infrastructure.services.dns.DNSZone(id, name, name_servers=<factory>)[source]

Bases: object

A DNS zone, e.g. an AWS Route53 hosted zone.

__init__(id, name, name_servers=<factory>)
id: str

The provider’s id of the zone, e.g. Z148QEXAMPLE8V.

name: str

The zone’s domain, e.g. example.com.

name_servers: list[str]

The zone’s authoritative name servers, which a parent domain delegates the zone to.

smarter.apps.infrastructure.services.dns.normalize_name(name)[source]

A DNS name without its trailing dot, in lower case, e.g. Example.com. -> example.com.

Return type:

str