§ Documentation
DNS
Emulated DNS zones, records, and health checks — driven with the real Route53, Azure DNS, and Cloud DNS SDKs, with weighted routing
aws Route53azr DNSgcp Cloud DNS
Emulates managed DNS — the hosted zones and resource records you'd create in Route53 to point a name at an address. You create a zone for a domain, then add records (A, CNAME, MX, TXT, and so on) that resolve names within it, and optionally attach health checks that gate which records serve traffic.
Reach for it when your code provisions zones, writes records, or depends on weighted routing to split traffic across endpoints — so you can exercise those paths without a live DNS provider. Because the SDK-compat server speaks the real wire protocol, your production DNS-management code runs unchanged against it. Under the hood a zone is a named container and each record is a name/type/value set with an optional TTL.
| Provider | Service | SDK-compat | Driver |
|---|---|---|---|
| AWS | Route53 | ✓ Live | aws.Route53 |
| Azure | DNS | ✓ Live | azure.DNS |
| GCP | Cloud DNS | ✓ Live | gcp.CloudDNS |
Drive it with the real SDK#
Run cloudemu as a server and point your existing production code at it — the same client, with only the endpoint redirected. Start it with cloudemu serve (or docker run --rm -p 4566:4566 ghcr.io/stackshy/cloudemu), which serves the AWS API on http://localhost:4566:
cloudemu serve # AWS API on http://localhost:4566Then point the stock Route53 client at that endpoint and create a hosted zone and add a record exactly as the real client would:
import (
"github.com/aws/aws-sdk-go-v2/aws"
awsr53 "github.com/aws/aws-sdk-go-v2/service/route53"
r53types "github.com/aws/aws-sdk-go-v2/service/route53/types"
)
client := awsr53.NewFromConfig(cfg, func(o *awsr53.Options) {
o.BaseEndpoint = aws.String("http://localhost:4566")
})
zone, _ := client.CreateHostedZone(ctx, &awsr53.CreateHostedZoneInput{
Name: aws.String("example.com."),
CallerReference: aws.String("ref-1"),
})
client.ChangeResourceRecordSets(ctx, &awsr53.ChangeResourceRecordSetsInput{
HostedZoneId: zone.HostedZone.Id,
ChangeBatch: &r53types.ChangeBatch{Changes: []r53types.Change{{
Action: r53types.ChangeActionCreate,
ResourceRecordSet: &r53types.ResourceRecordSet{
Name: aws.String("api.example.com."), Type: r53types.RRTypeA, TTL: aws.Int64(300),
ResourceRecords: []r53types.ResourceRecord{{Value: aws.String("10.0.0.1")}},
},
}}},
})The same pattern works with armdns (Azure) and cloud.google.com/go/dns (GCP) — only the endpoint changes. See the SDK-Compat Server page.
In-process (Go unit tests)#
For Go unit tests written inside cloudemu-aware code, stand the same wire server up in-process with httptest.NewServer and point the client at ts.URL. The Drivers you pass name exactly the drivers this service needs:
import (
"github.com/stackshy/cloudemu/v2"
awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{Route53: cloud.Route53}))
defer ts.Close()
// point the same route53 client at ts.URL instead of the running endpointCall the driver directly#
When you don't need to drive a real SDK — for example in cloudemu-only setup code — skip the HTTP hop and call the driver. A zone is the container your records live in; create one before adding any records:
import (
dnsdriver "github.com/stackshy/cloudemu/v2/services/dns/driver"
"github.com/stackshy/cloudemu/v2/services/scope"
)
zone, _ := aws.Route53.CreateZone(ctx, dnsdriver.ZoneConfig{Name: "example.com"})
aws.Route53.CreateRecord(ctx, dnsdriver.RecordConfig{
ZoneID: zone.ID, Name: "api.example.com", Type: "A", TTL: 300,
Values: []string{"10.0.0.1", "10.0.0.2"},
})
// scope.Scope{} lists every zone; pass a subscription/resource group or
// project to narrow the results.
zones, _ := aws.Route53.ListZones(ctx, scope.Scope{})
records, _ := aws.Route53.ListRecords(ctx, zone.ID)Weighted routing#
Weighted routing splits traffic across endpoints by giving several records the same name and type but a different Weight and a unique SetID — the Route53 pattern where each record's share of traffic is its weight over the total. Here www.example.com sends roughly 70% of resolutions to one address and 30% to the other:
w70 := 70
w30 := 30
aws.Route53.CreateRecord(ctx, dnsdriver.RecordConfig{
ZoneID: zone.ID, Name: "www.example.com", Type: "A", TTL: 300,
Values: []string{"1.1.1.1"}, Weight: &w70, SetID: "primary",
})
aws.Route53.CreateRecord(ctx, dnsdriver.RecordConfig{
ZoneID: zone.ID, Name: "www.example.com", Type: "A", TTL: 300,
Values: []string{"2.2.2.2"}, Weight: &w30, SetID: "secondary",
})Weight is a *int, so leaving it nil marks a record as unweighted; the SetID is what keeps two records at the same name from colliding.
Health checks#
Route53 health checks let a record serve traffic only while its endpoint is healthy. The driver models the full lifecycle — create, read, list, update, delete — plus a SetHealthCheckStatus control hook so you can flip an endpoint healthy or unhealthy and watch your failover logic react:
hc, _ := aws.Route53.CreateHealthCheck(ctx, dnsdriver.HealthCheckConfig{
Type: "HTTP", Port: 80, ResourcePath: "/healthz", FQDN: "api.example.com",
})
// Drive the endpoint unhealthy, then back, without any real probing.
aws.Route53.SetHealthCheckStatus(ctx, hc.ID, "unhealthy")
checks, _ := aws.Route53.ListHealthChecks(ctx)
aws.Route53.UpdateHealthCheck(ctx, hc.ID, dnsdriver.HealthCheckConfig{ResourcePath: "/ready"})
aws.Route53.DeleteHealthCheck(ctx, hc.ID)Behavior & fidelity#
| Behavior | What happens |
|---|---|
| Records key on name, type, and set ID | Weighted records at one name each carry a distinct SetID, and GetRecord resolves to a stable one rather than picking at random. |
| Deleting a name+type removes its whole set | Every weighted variant under it goes at once, matching how a resource record set is a single unit. |
| Health-check status is settable, not probed | SetHealthCheckStatus flips a check healthy or unhealthy on demand, so failover state is deterministic with no real polling. |
SDK-compat — Live#
Real route53, armdns, and Cloud DNS clients drive the emulator end-to-end:
| Provider | Coverage |
|---|---|
| AWS Route53 | Hosted zones, record sets, weighted routing, and health checks |
| Azure DNS | Zones and record sets via ARM |
| GCP Cloud DNS | Managed zones and record sets via REST |
See SDK-Compat for the full per-operation list.