testutil: allow skipping leader wait, update example

pull/964/head
Ryan Uber 10 years ago
parent db134f6190
commit 04d73628d1

@ -19,42 +19,46 @@ Following is some example usage:
package main package main
import ( import (
"github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil"
"testing" "testing"
) )
func TestMain(t *testing.T) { func TestMain(t *testing.T) {
// Create a server // Create a server
srv1 := testutil.NewTestServer(t) srv1 := testutil.NewTestServer(t)
defer srv1.Stop() defer srv1.Stop()
// Create a secondary server // Create a secondary server, passing in configuration
srv2 := testutil.NewTestServer(t) // to avoid bootstrapping or waiting for a leader.
defer srv2.Stop() srv2 := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) {
c.Bootstrap = false
c.NoLeaderWait = true
})
defer srv2.Stop()
// Join the servers together // Join the servers together
srv1.JoinLAN(srv2.LANAddr) srv1.JoinLAN(srv2.LANAddr)
// Create a test key/value pair // Create a test key/value pair
srv1.SetKV("foo", []byte("bar")) srv1.SetKV("foo", []byte("bar"))
// Create lots of test key/value pairs // Create lots of test key/value pairs
srv1.PopulateKV(map[string][]byte{ srv1.PopulateKV(map[string][]byte{
"bar": []byte("123"), "bar": []byte("123"),
"baz": []byte("456"), "baz": []byte("456"),
}) })
// Create a service // Create a service
srv1.AddService("redis", "passing", []string{"master"}) srv1.AddService("redis", "passing", []string{"master"})
// Create a service check // Create a service check
srv1.AddCheck("service:redis", "redis", "passing") srv1.AddCheck("service:redis", "redis", "passing")
// Create a node check // Create a node check
srv1.AddCheck("mem", "", "critical") srv1.AddCheck("mem", "", "critical")
// The HTTPAddr field contains the address of the Consul // The HTTPAddr field contains the address of the Consul
// API on the new test server instance. // API on the new test server instance.
println(srv1.HTTPAddr) println(srv1.HTTPAddr)
} }
``` ```

@ -59,6 +59,11 @@ type TestServerConfig struct {
Bind string `json:"bind_addr,omitempty"` Bind string `json:"bind_addr,omitempty"`
Addresses *TestAddressConfig `json:"addresses,omitempty"` Addresses *TestAddressConfig `json:"addresses,omitempty"`
Ports *TestPortConfig `json:"ports,omitempty"` Ports *TestPortConfig `json:"ports,omitempty"`
// NoLeaderWait is a special config option used to instruct
// the test harness not to wait for a leader. Useful for
// bootstrapping a multi-node cluster for testing.
NoLeaderWait bool `json:"-"`
} }
// ServerConfigCallback is a function interface which can be // ServerConfigCallback is a function interface which can be
@ -142,12 +147,11 @@ func NewTestServerConfig(t *testing.T, cb ServerConfigCallback) *TestServer {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
configFile, err := ioutil.TempFile("", "consul") configFile, err := ioutil.TempFile(dataDir, "config")
if err != nil { if err != nil {
defer os.RemoveAll(dataDir) defer os.RemoveAll(dataDir)
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
defer os.Remove(configFile.Name())
consulConfig := defaultServerConfig() consulConfig := defaultServerConfig()
consulConfig.DataDir = dataDir consulConfig.DataDir = dataDir
@ -203,7 +207,11 @@ func NewTestServerConfig(t *testing.T, cb ServerConfigCallback) *TestServer {
} }
// Wait for the server to be ready // Wait for the server to be ready
server.waitForLeader() if consulConfig.NoLeaderWait {
server.waitForAPI()
} else {
server.waitForLeader()
}
return server return server
} }
@ -219,6 +227,26 @@ func (s *TestServer) Stop() {
} }
} }
// waitForAPI waits for only the agent HTTP endpoint to start
// responding. This is an indication that the agent has started,
// but will likely return before a leader is elected.
func (s *TestServer) waitForAPI() {
WaitForResult(func() (bool, error) {
resp, err := s.HttpClient.Get(s.url("/v1/agent/self"))
if err != nil {
return false, err
}
defer resp.Body.Close()
if err := s.requireOK(resp); err != nil {
return false, err
}
return true, nil
}, func(err error) {
defer s.Stop()
s.t.Fatalf("err: %s", err)
})
}
// waitForLeader waits for the Consul server's HTTP API to become // waitForLeader waits for the Consul server's HTTP API to become
// available, and then waits for a known leader and an index of // available, and then waits for a known leader and an index of
// 1 or more to be observed to confirm leader election is done. // 1 or more to be observed to confirm leader election is done.

Loading…
Cancel
Save