mirror of https://github.com/hashicorp/consul
Ryan Uber
10 years ago
12 changed files with 228 additions and 203 deletions
@ -0,0 +1,156 @@ |
|||||||
|
package testutil |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"fmt" |
||||||
|
"io/ioutil" |
||||||
|
"net/http" |
||||||
|
"os" |
||||||
|
"os/exec" |
||||||
|
"sync/atomic" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
var offset uint64 |
||||||
|
|
||||||
|
type TestPortConfig struct { |
||||||
|
DNS int `json:"dns,omitempty"` |
||||||
|
HTTP int `json:"http,omitempty"` |
||||||
|
RPC int `json:"rpc,omitempty"` |
||||||
|
SerfLan int `json:"serf_lan,omitempty"` |
||||||
|
SerfWan int `json:"serf_wan,omitempty"` |
||||||
|
Server int `json:"server,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
type TestAddressConfig struct { |
||||||
|
HTTP string `json:"http,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
type TestServerConfig struct { |
||||||
|
Bootstrap bool `json:"bootstrap,omitempty"` |
||||||
|
Server bool `json:"server,omitempty"` |
||||||
|
DataDir string `json:"data_dir,omitempty"` |
||||||
|
LogLevel string `json:"log_level,omitempty"` |
||||||
|
Addresses *TestAddressConfig `json:"addresses,omitempty"` |
||||||
|
Ports *TestPortConfig `json:"ports,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
type ServerConfigCallback func(c *TestServerConfig) |
||||||
|
|
||||||
|
func defaultServerConfig() *TestServerConfig { |
||||||
|
idx := int(atomic.AddUint64(&offset, 1)) |
||||||
|
|
||||||
|
return &TestServerConfig{ |
||||||
|
Bootstrap: true, |
||||||
|
Server: true, |
||||||
|
LogLevel: "debug", |
||||||
|
Ports: &TestPortConfig{ |
||||||
|
DNS: 19000 + idx, |
||||||
|
HTTP: 18800 + idx, |
||||||
|
RPC: 18600 + idx, |
||||||
|
SerfLan: 18200 + idx, |
||||||
|
SerfWan: 18400 + idx, |
||||||
|
Server: 18000 + idx, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type TestServer struct { |
||||||
|
pid int |
||||||
|
dataDir string |
||||||
|
config *TestServerConfig |
||||||
|
} |
||||||
|
|
||||||
|
func NewTestServer(t *testing.T) *TestServer { |
||||||
|
return NewTestServerConfig(t, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func NewTestServerConfig(t *testing.T, cb ServerConfigCallback) *TestServer { |
||||||
|
if path, err := exec.LookPath("consul"); err != nil || path == "" { |
||||||
|
t.Log("consul not found on $PATH, skipping") |
||||||
|
t.SkipNow() |
||||||
|
} |
||||||
|
|
||||||
|
dataDir, err := ioutil.TempDir("", "consul") |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
|
||||||
|
configFile, err := ioutil.TempFile("", "consul") |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
defer os.Remove(configFile.Name()) |
||||||
|
|
||||||
|
consulConfig := defaultServerConfig() |
||||||
|
consulConfig.DataDir = dataDir |
||||||
|
|
||||||
|
if cb != nil { |
||||||
|
cb(consulConfig) |
||||||
|
} |
||||||
|
|
||||||
|
configContent, err := json.Marshal(consulConfig) |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
|
||||||
|
if _, err := configFile.Write(configContent); err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
configFile.Close() |
||||||
|
|
||||||
|
// Start the server
|
||||||
|
cmd := exec.Command("consul", "agent", "-config-file", configFile.Name()) |
||||||
|
cmd.Stdout = os.Stdout |
||||||
|
cmd.Stderr = os.Stderr |
||||||
|
if err := cmd.Start(); err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
|
||||||
|
server := &TestServer{ |
||||||
|
config: consulConfig, |
||||||
|
pid: cmd.Process.Pid, |
||||||
|
dataDir: dataDir, |
||||||
|
} |
||||||
|
|
||||||
|
if err := server.waitForLeader(); err != nil { |
||||||
|
t.Fatalf("err: %s", err) |
||||||
|
} |
||||||
|
return server |
||||||
|
} |
||||||
|
|
||||||
|
func (s *TestServer) Stop() { |
||||||
|
defer os.RemoveAll(s.dataDir) |
||||||
|
|
||||||
|
cmd := exec.Command("kill", "-9", fmt.Sprintf("%d", s.pid)) |
||||||
|
if err := cmd.Run(); err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (s *TestServer) waitForLeader() error { |
||||||
|
url := fmt.Sprintf("http://127.0.0.1:%d/v1/catalog/nodes", s.config.Ports.HTTP) |
||||||
|
|
||||||
|
WaitForResult(func() (bool, error) { |
||||||
|
resp, err := http.Get(url) |
||||||
|
if err != nil { |
||||||
|
return false, err |
||||||
|
} |
||||||
|
resp.Body.Close() |
||||||
|
|
||||||
|
// Ensure we have a leader and a node registeration
|
||||||
|
if leader := resp.Header.Get("X-Consul-KnownLeader"); leader != "true" { |
||||||
|
fmt.Println(leader) |
||||||
|
return false, fmt.Errorf("Consul leader status: %#v", leader) |
||||||
|
} |
||||||
|
if resp.Header.Get("X-Consul-Index") == "0" { |
||||||
|
return false, fmt.Errorf("Consul index is 0") |
||||||
|
} |
||||||
|
|
||||||
|
return true, nil |
||||||
|
}, func(err error) { |
||||||
|
panic(err) |
||||||
|
}) |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
Loading…
Reference in new issue