From bcf714d54c82edd4eb5be413e61901f70643d08f Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 00:00:51 +0000 Subject: [PATCH] feat(dns): support camelCase dns.serve action args Co-Authored-By: Virgil --- action.go | 37 ++++++++++++++++++++++++++++++++--- service_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/action.go b/action.go index 3e225ec..e474c76 100644 --- a/action.go +++ b/action.go @@ -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 +} diff --git a/service_test.go b/service_test.go index 8e75bdd..cf51419 100644 --- a/service_test.go +++ b/service_test.go @@ -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 {