func newEtcdClient(c *EtcdConfig) (*etcd.Client, error) { if c.Keyfile != "" || c.Certfile != "" || c.CAFile != "" { return etcd.NewTLSClient(c.Endpoints, c.Certfile, c.Keyfile, c.CAFile) } else { return etcd.NewClient(c.Endpoints), nil } }
func RunEtcdServer(t TestingT) (string, func()) { killCh := make(chan struct{}) doneCh := make(chan struct{}) dataDir, err := ioutil.TempDir("", "") if err != nil { t.Fatal("tempdir failed: ", err) } port, err := RandomPort() if err != nil { t.Fatal("error getting random etcd port: ", err) } clusterPort, err := RandomPort() if err != nil { t.Fatal("error getting random cluster port: ", err) } go func() { cmd := exec.Command("etcd", "--data-dir", dataDir, "--listen-client-urls", "http://127.0.0.1:"+port, "--advertise-client-urls", "http://127.0.0.1:"+port, "--listen-peer-urls", "http://127.0.0.1:"+clusterPort, "--initial-advertise-peer-urls", "http://127.0.0.1:"+clusterPort, "--initial-cluster", "default=http://127.0.0.1:"+clusterPort, ) var stderr, stdout io.Reader if os.Getenv("DEBUG") != "" { stderr, _ = cmd.StderrPipe() stdout, _ = cmd.StdoutPipe() } if err := cmd.Start(); err != nil { t.Fatal("etcd start failed: ", err) return } cmdDone := make(chan error) go func() { if stdout != nil { LogOutput("etcd", stdout, stderr) } cmdDone <- cmd.Wait() }() defer close(doneCh) select { case <-killCh: if err := cmd.Process.Kill(); err != nil { t.Fatal("failed to kill etcd: ", err) return } err := <-cmdDone t.Log("etcd process exited: ", err) case err := <-cmdDone: t.Log("etcd process exited unexpectedly: ", err) return } if err := os.RemoveAll(dataDir); err != nil { t.Log("etcd data removal failed: ", err) } }() addr := "http://127.0.0.1:" + port // wait for etcd to come up client := etcd.NewClient([]string{addr}) err = Attempts.Run(func() (err error) { _, err = client.Get("/", false, false) if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == 100 { // Valid 404 from etcd (> v0.5) err = nil } return }) if err != nil { t.Fatal("Failed to connect to etcd: ", err) } return addr, func() { close(killCh) <-doneCh } }