From 42c0c61d19eb88b7a72d754f18a5447f8a050181 Mon Sep 17 00:00:00 2001 From: anonpenguin23 Date: Thu, 29 Jan 2026 09:53:11 +0200 Subject: [PATCH] Round Robin DNS fix for deployments (update, rollback etc) --- pkg/cli/deployments/deploy.go | 8 +-- pkg/cli/deployments/list.go | 2 +- .../handlers/deployments/rollback_handler.go | 4 ++ .../handlers/deployments/update_handler.go | 3 ++ pkg/gateway/middleware.go | 2 +- pkg/gateway/routes.go | 49 +++++++++++++++++-- 6 files changed, 57 insertions(+), 11 deletions(-) diff --git a/pkg/cli/deployments/deploy.go b/pkg/cli/deployments/deploy.go index 2e9d0b7..1179d83 100644 --- a/pkg/cli/deployments/deploy.go +++ b/pkg/cli/deployments/deploy.go @@ -114,7 +114,7 @@ func deployStatic(cmd *cobra.Command, args []string) error { endpoint := "/v1/deployments/static/upload" if deployUpdate { - endpoint = "/v1/deployments/static/update" + endpoint = "/v1/deployments/static/update?name=" + deployName } resp, err := uploadDeployment(endpoint, tarball, map[string]string{ @@ -202,7 +202,7 @@ func deployNextJS(cmd *cobra.Command, args []string) error { endpoint := "/v1/deployments/nextjs/upload" if deployUpdate { - endpoint = "/v1/deployments/nextjs/update" + endpoint = "/v1/deployments/nextjs/update?name=" + deployName } resp, err := uploadDeployment(endpoint, tarball, map[string]string{ @@ -258,7 +258,7 @@ func deployGo(cmd *cobra.Command, args []string) error { endpoint := "/v1/deployments/go/upload" if deployUpdate { - endpoint = "/v1/deployments/go/update" + endpoint = "/v1/deployments/go/update?name=" + deployName } resp, err := uploadDeployment(endpoint, tarball, map[string]string{ @@ -313,7 +313,7 @@ func deployNodeJS(cmd *cobra.Command, args []string) error { endpoint := "/v1/deployments/nodejs/upload" if deployUpdate { - endpoint = "/v1/deployments/nodejs/update" + endpoint = "/v1/deployments/nodejs/update?name=" + deployName } resp, err := uploadDeployment(endpoint, tarball, map[string]string{ diff --git a/pkg/cli/deployments/list.go b/pkg/cli/deployments/list.go index 2699505..c3e4d3c 100644 --- a/pkg/cli/deployments/list.go +++ b/pkg/cli/deployments/list.go @@ -276,7 +276,7 @@ func rollbackDeployment(cmd *cobra.Command, args []string) error { } apiURL := getAPIURL() - url := apiURL + "/v1/deployments/rollback" + url := apiURL + "/v1/deployments/rollback?name=" + name payload := map[string]interface{}{ "name": name, diff --git a/pkg/gateway/handlers/deployments/rollback_handler.go b/pkg/gateway/handlers/deployments/rollback_handler.go index f752d70..89b1df0 100644 --- a/pkg/gateway/handlers/deployments/rollback_handler.go +++ b/pkg/gateway/handlers/deployments/rollback_handler.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net/http" + "os" "time" "github.com/DeBrosOfficial/network/pkg/deployments" @@ -236,6 +237,9 @@ func (h *RollbackHandler) rollbackDynamic(ctx context.Context, current *deployme stagingPath := deployPath + ".rollback" // Extract historical version + if err := os.MkdirAll(stagingPath, 0755); err != nil { + return nil, fmt.Errorf("failed to create staging directory: %w", err) + } if err := h.updateHandler.nextjsHandler.extractFromIPFS(ctx, cid, stagingPath); err != nil { return nil, fmt.Errorf("failed to extract historical version: %w", err) } diff --git a/pkg/gateway/handlers/deployments/update_handler.go b/pkg/gateway/handlers/deployments/update_handler.go index 275f593..3145365 100644 --- a/pkg/gateway/handlers/deployments/update_handler.go +++ b/pkg/gateway/handlers/deployments/update_handler.go @@ -196,6 +196,9 @@ func (h *UpdateHandler) updateDynamic(ctx context.Context, existing *deployments // Extract to staging directory stagingPath := fmt.Sprintf("%s.new", h.nextjsHandler.baseDeployPath+"/"+existing.Namespace+"/"+existing.Name) + if err := os.MkdirAll(stagingPath, 0755); err != nil { + return nil, fmt.Errorf("failed to create staging directory: %w", err) + } if err := h.nextjsHandler.extractFromIPFS(ctx, cid, stagingPath); err != nil { return nil, fmt.Errorf("failed to extract new build: %w", err) } diff --git a/pkg/gateway/middleware.go b/pkg/gateway/middleware.go index 4412789..a8b1098 100644 --- a/pkg/gateway/middleware.go +++ b/pkg/gateway/middleware.go @@ -926,7 +926,7 @@ func (g *Gateway) proxyCrossNode(w http.ResponseWriter, r *http.Request, deploym // Simple HTTP client for internal node-to-node communication httpClient := &http.Client{ - Timeout: 30 * time.Second, + Timeout: 120 * time.Second, } resp, err := httpClient.Do(proxyReq) diff --git a/pkg/gateway/routes.go b/pkg/gateway/routes.go index 0bc4a63..9d105f7 100644 --- a/pkg/gateway/routes.go +++ b/pkg/gateway/routes.go @@ -2,6 +2,8 @@ package gateway import ( "net/http" + + "github.com/DeBrosOfficial/network/pkg/gateway/ctxkeys" ) // Routes returns the http.Handler with all routes and middleware configured @@ -93,29 +95,31 @@ func (g *Gateway) Routes() http.Handler { if g.deploymentService != nil { // Static deployments mux.HandleFunc("/v1/deployments/static/upload", g.staticHandler.HandleUpload) - mux.HandleFunc("/v1/deployments/static/update", g.updateHandler.HandleUpdate) + mux.HandleFunc("/v1/deployments/static/update", g.withHomeNodeProxy(g.updateHandler.HandleUpdate)) // Next.js deployments mux.HandleFunc("/v1/deployments/nextjs/upload", g.nextjsHandler.HandleUpload) - mux.HandleFunc("/v1/deployments/nextjs/update", g.updateHandler.HandleUpdate) + mux.HandleFunc("/v1/deployments/nextjs/update", g.withHomeNodeProxy(g.updateHandler.HandleUpdate)) // Go backend deployments if g.goHandler != nil { mux.HandleFunc("/v1/deployments/go/upload", g.goHandler.HandleUpload) + mux.HandleFunc("/v1/deployments/go/update", g.withHomeNodeProxy(g.updateHandler.HandleUpdate)) } // Node.js backend deployments if g.nodejsHandler != nil { mux.HandleFunc("/v1/deployments/nodejs/upload", g.nodejsHandler.HandleUpload) + mux.HandleFunc("/v1/deployments/nodejs/update", g.withHomeNodeProxy(g.updateHandler.HandleUpdate)) } // Deployment management mux.HandleFunc("/v1/deployments/list", g.listHandler.HandleList) mux.HandleFunc("/v1/deployments/get", g.listHandler.HandleGet) - mux.HandleFunc("/v1/deployments/delete", g.listHandler.HandleDelete) - mux.HandleFunc("/v1/deployments/rollback", g.rollbackHandler.HandleRollback) + mux.HandleFunc("/v1/deployments/delete", g.withHomeNodeProxy(g.listHandler.HandleDelete)) + mux.HandleFunc("/v1/deployments/rollback", g.withHomeNodeProxy(g.rollbackHandler.HandleRollback)) mux.HandleFunc("/v1/deployments/versions", g.rollbackHandler.HandleListVersions) - mux.HandleFunc("/v1/deployments/logs", g.logsHandler.HandleLogs) + mux.HandleFunc("/v1/deployments/logs", g.withHomeNodeProxy(g.logsHandler.HandleLogs)) mux.HandleFunc("/v1/deployments/events", g.logsHandler.HandleGetEvents) // Custom domains @@ -136,3 +140,38 @@ func (g *Gateway) Routes() http.Handler { return g.withMiddleware(mux) } + +// withHomeNodeProxy wraps a deployment handler to proxy requests to the home node +// if the current node is not the home node for the deployment. +func (g *Gateway) withHomeNodeProxy(handler http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // Already proxied — prevent loops + if r.Header.Get("X-Orama-Proxy-Node") != "" { + handler(w, r) + return + } + name := r.URL.Query().Get("name") + if name == "" { + handler(w, r) + return + } + ctx := r.Context() + namespace, _ := ctx.Value(ctxkeys.NamespaceOverride).(string) + if namespace == "" { + handler(w, r) + return + } + deployment, err := g.deploymentService.GetDeployment(ctx, namespace, name) + if err != nil { + handler(w, r) // let handler return proper error + return + } + if g.nodePeerID != "" && deployment.HomeNodeID != "" && + deployment.HomeNodeID != g.nodePeerID { + if g.proxyCrossNode(w, r, deployment) { + return + } + } + handler(w, r) + } +}