func (v *vm) Run(command string, attempts attempt.Strategy, out io.Writer, stderr io.Writer) error { var sc *ssh.Client err := attempts.Run(func() (err error) { fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", v.IP()) sc, err = v.DialSSH() return }) if err != nil { return err } defer sc.Close() sess, err := sc.NewSession() sess.Stdin = bytes.NewBufferString(command) sess.Stdout = out sess.Stderr = stderr if err := sess.Run("bash"); err != nil { return fmt.Errorf("failed to run command on %s: %s", v.IP(), err) } return nil }
func (S) TestAttemptTiming(c *C) { testAttempt := attempt.Strategy{ Total: 0.25e9, Delay: 0.1e9, } want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9} got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing t0 := time.Now() for a := testAttempt.Start(); a.Next(); { got = append(got, time.Now().Sub(t0)) } got = append(got, time.Now().Sub(t0)) c.Assert(got, HasLen, len(want)) const margin = 0.01e9 for i, got := range want { lo := want[i] - margin hi := want[i] + margin if got < lo || got > hi { c.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds()) } } }
func (S) TestAttemptNextHasNext(c *C) { a := attempt.Strategy{}.Start() c.Assert(a.Next(), Equals, true) c.Assert(a.Next(), Equals, false) a = attempt.Strategy{}.Start() c.Assert(a.Next(), Equals, true) c.Assert(a.HasNext(), Equals, false) c.Assert(a.Next(), Equals, false) a = attempt.Strategy{Total: 2e8}.Start() c.Assert(a.Next(), Equals, true) c.Assert(a.HasNext(), Equals, true) time.Sleep(2e8) c.Assert(a.HasNext(), Equals, true) c.Assert(a.Next(), Equals, true) c.Assert(a.Next(), Equals, false) a = attempt.Strategy{Total: 1e8, Min: 2}.Start() time.Sleep(1e8) c.Assert(a.Next(), Equals, true) c.Assert(a.HasNext(), Equals, true) c.Assert(a.Next(), Equals, true) c.Assert(a.HasNext(), Equals, false) c.Assert(a.Next(), Equals, false) }