cmd/swarm/swarm-snapshot: add more comments and other minor adjustments

This commit is contained in:
Janos Guljas 2019-01-10 12:04:23 +01:00 committed by Elad Nachmias
parent 186dd02c3d
commit b226052576
5 changed files with 52 additions and 29 deletions

View file

@ -38,8 +38,9 @@ import (
cli "gopkg.in/urfave/cli.v1" cli "gopkg.in/urfave/cli.v1"
) )
const noConnectionTimeout = 2 * time.Second const noConnectionTimeout = 1 * time.Second
// create is used as the entry function for "create" app command.
func create(ctx *cli.Context) error { func create(ctx *cli.Context) error {
log.PrintOrigins(true) log.PrintOrigins(true)
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(true)))) log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
@ -51,14 +52,16 @@ func create(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
return createSnapshot(filename, ctx.Int("nodes"), ctx.String("services")) return createSnapshot(filename, ctx.Int("nodes"), strings.Split(ctx.String("services"), ","))
} }
func createSnapshot(filename string, nodes int, services string) (err error) { // createSnapshot creates a new snapshot on filesystem with provided filename,
// number of nodes and service names.
func createSnapshot(filename string, nodes int, services []string) (err error) {
log.Debug("create snapshot", "filename", filename, "nodes", nodes, "services", services) log.Debug("create snapshot", "filename", filename, "nodes", nodes, "services", services)
sim := simulation.New(map[string]simulation.ServiceFunc{ sim := simulation.New(map[string]simulation.ServiceFunc{
bzzServiceName: func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) { "bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
addr := network.NewAddr(ctx.Config.Node()) addr := network.NewAddr(ctx.Config.Node())
kad := network.NewKademlia(addr.Over(), network.NewKadParams()) kad := network.NewKademlia(addr.Over(), network.NewKadParams())
hp := network.NewHiveParams() hp := network.NewHiveParams()
@ -80,6 +83,8 @@ func createSnapshot(filename string, nodes int, services string) (err error) {
return fmt.Errorf("add nodes: %v", err) return fmt.Errorf("add nodes: %v", err)
} }
// wait for two some time to ensure no connections
// are established
events := make(chan *simulations.Event) events := make(chan *simulations.Event)
sub := sim.Net.Events().Subscribe(events) sub := sim.Net.Events().Subscribe(events)
select { select {
@ -109,19 +114,21 @@ func createSnapshot(filename string, nodes int, services string) (err error) {
var snap *simulations.Snapshot var snap *simulations.Snapshot
if len(services) > 0 { if len(services) > 0 {
addServices := strings.Split(services, ",") // If service names are provided, include them in the snapshot.
// But, check if "bzz" service is not among them to remove it
// form the snapshot as it exists on snapshot creation.
var removeServices []string var removeServices []string
var hasBzz bool var wantBzz bool
for _, s := range addServices { for _, s := range services {
if s == bzzServiceName { if s == "bzz" {
hasBzz = true wantBzz = true
break break
} }
} }
if !hasBzz { if !wantBzz {
removeServices = append(removeServices, bzzServiceName) removeServices = []string{"bzz"}
} }
snap, err = sim.Net.SnapshotWithServices(addServices, removeServices) snap, err = sim.Net.SnapshotWithServices(services, removeServices)
} else { } else {
snap, err = sim.Net.Snapshot() snap, err = sim.Net.Snapshot()
} }
@ -135,6 +142,8 @@ func createSnapshot(filename string, nodes int, services string) (err error) {
return ioutil.WriteFile(filename, jsonsnapshot, 0666) return ioutil.WriteFile(filename, jsonsnapshot, 0666)
} }
// touchPath creates an empty file and all subdirectories
// that are missing.
func touchPath(filename string) (string, error) { func touchPath(filename string) (string, error) {
if path.IsAbs(filename) { if path.IsAbs(filename) {
if _, err := os.Stat(filename); err == nil { if _, err := os.Stat(filename); err == nil {
@ -164,6 +173,5 @@ func touchPath(filename string) (string, error) {
} }
} }
filename = filePath return filePath, nil
return filename, nil
} }

View file

@ -29,7 +29,9 @@ import (
"github.com/ethereum/go-ethereum/p2p/simulations" "github.com/ethereum/go-ethereum/p2p/simulations"
) )
//TestSnapshotCreate is a high level e2e test that tests for snapshot generation // TestSnapshotCreate is a high level e2e test that tests for snapshot generation.
// It runs a few "create" commands with different flag values and loads generated
// snapshot files to validate their content.
func TestSnapshotCreate(t *testing.T) { func TestSnapshotCreate(t *testing.T) {
for _, v := range []struct { for _, v := range []struct {
name string name string
@ -48,8 +50,8 @@ func TestSnapshotCreate(t *testing.T) {
services: "stream,pss,zorglub", services: "stream,pss,zorglub",
}, },
{ {
name: "services with " + bzzServiceName, name: "services with bzz",
services: bzzServiceName + ",pss", services: "bzz,pss",
}, },
} { } {
t.Run(v.name, func(t *testing.T) { t.Run(v.name, func(t *testing.T) {
@ -75,8 +77,8 @@ func TestSnapshotCreate(t *testing.T) {
testCmd := runSnapshot(t, append(args, file.Name())...) testCmd := runSnapshot(t, append(args, file.Name())...)
testCmd.ExpectExit() testCmd.ExpectExit()
if testCmd.ExitStatus() != 0 { if code := testCmd.ExitStatus(); code != 0 {
t.Fatal("expected exit code 0") t.Fatalf("command exit code %v, expected 0", code)
} }
f, err := os.Open(file.Name()) f, err := os.Open(file.Name())
@ -117,8 +119,10 @@ func TestSnapshotCreate(t *testing.T) {
if v.services != "" { if v.services != "" {
wantServices = strings.Split(v.services, ",") wantServices = strings.Split(v.services, ",")
} else { } else {
wantServices = []string{bzzServiceName} wantServices = []string{"bzz"}
} }
// sort service names so they can be comparable
// as strings to every node sorted services
sort.Strings(wantServices) sort.Strings(wantServices)
for i, n := range snap.Nodes { for i, n := range snap.Nodes {

View file

@ -26,10 +26,8 @@ import (
var gitCommit string // Git SHA1 commit hash of the release (set via linker flags) var gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
const ( // default value for "create" command --nodes flag
defaultNodes = 10 const defaultNodes = 10
bzzServiceName = "bzz"
)
func main() { func main() {
err := newApp().Run(os.Args) err := newApp().Run(os.Args)
@ -39,12 +37,15 @@ func main() {
} }
} }
// newApp construct a new instance of Swarm Snapshot Utility.
// Method Run is called on it in the main function and in tests.
func newApp() (app *cli.App) { func newApp() (app *cli.App) {
app = utils.NewApp(gitCommit, "Swarm Snapshot Utility") app = utils.NewApp(gitCommit, "Swarm Snapshot Utility")
app.Name = "swarm-snapshot" app.Name = "swarm-snapshot"
app.Usage = "" app.Usage = ""
// app flags (for all commands)
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.IntFlag{ cli.IntFlag{
Name: "verbosity", Name: "verbosity",
@ -59,6 +60,9 @@ func newApp() (app *cli.App) {
Aliases: []string{"c"}, Aliases: []string{"c"},
Usage: "create a swarm snapshot", Usage: "create a swarm snapshot",
Action: create, Action: create,
// Flags only for "create" command.
// Allow app flags to be specified after the
// command argument.
Flags: append(app.Flags, Flags: append(app.Flags,
cli.IntFlag{ cli.IntFlag{
Name: "nodes", Name: "nodes",
@ -67,7 +71,7 @@ func newApp() (app *cli.App) {
}, },
cli.StringFlag{ cli.StringFlag{
Name: "services", Name: "services",
Value: bzzServiceName, Value: "bzz",
Usage: "comma separated list of services to boot the nodes with", Usage: "comma separated list of services to boot the nodes with",
}, },
), ),
@ -77,7 +81,9 @@ func newApp() (app *cli.App) {
Aliases: []string{"v"}, Aliases: []string{"v"},
Usage: "verify a swarm snapshot", Usage: "verify a swarm snapshot",
Action: verify, Action: verify,
Flags: app.Flags, // Allow app flags to be specified after the
// command argument.
Flags: app.Flags,
}, },
} }

View file

@ -32,6 +32,7 @@ import (
cli "gopkg.in/urfave/cli.v1" cli "gopkg.in/urfave/cli.v1"
) )
// verify is used as the entry function for "verify" app command.
func verify(ctx *cli.Context) error { func verify(ctx *cli.Context) error {
log.PrintOrigins(true) log.PrintOrigins(true)
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(true)))) log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
@ -42,9 +43,11 @@ func verify(ctx *cli.Context) error {
return verifySnapshot(ctx.Args()[0]) return verifySnapshot(ctx.Args()[0])
} }
// verifySnapshot constructs a simulation, uploads a snapshot from
// a file with provided filename and validates that kademlia is healthy.
func verifySnapshot(filename string) (err error) { func verifySnapshot(filename string) (err error) {
sim := simulation.New(map[string]simulation.ServiceFunc{ sim := simulation.New(map[string]simulation.ServiceFunc{
bzzServiceName: func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) { "bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
addr := network.NewAddr(ctx.Config.Node()) addr := network.NewAddr(ctx.Config.Node())
kad := network.NewKademlia(addr.Over(), network.NewKadParams()) kad := network.NewKademlia(addr.Over(), network.NewKadParams())
hp := network.NewHiveParams() hp := network.NewHiveParams()

View file

@ -20,6 +20,8 @@ import (
"testing" "testing"
) )
// TestSnapshotVerify executes "verify" command with a
// pregenerated snapshot file that is valid.
func TestSnapshotVerify(t *testing.T) { func TestSnapshotVerify(t *testing.T) {
snap := runSnapshot(t, snap := runSnapshot(t,
"verify", "verify",
@ -27,7 +29,7 @@ func TestSnapshotVerify(t *testing.T) {
) )
snap.ExpectExit() snap.ExpectExit()
if snap.ExitStatus() != 0 { if code := snap.ExitStatus(); code != 0 {
t.Fatal("expected exit code 0") t.Fatalf("command exit code %v, expected 0", code)
} }
} }