feat(dns): support camelCase dns.serve action args

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-04 00:00:51 +00:00
parent 8807fee752
commit bcf714d54c
2 changed files with 85 additions and 3 deletions

View file

@ -26,10 +26,13 @@ var (
const (
actionArgBind = "bind"
actionArgBindAddress = "bindAddress"
actionArgIP = "ip"
actionArgName = "name"
actionArgPort = "port"
actionArgDNSPort = "dnsPort"
actionArgHealthPort = "health_port"
actionArgHealthPortCamel = "healthPort"
)
type ActionDefinition struct {
@ -294,11 +297,11 @@ func (service *Service) handleReverseLookup(ctx context.Context, values map[stri
func (service *Service) handleServe(ctx context.Context, values map[string]any) (any, bool, error) {
_ = ctx
bind, err := stringActionValueOptional(values, actionArgBind)
bind, _, err := stringActionValueOptionalFromKeys(values, actionArgBind, actionArgBindAddress)
if err != nil {
return nil, false, err
}
port, portProvided, err := intActionValueOptional(values, actionArgPort)
port, portProvided, err := intActionValueOptionalFromKeys(values, actionArgPort, actionArgDNSPort)
if err != nil {
return nil, false, err
}
@ -306,7 +309,7 @@ func (service *Service) handleServe(ctx context.Context, values map[string]any)
port = service.ResolveDNSPort()
}
healthPort, healthPortProvided, err := intActionValueOptional(values, actionArgHealthPort)
healthPort, healthPortProvided, err := intActionValueOptionalFromKeys(values, actionArgHealthPort, actionArgHealthPortCamel)
if err != nil {
return nil, false, err
}
@ -365,6 +368,21 @@ func stringActionValueOptional(values map[string]any, key string) (string, error
return strings.TrimSpace(value), nil
}
func stringActionValueOptionalFromKeys(values map[string]any, keys ...string) (string, bool, error) {
for _, key := range keys {
raw, exists := values[key]
if !exists {
continue
}
value, ok := raw.(string)
if !ok {
return "", false, fmt.Errorf("%w: %s", errActionMissingValue, key)
}
return strings.TrimSpace(value), true, nil
}
return "", false, nil
}
func intActionValue(values map[string]any, key string) (int, error) {
if values == nil {
return 0, errActionMissingValue
@ -451,3 +469,16 @@ func intActionValueOptional(values map[string]any, key string) (int, bool, error
}
return value, true, nil
}
func intActionValueOptionalFromKeys(values map[string]any, keys ...string) (int, bool, error) {
for _, key := range keys {
value, valueProvided, err := intActionValueOptional(values, key)
if err != nil {
return 0, false, err
}
if valueProvided {
return value, true, nil
}
}
return 0, false, nil
}

View file

@ -2767,6 +2767,57 @@ func TestServiceHandleActionServeDefaultsToConfiguredHTTPPort(t *testing.T) {
}
}
func TestServiceHandleActionServeCamelCaseAliases(t *testing.T) {
dnsPort := pickFreeTCPPort(t)
healthPort := pickFreeTCPPort(t)
service := NewService(ServiceOptions{
Records: map[string]NameRecords{
"gateway.charon.lthn": {
A: []string{"10.10.10.10"},
},
},
})
payload, ok, err := service.HandleAction(ActionServe, map[string]any{
"bindAddress": "127.0.0.1",
"dnsPort": dnsPort,
"healthPort": healthPort,
})
if err != nil {
t.Fatalf("expected serve action to start runtime with camelCase args: %v", err)
}
if !ok {
t.Fatal("expected serve action to succeed with camelCase args")
}
runtime, ok := payload.(*ServiceRuntime)
if !ok {
t.Fatalf("expected ServiceRuntime payload, got %T", payload)
}
if runtime == nil {
t.Fatal("expected service runtime from serve action")
}
defer func() {
_ = runtime.Close()
}()
_, runtimeDNSPort, err := net.SplitHostPort(runtime.DNSAddress())
if err != nil {
t.Fatalf("expected dns address to include port: %v", err)
}
if runtimeDNSPort != strconv.Itoa(dnsPort) {
t.Fatalf("expected dns port %d, got %q", dnsPort, runtimeDNSPort)
}
_, runtimeHealthPort, err := net.SplitHostPort(runtime.HealthAddress())
if err != nil {
t.Fatalf("expected health address to include port: %v", err)
}
if runtimeHealthPort != strconv.Itoa(healthPort) {
t.Fatalf("expected health port %d, got %q", healthPort, runtimeHealthPort)
}
}
func TestServiceResolveServePortDefaultsToStandardDNSPort(t *testing.T) {
service := NewService(ServiceOptions{})
if service.ResolveDNSPort() != DefaultDNSPort {