package internal
import (
"context"
"net/http"
"github.com/envoyproxy/go-control-plane/pkg/cache/types"
resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
internalapi "envoy-control-plane/internal/api"
"envoy-control-plane/internal/pkg/snapshot"
)
// API holds reference to snapshot manager
type API struct {
Manager *snapshot.SnapshotManager
enableCertIssuance bool
acmeWebRootPath string
}
// NewAPI returns a new REST API handler
func NewAPI(sm *snapshot.SnapshotManager, enableCertIssuance bool, acmeWebRootPath string) *API {
return &API{
Manager: sm,
enableCertIssuance: enableCertIssuance,
acmeWebRootPath: acmeWebRootPath,
}
}
// RegisterRoutes mounts REST handlers
func (api *API) RegisterRoutes(mux *http.ServeMux) {
// -------------------------------------------------------------------------
// Management Handlers (xDS Resource CRUD)
// -------------------------------------------------------------------------
// Cluster Handlers
mux.HandleFunc("/add-cluster", func(w http.ResponseWriter, r *http.Request) {
api.addResourcesHandler(w, r, resourcev3.ClusterType, func(req interface{}) ([]types.Resource, bool) {
cr := req.(*internalapi.AddClusterRequest)
cls, er := snapshot.LoadResourceFromYAML(context.TODO(), cr.YAML, resourcev3.ClusterType)
if er != nil {
http.Error(w, "failed to load cluster", http.StatusBadRequest)
return nil, false
}
return cls, cr.Upsert
})
})
mux.HandleFunc("/disable-cluster", func(w http.ResponseWriter, r *http.Request) {
api.disableResourceHandler(w, r, resourcev3.ClusterType)
})
mux.HandleFunc("/enable-cluster", func(w http.ResponseWriter, r *http.Request) {
api.enableResourceHandler(w, r, resourcev3.ClusterType)
})
mux.HandleFunc("/remove-cluster", func(w http.ResponseWriter, r *http.Request) {
api.removeResourceHandler(w, r, resourcev3.ClusterType)
})
// Listener Handlers
mux.HandleFunc("/add-listener", func(w http.ResponseWriter, r *http.Request) {
api.addResourcesHandler(w, r, resourcev3.ListenerType, func(req interface{}) ([]types.Resource, bool) {
lr := req.(*internalapi.AddListenerRequest)
lss, err := snapshot.LoadResourceFromYAML(context.TODO(), lr.YAML, resourcev3.ListenerType)
if err != nil {
http.Error(w, "failed to load listener", http.StatusBadRequest)
return nil, false
}
return lss, lr.Upsert
})
})
mux.HandleFunc("/disable-listener", func(w http.ResponseWriter, r *http.Request) {
api.disableResourceHandler(w, r, resourcev3.ListenerType)
})
mux.HandleFunc("/enable-listener", func(w http.ResponseWriter, r *http.Request) {
api.enableResourceHandler(w, r, resourcev3.ListenerType)
})
mux.HandleFunc("/remove-listener", func(w http.ResponseWriter, r *http.Request) {
api.removeResourceHandler(w, r, resourcev3.ListenerType)
})
// Secret Handlers
mux.HandleFunc("/add-secret", func(w http.ResponseWriter, r *http.Request) {
api.addResourcesHandler(w, r, resourcev3.SecretType, func(req interface{}) ([]types.Resource, bool) {
sr := req.(*internalapi.AddSecretRequest)
srs, err := snapshot.LoadResourceFromYAML(context.TODO(), sr.YAML, resourcev3.SecretType)
if err != nil {
http.Error(w, "failed to load secret", http.StatusBadRequest)
return nil, false
}
return srs, sr.Upsert
})
})
mux.HandleFunc("/disable-secret", func(w http.ResponseWriter, r *http.Request) {
api.disableResourceHandler(w, r, resourcev3.SecretType)
})
mux.HandleFunc("/enable-secret", func(w http.ResponseWriter, r *http.Request) {
api.enableResourceHandler(w, r, resourcev3.SecretType)
})
mux.HandleFunc("/remove-secret", func(w http.ResponseWriter, r *http.Request) {
api.removeResourceHandler(w, r, resourcev3.SecretType)
})
// -------------------------------------------------------------------------
// ExtensionConfig Handlers (ADDED)
// -------------------------------------------------------------------------
extConfigType := resourcev3.ExtensionConfigType // Use the defined resource type for consistency
// Create / Update
mux.HandleFunc("/add-extensionconfig", func(w http.ResponseWriter, r *http.Request) {
api.addResourcesHandler(w, r, extConfigType, func(req interface{}) ([]types.Resource, bool) {
er := req.(*internalapi.AddExtensionConfigRequest) // Assuming this struct exists
ecs, err := snapshot.LoadResourceFromYAML(context.TODO(), er.YAML, extConfigType)
if err != nil {
http.Error(w, "failed to load extension config", http.StatusBadRequest)
return nil, false
}
return ecs, er.Upsert
})
})
// Read / Query
mux.HandleFunc("/list-extensionconfigs", func(w http.ResponseWriter, r *http.Request) {
api.listResourceHandler(w, r, extConfigType)
})
mux.HandleFunc("/get-extensionconfig", func(w http.ResponseWriter, r *http.Request) {
api.getResourceHandler(w, r, extConfigType)
})
// Update / Disable
mux.HandleFunc("/disable-extensionconfig", func(w http.ResponseWriter, r *http.Request) {
api.disableResourceHandler(w, r, extConfigType)
})
mux.HandleFunc("/enable-extensionconfig", func(w http.ResponseWriter, r *http.Request) {
api.enableResourceHandler(w, r, extConfigType)
})
// Delete
mux.HandleFunc("/remove-extensionconfig", func(w http.ResponseWriter, r *http.Request) {
api.removeResourceHandler(w, r, extConfigType)
})
// -------------------------------------------------------------------------
// Listener Filter Chain Handlers
// -------------------------------------------------------------------------
mux.HandleFunc("/append-filter-chain", func(w http.ResponseWriter, r *http.Request) {
api.appendFilterChainHandler(w, r)
})
mux.HandleFunc("/update-filter-chain", func(w http.ResponseWriter, r *http.Request) {
api.updateFilterChainHandler(w, r)
})
mux.HandleFunc("/remove-filter-chain", func(w http.ResponseWriter, r *http.Request) {
api.removeFilterChainHandler(w, r)
})
// -------------------------------------------------------------------------
// Query / List Handlers (consolidated READ operations)
// -------------------------------------------------------------------------
mux.HandleFunc("/list-clusters", func(w http.ResponseWriter, r *http.Request) {
api.listResourceHandler(w, r, resourcev3.ClusterType)
})
mux.HandleFunc("/get-cluster", func(w http.ResponseWriter, r *http.Request) {
api.getResourceHandler(w, r, resourcev3.ClusterType)
})
mux.HandleFunc("/list-listeners", func(w http.ResponseWriter, r *http.Request) {
api.listResourceHandler(w, r, resourcev3.ListenerType)
})
mux.HandleFunc("/get-listener", func(w http.ResponseWriter, r *http.Request) {
api.getResourceHandler(w, r, resourcev3.ListenerType)
})
mux.HandleFunc("/list-secrets", func(w http.ResponseWriter, r *http.Request) {
api.listResourceHandler(w, r, resourcev3.SecretType)
})
mux.HandleFunc("/get-secret", func(w http.ResponseWriter, r *http.Request) {
api.getResourceHandler(w, r, resourcev3.SecretType)
})
// -------------------------------------------------------------------------
// Persistence Handlers
// -------------------------------------------------------------------------
mux.HandleFunc("/load-from-db", api.loadSnapshotFromDB)
mux.HandleFunc("/flush-to-db", api.flushCacheToDB)
mux.HandleFunc("/load-from-file", api.loadSnapshotFromFile)
mux.HandleFunc("/save-to-file", api.saveSnapshotToFile)
// -------------------------------------------------------------------------
// Certificate Handlers
// -------------------------------------------------------------------------
mux.HandleFunc("/issue-certificate", api.issueCertificateHandler)
mux.HandleFunc("/parse-certificate", api.parseCertificateHandler)
mux.HandleFunc("/check-certificate-validity", api.checkCertificateValidityHandler)
mux.HandleFunc("/get-certificate", api.getCertificateHandler)
// Renew Certificate Handler
mux.HandleFunc("/renew-certificate", api.renewCertificateHandler)
// Certificate Rotation Handler
mux.HandleFunc("/enable-certificate-rotation", api.enableCertificateRotationHandler)
mux.HandleFunc("/disable-certificate-rotation", api.disableCertificateRotationHandler)
mux.HandleFunc("/list-rotating-certificates", api.listRotatingCertificatesHandler)
// -------------------------------------------------------------------------
// Utility Handlers
// -------------------------------------------------------------------------
// Consistency Handler
mux.HandleFunc("/is-consistent", api.isConsistentHandler)
mux.HandleFunc("/storage-dump", api.storageDumpHandler)
}