|
|
|
@ -16,6 +16,7 @@ import (
|
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
metrics "github.com/armon/go-metrics" |
|
|
|
|
"github.com/hashicorp/errwrap" |
|
|
|
|
"github.com/hashicorp/go-hclog" |
|
|
|
|
uuid "github.com/hashicorp/go-uuid" |
|
|
|
|
|
|
|
|
@ -100,15 +101,12 @@ func NewTestAgent(t *testing.T, name string, hcl string) *TestAgent {
|
|
|
|
|
func NewTestAgentWithFields(t *testing.T, start bool, ta TestAgent) *TestAgent { |
|
|
|
|
// copy values
|
|
|
|
|
a := ta |
|
|
|
|
if a.Name == "" { |
|
|
|
|
a.Name = t.Name() |
|
|
|
|
} |
|
|
|
|
if !start { |
|
|
|
|
return &a |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
retry.RunWith(retry.ThreeTimes(), t, func(r *retry.R) { |
|
|
|
|
if err := a.Start(); err != nil { |
|
|
|
|
if err := a.Start(t); err != nil { |
|
|
|
|
r.Fatal(err) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
@ -118,32 +116,45 @@ func NewTestAgentWithFields(t *testing.T, start bool, ta TestAgent) *TestAgent {
|
|
|
|
|
|
|
|
|
|
// Start starts a test agent. It returns an error if the agent could not be started.
|
|
|
|
|
// If no error is returned, the caller must call Shutdown() when finished.
|
|
|
|
|
func (a *TestAgent) Start() (err error) { |
|
|
|
|
func (a *TestAgent) Start(t *testing.T) (err error) { |
|
|
|
|
if a.Agent != nil { |
|
|
|
|
return fmt.Errorf("TestAgent already started") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
name := a.Name |
|
|
|
|
// Many tests set Name to t.Name(), which takes up a lot of space at the
|
|
|
|
|
// start of the log messages. The only time we need to care about a name is
|
|
|
|
|
// when a test using multiple TestAgents.
|
|
|
|
|
// As a temporary workaround we ignore the default name and use a shorter
|
|
|
|
|
// default value. Tests which set a custom name for multiple agents will
|
|
|
|
|
// use the provided name.
|
|
|
|
|
// TODO: remove TestAgent.Name and accept a name arg on Start, to remove
|
|
|
|
|
// this workaround.
|
|
|
|
|
if name == "" || name == t.Name() { |
|
|
|
|
name = "TestAgent" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var cleanupTmpDir = func() { |
|
|
|
|
// Clean out the data dir if we are responsible for it before we
|
|
|
|
|
// try again, since the old ports may have gotten written to
|
|
|
|
|
// the data dir, such as in the Raft configuration.
|
|
|
|
|
if a.DataDir != "" { |
|
|
|
|
if err := os.RemoveAll(a.DataDir); err != nil { |
|
|
|
|
fmt.Printf("%s Error resetting data dir: %s", a.Name, err) |
|
|
|
|
fmt.Printf("%s Error resetting data dir: %s", name, err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var hclDataDir string |
|
|
|
|
if a.DataDir == "" { |
|
|
|
|
name := "agent" |
|
|
|
|
if a.Name != "" { |
|
|
|
|
name = a.Name + "-agent" |
|
|
|
|
dirname := "agent" |
|
|
|
|
if name != "" { |
|
|
|
|
dirname = name + "-agent" |
|
|
|
|
} |
|
|
|
|
name = strings.Replace(name, "/", "_", -1) |
|
|
|
|
d, err := ioutil.TempDir(TempDir, name) |
|
|
|
|
dirname = strings.Replace(dirname, "/", "_", -1) |
|
|
|
|
d, err := ioutil.TempDir(TempDir, dirname) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("Error creating data dir %s: %s", filepath.Join(TempDir, name), err) |
|
|
|
|
return fmt.Errorf("Error creating data dir %s: %s", filepath.Join(TempDir, dirname), err) |
|
|
|
|
} |
|
|
|
|
// Convert windows style path to posix style path
|
|
|
|
|
// to avoid illegal char escape error when hcl
|
|
|
|
@ -161,14 +172,15 @@ func (a *TestAgent) Start() (err error) {
|
|
|
|
|
Level: hclog.Debug, |
|
|
|
|
Output: logOutput, |
|
|
|
|
TimeFormat: "04:05.000", |
|
|
|
|
Name: name, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
portsConfig, returnPortsFn := randomPortsSource(a.UseTLS) |
|
|
|
|
a.returnPortsFn = returnPortsFn |
|
|
|
|
a.Config = TestConfig(logger, |
|
|
|
|
portsConfig, |
|
|
|
|
config.Source{Name: a.Name, Format: "hcl", Data: a.HCL}, |
|
|
|
|
config.Source{Name: a.Name + ".data_dir", Format: "hcl", Data: hclDataDir}, |
|
|
|
|
config.Source{Name: name, Format: "hcl", Data: a.HCL}, |
|
|
|
|
config.Source{Name: name + ".data_dir", Format: "hcl", Data: hclDataDir}, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
defer func() { |
|
|
|
@ -214,7 +226,7 @@ func (a *TestAgent) Start() (err error) {
|
|
|
|
|
agent.ShutdownAgent() |
|
|
|
|
agent.ShutdownEndpoints() |
|
|
|
|
|
|
|
|
|
return fmt.Errorf("%s %s Error starting agent: %s", id, a.Name, err) |
|
|
|
|
return fmt.Errorf("%s %s Error starting agent: %s", id, name, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
a.Agent = agent |
|
|
|
@ -225,7 +237,7 @@ func (a *TestAgent) Start() (err error) {
|
|
|
|
|
if err := a.waitForUp(); err != nil { |
|
|
|
|
cleanupTmpDir() |
|
|
|
|
a.Shutdown() |
|
|
|
|
return err |
|
|
|
|
return errwrap.Wrapf(name+": {{err}}", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
a.dns = a.dnsServers[0] |
|
|
|
@ -243,7 +255,7 @@ func (a *TestAgent) waitForUp() error {
|
|
|
|
|
var out structs.IndexedNodes |
|
|
|
|
for ; !time.Now().After(deadline); time.Sleep(timer.Wait) { |
|
|
|
|
if len(a.httpServers) == 0 { |
|
|
|
|
retErr = fmt.Errorf("%s: waiting for server", a.Name) |
|
|
|
|
retErr = fmt.Errorf("waiting for server") |
|
|
|
|
continue // fail, try again
|
|
|
|
|
} |
|
|
|
|
if a.Config.Bootstrap && a.Config.ServerMode { |
|
|
|
@ -260,11 +272,11 @@ func (a *TestAgent) waitForUp() error {
|
|
|
|
|
continue // fail, try again
|
|
|
|
|
} |
|
|
|
|
if !out.QueryMeta.KnownLeader { |
|
|
|
|
retErr = fmt.Errorf("%s: No leader", a.Name) |
|
|
|
|
retErr = fmt.Errorf("No leader") |
|
|
|
|
continue // fail, try again
|
|
|
|
|
} |
|
|
|
|
if out.Index == 0 { |
|
|
|
|
retErr = fmt.Errorf("%s: Consul index is 0", a.Name) |
|
|
|
|
retErr = fmt.Errorf("Consul index is 0") |
|
|
|
|
continue // fail, try again
|
|
|
|
|
} |
|
|
|
|
return nil // success
|
|
|
|
@ -273,7 +285,7 @@ func (a *TestAgent) waitForUp() error {
|
|
|
|
|
resp := httptest.NewRecorder() |
|
|
|
|
_, err := a.httpServers[0].AgentSelf(resp, req) |
|
|
|
|
if err != nil || resp.Code != 200 { |
|
|
|
|
retErr = fmt.Errorf("%s: failed OK response: %v", a.Name, err) |
|
|
|
|
retErr = fmt.Errorf("failed OK response: %v", err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
return nil // success
|
|
|
|
|