Refactored private network implementation + config.

This commit is contained in:
dgrisham 2017-07-04 14:39:10 -06:00
parent 59fde30e1e
commit 98335901fc
8 changed files with 127 additions and 105 deletions

View File

@ -865,17 +865,16 @@ func makeHost(ctx context.Context, cfg *Config) (host.Host, error) {
publicKey := privateKey.GetPublic()
var protec ipnet.Protector
if len(cfg.SwarmSecret) != 0 {
if len(cfg.ClusterSecret) != 0 {
var err error
swarmKey, err := swarmSecretToKey(cfg.SwarmSecret)
clusterKey, err := clusterSecretToKey(cfg.ClusterSecret)
if err != nil {
return nil, err
}
protec, err = pnet.NewProtector(strings.NewReader(swarmKey))
protec, err = pnet.NewProtector(strings.NewReader(clusterKey))
if err != nil {
return nil, err
}
cfg.PNetFingerprint = protec.Fingerprint()
// this is in go-ipfs, not sure whether we want something like it here
/* go func() {
t := time.NewTicker(30 * time.Second)

View File

@ -81,12 +81,10 @@ func (ipfs *mockConnector) ConnectSwarms() error { retu
func (ipfs *mockConnector) ConfigKey(keypath string) (interface{}, error) { return nil, nil }
func (ipfs *mockConnector) RepoSize() (int, error) { return 0, nil }
func testingCluster(t *testing.T, uniqueSwarm bool) (*Cluster, *mockAPI, *mockConnector, *mapstate.MapState, *maptracker.MapPinTracker) {
func testingCluster(t *testing.T) (*Cluster, *mockAPI, *mockConnector, *mapstate.MapState, *maptracker.MapPinTracker) {
api := &mockAPI{}
ipfs := &mockConnector{}
swarmSecret, err := testingSwarmSecret(uniqueSwarm)
checkErr(t, err)
cfg := testingConfig(swarmSecret)
cfg := testingConfig()
st := mapstate.NewMapState()
tracker := maptracker.NewMapPinTracker(cfg.ID)
mon := basic.NewStdPeerMonitor(2)
@ -114,13 +112,13 @@ func cleanRaft() {
}
func testClusterShutdown(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
err := cl.Shutdown()
if err != nil {
t.Error("cluster shutdown failed:", err)
}
cl.Shutdown()
cl, _, _, _, _ = testingCluster(t, false)
cl, _, _, _, _ = testingCluster(t)
err = cl.Shutdown()
if err != nil {
t.Error("cluster shutdown failed:", err)
@ -129,7 +127,7 @@ func testClusterShutdown(t *testing.T) {
func TestClusterStateSync(t *testing.T) {
cleanRaft()
cl, _, _, st, _ := testingCluster(t, false)
cl, _, _, st, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
_, err := cl.StateSync()
@ -158,7 +156,7 @@ func TestClusterStateSync(t *testing.T) {
}
func TestClusterID(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
id := cl.ID()
@ -177,7 +175,7 @@ func TestClusterID(t *testing.T) {
}
func TestClusterPin(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
@ -196,7 +194,7 @@ func TestClusterPin(t *testing.T) {
}
func TestClusterPins(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
@ -216,7 +214,7 @@ func TestClusterPins(t *testing.T) {
}
func TestClusterPinGet(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
@ -242,7 +240,7 @@ func TestClusterPinGet(t *testing.T) {
}
func TestClusterUnpin(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
@ -261,20 +259,20 @@ func TestClusterUnpin(t *testing.T) {
}
func TestClusterPeers(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
peers := cl.Peers()
if len(peers) != 1 {
t.Fatal("expected 1 peer")
}
if peers[0].ID != testingConfig("").ID {
if peers[0].ID != testingConfig().ID {
t.Error("bad member")
}
}
func TestVersion(t *testing.T) {
cl, _, _, _, _ := testingCluster(t, false)
cl, _, _, _, _ := testingCluster(t)
defer cleanRaft()
defer cl.Shutdown()
if cl.Version() != Version {

View File

@ -4,7 +4,6 @@ import (
"bytes"
crand "crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
@ -37,10 +36,10 @@ type Config struct {
ID peer.ID
PrivateKey crypto.PrivKey
// Swarm key for private network
SwarmSecret string
// Fingerprint for private network
PNetFingerprint []byte
// Cluster secret for private network. Peers will be in the same cluster if and
// only if they have the same ClusterSecret. If this value is empty, then the
// cluster will be on a unprotected public network (accessible by anyone).
ClusterSecret []byte
// ClusterPeers is the list of peers in the Cluster. They are used
// as the initial peers in the consensus. When bootstrapping a peer,
@ -111,8 +110,10 @@ type JSONConfig struct {
ID string `json:"id"`
PrivateKey string `json:"private_key"`
// Swarm key for private network
SwarmSecret string `json:"swarm_key"`
// Cluster secret for private network. Peers will be in the same cluster if and
// only if they have the same ClusterSecret. If this value is empty, then the
// cluster will be on a unprotected public network (accessible by anyone).
ClusterSecret string `json:"cluster_secret"`
// ClusterPeers is the list of peers' multiaddresses in the Cluster.
// They are used as the initial peers in the consensus. When
@ -205,7 +206,7 @@ func (cfg *Config) ToJSONConfig() (j *JSONConfig, err error) {
j = &JSONConfig{
ID: cfg.ID.Pretty(),
PrivateKey: pKey,
SwarmSecret: cfg.SwarmSecret,
ClusterSecret: string(cfg.ClusterSecret),
ClusterPeers: clusterPeers,
Bootstrap: bootstrap,
LeaveOnShutdown: cfg.LeaveOnShutdown,
@ -311,7 +312,7 @@ func (jcfg *JSONConfig) ToConfig() (c *Config, err error) {
c = &Config{
ID: id,
PrivateKey: pKey,
SwarmSecret: jcfg.SwarmSecret,
ClusterSecret: []byte(jcfg.ClusterSecret),
ClusterPeers: clusterPeers,
Bootstrap: bootstrap,
LeaveOnShutdown: jcfg.LeaveOnShutdown,
@ -408,26 +409,23 @@ func (cfg *Config) unshadow() {
cfg.shadow = nil
}
// copied/modified from github.com/Kubuxu/go-ipfs-swarm-key-gen
func generateSwarmSecret() (string, error) {
key := make([]byte, 32)
_, err := crand.Read(key)
func generateClusterSecret() ([]byte, error) {
encodedSecretLength := 64
secret := make([]byte, base64.StdEncoding.DecodedLen(encodedSecretLength))
_, err := crand.Read(secret)
if err != nil {
return "", fmt.Errorf("Error reading from rand: %v", err)
return nil, fmt.Errorf("Error reading from rand: %v", err)
}
return hex.EncodeToString(key), nil
encodedSecret := make([]byte, encodedSecretLength)
base64.StdEncoding.Encode(encodedSecret, secret)
return encodedSecret, nil
}
func swarmSecretToKey(secret string) (string, error) {
hexSecret := hex.EncodeToString([]byte(secret))[:68]
if len(hexSecret) < 10 {
return "", fmt.Errorf("Swarm secret must be >= 10 chars, but is %d\n",
len(hexSecret))
}
func clusterSecretToKey(secret []byte) (string, error) {
var key bytes.Buffer
key.WriteString("/key/swarm/psk/1.0.0/\n")
key.WriteString("/base16/\n")
key.WriteString(hexSecret)
key.WriteString("/base64/\n")
key.Write(secret)
return key.String(), nil
}
@ -445,6 +443,10 @@ func NewDefaultConfig() (*Config, error) {
if err != nil {
return nil, err
}
clusterSecret, err := generateClusterSecret()
if err != nil {
return nil, err
}
clusterAddr, _ := ma.NewMultiaddr(DefaultClusterAddr)
apiAddr, _ := ma.NewMultiaddr(DefaultAPIAddr)
@ -454,6 +456,7 @@ func NewDefaultConfig() (*Config, error) {
return &Config{
ID: pid,
PrivateKey: priv,
ClusterSecret: clusterSecret,
ClusterPeers: []ma.Multiaddr{},
Bootstrap: []ma.Multiaddr{},
LeaveOnShutdown: false,

View File

@ -2,11 +2,13 @@ package ipfscluster
import "testing"
func testingConfig(swarmSecret string) *Config {
var testingClusterSecret = []byte("2951539a3737c06a5aee55834c27145ca1783bdc7daeaa92f9712b3ff6e9fa25")
func testingConfig() *Config {
jcfg := &JSONConfig{
ID: "QmUfSFm12eYCaRdypg48m8RqkXfLW7A2ZeGZb2skeHHDGA",
PrivateKey: "CAASqAkwggSkAgEAAoIBAQDpT16IRF6bb9tHsCbQ7M+nb2aI8sz8xyt8PoAWM42ki+SNoESIxKb4UhFxixKvtEdGxNE6aUUVc8kFk6wTStJ/X3IGiMetwkXiFiUxabUF/8A6SyvnSVDm+wFuavugpVrZikjLcfrf2xOVgnG3deQQvd/qbAv14jTwMFl+T+8d/cXBo8Mn/leLZCQun/EJEnkXP5MjgNI8XcWUE4NnH3E0ESSm6Pkm8MhMDZ2fmzNgqEyJ0GVinNgSml3Pyha3PBSj5LRczLip/ie4QkKx5OHvX2L3sNv/JIUHse5HSbjZ1c/4oGCYMVTYCykWiczrxBUOlcr8RwnZLOm4n2bCt5ZhAgMBAAECggEAVkePwfzmr7zR7tTpxeGNeXHtDUAdJm3RWwUSASPXgb5qKyXVsm5nAPX4lXDE3E1i/nzSkzNS5PgIoxNVU10cMxZs6JW0okFx7oYaAwgAddN6lxQtjD7EuGaixN6zZ1k/G6vT98iS6i3uNCAlRZ9HVBmjsOF8GtYolZqLvfZ5izEVFlLVq/BCs7Y5OrDrbGmn3XupfitVWYExV0BrHpobDjsx2fYdTZkmPpSSvXNcm4Iq2AXVQzoqAfGo7+qsuLCZtVlyTfVKQjMvE2ffzN1dQunxixOvev/fz4WSjGnRpC6QLn6Oqps9+VxQKqKuXXqUJC+U45DuvA94Of9MvZfAAQKBgQD7xmXueXRBMr2+0WftybAV024ap0cXFrCAu+KWC1SUddCfkiV7e5w+kRJx6RH1cg4cyyCL8yhHZ99Z5V0Mxa/b/usuHMadXPyX5szVI7dOGgIC9q8IijN7B7GMFAXc8+qC7kivehJzjQghpRRAqvRzjDls4gmbNPhbH1jUiU124QKBgQDtOaW5/fOEtOq0yWbDLkLdjImct6oKMLhENL6yeIKjMYgifzHb2adk7rWG3qcMrdgaFtDVfqv8UmMEkzk7bSkovMVj3SkLzMz84ii1SkSfyaCXgt/UOzDkqAUYB0cXMppYA7jxHa2OY8oEHdBgmyJXdLdzJxCp851AoTlRUSePgQKBgQCQgKgUHOUaXnMEx88sbOuBO14gMg3dNIqM+Ejt8QbURmI8k3arzqA4UK8Tbb9+7b0nzXWanS5q/TT1tWyYXgW28DIuvxlHTA01aaP6WItmagrphIelERzG6f1+9ib/T4czKmvROvDIHROjq8lZ7ERs5Pg4g+sbh2VbdzxWj49EQQKBgFEna36ZVfmMOs7mJ3WWGeHY9ira2hzqVd9fe+1qNKbHhx7mDJR9fTqWPxuIh/Vac5dZPtAKqaOEO8OQ6f9edLou+ggT3LrgsS/B3tNGOPvA6mNqrk/Yf/15TWTO+I8DDLIXc+lokbsogC+wU1z5NWJd13RZZOX/JUi63vTmonYBAoGBAIpglLCH2sPXfmguO6p8QcQcv4RjAU1c0GP4P5PNN3Wzo0ItydVd2LHJb6MdmL6ypeiwNklzPFwTeRlKTPmVxJ+QPg1ct/3tAURN/D40GYw9ojDhqmdSl4HW4d6gHS2lYzSFeU5jkG49y5nirOOoEgHy95wghkh6BfpwHujYJGw4",
SwarmSecret: swarmSecret,
ID: "QmUfSFm12eYCaRdypg48m8RqkXfLW7A2ZeGZb2skeHHDGA",
PrivateKey: "CAASqAkwggSkAgEAAoIBAQDpT16IRF6bb9tHsCbQ7M+nb2aI8sz8xyt8PoAWM42ki+SNoESIxKb4UhFxixKvtEdGxNE6aUUVc8kFk6wTStJ/X3IGiMetwkXiFiUxabUF/8A6SyvnSVDm+wFuavugpVrZikjLcfrf2xOVgnG3deQQvd/qbAv14jTwMFl+T+8d/cXBo8Mn/leLZCQun/EJEnkXP5MjgNI8XcWUE4NnH3E0ESSm6Pkm8MhMDZ2fmzNgqEyJ0GVinNgSml3Pyha3PBSj5LRczLip/ie4QkKx5OHvX2L3sNv/JIUHse5HSbjZ1c/4oGCYMVTYCykWiczrxBUOlcr8RwnZLOm4n2bCt5ZhAgMBAAECggEAVkePwfzmr7zR7tTpxeGNeXHtDUAdJm3RWwUSASPXgb5qKyXVsm5nAPX4lXDE3E1i/nzSkzNS5PgIoxNVU10cMxZs6JW0okFx7oYaAwgAddN6lxQtjD7EuGaixN6zZ1k/G6vT98iS6i3uNCAlRZ9HVBmjsOF8GtYolZqLvfZ5izEVFlLVq/BCs7Y5OrDrbGmn3XupfitVWYExV0BrHpobDjsx2fYdTZkmPpSSvXNcm4Iq2AXVQzoqAfGo7+qsuLCZtVlyTfVKQjMvE2ffzN1dQunxixOvev/fz4WSjGnRpC6QLn6Oqps9+VxQKqKuXXqUJC+U45DuvA94Of9MvZfAAQKBgQD7xmXueXRBMr2+0WftybAV024ap0cXFrCAu+KWC1SUddCfkiV7e5w+kRJx6RH1cg4cyyCL8yhHZ99Z5V0Mxa/b/usuHMadXPyX5szVI7dOGgIC9q8IijN7B7GMFAXc8+qC7kivehJzjQghpRRAqvRzjDls4gmbNPhbH1jUiU124QKBgQDtOaW5/fOEtOq0yWbDLkLdjImct6oKMLhENL6yeIKjMYgifzHb2adk7rWG3qcMrdgaFtDVfqv8UmMEkzk7bSkovMVj3SkLzMz84ii1SkSfyaCXgt/UOzDkqAUYB0cXMppYA7jxHa2OY8oEHdBgmyJXdLdzJxCp851AoTlRUSePgQKBgQCQgKgUHOUaXnMEx88sbOuBO14gMg3dNIqM+Ejt8QbURmI8k3arzqA4UK8Tbb9+7b0nzXWanS5q/TT1tWyYXgW28DIuvxlHTA01aaP6WItmagrphIelERzG6f1+9ib/T4czKmvROvDIHROjq8lZ7ERs5Pg4g+sbh2VbdzxWj49EQQKBgFEna36ZVfmMOs7mJ3WWGeHY9ira2hzqVd9fe+1qNKbHhx7mDJR9fTqWPxuIh/Vac5dZPtAKqaOEO8OQ6f9edLou+ggT3LrgsS/B3tNGOPvA6mNqrk/Yf/15TWTO+I8DDLIXc+lokbsogC+wU1z5NWJd13RZZOX/JUi63vTmonYBAoGBAIpglLCH2sPXfmguO6p8QcQcv4RjAU1c0GP4P5PNN3Wzo0ItydVd2LHJb6MdmL6ypeiwNklzPFwTeRlKTPmVxJ+QPg1ct/3tAURN/D40GYw9ojDhqmdSl4HW4d6gHS2lYzSFeU5jkG49y5nirOOoEgHy95wghkh6BfpwHujYJGw4",
ClusterSecret: string(testingClusterSecret),
ClusterListenMultiaddress: "/ip4/127.0.0.1/tcp/10000",
APIListenMultiaddress: "/ip4/127.0.0.1/tcp/10002",

View File

@ -1,6 +1,7 @@
package main
import (
"bufio"
"errors"
"fmt"
"os"
@ -104,8 +105,6 @@ var (
DefaultConfigFile = "service.json"
// The name of the data folder inside DefaultPath
DefaultDataFolder = "data"
// The name of the swarm key for pnets inside of DefaultPath
//DefaultSwarmKeyFile = "swarm.key"
)
var (
@ -159,6 +158,11 @@ func main() {
Usage: "path to the configuration and data `FOLDER`",
EnvVar: "IPFS_CLUSTER_PATH",
},
cli.StringFlag{
Name: "env-cluster-secret",
EnvVar: "CLUSTER_SECRET",
Hidden: true,
},
cli.BoolFlag{
Name: "force, f",
Usage: "forcefully proceed with some actions. i.e. overwriting configuration",
@ -192,8 +196,15 @@ func main() {
{
Name: "init",
Usage: "create a default configuration and exit",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "gen-secret, g",
Usage: "automatically generate cluster secret",
},
},
Action: func(c *cli.Context) error {
initConfig(c.GlobalBool("force"))
initConfig(c.GlobalBool("force"), c.Bool("gen-secret"),
[]byte(c.GlobalString("env-cluster-secret")))
return nil
},
},
@ -227,7 +238,7 @@ func main() {
func run(c *cli.Context) error {
if c.Bool("init") {
initConfig(c.Bool("force"))
initConfig(c.Bool("force"), false, nil)
return nil
}
@ -339,13 +350,26 @@ func setupDebug() {
//SetFacilityLogLevel("libp2p-raft", l)
}
func initConfig(force bool) {
func initConfig(force bool, generateSecret bool, envSecret []byte) {
if _, err := os.Stat(configPath); err == nil && !force {
err := fmt.Errorf("%s exists. Try running with -f", configPath)
checkErr("", err)
}
cfg, err := ipfscluster.NewDefaultConfig()
checkErr("creating default configuration", err)
if !generateSecret {
if len(envSecret) != 0 {
// read cluster secret from env variable
fmt.Println("Reading cluster secret from CLUSTER_SECRET environment variable.")
cfg.ClusterSecret = []byte(envSecret)
} else {
// get cluster secret from user
cfg.ClusterSecret = []byte(promptUser("Enter cluster secret (to automatically generate, rerun with --gen-secret): "))
}
}
cfg.ConsensusDataFolder = dataPath
err = os.MkdirAll(filepath.Dir(configPath), 0700)
err = cfg.Save(configPath)
@ -357,3 +381,10 @@ func initConfig(force bool) {
func loadConfig() (*ipfscluster.Config, error) {
return ipfscluster.LoadConfig(configPath)
}
func promptUser(msg string) string {
scanner := bufio.NewScanner(os.Stdin)
fmt.Print(msg)
scanner.Scan()
return scanner.Text()
}

View File

@ -39,19 +39,8 @@ var (
clusterPort = 20000
apiPort = 20500
ipfsProxyPort = 21000
// reusable swarm key
constSwarmSecret string = "2951539a3737c06a5aee55834c27145ca1783bdc7daeaa92f9712b3ff6e9fa25"
)
func testingSwarmSecret(uniqueSwarm bool) (string, error) {
if uniqueSwarm {
return generateSwarmSecret()
} else {
return constSwarmSecret, nil
}
}
func init() {
rand.Seed(time.Now().UnixNano())
}
@ -71,7 +60,7 @@ func randomBytes() []byte {
return bs
}
func createComponents(t *testing.T, i int, uniqueSwarm bool) (*Config, API, IPFSConnector, state.State, PinTracker, PeerMonitor, PinAllocator, Informer, *test.IpfsMock) {
func createComponents(t *testing.T, i int, clusterSecret []byte) (*Config, API, IPFSConnector, state.State, PinTracker, PeerMonitor, PinAllocator, Informer, *test.IpfsMock) {
mock := test.NewIpfsMock()
clusterAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", clusterPort+i))
apiAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", apiPort+i))
@ -81,13 +70,11 @@ func createComponents(t *testing.T, i int, uniqueSwarm bool) (*Config, API, IPFS
checkErr(t, err)
pid, err := peer.IDFromPublicKey(pub)
checkErr(t, err)
swarmSecret, err := testingSwarmSecret(uniqueSwarm)
checkErr(t, err)
cfg, _ := NewDefaultConfig()
cfg.ID = pid
cfg.PrivateKey = priv
cfg.SwarmSecret = swarmSecret
cfg.ClusterSecret = clusterSecret
cfg.Bootstrap = []ma.Multiaddr{}
cfg.ClusterAddr = clusterAddr
cfg.APIAddr = apiAddr
@ -121,8 +108,8 @@ func createCluster(t *testing.T, cfg *Config, api API, ipfs IPFSConnector, state
return cl
}
func createOnePeerCluster(t *testing.T, nth int, uniqueSwarm bool) (*Cluster, *test.IpfsMock) {
cfg, api, ipfs, state, tracker, mon, alloc, inf, mock := createComponents(t, nth, uniqueSwarm)
func createOnePeerCluster(t *testing.T, nth int, clusterSecret []byte) (*Cluster, *test.IpfsMock) {
cfg, api, ipfs, state, tracker, mon, alloc, inf, mock := createComponents(t, nth, clusterSecret)
cl := createCluster(t, cfg, api, ipfs, state, tracker, mon, alloc, inf)
return cl, mock
}
@ -142,7 +129,7 @@ func createClusters(t *testing.T) ([]*Cluster, []*test.IpfsMock) {
clusterPeers := make([]ma.Multiaddr, nClusters, nClusters)
for i := 0; i < nClusters; i++ {
cfg, api, ipfs, state, tracker, mon, alloc, inf, mock := createComponents(t, i, false)
cfg, api, ipfs, state, tracker, mon, alloc, inf, mock := createComponents(t, i, testingClusterSecret)
cfgs[i] = cfg
apis[i] = api
ipfss[i] = ipfs

View File

@ -21,7 +21,7 @@ func peerManagerClusters(t *testing.T) ([]*Cluster, []*test.IpfsMock) {
wg.Add(1)
go func(i int) {
defer wg.Done()
cl, m := createOnePeerCluster(t, i, false)
cl, m := createOnePeerCluster(t, i, testingClusterSecret)
cls[i] = cl
mocks[i] = m
}(i)

View File

@ -3,47 +3,49 @@ package ipfscluster
import "testing"
func TestSimplePNet(t *testing.T) {
clusters, mocks := peerManagerClusters(t)
defer cleanRaft()
defer shutdownClusters(t, clusters, mocks)
clusters, mocks := peerManagerClusters(t)
defer cleanRaft()
defer shutdownClusters(t, clusters, mocks)
if len(clusters) < 2 {
t.Skip("need at least 2 nodes for this test")
}
_, err := clusters[0].PeerAdd(clusterAddr(clusters[1]))
_, err := clusters[0].PeerAdd(clusterAddr(clusters[1]))
if err != nil {
t.Fatal(err)
}
if len(clusters[0].Peers()) != len(clusters[1].Peers()) {
t.Fatal("Expected same number of peers")
}
if len(clusters[0].Peers()) != 2 {
t.Fatal("Expected 2 peers")
}
}
func TestClusterSecretRequired(t *testing.T) {
cl1Secret, err := generateClusterSecret()
if err != nil {
t.Fatal(err)
t.Fatal("Unable to generate cluster secret")
}
cl1, _ := createOnePeerCluster(t, 1, cl1Secret)
cl2, _ := createOnePeerCluster(t, 2, testingClusterSecret)
defer cleanRaft()
defer cl1.Shutdown()
defer cl2.Shutdown()
peers1 := cl1.Peers()
peers2 := cl2.Peers()
if len(clusters[0].Peers()) != len(clusters[1].Peers()) {
t.Fatal("Expected same number of peers")
}
if len(clusters[0].Peers()) != 2 {
t.Fatal("Expected 2 peers")
}
_, err = cl1.PeerAdd(clusterAddr(cl2))
if err == nil {
t.Fatal("Peer entered private cluster without key.")
}
if len(peers1) != len(peers2) {
t.Fatal("Expected same number of peers")
}
if len(peers1) != 1 {
t.Fatal("Expected no peers other than self")
}
}
func TestSwarmKeyRequired(t *testing.T) {
cl1, _ := createOnePeerCluster(t, 1, true)
cl2, _ := createOnePeerCluster(t, 2, false)
defer cleanRaft()
defer cl1.Shutdown()
defer cl2.Shutdown()
peers1 := cl1.Peers()
peers2 := cl2.Peers()
_, err := cl1.PeerAdd(clusterAddr(cl2))
if err == nil {
t.Fatal("Peer entered private cluster without key.")
}
//fmt.Printf("@GRISH: %s\n", err.Error())
if len(peers1) != len(peers2) {
t.Fatal("Expected same number of peers")
}
if len(peers1) != 1 {
t.Fatal("Expected no peers other than self")
}
}