From c2071586f8e9ab30c91df6c468d4f861a8a7a231 Mon Sep 17 00:00:00 2001 From: anonpenguin23 Date: Thu, 22 Jan 2026 15:42:54 +0200 Subject: [PATCH] fixed more tests --- e2e/domain_routing_test.go | 2 +- pkg/gateway/middleware.go | 2 +- pkg/ipfs/client.go | 9 ++- pkg/node/dns_registration.go | 134 +++++++++++++++++++++++++++++++++++ pkg/node/node.go | 9 +++ 5 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 pkg/node/dns_registration.go diff --git a/e2e/domain_routing_test.go b/e2e/domain_routing_test.go index 7fc9dde..1fdeb00 100644 --- a/e2e/domain_routing_test.go +++ b/e2e/domain_routing_test.go @@ -145,7 +145,7 @@ func TestDomainRouting_MultipleDeployments(t *testing.T) { // Test deployment 2 resp2 := TestDeploymentWithHostHeader(t, env, domain2, "/") - defer resp2.Close() + defer resp2.Body.Close() assert.Equal(t, http.StatusOK, resp2.StatusCode, "Deployment 2 should serve") diff --git a/pkg/gateway/middleware.go b/pkg/gateway/middleware.go index 3683b66..2f0f67c 100644 --- a/pkg/gateway/middleware.go +++ b/pkg/gateway/middleware.go @@ -500,7 +500,7 @@ func (g *Gateway) getDeploymentByDomain(ctx context.Context, domain string) (*de WHERE (d.name || '.' || d.home_node_id || '.orama.network' = ? OR d.name || '.node-' || d.home_node_id || '.orama.network' = ? OR d.name || '.orama.network' = ? - OR dd.domain = ? AND dd.verification_status = 'verified') + OR dd.domain = ? AND dd.verified_at IS NOT NULL) AND d.status = 'active' LIMIT 1 ` diff --git a/pkg/ipfs/client.go b/pkg/ipfs/client.go index 7f517e5..7973291 100644 --- a/pkg/ipfs/client.go +++ b/pkg/ipfs/client.go @@ -10,6 +10,7 @@ import ( "mime/multipart" "net/http" "net/url" + "strings" "time" "go.uber.org/zap" @@ -177,7 +178,13 @@ func (c *Client) Add(ctx context.Context, reader io.Reader, name string) (*AddRe return nil, fmt.Errorf("failed to close writer: %w", err) } - req, err := http.NewRequestWithContext(ctx, "POST", c.apiURL+"/add", &buf) + // Add query parameters for tarball extraction + apiURL := c.apiURL + "/add" + if strings.HasSuffix(strings.ToLower(name), ".tar.gz") || strings.HasSuffix(strings.ToLower(name), ".tgz") { + apiURL += "?extract=true" + } + + req, err := http.NewRequestWithContext(ctx, "POST", apiURL, &buf) if err != nil { return nil, fmt.Errorf("failed to create add request: %w", err) } diff --git a/pkg/node/dns_registration.go b/pkg/node/dns_registration.go new file mode 100644 index 0000000..c3645e1 --- /dev/null +++ b/pkg/node/dns_registration.go @@ -0,0 +1,134 @@ +package node + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/DeBrosOfficial/network/pkg/logging" + "go.uber.org/zap" +) + +// registerDNSNode registers this node in the dns_nodes table for deployment routing +func (n *Node) registerDNSNode(ctx context.Context) error { + if n.rqliteAdapter == nil { + return fmt.Errorf("rqlite adapter not initialized") + } + + // Get node ID (use peer ID) + nodeID := n.GetPeerID() + if nodeID == "" { + return fmt.Errorf("node peer ID not available") + } + + // Get external IP address + ipAddress, err := n.getNodeIPAddress() + if err != nil { + n.logger.ComponentWarn(logging.ComponentNode, "Failed to determine node IP, using localhost", zap.Error(err)) + ipAddress = "127.0.0.1" + } + + // Get internal IP (same as external for now, or could use private network IP) + internalIP := ipAddress + + // Determine region (defaulting to "local" for now, could be from cloud metadata in future) + region := "local" + + // Insert or update node record + query := ` + INSERT INTO dns_nodes (id, ip_address, internal_ip, region, status, last_seen, created_at, updated_at) + VALUES (?, ?, ?, ?, 'active', datetime('now'), datetime('now'), datetime('now')) + ON CONFLICT(id) DO UPDATE SET + ip_address = excluded.ip_address, + internal_ip = excluded.internal_ip, + region = excluded.region, + status = 'active', + last_seen = datetime('now'), + updated_at = datetime('now') + ` + + db := n.rqliteAdapter.GetSQLDB() + _, err = db.ExecContext(ctx, query, nodeID, ipAddress, internalIP, region) + if err != nil { + return fmt.Errorf("failed to register DNS node: %w", err) + } + + n.logger.ComponentInfo(logging.ComponentNode, "Registered DNS node", + zap.String("node_id", nodeID), + zap.String("ip_address", ipAddress), + zap.String("region", region), + ) + + return nil +} + +// startDNSHeartbeat starts a goroutine that periodically updates the node's last_seen timestamp +func (n *Node) startDNSHeartbeat(ctx context.Context) { + go func() { + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + n.logger.ComponentInfo(logging.ComponentNode, "DNS heartbeat stopped") + return + case <-ticker.C: + if err := n.updateDNSHeartbeat(ctx); err != nil { + n.logger.ComponentWarn(logging.ComponentNode, "Failed to update DNS heartbeat", zap.Error(err)) + } + } + } + }() + + n.logger.ComponentInfo(logging.ComponentNode, "Started DNS heartbeat (30s interval)") +} + +// updateDNSHeartbeat updates the node's last_seen timestamp in dns_nodes +func (n *Node) updateDNSHeartbeat(ctx context.Context) error { + if n.rqliteAdapter == nil { + return fmt.Errorf("rqlite adapter not initialized") + } + + nodeID := n.GetPeerID() + if nodeID == "" { + return fmt.Errorf("node peer ID not available") + } + + query := `UPDATE dns_nodes SET last_seen = datetime('now'), updated_at = datetime('now') WHERE id = ?` + db := n.rqliteAdapter.GetSQLDB() + _, err := db.ExecContext(ctx, query, nodeID) + if err != nil { + return fmt.Errorf("failed to update DNS heartbeat: %w", err) + } + + return nil +} + +// getNodeIPAddress attempts to determine the node's external IP address +func (n *Node) getNodeIPAddress() (string, error) { + // Try to detect external IP by connecting to a public server + conn, err := net.Dial("udp", "8.8.8.8:80") + if err != nil { + // If that fails, try to get first non-loopback interface IP + addrs, err := net.InterfaceAddrs() + if err != nil { + return "", err + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String(), nil + } + } + } + + return "", fmt.Errorf("no suitable IP address found") + } + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) + return localAddr.IP.String(), nil +} diff --git a/pkg/node/node.go b/pkg/node/node.go index eeb4d3b..4c07338 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -113,6 +113,15 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("failed to start RQLite: %w", err) } + // Register this node in dns_nodes table for deployment routing + if err := n.registerDNSNode(ctx); err != nil { + n.logger.ComponentWarn(logging.ComponentNode, "Failed to register DNS node", zap.Error(err)) + // Don't fail startup if DNS registration fails, it will retry on heartbeat + } else { + // Start DNS heartbeat to keep node status fresh + n.startDNSHeartbeat(ctx) + } + // Get listen addresses for logging var listenAddrs []string if n.host != nil {