feat: enhance IPFS and Cluster integration in setup

- Added automatic setup for IPFS and IPFS Cluster during the network setup process.
- Implemented initialization of IPFS repositories and Cluster configurations for each node.
- Enhanced Makefile to support starting IPFS and Cluster daemons with improved logging.
- Introduced a new documentation guide for IPFS Cluster setup, detailing configuration and verification steps.
- Updated changelog to reflect the new features and improvements.
This commit is contained in:
anonpenguin23 2025-11-05 10:52:40 +02:00
parent d6009bb33f
commit 69d7ccf4c7
18 changed files with 91 additions and 77 deletions

View File

@ -11,7 +11,7 @@
"program": "./cmd/gateway", "program": "./cmd/gateway",
"env": { "env": {
"GATEWAY_ADDR": ":6001", "GATEWAY_ADDR": ":6001",
"GATEWAY_BOOTSTRAP_PEERS": "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWSHHwEY6cga3ng7tD1rzStAU58ogQXVMX3LZJ6Gqf6dee", "GATEWAY_BOOTSTRAP_PEERS": "/ip4/localhost/tcp/4001/p2p/12D3KooWSHHwEY6cga3ng7tD1rzStAU58ogQXVMX3LZJ6Gqf6dee",
"GATEWAY_NAMESPACE": "default", "GATEWAY_NAMESPACE": "default",
"GATEWAY_API_KEY": "ak_iGustrsFk9H8uXpwczCATe5U:default" "GATEWAY_API_KEY": "ak_iGustrsFk9H8uXpwczCATe5U:default"
} }
@ -36,7 +36,7 @@
"program": "./cmd/gateway", "program": "./cmd/gateway",
"env": { "env": {
"GATEWAY_ADDR": ":6001", "GATEWAY_ADDR": ":6001",
"GATEWAY_BOOTSTRAP_PEERS": "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWSHHwEY6cga3ng7tD1rzStAU58ogQXVMX3LZJ6Gqf6dee", "GATEWAY_BOOTSTRAP_PEERS": "/ip4/localhost/tcp/4001/p2p/12D3KooWSHHwEY6cga3ng7tD1rzStAU58ogQXVMX3LZJ6Gqf6dee",
"GATEWAY_NAMESPACE": "default", "GATEWAY_NAMESPACE": "default",
"GATEWAY_API_KEY": "ak_iGustrsFk9H8uXpwczCATe5U:default" "GATEWAY_API_KEY": "ak_iGustrsFk9H8uXpwczCATe5U:default"
} }

View File

@ -7,12 +7,12 @@ test:
# Gateway-focused E2E tests assume gateway and nodes are already running # Gateway-focused E2E tests assume gateway and nodes are already running
# Configure via env: # Configure via env:
# GATEWAY_BASE_URL (default http://127.0.0.1:6001) # GATEWAY_BASE_URL (default http://localhost:6001)
# GATEWAY_API_KEY (required for auth-protected routes) # GATEWAY_API_KEY (required for auth-protected routes)
.PHONY: test-e2e .PHONY: test-e2e
test-e2e: test-e2e:
@echo "Running gateway E2E tests (HTTP/WS only)..." @echo "Running gateway E2E tests (HTTP/WS only)..."
@echo "Base URL: $${GATEWAY_BASE_URL:-http://127.0.0.1:6001}" @echo "Base URL: $${GATEWAY_BASE_URL:-http://localhost:6001}"
@test -n "$$GATEWAY_API_KEY" || (echo "GATEWAY_API_KEY must be set" && exit 1) @test -n "$$GATEWAY_API_KEY" || (echo "GATEWAY_API_KEY must be set" && exit 1)
go test -v -tags e2e ./e2e go test -v -tags e2e ./e2e
@ -57,7 +57,7 @@ run-node:
go run ./cmd/node --config node.yaml go run ./cmd/node --config node.yaml
# Run second node (regular) - requires join address of bootstrap node # Run second node (regular) - requires join address of bootstrap node
# Usage: make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002 # Usage: make run-node2 JOINADDR=/ip4/localhost/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002
run-node2: run-node2:
@echo "Starting regular node (node.yaml)..." @echo "Starting regular node (node.yaml)..."
@echo "Config: ~/.debros/node.yaml" @echo "Config: ~/.debros/node.yaml"
@ -65,7 +65,7 @@ run-node2:
go run ./cmd/node --config node2.yaml go run ./cmd/node --config node2.yaml
# Run third node (regular) - requires join address of bootstrap node # Run third node (regular) - requires join address of bootstrap node
# Usage: make run-node3 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5003 RAFT=7003 P2P=4003 # Usage: make run-node3 JOINADDR=/ip4/localhost/tcp/5001 HTTP=5003 RAFT=7003 P2P=4003
run-node3: run-node3:
@echo "Starting regular node (node2.yaml)..." @echo "Starting regular node (node2.yaml)..."
@echo "Config: ~/.debros/node2.yaml" @echo "Config: ~/.debros/node2.yaml"
@ -122,9 +122,9 @@ dev: build
echo " Initializing IPFS..."; \ echo " Initializing IPFS..."; \
mkdir -p $$HOME/.debros/bootstrap/ipfs; \ mkdir -p $$HOME/.debros/bootstrap/ipfs; \
IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \ IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \
IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.API '["/ip4/127.0.0.1/tcp/5001"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.API '["/ip4/localhost/tcp/5001"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/127.0.0.1/tcp/8080"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/localhost/tcp/8080"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4001","/ip6/::/tcp/4001"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/bootstrap/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4101","/ip6/::/tcp/4101"]' 2>&1 | grep -v "generating" || true; \
fi; \ fi; \
echo " Initializing IPFS Cluster..."; \ echo " Initializing IPFS Cluster..."; \
mkdir -p $$HOME/.debros/bootstrap/ipfs-cluster; \ mkdir -p $$HOME/.debros/bootstrap/ipfs-cluster; \
@ -135,9 +135,9 @@ dev: build
echo " Initializing IPFS..."; \ echo " Initializing IPFS..."; \
mkdir -p $$HOME/.debros/node2/ipfs; \ mkdir -p $$HOME/.debros/node2/ipfs; \
IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \ IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \
IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.API '["/ip4/127.0.0.1/tcp/5002"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.API '["/ip4/localhost/tcp/5002"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/127.0.0.1/tcp/8081"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/localhost/tcp/8081"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4002","/ip6/::/tcp/4002"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node2/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4102","/ip6/::/tcp/4102"]' 2>&1 | grep -v "generating" || true; \
fi; \ fi; \
echo " Initializing IPFS Cluster..."; \ echo " Initializing IPFS Cluster..."; \
mkdir -p $$HOME/.debros/node2/ipfs-cluster; \ mkdir -p $$HOME/.debros/node2/ipfs-cluster; \
@ -148,9 +148,9 @@ dev: build
echo " Initializing IPFS..."; \ echo " Initializing IPFS..."; \
mkdir -p $$HOME/.debros/node3/ipfs; \ mkdir -p $$HOME/.debros/node3/ipfs; \
IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \ IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs init --profile=server 2>&1 | grep -v "generating" | grep -v "peer identity" || true; \
IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.API '["/ip4/127.0.0.1/tcp/5003"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.API '["/ip4/localhost/tcp/5003"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/127.0.0.1/tcp/8082"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.Gateway '["/ip4/localhost/tcp/8082"]' 2>&1 | grep -v "generating" || true; \
IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4003","/ip6/::/tcp/4003"]' 2>&1 | grep -v "generating" || true; \ IPFS_PATH=$$HOME/.debros/node3/ipfs/repo ipfs config --json Addresses.Swarm '["/ip4/0.0.0.0/tcp/4103","/ip6/::/tcp/4103"]' 2>&1 | grep -v "generating" || true; \
fi; \ fi; \
echo " Initializing IPFS Cluster..."; \ echo " Initializing IPFS Cluster..."; \
mkdir -p $$HOME/.debros/node3/ipfs-cluster; \ mkdir -p $$HOME/.debros/node3/ipfs-cluster; \

View File

@ -68,7 +68,7 @@ Use `make dev` for the complete stack or run binaries individually with `go run
All runtime configuration lives in `~/.debros/`. All runtime configuration lives in `~/.debros/`.
- `bootstrap.yaml`: `type: bootstrap`, blank `database.rqlite_join_address` - `bootstrap.yaml`: `type: bootstrap`, blank `database.rqlite_join_address`
- `node*.yaml`: `type: node`, set `database.rqlite_join_address` (e.g. `127.0.0.1:7001`) and include the bootstrap `discovery.bootstrap_peers` - `node*.yaml`: `type: node`, set `database.rqlite_join_address` (e.g. `localhost:7001`) and include the bootstrap `discovery.bootstrap_peers`
- `gateway.yaml`: configure `gateway.bootstrap_peers`, `gateway.namespace`, and optional auth flags - `gateway.yaml`: configure `gateway.bootstrap_peers`, `gateway.namespace`, and optional auth flags
Validation reminders: Validation reminders:
@ -127,7 +127,7 @@ Environment overrides:
```bash ```bash
export GATEWAY_ADDR="0.0.0.0:6001" export GATEWAY_ADDR="0.0.0.0:6001"
export GATEWAY_NAMESPACE="my-app" export GATEWAY_NAMESPACE="my-app"
export GATEWAY_BOOTSTRAP_PEERS="/ip4/127.0.0.1/tcp/4001/p2p/<peerID>" export GATEWAY_BOOTSTRAP_PEERS="/ip4/localhost/tcp/4001/p2p/<peerID>"
export GATEWAY_REQUIRE_AUTH=true export GATEWAY_REQUIRE_AUTH=true
export GATEWAY_API_KEYS="key1:namespace1,key2:namespace2" export GATEWAY_API_KEYS="key1:namespace1,key2:namespace2"
``` ```

View File

@ -255,10 +255,10 @@ func main() {
// Set default advertised addresses if empty // Set default advertised addresses if empty
if cfg.Discovery.HttpAdvAddress == "" { if cfg.Discovery.HttpAdvAddress == "" {
cfg.Discovery.HttpAdvAddress = fmt.Sprintf("127.0.0.1:%d", cfg.Database.RQLitePort) cfg.Discovery.HttpAdvAddress = fmt.Sprintf("localhost:%d", cfg.Database.RQLitePort)
} }
if cfg.Discovery.RaftAdvAddress == "" { if cfg.Discovery.RaftAdvAddress == "" {
cfg.Discovery.RaftAdvAddress = fmt.Sprintf("127.0.0.1:%d", cfg.Database.RQLiteRaftPort) cfg.Discovery.RaftAdvAddress = fmt.Sprintf("localhost:%d", cfg.Database.RQLiteRaftPort)
} }
// Validate configuration // Validate configuration

View File

@ -122,7 +122,7 @@ If automatic setup didn't work, you can manually initialize:
```bash ```bash
sudo -u debros ipfs init --profile=server --repo-dir=~/.debros/bootstrap/ipfs/repo sudo -u debros ipfs init --profile=server --repo-dir=~/.debros/bootstrap/ipfs/repo
sudo -u debros ipfs config --json Addresses.API '["/ip4/127.0.0.1/tcp/5001"]' --repo-dir=~/.debros/bootstrap/ipfs/repo sudo -u debros ipfs config --json Addresses.API '["/ip4/localhost/tcp/5001"]' --repo-dir=~/.debros/bootstrap/ipfs/repo
``` ```
### 2. Initialize Cluster ### 2. Initialize Cluster

View File

@ -37,7 +37,7 @@ func requireAPIKey(t *testing.T) string {
} }
func gatewayBaseURL() string { func gatewayBaseURL() string {
return getEnv("GATEWAY_BASE_URL", "http://127.0.0.1:6001") return getEnv("GATEWAY_BASE_URL", "http://localhost:6001")
} }
func httpClient() *http.Client { func httpClient() *http.Client {

View File

@ -19,7 +19,7 @@ var disabled bool
func SetDisabled(v bool) { disabled = v } func SetDisabled(v bool) { disabled = v }
// Enabled reports whether Anyone proxy routing is active. // Enabled reports whether Anyone proxy routing is active.
// Defaults to true, using SOCKS5 at 127.0.0.1:9050, unless explicitly disabled // Defaults to true, using SOCKS5 at localhost:9050, unless explicitly disabled
// via SetDisabled(true) or environment variable ANYONE_DISABLE=1. // via SetDisabled(true) or environment variable ANYONE_DISABLE=1.
// ANYONE_SOCKS5 may override the proxy address. // ANYONE_SOCKS5 may override the proxy address.
func Enabled() bool { func Enabled() bool {
@ -31,7 +31,7 @@ func Enabled() bool {
// socksAddr returns the SOCKS5 address to use for proxying (host:port). // socksAddr returns the SOCKS5 address to use for proxying (host:port).
func socksAddr() string { func socksAddr() string {
return "127.0.0.1:9050" return "localhost:9050"
} }
// socksContextDialer implements tcp.ContextDialer over a SOCKS5 proxy. // socksContextDialer implements tcp.ContextDialer over a SOCKS5 proxy.
@ -57,7 +57,7 @@ func (d *socksContextDialer) DialContext(ctx context.Context, network, address s
// DialerForAddr returns a tcp.DialerForAddr that routes through the Anyone SOCKS5 proxy. // DialerForAddr returns a tcp.DialerForAddr that routes through the Anyone SOCKS5 proxy.
// It automatically BYPASSES the proxy for loopback, private, and link-local addresses // It automatically BYPASSES the proxy for loopback, private, and link-local addresses
// to allow local/dev networking (e.g. 127.0.0.1, 10.0.0.0/8, 192.168.0.0/16, fc00::/7, fe80::/10). // to allow local/dev networking (e.g. localhost, 10.0.0.0/8, 192.168.0.0/16, fc00::/7, fe80::/10).
func DialerForAddr() tcp.DialerForAddr { func DialerForAddr() tcp.DialerForAddr {
return func(raddr ma.Multiaddr) (tcp.ContextDialer, error) { return func(raddr ma.Multiaddr) (tcp.ContextDialer, error) {
// Prefer direct dialing for local/private targets // Prefer direct dialing for local/private targets

View File

@ -286,7 +286,7 @@ func initFullStack(force bool) {
fmt.Printf("✅ Generated bootstrap identity: %s (Peer ID: %s)\n", bootstrapIdentityPath, bootstrapInfo.PeerID.String()) fmt.Printf("✅ Generated bootstrap identity: %s (Peer ID: %s)\n", bootstrapIdentityPath, bootstrapInfo.PeerID.String())
// Construct bootstrap multiaddr // Construct bootstrap multiaddr
bootstrapMultiaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/4001/p2p/%s", bootstrapInfo.PeerID.String()) bootstrapMultiaddr := fmt.Sprintf("/ip4/localhost/tcp/4001/p2p/%s", bootstrapInfo.PeerID.String())
fmt.Printf(" Bootstrap multiaddr: %s\n", bootstrapMultiaddr) fmt.Printf(" Bootstrap multiaddr: %s\n", bootstrapMultiaddr)
// Generate configs for all nodes... // Generate configs for all nodes...
@ -430,8 +430,8 @@ discovery:
%s %s
discovery_interval: "15s" discovery_interval: "15s"
bootstrap_port: %d bootstrap_port: %d
http_adv_address: "127.0.0.1:%d" http_adv_address: "localhost:%d"
raft_adv_address: "127.0.0.1:%d" raft_adv_address: "localhost:%d"
node_namespace: "default" node_namespace: "default"
security: security:
@ -477,8 +477,8 @@ discovery:
bootstrap_peers: [] bootstrap_peers: []
discovery_interval: "15s" discovery_interval: "15s"
bootstrap_port: %d bootstrap_port: %d
http_adv_address: "127.0.0.1:%d" http_adv_address: "localhost:%d"
raft_adv_address: "127.0.0.1:%d" raft_adv_address: "localhost:%d"
node_namespace: "default" node_namespace: "default"
security: security:

View File

@ -1102,12 +1102,12 @@ func installOlric() {
configPath := olricConfigDir + "/config.yaml" configPath := olricConfigDir + "/config.yaml"
if _, err := os.Stat(configPath); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
configContent := `server: configContent := `server:
bindAddr: "127.0.0.1" bindAddr: "localhost"
bindPort: 3320 bindPort: 3320
memberlist: memberlist:
environment: local environment: local
bindAddr: "127.0.0.1" bindAddr: "localhost"
bindPort: 3322 bindPort: 3322
` `
@ -1907,8 +1907,8 @@ func initializeIPFSForNode(nodeID, vpsIP string, isBootstrap bool) error {
} }
// Configure IPFS API and Gateway addresses // Configure IPFS API and Gateway addresses
exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.API", `["/ip4/127.0.0.1/tcp/5001"]`, "--repo-dir="+ipfsRepoPath).Run() exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.API", `["/ip4/localhost/tcp/5001"]`, "--repo-dir="+ipfsRepoPath).Run()
exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.Gateway", `["/ip4/127.0.0.1/tcp/8080"]`, "--repo-dir="+ipfsRepoPath).Run() exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.Gateway", `["/ip4/localhost/tcp/8080"]`, "--repo-dir="+ipfsRepoPath).Run()
exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.Swarm", `["/ip4/0.0.0.0/tcp/4001","/ip6/::/tcp/4001"]`, "--repo-dir="+ipfsRepoPath).Run() exec.Command("sudo", "-u", "debros", "ipfs", "config", "--json", "Addresses.Swarm", `["/ip4/0.0.0.0/tcp/4001","/ip6/::/tcp/4001"]`, "--repo-dir="+ipfsRepoPath).Run()
fmt.Printf(" ✓ IPFS initialized\n") fmt.Printf(" ✓ IPFS initialized\n")
} }
@ -2059,7 +2059,7 @@ func generateClusterServiceConfig(nodeID, vpsIP, secret string, isBootstrap bool
}, },
IPFSConnector: ipfsConnectorConfig{ IPFSConnector: ipfsConnectorConfig{
IPFSHTTP: ipfsHTTPConfig{ IPFSHTTP: ipfsHTTPConfig{
NodeMultiaddress: "/ip4/127.0.0.1/tcp/5001", NodeMultiaddress: "/ip4/localhost/tcp/5001",
}, },
}, },
Datastore: datastoreConfig{ Datastore: datastoreConfig{

View File

@ -11,7 +11,7 @@ func TestDefaultBootstrapPeersNonEmpty(t *testing.T) {
old := os.Getenv("DEBROS_BOOTSTRAP_PEERS") old := os.Getenv("DEBROS_BOOTSTRAP_PEERS")
t.Cleanup(func() { os.Setenv("DEBROS_BOOTSTRAP_PEERS", old) }) t.Cleanup(func() { os.Setenv("DEBROS_BOOTSTRAP_PEERS", old) })
// Set a valid bootstrap peer // Set a valid bootstrap peer
validPeer := "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj" validPeer := "/ip4/localhost/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj"
_ = os.Setenv("DEBROS_BOOTSTRAP_PEERS", validPeer) _ = os.Setenv("DEBROS_BOOTSTRAP_PEERS", validPeer)
peers := DefaultBootstrapPeers() peers := DefaultBootstrapPeers()
if len(peers) == 0 { if len(peers) == 0 {
@ -50,8 +50,8 @@ func TestNormalizeEndpoints(t *testing.T) {
} }
func TestEndpointFromMultiaddr(t *testing.T) { func TestEndpointFromMultiaddr(t *testing.T) {
ma, _ := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/4001") ma, _ := multiaddr.NewMultiaddr("/ip4/localhost/tcp/4001")
if ep := endpointFromMultiaddr(ma, 5001); ep != "http://127.0.0.1:5001" { if ep := endpointFromMultiaddr(ma, 5001); ep != "http://localhost:5001" {
t.Fatalf("unexpected endpoint: %s", ep) t.Fatalf("unexpected endpoint: %s", ep)
} }
} }

View File

@ -7,7 +7,7 @@ import (
// validConfigForType returns a valid config for the given node type // validConfigForType returns a valid config for the given node type
func validConfigForType(nodeType string) *Config { func validConfigForType(nodeType string) *Config {
validPeer := "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj" validPeer := "/ip4/localhost/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj"
cfg := &Config{ cfg := &Config{
Node: NodeConfig{ Node: NodeConfig{
Type: nodeType, Type: nodeType,
@ -30,8 +30,8 @@ func validConfigForType(nodeType string) *Config {
BootstrapPeers: []string{validPeer}, BootstrapPeers: []string{validPeer},
DiscoveryInterval: 15 * time.Second, DiscoveryInterval: 15 * time.Second,
BootstrapPort: 4001, BootstrapPort: 4001,
HttpAdvAddress: "127.0.0.1:5001", HttpAdvAddress: "localhost:5001",
RaftAdvAddress: "127.0.0.1:7001", RaftAdvAddress: "localhost:7001",
NodeNamespace: "default", NodeNamespace: "default",
}, },
Logging: LoggingConfig{ Logging: LoggingConfig{
@ -205,7 +205,7 @@ func TestValidateRQLiteJoinAddress(t *testing.T) {
} }
func TestValidateBootstrapPeers(t *testing.T) { func TestValidateBootstrapPeers(t *testing.T) {
validPeer := "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj" validPeer := "/ip4/localhost/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj"
tests := []struct { tests := []struct {
name string name string
nodeType string nodeType string
@ -217,9 +217,9 @@ func TestValidateBootstrapPeers(t *testing.T) {
{"bootstrap with peer", "bootstrap", []string{validPeer}, false}, {"bootstrap with peer", "bootstrap", []string{validPeer}, false},
{"bootstrap without peer", "bootstrap", []string{}, false}, {"bootstrap without peer", "bootstrap", []string{}, false},
{"invalid multiaddr", "node", []string{"invalid"}, true}, {"invalid multiaddr", "node", []string{"invalid"}, true},
{"missing p2p", "node", []string{"/ip4/127.0.0.1/tcp/4001"}, true}, {"missing p2p", "node", []string{"/ip4/localhost/tcp/4001"}, true},
{"duplicate peer", "node", []string{validPeer, validPeer}, true}, {"duplicate peer", "node", []string{validPeer, validPeer}, true},
{"invalid port", "node", []string{"/ip4/127.0.0.1/tcp/99999/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj"}, true}, {"invalid port", "node", []string{"/ip4/localhost/tcp/99999/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj"}, true},
} }
for _, tt := range tests { for _, tt := range tests {
@ -392,17 +392,17 @@ func TestValidateCompleteConfig(t *testing.T) {
BackupInterval: 24 * time.Hour, BackupInterval: 24 * time.Hour,
RQLitePort: 5002, RQLitePort: 5002,
RQLiteRaftPort: 7002, RQLiteRaftPort: 7002,
RQLiteJoinAddress: "127.0.0.1:7001", RQLiteJoinAddress: "localhost:7001",
MinClusterSize: 1, MinClusterSize: 1,
}, },
Discovery: DiscoveryConfig{ Discovery: DiscoveryConfig{
BootstrapPeers: []string{ BootstrapPeers: []string{
"/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj", "/ip4/localhost/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj",
}, },
DiscoveryInterval: 15 * time.Second, DiscoveryInterval: 15 * time.Second,
BootstrapPort: 4001, BootstrapPort: 4001,
HttpAdvAddress: "127.0.0.1:5001", HttpAdvAddress: "localhost:5001",
RaftAdvAddress: "127.0.0.1:7001", RaftAdvAddress: "localhost:7001",
NodeNamespace: "default", NodeNamespace: "default",
}, },
Security: SecurityConfig{ Security: SecurityConfig{

View File

@ -234,7 +234,7 @@ func isPrivateOrLocalHost(host string) bool {
} }
// Check for localhost variants // Check for localhost variants
if host == "localhost" || host == "127.0.0.1" || host == "::1" { if host == "localhost" || host == "localhost" || host == "::1" {
return true return true
} }

View File

@ -92,7 +92,7 @@ func TestAnonProxyHandler_PrivateAddressBlocking(t *testing.T) {
url string url string
}{ }{
{"localhost", "http://localhost/test"}, {"localhost", "http://localhost/test"},
{"127.0.0.1", "http://127.0.0.1/test"}, {"localhost", "http://localhost/test"},
{"private 10.x", "http://10.0.0.1/test"}, {"private 10.x", "http://10.0.0.1/test"},
{"private 192.168.x", "http://192.168.1.1/test"}, {"private 192.168.x", "http://192.168.1.1/test"},
{"private 172.16.x", "http://172.16.0.1/test"}, {"private 172.16.x", "http://172.16.0.1/test"},
@ -166,7 +166,7 @@ func TestIsPrivateOrLocalHost(t *testing.T) {
expected bool expected bool
}{ }{
{"localhost", true}, {"localhost", true},
{"127.0.0.1", true}, {"localhost", true},
{"::1", true}, {"::1", true},
{"10.0.0.1", true}, {"10.0.0.1", true},
{"192.168.1.1", true}, {"192.168.1.1", true},

View File

@ -371,7 +371,7 @@ func discoverOlricServers(networkClient client.NetworkClient, logger *zap.Logger
} }
// Skip localhost loopback addresses (we'll use localhost:3320 as fallback) // Skip localhost loopback addresses (we'll use localhost:3320 as fallback)
if ip == "127.0.0.1" || ip == "::1" || ip == "localhost" { if ip == "localhost" || ip == "::1" || ip == "localhost" {
continue continue
} }
@ -402,7 +402,7 @@ func discoverOlricServers(networkClient client.NetworkClient, logger *zap.Logger
} }
// Skip localhost // Skip localhost
if ip == "127.0.0.1" || ip == "::1" || ip == "localhost" { if ip == "localhost" || ip == "::1" || ip == "localhost" {
continue continue
} }

View File

@ -18,11 +18,12 @@ import (
// mockIPFSClient is a mock implementation of ipfs.IPFSClient for testing // mockIPFSClient is a mock implementation of ipfs.IPFSClient for testing
type mockIPFSClient struct { type mockIPFSClient struct {
addFunc func(ctx context.Context, reader io.Reader, name string) (*ipfs.AddResponse, error) addFunc func(ctx context.Context, reader io.Reader, name string) (*ipfs.AddResponse, error)
pinFunc func(ctx context.Context, cid string, name string, replicationFactor int) (*ipfs.PinResponse, error) pinFunc func(ctx context.Context, cid string, name string, replicationFactor int) (*ipfs.PinResponse, error)
pinStatusFunc func(ctx context.Context, cid string) (*ipfs.PinStatus, error) pinStatusFunc func(ctx context.Context, cid string) (*ipfs.PinStatus, error)
getFunc func(ctx context.Context, cid string, ipfsAPIURL string) (io.ReadCloser, error) getFunc func(ctx context.Context, cid string, ipfsAPIURL string) (io.ReadCloser, error)
unpinFunc func(ctx context.Context, cid string) error unpinFunc func(ctx context.Context, cid string) error
getPeerCountFunc func(ctx context.Context) (int, error)
} }
func (m *mockIPFSClient) Add(ctx context.Context, reader io.Reader, name string) (*ipfs.AddResponse, error) { func (m *mockIPFSClient) Add(ctx context.Context, reader io.Reader, name string) (*ipfs.AddResponse, error) {
@ -72,6 +73,13 @@ func (m *mockIPFSClient) Health(ctx context.Context) error {
return nil return nil
} }
func (m *mockIPFSClient) GetPeerCount(ctx context.Context) (int, error) {
if m.getPeerCountFunc != nil {
return m.getPeerCountFunc(ctx)
}
return 3, nil
}
func (m *mockIPFSClient) Close(ctx context.Context) error { func (m *mockIPFSClient) Close(ctx context.Context) error {
return nil return nil
} }

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -158,14 +159,19 @@ func TestClient_Pin(t *testing.T) {
t.Errorf("Expected method POST, got %s", r.Method) t.Errorf("Expected method POST, got %s", r.Method)
} }
var reqBody map[string]interface{} if cid := strings.TrimPrefix(r.URL.Path, "/pins/"); cid != expectedCID {
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil { t.Errorf("Expected CID %s in path, got %s", expectedCID, cid)
t.Errorf("Failed to decode request: %v", err)
return
} }
if reqBody["cid"] != expectedCID { query := r.URL.Query()
t.Errorf("Expected CID %s, got %v", expectedCID, reqBody["cid"]) if got := query.Get("replication-min"); got != strconv.Itoa(expectedReplicationFactor) {
t.Errorf("Expected replication-min %d, got %s", expectedReplicationFactor, got)
}
if got := query.Get("replication-max"); got != strconv.Itoa(expectedReplicationFactor) {
t.Errorf("Expected replication-max %d, got %s", expectedReplicationFactor, got)
}
if got := query.Get("name"); got != expectedName {
t.Errorf("Expected name %s, got %s", expectedName, got)
} }
response := PinResponse{ response := PinResponse{
@ -231,14 +237,14 @@ func TestClient_PinStatus(t *testing.T) {
t.Errorf("Expected method GET, got %s", r.Method) t.Errorf("Expected method GET, got %s", r.Method)
} }
response := PinStatus{ response := map[string]interface{}{
Cid: expectedCID, "cid": expectedCID,
Name: "test-file", "name": "test-file",
Status: "pinned", "peer_map": map[string]interface{}{
ReplicationMin: 3, "peer1": map[string]interface{}{"status": "pinned"},
ReplicationMax: 3, "peer2": map[string]interface{}{"status": "pinned"},
ReplicationFactor: 3, "peer3": map[string]interface{}{"status": "pinned"},
Peers: []string{"peer1", "peer2", "peer3"}, },
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) json.NewEncoder(w).Encode(response)

View File

@ -321,7 +321,7 @@ func (n *Node) startLibP2P() error {
// For localhost/development, disable NAT services // For localhost/development, disable NAT services
// For production, these would be enabled // For production, these would be enabled
isLocalhost := len(n.config.Node.ListenAddresses) > 0 && isLocalhost := len(n.config.Node.ListenAddresses) > 0 &&
(strings.Contains(n.config.Node.ListenAddresses[0], "127.0.0.1") || (strings.Contains(n.config.Node.ListenAddresses[0], "localhost") ||
strings.Contains(n.config.Node.ListenAddresses[0], "localhost")) strings.Contains(n.config.Node.ListenAddresses[0], "localhost"))
if isLocalhost { if isLocalhost {

View File

@ -177,13 +177,13 @@ func TestHashBootstrapConnections(t *testing.T) {
} }
// Create two hosts (A and B) listening on localhost TCP // Create two hosts (A and B) listening on localhost TCP
hA, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")) hA, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/localhost/tcp/0"))
if err != nil { if err != nil {
t.Fatalf("libp2p.New (A): %v", err) t.Fatalf("libp2p.New (A): %v", err)
} }
defer hA.Close() defer hA.Close()
hB, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")) hB, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/localhost/tcp/0"))
if err != nil { if err != nil {
t.Fatalf("libp2p.New (B): %v", err) t.Fatalf("libp2p.New (B): %v", err)
} }
@ -244,19 +244,19 @@ func TestHashBootstrapConnections(t *testing.T) {
} }
// Create three hosts (A, B, C) listening on localhost TCP // Create three hosts (A, B, C) listening on localhost TCP
hA, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")) hA, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/localhost/tcp/0"))
if err != nil { if err != nil {
t.Fatalf("libp2p.New (A): %v", err) t.Fatalf("libp2p.New (A): %v", err)
} }
defer hA.Close() defer hA.Close()
hB, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")) hB, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/localhost/tcp/0"))
if err != nil { if err != nil {
t.Fatalf("libp2p.New (B): %v", err) t.Fatalf("libp2p.New (B): %v", err)
} }
defer hB.Close() defer hB.Close()
hC, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")) hC, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/localhost/tcp/0"))
if err != nil { if err != nil {
t.Fatalf("libp2p.New (C): %v", err) t.Fatalf("libp2p.New (C): %v", err)
} }