Skip to content

Commit

Permalink
Merge pull request #61 from ipfs/feat/interface-plugins
Browse files Browse the repository at this point in the history
interface'ifying things
  • Loading branch information
Travis Person authored Aug 15, 2018
2 parents d95a61a + 5e19097 commit e136336
Show file tree
Hide file tree
Showing 40 changed files with 3,693 additions and 1,982 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.so
iptb
22 changes: 20 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
all:
CLEAN =

all: iptb

iptb:
go build

plugins:
make -C plugins all

install_plugins:
make -C plugins install

CLEAN += iptb

install:
go install

test:
make -C sharness all

.PHONY: all test
clean:
rm $(CLEAN)

.PHONY: all test iptb install plugins clean
57 changes: 31 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
# IPTB

`iptb` is a program used to create and manage a cluster of sandboxed IPFS nodes locally on your computer. Spin up 1000s of nodes! It exposes various options, such as different bootstrapping patterns. `iptb` makes testing IPFS networks easy!
`iptb` is a program used to create and manage a cluster of sandboxed nodes
locally on your computer. Spin up 1000s of nodes! Using `iptb` makes testing
libp2p networks easy!

### Example

```
$ iptb init -n 5
$ iptb auto -count 5 >/dev/null
$ iptb start
Started daemon 0, pid = 12396
Started daemon 1, pid = 12406
Started daemon 2, pid = 12415
Started daemon 3, pid = 12424
Started daemon 4, pid = 12434
$ iptb shell 0
$ echo $IPFS_PATH
/home/noffle/testbed/0
/home/iptb/testbed/testbeds/default/0
$ echo 'hey!' | ipfs add -q
QmNqugRcYjwh9pEQUK7MLuxvLjxDNZL1DH8PJJgWtQXxuF
Expand All @@ -32,42 +29,50 @@ hey!

### Usage
```
$ iptb --help
NAME:
iptb - The IPFS TestBed
iptb - iptb is a tool for managing test clusters of libp2p nodes
USAGE:
iptb [global options] command [command options] [arguments...]
iptb [global options] command [command options] [arguments...]
VERSION:
0.0.0
COMMANDS:
init create and initialize testbed configuration
start start up all testbed nodes
kill, stop kill a specific node (or all nodes, if none specified)
restart kill all nodes, then restart
shell spawn a subshell with certain IPFS environment variables set
get get an attribute of the given node
connect connect two nodes together
dump-stack get a stack dump from the given daemon
help, h show a list of subcommands, or help for a specific subcommand
auto create default testbed and initialize
testbed manage testbeds
help, h Shows a list of commands or help for one command
ATTRIBUTES:
attr get, set, list attributes
CORE:
init initialize specified nodes (or all)
start start specified nodes (or all)
stop stop specified nodes (or all)
restart restart specified nodes (or all)
run run command on specified nodes (or all)
connect connect sets of nodes together (or all)
shell starts a shell within the context of node
METRICS:
logs show logs from specified nodes (or all)
events stream events from specified nodes (or all)
metric get metric from node
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
--testbed value Name of testbed to use under IPTB_ROOT (default: "default") [$IPTB_TESTBED]
--help, -h show help
--version, -v print the version
```

### Install

```
go get github.com/ipfs/iptb
$ go get github.com/ipfs/iptb
```

### Configuration

By default, `iptb` uses `$HOME/testbed` to store created nodes. This path is configurable via the environment variables `IPTB_ROOT`.



### License

MIT
181 changes: 181 additions & 0 deletions commands/attr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package commands

import (
"fmt"
"path"
"strconv"

cli "github.com/urfave/cli"

"github.com/ipfs/iptb/testbed"
"github.com/ipfs/iptb/testbed/interfaces"
)

var AttrCmd = cli.Command{
Category: "ATTRIBUTES",
Name: "attr",
Usage: "get, set, list attributes",
Subcommands: []cli.Command{
AttrSetCmd,
AttrGetCmd,
AttrListCmd,
},
}

var AttrSetCmd = cli.Command{
Name: "set",
Usage: "set an attribute for a node",
ArgsUsage: "<node> <attr> <value>",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "save",
Usage: "saves attribute value to nodespec",
},
},
Action: func(c *cli.Context) error {
flagRoot := c.GlobalString("IPTB_ROOT")
flagTestbed := c.GlobalString("testbed")
flagSave := c.Bool("save")

if c.NArg() != 3 {
return NewUsageError("set takes exactly 3 argument")
}

argNode := c.Args()[0]
argAttr := c.Args()[1]
argValue := c.Args()[2]

i, err := strconv.Atoi(argNode)
if err != nil {
return fmt.Errorf("parse err: %s", err)
}

tb := testbed.NewTestbed(path.Join(flagRoot, "testbeds", flagTestbed))

node, err := tb.Node(i)
if err != nil {
return err
}

attrNode, ok := node.(testbedi.Attribute)
if !ok {
return fmt.Errorf("node does not implement attributes")
}

if err := attrNode.SetAttr(argAttr, argValue); err != nil {
return err
}

if flagSave {
specs, err := tb.Specs()
if err != nil {
return err
}

specs[i].SetAttr(argAttr, argValue)

if err := testbed.WriteNodeSpecs(tb.Dir(), specs); err != nil {
return err
}
}

return nil
},
}

var AttrGetCmd = cli.Command{
Name: "get",
Usage: "get an attribute for a node",
ArgsUsage: "<node> <attr>",
Action: func(c *cli.Context) error {
flagRoot := c.GlobalString("IPTB_ROOT")
flagTestbed := c.GlobalString("testbed")

if c.NArg() != 2 {
return NewUsageError("get takes exactly 2 argument")
}

argNode := c.Args()[0]
argAttr := c.Args()[1]

i, err := strconv.Atoi(argNode)
if err != nil {
return fmt.Errorf("parse err: %s", err)
}

tb := testbed.NewTestbed(path.Join(flagRoot, "testbeds", flagTestbed))

node, err := tb.Node(i)
if err != nil {
return err
}

attrNode, ok := node.(testbedi.Attribute)
if !ok {
return fmt.Errorf("node does not implement attributes")
}

value, err := attrNode.Attr(argAttr)
if err != nil {
return err
}

_, err = fmt.Fprintf(c.App.Writer, "%s\n", value)

return err
},
}

var AttrListCmd = cli.Command{
Name: "list",
Usage: "list attributes available for a node",
ArgsUsage: "<node>",
Flags: []cli.Flag{
cli.StringFlag{
Name: "type",
Usage: "look up attributes for node type",
},
},
Action: func(c *cli.Context) error {
flagRoot := c.GlobalString("IPTB_ROOT")
flagTestbed := c.GlobalString("testbed")
flagType := c.String("type")

if !c.Args().Present() && len(flagType) == 0 {
return NewUsageError("specify a node, or a type")
}

if c.Args().Present() {
i, err := strconv.Atoi(c.Args().First())
if err != nil {
return fmt.Errorf("parse err: %s", err)
}

tb := testbed.NewTestbed(path.Join(flagRoot, "testbeds", flagTestbed))

spec, err := tb.Spec(i)
if err != nil {
return err
}

flagType = spec.Type
}

plg, ok := testbed.GetPlugin(flagType)
if !ok {
return fmt.Errorf("Unknown plugin %s", flagType)
}

attrList := plg.GetAttrList()
for _, a := range attrList {
desc, err := plg.GetAttrDesc(a)
if err != nil {
return fmt.Errorf("error getting attribute description: %s", err)
}

fmt.Fprintf(c.App.Writer, "\t%s: %s\n", a, desc)
}

return nil
},
}
Loading

0 comments on commit e136336

Please sign in to comment.