diff --git a/test/e2e/pkg/infra/digitalocean/digitalocean.go b/test/e2e/pkg/infra/digitalocean/digitalocean.go index 3529a78b8..40823bd85 100644 --- a/test/e2e/pkg/infra/digitalocean/digitalocean.go +++ b/test/e2e/pkg/infra/digitalocean/digitalocean.go @@ -42,3 +42,17 @@ func (p Provider) TerminateTendermint(ctx context.Context, n *e2e.Node) error { func (p Provider) KillTendermint(ctx context.Context, n *e2e.Node) error { return e2essh.Exec(p.SSHConfig, fmt.Sprintf("%s:%d", n.IP, sshPort), fmt.Sprintf("systemctl -s SIGKILL %s", testappName)) } +func (p Provider) Disconnect(ctx context.Context, n *e2e.Node) error { + return e2essh.MultiExec(p.SSHConfig, fmt.Sprintf("%s:%d", n.IP, sshPort), + "iptables -A INPUT -p tcp --destination-port 26656 -j DROP", + "iptables -A OUTPUT -p tcp --destination-port 26656 -j DROP", + "service iptables save", + ) +} +func (p Provider) Connect(ctx context.Context, n *e2e.Node) error { + return e2essh.MultiExec(p.SSHConfig, fmt.Sprintf("%s:%d", n.IP, sshPort), + "iptables -D INPUT -p tcp --destination-port 26656 -j DROP", + "iptables -D OUTPUT -p tcp --destination-port 26656 -j DROP", + "service iptables save", + ) +} diff --git a/test/e2e/pkg/infra/docker/docker.go b/test/e2e/pkg/infra/docker/docker.go index a17700298..bc33f8ab5 100644 --- a/test/e2e/pkg/infra/docker/docker.go +++ b/test/e2e/pkg/infra/docker/docker.go @@ -47,6 +47,12 @@ func (p Provider) TerminateTendermint(ctx context.Context, n *e2e.Node) error { func (p Provider) KillTendermint(ctx context.Context, n *e2e.Node) error { return ExecCompose(ctx, p.Testnet.Dir, "kill", "-s", "SIGKILL", n.Name) } +func (p Provider) Connect(ctx context.Context, n *e2e.Node) error { + return Exec(ctx, "network", "connect", p.Testnet.Name+"_"+p.Testnet.Name, n.Name) +} +func (p Provider) Disconnect(ctx context.Context, n *e2e.Node) error { + return Exec(ctx, "network", "disconnect", p.Testnet.Name+"_"+p.Testnet.Name, n.Name) +} // dockerComposeBytes generates a Docker Compose config file for a testnet and returns the // file as bytes to be written out to disk. diff --git a/test/e2e/pkg/infra/provider.go b/test/e2e/pkg/infra/provider.go index 0fdcc86ba..4de74b9bd 100644 --- a/test/e2e/pkg/infra/provider.go +++ b/test/e2e/pkg/infra/provider.go @@ -18,6 +18,8 @@ type Provider interface { StartTendermint(context.Context, *e2e.Node) error KillTendermint(context.Context, *e2e.Node) error TerminateTendermint(context.Context, *e2e.Node) error + Connect(context.Context, *e2e.Node) error + Disconnect(context.Context, *e2e.Node) error } // NoopProvider implements the provider interface by performing noops for every @@ -31,5 +33,7 @@ func (NoopProvider) CreateNode(_ context.Context, _ *e2e.Node) error { func (NoopProvider) StartTendermint(_ context.Context, _ *e2e.Node) error { return nil } func (NoopProvider) TerminateTendermint(_ context.Context, _ *e2e.Node) error { return nil } func (NoopProvider) KillTendermint(_ context.Context, _ *e2e.Node) error { return nil } +func (NoopProvider) Connect(_ context.Context, _ *e2e.Node) error { return nil } +func (NoopProvider) Disconnect(_ context.Context, _ *e2e.Node) error { return nil } var _ Provider = NoopProvider{} diff --git a/test/e2e/pkg/ssh/ssh.go b/test/e2e/pkg/ssh/ssh.go index 5246ada83..cdca8d087 100644 --- a/test/e2e/pkg/ssh/ssh.go +++ b/test/e2e/pkg/ssh/ssh.go @@ -27,6 +27,22 @@ func Exec(cfg *ssh.ClientConfig, addr, cmd string) error { return nil } +func MultiExec(cfg *ssh.ClientConfig, addr string, cmds ...string) error { + c, err := ssh.Dial("tcp", addr, cfg) + s, err := c.NewSession() + if err != nil { + return err + } + defer s.Close() + for _, cmd := range cmds { + err := s.Run(cmd) + if err != nil { + return err + } + } + return nil +} + func NewClientConfig() (*ssh.ClientConfig, error) { ss := os.Getenv("SSH_AUTH_SOCK") if ss == "" { diff --git a/test/e2e/runner/main.go b/test/e2e/runner/main.go index be11e0599..3b7a6f3f8 100644 --- a/test/e2e/runner/main.go +++ b/test/e2e/runner/main.go @@ -137,7 +137,7 @@ func NewCLI() *CLI { } if cli.testnet.HasPerturbations() { - if err := Perturb(cli.testnet); err != nil { + if err := Perturb(cli.testnet, cli.infp); err != nil { return err } if err := Wait(cli.testnet, 5); err != nil { // allow some txs to go through @@ -210,7 +210,7 @@ func NewCLI() *CLI { Use: "perturb", Short: "Perturbs the Docker testnet, e.g. by restarting or disconnecting nodes", RunE: func(cmd *cobra.Command, args []string) error { - return Perturb(cli.testnet) + return Perturb(cli.testnet, cli.infp) }, }) diff --git a/test/e2e/runner/perturb.go b/test/e2e/runner/perturb.go index dfd0ff8b7..9d90f59aa 100644 --- a/test/e2e/runner/perturb.go +++ b/test/e2e/runner/perturb.go @@ -8,14 +8,15 @@ import ( "github.com/tendermint/tendermint/libs/log" rpctypes "github.com/tendermint/tendermint/rpc/core/types" e2e "github.com/tendermint/tendermint/test/e2e/pkg" + "github.com/tendermint/tendermint/test/e2e/pkg/infra" "github.com/tendermint/tendermint/test/e2e/pkg/infra/docker" ) // Perturbs a running testnet. -func Perturb(testnet *e2e.Testnet) error { +func Perturb(testnet *e2e.Testnet, ifp infra.Provider) error { for _, node := range testnet.Nodes { for _, perturbation := range node.Perturbations { - _, err := PerturbNode(node, perturbation) + _, err := PerturbNode(node, perturbation, ifp) if err != nil { return err } @@ -27,16 +28,16 @@ func Perturb(testnet *e2e.Testnet) error { // PerturbNode perturbs a node with a given perturbation, returning its status // after recovering. -func PerturbNode(node *e2e.Node, perturbation e2e.Perturbation) (*rpctypes.ResultStatus, error) { +func PerturbNode(node *e2e.Node, perturbation e2e.Perturbation, ifp infra.Provider) (*rpctypes.ResultStatus, error) { testnet := node.Testnet switch perturbation { case e2e.PerturbationDisconnect: logger.Info("perturb node", "msg", log.NewLazySprintf("Disconnecting node %v...", node.Name)) - if err := docker.Exec(context.Background(), "network", "disconnect", testnet.Name+"_"+testnet.Name, node.Name) ; err != nil { + if err := ifp.Disconnect(context.Background(), node); err != nil { return nil, err } time.Sleep(10 * time.Second) - if err := docker.Exec(context.Background(), "network", "connect", testnet.Name+"_"+testnet.Name, node.Name) ; err != nil { + if err := ifp.Connect(context.Background(), node); err != nil { return nil, err }