@cryptotaxi247 / kubo / commits / 89ff6dfda

add clone of 3node test using iptb instead of docker

rename directory and update vendored dep cleanup

Jeromy committed Apr 21, 2015 at 11:41 UTC 89ff6dfdaab54f2a5034c596ec4b18f340a29557
7 files changed +493 -1
Godeps/Godeps.json
+4
@@ -36,6 +36,10 @@
36 "ImportPath": "github.com/ActiveState/tail",
37 "Rev": "068b72961a6bc5b4a82cf4fc14ccc724c0cfa73a"
38 },
39 + {
40 + "ImportPath":"github.com/whyrusleeping/iptb",
41 + "Rev": "5ee5bc0bb43502dfc798786a78df2448c91dd764"
42 + },
43 {
44 "ImportPath": "github.com/Sirupsen/logrus",
45 "Comment": "v0.7.1",
Godeps/_workspace/src/github.com/whyrusleeping/iptb/LICENSE new
+21
@@ -0,0 +1,21 @@
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2015 Jeromy Johnson
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
Godeps/_workspace/src/github.com/whyrusleeping/iptb/README.md new
+20
@@ -0,0 +1,20 @@
1 +#Ipfs Testbed
2 +
3 +##commands:
4 +
5 +### init -n=[number of nodes]
6 +creates and initializes 'n' repos
7 +
8 +### start
9 +starts up all testbed nodes
10 +
11 +### stop
12 +kills all testbed nodes
13 +
14 +### restart
15 +kills, then restarts all testbed nodes
16 +
17 +### shell [n]
18 +execs your shell with environment variables set as follows:
19 +- IPFS_PATH - set to testbed node n's IPFS_PATH
20 +- NODE[x] - set to the peer ID of node x
Godeps/_workspace/src/github.com/whyrusleeping/iptb/main.go new
+403
@@ -0,0 +1,403 @@
1 +package main
2 +
3 +import (
4 + "flag"
5 + "fmt"
6 + serial "github.com/ipfs/go-ipfs/repo/fsrepo/serialize"
7 + "io/ioutil"
8 + "log"
9 + "net"
10 + "os"
11 + "os/exec"
12 + "path"
13 + "strconv"
14 + "sync"
15 + "syscall"
16 + "time"
17 +)
18 +
19 +// GetNumNodes returns the number of testbed nodes configured in the testbed directory
20 +func GetNumNodes() int {
21 + for i := 0; i < 2000; i++ {
22 + _, err := os.Stat(IpfsDirN(i))
23 + if os.IsNotExist(err) {
24 + return i
25 + }
26 + }
27 + panic("i dont know whats going on")
28 +}
29 +
30 +func TestBedDir() string {
31 + tbd := os.Getenv("IPTB_ROOT")
32 + if len(tbd) != 0 {
33 + return tbd
34 + }
35 +
36 + home := os.Getenv("HOME")
37 + if len(home) == 0 {
38 + panic("could not find home")
39 + }
40 +
41 + return path.Join(home, "testbed")
42 +}
43 +
44 +func IpfsDirN(n int) string {
45 + return path.Join(TestBedDir(), fmt.Sprint(n))
46 +}
47 +
48 +func YesNoPrompt(prompt string) bool {
49 + var s string
50 + for {
51 + fmt.Println(prompt)
52 + fmt.Scanf("%s", &s)
53 + switch s {
54 + case "y", "Y":
55 + return true
56 + case "n", "N":
57 + return false
58 + }
59 + fmt.Println("Please press either 'y' or 'n'")
60 + }
61 +}
62 +
63 +type initCfg struct {
64 + Count int
65 + Force bool
66 + Bootstrap string
67 +}
68 +
69 +func IpfsInit(cfg *initCfg) error {
70 + p := IpfsDirN(0)
71 + if _, err := os.Stat(p); !os.IsNotExist(err) {
72 + if !cfg.Force && !YesNoPrompt("testbed nodes already exist, overwrite? [y/n]") {
73 + return nil
74 + }
75 + err := os.RemoveAll(TestBedDir())
76 + if err != nil {
77 + return err
78 + }
79 + }
80 + wait := sync.WaitGroup{}
81 + for i := 0; i < cfg.Count; i++ {
82 + wait.Add(1)
83 + go func(v int) {
84 + defer wait.Done()
85 + dir := IpfsDirN(v)
86 + err := os.MkdirAll(dir, 0777)
87 + if err != nil {
88 + log.Println("ERROR: ", err)
89 + return
90 + }
91 +
92 + cmd := exec.Command("ipfs", "init", "-b=1024")
93 + cmd.Env = append(cmd.Env, "IPFS_PATH="+dir)
94 + out, err := cmd.CombinedOutput()
95 + if err != nil {
96 + log.Println("ERROR: ", err)
97 + log.Println(string(out))
98 + }
99 + }(i)
100 + }
101 + wait.Wait()
102 +
103 + // Now setup bootstrapping
104 + switch cfg.Bootstrap {
105 + case "star":
106 + err := starBootstrap(cfg)
107 + if err != nil {
108 + return err
109 + }
110 + case "none":
111 + err := clearBootstrapping(cfg)
112 + if err != nil {
113 + return err
114 + }
115 + default:
116 + return fmt.Errorf("unrecognized bootstrapping option: %s", cfg.Bootstrap)
117 + }
118 +
119 + return nil
120 +}
121 +
122 +func starBootstrap(cfg *initCfg) error {
123 + // '0' node is the bootstrap node
124 + cfgpath := path.Join(IpfsDirN(0), "config")
125 + bcfg, err := serial.Load(cfgpath)
126 + if err != nil {
127 + return err
128 + }
129 + bcfg.Bootstrap = nil
130 + bcfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/tcp/4002"}
131 + bcfg.Addresses.API = "/ip4/127.0.0.1/tcp/5002"
132 + bcfg.Addresses.Gateway = ""
133 + err = serial.WriteConfigFile(cfgpath, bcfg)
134 + if err != nil {
135 + return err
136 + }
137 +
138 + for i := 1; i < cfg.Count; i++ {
139 + cfgpath := path.Join(IpfsDirN(i), "config")
140 + cfg, err := serial.Load(cfgpath)
141 + if err != nil {
142 + return err
143 + }
144 +
145 + cfg.Bootstrap = []string{fmt.Sprintf("%s/ipfs/%s", bcfg.Addresses.Swarm[0], bcfg.Identity.PeerID)}
146 + cfg.Addresses.Gateway = ""
147 + cfg.Addresses.Swarm = []string{
148 + fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", 4002+i),
149 + }
150 + cfg.Addresses.API = fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 5002+i)
151 + err = serial.WriteConfigFile(cfgpath, cfg)
152 + if err != nil {
153 + return err
154 + }
155 + }
156 + return nil
157 +}
158 +
159 +func clearBootstrapping(cfg *initCfg) error {
160 + for i := 0; i < cfg.Count; i++ {
161 + cfgpath := path.Join(IpfsDirN(i), "config")
162 + cfg, err := serial.Load(cfgpath)
163 + if err != nil {
164 + return err
165 + }
166 +
167 + cfg.Bootstrap = nil
168 + cfg.Addresses.Gateway = ""
169 + cfg.Addresses.Swarm = []string{
170 + fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", 4002+i),
171 + }
172 + cfg.Addresses.API = fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 5002+i)
173 + err = serial.WriteConfigFile(cfgpath, cfg)
174 + if err != nil {
175 + return err
176 + }
177 + }
178 + return nil
179 +}
180 +
181 +func IpfsPidOf(n int) (int, error) {
182 + dir := IpfsDirN(n)
183 + b, err := ioutil.ReadFile(path.Join(dir, "daemon.pid"))
184 + if err != nil {
185 + return -1, err
186 + }
187 +
188 + return strconv.Atoi(string(b))
189 +}
190 +
191 +func IpfsKill() error {
192 + n := GetNumNodes()
193 + for i := 0; i < n; i++ {
194 + pid, err := IpfsPidOf(i)
195 + if err != nil {
196 + fmt.Printf("error killing daemon %d: %s\n", i, err)
197 + continue
198 + }
199 +
200 + p, err := os.FindProcess(pid)
201 + if err != nil {
202 + fmt.Printf("error killing daemon %d: %s\n", i, err)
203 + continue
204 + }
205 + err = p.Kill()
206 + if err != nil {
207 + fmt.Printf("error killing daemon %d: %s\n", i, err)
208 + continue
209 + }
210 +
211 + p.Wait()
212 +
213 + err = os.Remove(path.Join(IpfsDirN(i), "daemon.pid"))
214 + if err != nil {
215 + fmt.Printf("error removing pid file for daemon %d: %s\n", i, err)
216 + continue
217 + }
218 + }
219 + return nil
220 +}
221 +
222 +func IpfsStart(waitall bool) error {
223 + n := GetNumNodes()
224 + for i := 0; i < n; i++ {
225 + dir := IpfsDirN(i)
226 + cmd := exec.Command("ipfs", "daemon")
227 + cmd.Dir = dir
228 + cmd.Env = []string{"IPFS_PATH=" + dir}
229 +
230 + cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
231 +
232 + stdout, err := os.Create(path.Join(dir, "daemon.stdout"))
233 + if err != nil {
234 + return err
235 + }
236 +
237 + stderr, err := os.Create(path.Join(dir, "daemon.stderr"))
238 + if err != nil {
239 + return err
240 + }
241 +
242 + cmd.Stdout = stdout
243 + cmd.Stderr = stderr
244 +
245 + err = cmd.Start()
246 + if err != nil {
247 + return err
248 + }
249 + pid := cmd.Process.Pid
250 +
251 + fmt.Printf("Started daemon %d, pid = %d\n", i, pid)
252 + err = ioutil.WriteFile(path.Join(dir, "daemon.pid"), []byte(fmt.Sprint(pid)), 0666)
253 + if err != nil {
254 + return err
255 + }
256 +
257 + // Make sure node 0 is up before starting the rest so
258 + // bootstrapping works properly
259 + if i == 0 || waitall {
260 + err := waitForLive(fmt.Sprintf("localhost:%d", 5002+i))
261 + if err != nil {
262 + return err
263 + }
264 + }
265 + }
266 + return nil
267 +}
268 +
269 +// waitForLive polls the given endpoint until it is up, or until
270 +// a timeout
271 +func waitForLive(addr string) error {
272 + for i := 0; i < 50; i++ {
273 + c, err := net.Dial("tcp", addr)
274 + if err == nil {
275 + c.Close()
276 + return nil
277 + }
278 + time.Sleep(time.Millisecond * 200)
279 + }
280 + return fmt.Errorf("node at %s failed to come online in given time period", addr)
281 +}
282 +
283 +// GetPeerID reads the config of node 'n' and returns its peer ID
284 +func GetPeerID(n int) (string, error) {
285 + cfg, err := serial.Load(path.Join(IpfsDirN(n), "config"))
286 + if err != nil {
287 + return "", err
288 + }
289 + return cfg.Identity.PeerID, nil
290 +}
291 +
292 +// IpfsShell sets up environment variables for a new shell to more easily
293 +// control the given daemon
294 +func IpfsShell(n int) error {
295 + shell := os.Getenv("SHELL")
296 + if shell == "" {
297 + return fmt.Errorf("couldnt find shell!")
298 + }
299 +
300 + dir := IpfsDirN(n)
301 + nenvs := []string{"IPFS_PATH=" + dir}
302 +
303 + nnodes := GetNumNodes()
304 + for i := 0; i < nnodes; i++ {
305 + peerid, err := GetPeerID(i)
306 + if err != nil {
307 + return err
308 + }
309 + nenvs = append(nenvs, fmt.Sprintf("NODE%d=%s", i, peerid))
310 + }
311 + nenvs = append(os.Environ(), nenvs...)
312 +
313 + return syscall.Exec(shell, []string{shell}, nenvs)
314 +}
315 +
316 +var helptext = `Ipfs Testbed
317 +
318 +Commands:
319 + init
320 + creates and initializes 'n' repos
321 +
322 + Options:
323 + -n=[number of nodes]
324 + -f - force overwriting of existing nodes
325 + -bootstrap - select bootstrapping style for cluster
326 + choices: star, none
327 +
328 + start
329 + starts up all testbed nodes
330 +
331 + Options:
332 + -wait - wait until daemons are fully initialized
333 + stop
334 + kills all testbed nodes
335 + restart
336 + kills, then restarts all testbed nodes
337 +
338 + shell [n]
339 + execs your shell with environment variables set as follows:
340 + IPFS_PATH - set to testbed node n's IPFS_PATH
341 + NODE[x] - set to the peer ID of node x
342 +
343 +Env Vars:
344 +
345 +IPTB_ROOT:
346 + Used to specify the directory that nodes will be created in.
347 +`
348 +
349 +func handleErr(s string, err error) {
350 + if err != nil {
351 + fmt.Println(s, err)
352 + os.Exit(1)
353 + }
354 +}
355 +
356 +func main() {
357 + cfg := new(initCfg)
358 + flag.IntVar(&cfg.Count, "n", 0, "number of ipfs nodes to initialize")
359 + flag.BoolVar(&cfg.Force, "f", false, "force initialization (overwrite existing configs)")
360 + flag.StringVar(&cfg.Bootstrap, "bootstrap", "star", "select bootstrapping style for cluster")
361 +
362 + wait := flag.Bool("wait", false, "wait for nodes to come fully online before exiting")
363 + flag.Usage = func() {
364 + fmt.Println(helptext)
365 + }
366 +
367 + flag.Parse()
368 +
369 + switch flag.Arg(0) {
370 + case "init":
371 + if cfg.Count == 0 {
372 + fmt.Printf("please specify number of nodes: '%s -n=10 init'\n", os.Args[0])
373 + os.Exit(1)
374 + }
375 + err := IpfsInit(cfg)
376 + handleErr("ipfs init err: ", err)
377 + case "start":
378 + err := IpfsStart(*wait)
379 + handleErr("ipfs start err: ", err)
380 + case "stop", "kill":
381 + err := IpfsKill()
382 + handleErr("ipfs kill err: ", err)
383 + case "restart":
384 + err := IpfsKill()
385 + handleErr("ipfs kill err: ", err)
386 +
387 + err = IpfsStart(*wait)
388 + handleErr("ipfs start err: ", err)
389 + case "shell":
390 + if len(flag.Args()) < 2 {
391 + fmt.Println("please specify which node you want a shell for")
392 + os.Exit(1)
393 + }
394 + n, err := strconv.Atoi(flag.Arg(1))
395 + handleErr("parse err: ", err)
396 +
397 + err = IpfsShell(n)
398 + handleErr("ipfs shell err: ", err)
399 + default:
400 + flag.Usage()
401 + os.Exit(1)
402 + }
403 +}
test/Makefile
+5
@@ -4,6 +4,7 @@ IPFS_ROOT = ../
4 IPFS_CMD = ../cmd/ipfs
5 RANDOM_SRC = ../Godeps/_workspace/src/github.com/jbenet/go-random
6 MULTIHASH_SRC = ../Godeps/_workspace/src/github.com/jbenet/go-multihash
7 +IPTB_SRC = ../Godeps/_workspace/src/github.com/whyrusleeping/iptb
8 POLLENDPOINT_SRC= ../thirdparty/pollEndpoint
9
10 # User might want to override those on the command line
@@ -36,6 +37,10 @@ bin/pollEndpoint: $(call find_go_files, $(POLLENDPOINT_SRC)) IPFS-BUILD-OPTIONS
37 @echo "*** installing $@ ***"
38 go build $(GOFLAGS) -o bin/pollEndpoint $(POLLENDPOINT_SRC)
39
40 +bin/iptb: $(call find_go_files, $(IPTB_SRC)) IPFS-BUILD-OPTIONS
41 + @echo "*** installing $@ ***"
42 + go build $(GOFLAGS) -o bin/iptb $(IPTB_SRC)
43 +
44 test: test_expensive
45
46 test_expensive:
test/sharness/Makefile
+2 -1
@@ -7,7 +7,8 @@
7 # NOTE: run with TEST_VERBOSE=1 for verbose sharness tests.
8
9 T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
10 -BINS = bin/random bin/multihash bin/ipfs bin/pollEndpoint
10 +BINS = bin/random bin/multihash bin/ipfs bin/pollEndpoint \
11 + bin/iptb
12 SHARNESS = lib/sharness/sharness.sh
13 IPFS_ROOT = ../..
14
test/sharness/t0130-multinode.sh new
+38
@@ -0,0 +1,38 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2015 Jeromy Johnson
4 +# MIT Licensed; see the LICENSE file in this repository.
5 +#
6 +
7 +test_description="Test multiple ipfs nodes"
8 +
9 +. lib/test-lib.sh
10 +
11 +export IPTB_ROOT="`pwd`/.iptb"
12 +
13 +test_expect_success "set up a few nodes" '
14 + iptb -n=3 init &&
15 + iptb -wait start
16 +'
17 +
18 +test_expect_success "add a file on node1" '
19 + export IPFS_PATH="$IPTB_ROOT/1"
20 + random 1000000 > filea &&
21 + FILEA_HASH=`ipfs add -q filea`
22 +'
23 +
24 +test_expect_success "cat that file on node2" '
25 + export IPFS_PATH="$IPTB_ROOT/2"
26 + ipfs cat $FILEA_HASH | multihash > actual1
27 +'
28 +
29 +test_expect_success "verify files match" '
30 + multihash filea > expected1 &&
31 + test_cmp actual1 expected1
32 +'
33 +
34 +test_expect_success "shut down nodes" '
35 + iptb stop
36 +'
37 +
38 +test_done