refactor: Replace 'reach' field with 'public' boolean in service registration and related components
This commit is contained in:
@@ -221,8 +221,10 @@ func (api *API) RegisterRoutes(r *mux.Router) {
|
||||
r.HandleFunc("/api/v1/crowdsec/decisions/{id}", api.CrowdSecDeleteDecision).Methods("DELETE")
|
||||
r.HandleFunc("/api/v1/crowdsec/decisions/ip/{ip}", api.CrowdSecDeleteDecisionByIP).Methods("DELETE")
|
||||
r.HandleFunc("/api/v1/crowdsec/machines", api.CrowdSecGetMachines).Methods("GET")
|
||||
r.HandleFunc("/api/v1/crowdsec/machines", api.CrowdSecAddMachine).Methods("POST")
|
||||
r.HandleFunc("/api/v1/crowdsec/machines/{name}", api.CrowdSecDeleteMachine).Methods("DELETE")
|
||||
r.HandleFunc("/api/v1/crowdsec/bouncers", api.CrowdSecGetBouncers).Methods("GET")
|
||||
r.HandleFunc("/api/v1/crowdsec/bouncers", api.CrowdSecAddBouncer).Methods("POST")
|
||||
r.HandleFunc("/api/v1/crowdsec/bouncers/{name}", api.CrowdSecDeleteBouncer).Methods("DELETE")
|
||||
|
||||
// Cloudflare management
|
||||
|
||||
@@ -170,5 +170,46 @@ func (api *API) CrowdSecDeleteBouncer(w http.ResponseWriter, r *http.Request) {
|
||||
respondJSON(w, http.StatusOK, map[string]string{"message": "Bouncer deleted"})
|
||||
}
|
||||
|
||||
// Note: CrowdSecProvision (instance-specific provisioning) has been removed.
|
||||
// Instance provisioning will be handled by the Wild Cloud API, not Wild Central.
|
||||
// CrowdSecAddMachine registers a new CrowdSec agent machine with pre-generated credentials.
|
||||
// Body: { "name": "...", "password": "..." }
|
||||
func (api *API) CrowdSecAddMachine(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondError(w, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
if req.Name == "" || req.Password == "" {
|
||||
respondError(w, http.StatusBadRequest, "name and password are required")
|
||||
return
|
||||
}
|
||||
if err := api.crowdsec.AddMachine(req.Name, req.Password); err != nil {
|
||||
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to add machine: %v", err))
|
||||
return
|
||||
}
|
||||
respondJSON(w, http.StatusCreated, map[string]string{"message": fmt.Sprintf("Machine %s registered", req.Name)})
|
||||
}
|
||||
|
||||
// CrowdSecAddBouncer registers a new bouncer with a pre-generated API key.
|
||||
// Body: { "name": "...", "apiKey": "..." }
|
||||
func (api *API) CrowdSecAddBouncer(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondError(w, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
if req.Name == "" || req.APIKey == "" {
|
||||
respondError(w, http.StatusBadRequest, "name and apiKey are required")
|
||||
return
|
||||
}
|
||||
if err := api.crowdsec.AddBouncer(req.Name, req.APIKey); err != nil {
|
||||
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to add bouncer: %v", err))
|
||||
return
|
||||
}
|
||||
respondJSON(w, http.StatusCreated, map[string]string{"message": fmt.Sprintf("Bouncer %s registered", req.Name)})
|
||||
}
|
||||
|
||||
@@ -26,26 +26,26 @@ func TestReconciliation_HAProxyConfigFromServices(t *testing.T) {
|
||||
Source: "wild-cloud",
|
||||
Backend: services.Backend{Address: "192.168.8.240:443", Type: services.BackendTCPPassthrough},
|
||||
Subdomains: true,
|
||||
Reach: services.ReachPublic,
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
Domain: "payne.io",
|
||||
Source: "wild-cloud",
|
||||
Backend: services.Backend{Address: "192.168.8.240:443", Type: services.BackendTCPPassthrough},
|
||||
Subdomains: false,
|
||||
Reach: services.ReachPublic,
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
Domain: "wild-cloud.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: services.Backend{Address: "127.0.0.1:5055", Type: services.BackendHTTP},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
},
|
||||
{
|
||||
Domain: "my-api.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: services.Backend{Address: "192.168.8.60:9001", Type: services.BackendHTTP, Health: "/health"},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
},
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func TestReconciliation_HAProxyConfigFromServices(t *testing.T) {
|
||||
Domain: "central.payne.io",
|
||||
Source: "central",
|
||||
Backend: services.Backend{Address: "127.0.0.1:5055", Type: services.BackendHTTP},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
TLS: services.TLSTerminate,
|
||||
}); err != nil {
|
||||
t.Fatalf("Register central failed: %v", err)
|
||||
@@ -181,21 +181,21 @@ func TestReconciliation_DnsmasqConfigFromServices(t *testing.T) {
|
||||
Source: "wild-cloud",
|
||||
Backend: services.Backend{Address: "192.168.8.240:443", Type: services.BackendTCPPassthrough},
|
||||
Subdomains: true,
|
||||
Reach: services.ReachPublic,
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
// http, internal → DNS points to Central IP, has local=/
|
||||
Domain: "my-api.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: services.Backend{Address: "192.168.8.60:9001", Type: services.BackendHTTP},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
},
|
||||
{
|
||||
// http, public → DNS points to Central IP, NO local=/
|
||||
Domain: "public-app.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: services.Backend{Address: "192.168.8.60:8080", Type: services.BackendHTTP},
|
||||
Reach: services.ReachPublic,
|
||||
Public: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ func TestReconciliation_DnsmasqConfigFromServices(t *testing.T) {
|
||||
ic := config.InstanceConfig{}
|
||||
ic.Cluster.LoadBalancerIp = dnsIP
|
||||
|
||||
if svc.Reach == services.ReachInternal {
|
||||
if !svc.Public {
|
||||
ic.Cloud.InternalDomain = svc.Domain
|
||||
} else {
|
||||
ic.Cloud.Domain = svc.Domain
|
||||
@@ -277,7 +277,7 @@ func TestReconciliation_CentralDomainInHAProxy(t *testing.T) {
|
||||
Domain: "central.payne.io",
|
||||
Source: "central",
|
||||
Backend: services.Backend{Address: fmt.Sprintf("127.0.0.1:%d", centralPort), Type: services.BackendHTTP},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
TLS: services.TLSTerminate,
|
||||
}); err != nil {
|
||||
t.Fatalf("Register central failed: %v", err)
|
||||
@@ -288,7 +288,7 @@ func TestReconciliation_CentralDomainInHAProxy(t *testing.T) {
|
||||
Domain: "my-app.payne.io",
|
||||
Source: "wild-works",
|
||||
Backend: services.Backend{Address: "192.168.8.60:9001", Type: services.BackendHTTP},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false
|
||||
}); err != nil {
|
||||
t.Fatalf("Register failed: %v", err)
|
||||
}
|
||||
@@ -337,7 +337,7 @@ func TestReconciliation_TCPPassthroughDNSTarget(t *testing.T) {
|
||||
Source: "wild-cloud",
|
||||
Backend: services.Backend{Address: "192.168.8.240:443", Type: services.BackendTCPPassthrough},
|
||||
Subdomains: true,
|
||||
Reach: services.ReachPublic,
|
||||
Public: true,
|
||||
}); err != nil {
|
||||
t.Fatalf("Register failed: %v", err)
|
||||
}
|
||||
@@ -354,7 +354,7 @@ func TestReconciliation_TCPPassthroughDNSTarget(t *testing.T) {
|
||||
|
||||
ic := config.InstanceConfig{}
|
||||
ic.Cluster.LoadBalancerIp = dnsIP
|
||||
if svc.Reach == services.ReachInternal {
|
||||
if !svc.Public {
|
||||
ic.Cloud.InternalDomain = svc.Domain
|
||||
} else {
|
||||
ic.Cloud.Domain = svc.Domain
|
||||
|
||||
@@ -20,7 +20,6 @@ func TestServicesRegister(t *testing.T) {
|
||||
"address": "192.168.8.60:9001",
|
||||
"type": "http",
|
||||
},
|
||||
"reach": "internal",
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
@@ -57,7 +56,7 @@ func TestServicesRegister_TCPPassthrough(t *testing.T) {
|
||||
"type": "tcp-passthrough",
|
||||
},
|
||||
"subdomains": true,
|
||||
"reach": "public",
|
||||
"public": true,
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
@@ -107,7 +106,6 @@ func TestServicesGet(t *testing.T) {
|
||||
"domain": "get-test.example.com",
|
||||
"source": "test",
|
||||
"backend": map[string]any{"address": "127.0.0.1:9000", "type": "http"},
|
||||
"reach": "internal",
|
||||
})
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
@@ -151,14 +149,13 @@ func TestServicesUpdate(t *testing.T) {
|
||||
"domain": "update-test.example.com",
|
||||
"source": "test",
|
||||
"backend": map[string]any{"address": "127.0.0.1:9000", "type": "http"},
|
||||
"reach": "internal",
|
||||
})
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
api.ServicesRegister(w, req)
|
||||
|
||||
// Update reach to public
|
||||
update, _ := json.Marshal(map[string]any{"reach": "public"})
|
||||
// Update public to true
|
||||
update, _ := json.Marshal(map[string]any{"public": true})
|
||||
req = httptest.NewRequest("PATCH", "/api/v1/services/update-test.example.com", bytes.NewReader(update))
|
||||
req = mux.SetURLVars(req, map[string]string{"domain": "update-test.example.com"})
|
||||
w = httptest.NewRecorder()
|
||||
@@ -171,8 +168,8 @@ func TestServicesUpdate(t *testing.T) {
|
||||
var resp map[string]any
|
||||
json.Unmarshal(w.Body.Bytes(), &resp)
|
||||
svc := resp["service"].(map[string]any)
|
||||
if svc["reach"] != "public" {
|
||||
t.Errorf("expected reach=public, got %v", svc["reach"])
|
||||
if svc["public"] != true {
|
||||
t.Errorf("expected public=true, got %v", svc["public"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +181,6 @@ func TestServicesDeregister(t *testing.T) {
|
||||
"domain": "delete-me.example.com",
|
||||
"source": "test",
|
||||
"backend": map[string]any{"address": "127.0.0.1:9000", "type": "http"},
|
||||
"reach": "internal",
|
||||
})
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
@@ -216,7 +212,6 @@ func TestServicesRegister_Validation(t *testing.T) {
|
||||
// Missing domain
|
||||
body, _ := json.Marshal(map[string]any{
|
||||
"backend": map[string]any{"address": "127.0.0.1:80", "type": "http"},
|
||||
"reach": "internal",
|
||||
})
|
||||
req := httptest.NewRequest("POST", "/api/v1/services", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
@@ -52,7 +52,7 @@ func (api *API) EnsureCentralService() {
|
||||
Address: backend,
|
||||
Type: services.BackendHTTP,
|
||||
},
|
||||
Reach: services.ReachInternal,
|
||||
// Public defaults to false (private)
|
||||
TLS: services.TLSTerminate,
|
||||
})
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (api *API) reconcileNetworking() {
|
||||
ic := config.InstanceConfig{}
|
||||
ic.Cluster.LoadBalancerIp = dnsIP
|
||||
|
||||
if svc.Reach == services.ReachInternal {
|
||||
if !svc.Public {
|
||||
// Internal-only: local=/ prevents upstream DNS forwarding
|
||||
ic.Cloud.InternalDomain = svc.Domain
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user