diff --git a/cluster/main.go b/cluster/main.go index f63007d7..c00f2108 100644 --- a/cluster/main.go +++ b/cluster/main.go @@ -36,19 +36,27 @@ func NewClusterSecret() (string, error) { return hex.EncodeToString(secret), nil } -func InitCluster(repoPath, secret string) error { - decoded, err := ipfscluster.DecodeClusterSecret(secret) +func InitCluster(repoPath, secret string, listenAddr string) error { + cfgMgr, cfgs := makeClusterConfigs() + err := cfgMgr.Default() if err != nil { return err } - cfgMgr, cfgs := makeClusterConfigs() - err = cfgMgr.Default() + decoded, err := ipfscluster.DecodeClusterSecret(secret) if err != nil { return err } cfgs.ClusterCfg.Secret = decoded + if listenAddr != "" { + addr, err := ma.NewMultiaddr(listenAddr) + if err != nil { + return err + } + cfgs.ClusterCfg.ListenAddr = addr + } + return cfgMgr.SaveJSON(ConfigPath(repoPath)) } diff --git a/cluster/cluster_test.go b/cluster/main_test.go similarity index 68% rename from cluster/cluster_test.go rename to cluster/main_test.go index 3c62aa3b..2ed5134a 100644 --- a/cluster/cluster_test.go +++ b/cluster/main_test.go @@ -10,10 +10,12 @@ import ( icid "github.com/ipfs/go-cid" icore "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/repo/fsrepo" + "github.com/ipfs/ipfs-cluster/api" "github.com/textileio/go-textile/cluster" "github.com/textileio/go-textile/core" "github.com/textileio/go-textile/ipfs" "github.com/textileio/go-textile/keypair" + "github.com/textileio/go-textile/pb" "github.com/textileio/go-textile/repo/config" ) @@ -59,12 +61,13 @@ func TestInitCluster(t *testing.T) { t.Fatalf("init node1 failed: %s", err) } err = core.InitRepo(core.InitConfig{ - Account: accnt2, - RepoPath: vars.repoPath2, - ApiAddr: fmt.Sprintf("127.0.0.1:%s", core.GetRandomPort()), - SwarmPorts: swarmPort2, - ClusterSecret: secret, - Debug: true, + Account: accnt2, + RepoPath: vars.repoPath2, + ApiAddr: fmt.Sprintf("127.0.0.1:%s", core.GetRandomPort()), + SwarmPorts: swarmPort2, + ClusterSecret: secret, + ClusterBindMultiaddr: "/ip4/0.0.0.0/tcp/9097", + Debug: true, }) if err != nil { t.Fatalf("init node2 failed: %s", err) @@ -106,18 +109,45 @@ func TestStartCluster(t *testing.T) { t.Fatalf("create node2 failed: %s", err) } + // set cluster logs to debug + level := &pb.LogLevel{ + Systems: map[string]pb.LogLevel_Level{ + "cluster": pb.LogLevel_DEBUG, + }, + } + err = vars.node1.SetLogLevel(level) + if err != nil { + t.Fatal(err) + } + err = vars.node2.SetLogLevel(level) + if err != nil { + t.Fatal(err) + } + + // start nodes err = vars.node1.Start() if err != nil { t.Fatalf("start node1 failed: %s", err) } + <-vars.node1.OnlineCh() + <-vars.node1.Cluster().Ready() + + // let node1 warm up + timer := time.NewTimer(time.Second * 5) + <-timer.C + err = vars.node2.Start() if err != nil { t.Fatalf("start node2 failed: %s", err) } - - <-vars.node1.OnlineCh() <-vars.node2.OnlineCh() + <-vars.node2.Cluster().Ready() + // let node2 warm up + timer = time.NewTimer(time.Second * 5) + <-timer.C + + // pin some data to node1 cid, err := pinTestData(vars.node1.Ipfs()) if err != nil { t.Fatal(err) @@ -125,25 +155,44 @@ func TestStartCluster(t *testing.T) { vars.cid = *cid } +func TestTextileClusterPeers(t *testing.T) { + ctx, cancel := context.WithTimeout(vars.node1.Ipfs().Context(), time.Minute) + defer cancel() + + var ok bool + for _, p := range vars.node1.Cluster().Peers(ctx) { + if p.ID.Pretty() == vars.node2.Ipfs().Identity.Pretty() { + ok = true + break + } + } + if !ok { + t.Fatal("node2 not found in node1's peers") + } + ok = false + for _, p := range vars.node2.Cluster().Peers(ctx) { + if p.ID.Pretty() == vars.node1.Ipfs().Identity.Pretty() { + ok = true + break + } + } + if !ok { + t.Fatal("node1 not found in node2's peers") + } +} + func TestTextileClusterSync(t *testing.T) { ctx, cancel := context.WithTimeout(vars.node1.Ipfs().Context(), time.Minute) defer cancel() - info, err := vars.node1.Cluster().SyncAll(ctx) + _, err := vars.node1.Cluster().SyncAll(ctx) if err != nil { t.Fatalf("sync all failed: %s", err) } - var foundCid bool - for _, i := range info { - fmt.Println(i.String()) - if i.Cid.Equals(vars.cid) { - foundCid = true - } - } - - if !foundCid { - //t.Fatalf("failed to find cid in cluster: %s", vars.cid.String()) + info := vars.node2.Cluster().StatusLocal(ctx, vars.cid) + if !info.Status.Match(api.TrackerStatusPinned) { + t.Fatalf("node1 cid not pinned on node2: %s", vars.cid.String()) } } diff --git a/cmd/main.go b/cmd/main.go index 77c1ece8..bafefa3e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -439,6 +439,7 @@ Stacks may include: initCafeNeighborURL := initCmd.Flag("cafe-neighbor-url", "Specify the URL of a secondary cafe. Must return cafe info, e.g., via a Gateway: https://my-gateway.yolo.com/cafe, or a cafe API: https://my-cafe.yolo.com").Envar("CAFE_HOST_NEIGHBOR_URL").String() initIpfsCluster := initCmd.Flag("cluster", "Attach an IPFS Cluster service").Bool() initIpfsClusterSecret := initCmd.Flag("cluster-secret", "IPFS Cluster secret, omit to auto-generate").String() + initIpfsClusterBindMultiaddr := initCmd.Flag("cluster-bind-maddr", "Set the IPFS Cluster multiaddrs").Default("/ip4/0.0.0.0/tcp/9096").String() initIpfsClusterPeers := initCmd.Flag("cluster-peer", "IPFS Cluster peers to sync with").Strings() cmds[initCmd.FullCommand()] = func() error { kp, err := keypair.Parse(*initAccountSeed) @@ -469,23 +470,24 @@ Stacks may include: } config := core.InitConfig{ - Account: account, - PinCode: *initPin, // @todo rename to pin - RepoPath: repo, // @todo rename to repo - SwarmPorts: *initIpfsSwarmPorts, - ApiAddr: *initApiBindAddr, - CafeApiAddr: *initCafeApiBindAddr, - GatewayAddr: *initGatewayBindAddr, - ProfilingAddr: *initProfilingBindAddr, - IsMobile: false, - IsServer: *initIpfsServerMode, - LogToDisk: *initLogFiles, - Debug: *logDebug, - CafeOpen: *initCafeOpen, - CafeURL: *initCafeURL, - CafeNeighborURL: *initCafeNeighborURL, - ClusterSecret: secret, - ClusterPeers: *initIpfsClusterPeers, + Account: account, + PinCode: *initPin, // @todo rename to pin + RepoPath: repo, // @todo rename to repo + SwarmPorts: *initIpfsSwarmPorts, + ApiAddr: *initApiBindAddr, + CafeApiAddr: *initCafeApiBindAddr, + GatewayAddr: *initGatewayBindAddr, + ProfilingAddr: *initProfilingBindAddr, + IsMobile: false, + IsServer: *initIpfsServerMode, + LogToDisk: *initLogFiles, + Debug: *logDebug, + CafeOpen: *initCafeOpen, + CafeURL: *initCafeURL, + CafeNeighborURL: *initCafeNeighborURL, + ClusterSecret: secret, + ClusterBindMultiaddr: *initIpfsClusterBindMultiaddr, + ClusterPeers: *initIpfsClusterPeers, } return InitCommand(config) diff --git a/core/main.go b/core/main.go index c7b864bb..31215a19 100644 --- a/core/main.go +++ b/core/main.go @@ -49,23 +49,24 @@ const kSyncAccountFreq = time.Hour // InitConfig is used to setup a textile node type InitConfig struct { - Account *keypair.Full - PinCode string - RepoPath string - SwarmPorts string - ApiAddr string - CafeApiAddr string - GatewayAddr string - ProfilingAddr string - IsMobile bool - IsServer bool - LogToDisk bool - Debug bool - CafeOpen bool - CafeURL string - CafeNeighborURL string // Deprecated - ClusterSecret string - ClusterPeers []string + Account *keypair.Full + PinCode string + RepoPath string + SwarmPorts string + ApiAddr string + CafeApiAddr string + GatewayAddr string + ProfilingAddr string + IsMobile bool + IsServer bool + LogToDisk bool + Debug bool + CafeOpen bool + CafeURL string + CafeNeighborURL string // Deprecated + ClusterSecret string + ClusterBindMultiaddr string + ClusterPeers []string } // MigrateConfig is used to define options during a major migration @@ -146,7 +147,7 @@ func InitRepo(conf InitConfig) error { // init cluster if conf.ClusterSecret != "" { - err = cluster.InitCluster(conf.RepoPath, conf.ClusterSecret) + err = cluster.InitCluster(conf.RepoPath, conf.ClusterSecret, conf.ClusterBindMultiaddr) if err != nil { return err }