refactor: Replace 'reach' field with 'public' boolean in service registration and related components
This commit is contained in:
@@ -17,14 +17,6 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Reach describes how a service is exposed.
|
||||
type Reach string
|
||||
|
||||
const (
|
||||
ReachInternal Reach = "internal" // LAN-visible — DNS + proxy + TLS
|
||||
ReachPublic Reach = "public" // internet-visible — + DDNS + external HAProxy
|
||||
)
|
||||
|
||||
// BackendType describes how the gateway handles traffic for this service.
|
||||
type BackendType string
|
||||
|
||||
@@ -54,7 +46,7 @@ type Service struct {
|
||||
Source string `yaml:"source,omitempty" json:"source,omitempty"` // who registered: wild-cloud, wild-works, manual
|
||||
Backend Backend `yaml:"backend" json:"backend"` // where to route
|
||||
Subdomains bool `yaml:"subdomains,omitempty" json:"subdomains,omitempty"` // also match *.domain
|
||||
Reach Reach `yaml:"reach" json:"reach"` // internal or public
|
||||
Public bool `yaml:"public,omitempty" json:"public,omitempty"` // true = internet-visible (DDNS + external), false = LAN only
|
||||
TLS TLSMode `yaml:"tls,omitempty" json:"tls,omitempty"` // passthrough or terminate
|
||||
}
|
||||
|
||||
@@ -106,9 +98,7 @@ func (m *Manager) Register(svc Service) error {
|
||||
if svc.Backend.Type == "" {
|
||||
return fmt.Errorf("backend type is required")
|
||||
}
|
||||
if svc.Reach == "" {
|
||||
return fmt.Errorf("reach is required")
|
||||
}
|
||||
// Public field is a bool — no validation needed (defaults to false)
|
||||
|
||||
// Default TLS mode based on backend type
|
||||
if svc.TLS == "" {
|
||||
@@ -133,7 +123,7 @@ func (m *Manager) Register(svc Service) error {
|
||||
return fmt.Errorf("writing service file: %w", err)
|
||||
}
|
||||
|
||||
slog.Info("service registered", "domain", svc.Domain, "reach", svc.Reach, "source", svc.Source, "subdomains", svc.Subdomains)
|
||||
slog.Info("service registered", "domain", svc.Domain, "public", svc.Public, "source", svc.Source, "subdomains", svc.Subdomains)
|
||||
|
||||
if m.reconcileFn != nil {
|
||||
go m.reconcileFn()
|
||||
@@ -249,8 +239,8 @@ func (m *Manager) Update(domain string, updates map[string]any) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if reach, ok := updates["reach"].(string); ok {
|
||||
svc.Reach = Reach(reach)
|
||||
if public, ok := updates["public"].(bool); ok {
|
||||
svc.Public = public
|
||||
}
|
||||
if sub, ok := updates["subdomains"].(bool); ok {
|
||||
svc.Subdomains = sub
|
||||
|
||||
@@ -16,7 +16,7 @@ func TestRegisterAndGet(t *testing.T) {
|
||||
Address: "192.168.8.60:9001",
|
||||
Type: BackendHTTP,
|
||||
},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}
|
||||
|
||||
if err := mgr.Register(svc); err != nil {
|
||||
@@ -53,7 +53,7 @@ func TestRegisterTCPPassthrough(t *testing.T) {
|
||||
Type: BackendTCPPassthrough,
|
||||
},
|
||||
Subdomains: true,
|
||||
Reach: ReachPublic,
|
||||
Public: true,
|
||||
}
|
||||
|
||||
if err := mgr.Register(svc); err != nil {
|
||||
@@ -71,8 +71,8 @@ func TestRegisterTCPPassthrough(t *testing.T) {
|
||||
if !got.Subdomains {
|
||||
t.Error("expected subdomains=true")
|
||||
}
|
||||
if got.Reach != ReachPublic {
|
||||
t.Errorf("expected reach public, got %s", got.Reach)
|
||||
if !got.Public {
|
||||
t.Error("expected public=true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestListServices(t *testing.T) {
|
||||
Domain: domain,
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}); err != nil {
|
||||
t.Fatalf("Register %s failed: %v", domain, err)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func TestDeregister(t *testing.T) {
|
||||
Domain: "temp.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}); err != nil {
|
||||
t.Fatalf("Register failed: %v", err)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func TestDeregisterBySource(t *testing.T) {
|
||||
Domain: domain,
|
||||
Source: "wild-cloud",
|
||||
Backend: Backend{Address: "192.168.8.240:443", Type: BackendTCPPassthrough},
|
||||
Reach: ReachPublic,
|
||||
Public: true,
|
||||
})
|
||||
}
|
||||
// Register 1 service from wild-works (different source)
|
||||
@@ -137,7 +137,7 @@ func TestDeregisterBySource(t *testing.T) {
|
||||
Domain: "my-api.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: Backend{Address: "127.0.0.1:9001", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
})
|
||||
|
||||
// Deregister all wild-cloud services with backend 192.168.8.240:443
|
||||
@@ -161,19 +161,19 @@ func TestUpdate(t *testing.T) {
|
||||
Domain: "updatable.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
})
|
||||
|
||||
if err := mgr.Update("updatable.example.com", map[string]any{
|
||||
"reach": "public",
|
||||
"public": true,
|
||||
"subdomains": true,
|
||||
}); err != nil {
|
||||
t.Fatalf("Update failed: %v", err)
|
||||
}
|
||||
|
||||
got, _ := mgr.Get("updatable.example.com")
|
||||
if got.Reach != ReachPublic {
|
||||
t.Errorf("expected reach public after update, got %s", got.Reach)
|
||||
if !got.Public {
|
||||
t.Error("expected public=true after update")
|
||||
}
|
||||
if !got.Subdomains {
|
||||
t.Error("expected subdomains=true after update")
|
||||
@@ -184,24 +184,19 @@ func TestRegisterValidation(t *testing.T) {
|
||||
mgr := NewManager(t.TempDir())
|
||||
|
||||
// Missing domain
|
||||
if err := mgr.Register(Service{Backend: Backend{Address: "127.0.0.1:80", Type: BackendHTTP}, Reach: ReachInternal}); err == nil {
|
||||
if err := mgr.Register(Service{Backend: Backend{Address: "127.0.0.1:80", Type: BackendHTTP}}); err == nil {
|
||||
t.Error("expected error for missing domain")
|
||||
}
|
||||
|
||||
// Missing backend address
|
||||
if err := mgr.Register(Service{Domain: "x.com", Backend: Backend{Type: BackendHTTP}, Reach: ReachInternal}); err == nil {
|
||||
if err := mgr.Register(Service{Domain: "x.com", Backend: Backend{Type: BackendHTTP}}); err == nil {
|
||||
t.Error("expected error for missing backend address")
|
||||
}
|
||||
|
||||
// Missing backend type
|
||||
if err := mgr.Register(Service{Domain: "x.com", Backend: Backend{Address: "127.0.0.1:80"}, Reach: ReachInternal}); err == nil {
|
||||
if err := mgr.Register(Service{Domain: "x.com", Backend: Backend{Address: "127.0.0.1:80"}}); err == nil {
|
||||
t.Error("expected error for missing backend type")
|
||||
}
|
||||
|
||||
// Missing reach
|
||||
if err := mgr.Register(Service{Domain: "x.com", Backend: Backend{Address: "127.0.0.1:80", Type: BackendHTTP}}); err == nil {
|
||||
t.Error("expected error for missing reach")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultSource(t *testing.T) {
|
||||
@@ -210,7 +205,7 @@ func TestDefaultSource(t *testing.T) {
|
||||
mgr.Register(Service{
|
||||
Domain: "test.com",
|
||||
Backend: Backend{Address: "127.0.0.1:80", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
})
|
||||
|
||||
got, _ := mgr.Get("test.com")
|
||||
@@ -226,7 +221,7 @@ func TestRegisterIdempotent(t *testing.T) {
|
||||
Domain: "idempotent.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}
|
||||
|
||||
// Register twice with same domain
|
||||
@@ -274,7 +269,7 @@ func TestListNoDuplicates(t *testing.T) {
|
||||
Domain: domain,
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}); err != nil {
|
||||
t.Fatalf("Register %s failed: %v", domain, err)
|
||||
}
|
||||
@@ -285,7 +280,7 @@ func TestListNoDuplicates(t *testing.T) {
|
||||
Domain: "beta.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:9090", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}); err != nil {
|
||||
t.Fatalf("Re-register beta failed: %v", err)
|
||||
}
|
||||
@@ -353,13 +348,13 @@ func TestDeregisterBySource_NoMatch(t *testing.T) {
|
||||
Domain: "a.example.com",
|
||||
Source: "wild-cloud",
|
||||
Backend: Backend{Address: "10.0.0.1:443", Type: BackendTCPPassthrough},
|
||||
Reach: ReachPublic,
|
||||
Public: true,
|
||||
})
|
||||
mgr.Register(Service{
|
||||
Domain: "b.example.com",
|
||||
Source: "wild-works",
|
||||
Backend: Backend{Address: "10.0.0.2:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
})
|
||||
|
||||
// Deregister with a source that doesn't match anything
|
||||
@@ -383,13 +378,13 @@ func TestDeregisterBySource_PartialMatch(t *testing.T) {
|
||||
Domain: "a.example.com",
|
||||
Source: "wild-cloud",
|
||||
Backend: Backend{Address: "10.0.0.1:443", Type: BackendTCPPassthrough},
|
||||
Reach: ReachPublic,
|
||||
Public: true,
|
||||
})
|
||||
mgr.Register(Service{
|
||||
Domain: "b.example.com",
|
||||
Source: "wild-cloud",
|
||||
Backend: Backend{Address: "10.0.0.2:443", Type: BackendTCPPassthrough},
|
||||
Reach: ReachPublic,
|
||||
Public: true,
|
||||
})
|
||||
|
||||
// Deregister only the ones matching source AND backend
|
||||
@@ -411,7 +406,7 @@ func TestUpdate_NotFound(t *testing.T) {
|
||||
mgr := NewManager(t.TempDir())
|
||||
|
||||
err := mgr.Update("nonexistent.example.com", map[string]any{
|
||||
"reach": "public",
|
||||
"public": true,
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("expected error when updating non-existent domain, got nil")
|
||||
@@ -426,7 +421,7 @@ func TestRegister_OverwritePreservesFile(t *testing.T) {
|
||||
Domain: "overwrite.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
}
|
||||
|
||||
// Register first time
|
||||
@@ -477,7 +472,7 @@ func TestList_IgnoresNonYAML(t *testing.T) {
|
||||
Domain: "real.example.com",
|
||||
Source: "test",
|
||||
Backend: Backend{Address: "127.0.0.1:8080", Type: BackendHTTP},
|
||||
Reach: ReachInternal,
|
||||
// Public defaults to false
|
||||
})
|
||||
|
||||
// Create non-YAML files in the services directory
|
||||
|
||||
Reference in New Issue
Block a user