Example #1
0
// StartEmbeddedEtcd will start an embedded etcd server using embed.Config
// passed to it. If unsuccessful, this function returns an error.
func StartEmbeddedEtcd(cfg *embed.Config) error {

	etcdInstance.Lock()
	defer etcdInstance.Unlock()

	if etcdInstance.etcd != nil {
		return errors.New("An instance of etcd embedded server is already running")
	}

	// Start embedded etcd server
	etcd, err := embed.StartEtcd(cfg)
	if err != nil {
		return err
	}

	// The returned embed.Etcd.Server instance is not guaranteed to have
	// joined the cluster yet. Wait on the embed.Etcd.Server.ReadyNotify()
	// channel to know when it's ready for use. Stop waiting after an
	// arbitrary timeout (make it configurable?) of 42 seconds.
	select {
	case <-etcd.Server.ReadyNotify():
		log.Info("Etcd embedded server is ready.")
		etcdInstance.etcd = etcd
		return nil
	case <-time.After(42 * time.Second):
		etcd.Server.Stop() // trigger a shutdown
		return errors.New("Etcd embedded server took too long to start")
	case err := <-etcd.Err():
		return err
	}
}
Example #2
0
// startEtcd runs StartEtcd in addition to hooks needed for standalone etcd.
func startEtcd(cfg *embed.Config) (<-chan struct{}, <-chan error, error) {
	e, err := embed.StartEtcd(cfg)
	if err != nil {
		return nil, nil, err
	}
	osutil.RegisterInterruptHandler(e.Server.Stop)
	return e.Server.StopNotify(), e.Err(), nil
}
Example #3
0
// startEtcd runs StartEtcd in addition to hooks needed for standalone etcd.
func startEtcd(cfg *embed.Config) (<-chan struct{}, <-chan error, error) {
	defaultHost, dhErr := cfg.IsDefaultHost()
	if defaultHost != "" {
		if dhErr == nil {
			plog.Infof("advertising using detected default host %q", defaultHost)
		} else {
			plog.Noticef("failed to detect default host, advertise falling back to %q (%v)", defaultHost, dhErr)
		}
	}

	e, err := embed.StartEtcd(cfg)
	if err != nil {
		return nil, nil, err
	}
	osutil.RegisterInterruptHandler(e.Server.Stop)
	<-e.Server.ReadyNotify() // wait for e.Server to join the cluster
	return e.Server.StopNotify(), e.Err(), nil
}
Example #4
0
func TestEmbedEtcd(t *testing.T) {
	tests := []struct {
		cfg embed.Config

		werr     string
		wpeers   int
		wclients int
	}{
		{werr: "multiple discovery"},
		{werr: "advertise-client-urls is required"},
		{werr: "should be at least"},
		{werr: "is too long"},
		{wpeers: 1, wclients: 1},
		{wpeers: 2, wclients: 1},
		{wpeers: 1, wclients: 2},
	}

	urls := newEmbedURLs(10)

	// setup defaults
	for i := range tests {
		tests[i].cfg = *embed.NewConfig()
	}

	tests[0].cfg.Durl = "abc"
	setupEmbedCfg(&tests[1].cfg, []url.URL{urls[0]}, []url.URL{urls[1]})
	tests[1].cfg.ACUrls = nil
	tests[2].cfg.TickMs = tests[2].cfg.ElectionMs - 1
	tests[3].cfg.ElectionMs = 999999
	setupEmbedCfg(&tests[4].cfg, []url.URL{urls[2]}, []url.URL{urls[3]})
	setupEmbedCfg(&tests[5].cfg, []url.URL{urls[4]}, []url.URL{urls[5], urls[6]})
	setupEmbedCfg(&tests[6].cfg, []url.URL{urls[7], urls[8]}, []url.URL{urls[9]})

	dir := path.Join(os.TempDir(), fmt.Sprintf("embed-etcd"))
	os.RemoveAll(dir)
	defer os.RemoveAll(dir)

	for i, tt := range tests {
		tests[i].cfg.Dir = dir
		e, err := embed.StartEtcd(&tests[i].cfg)
		if tt.werr != "" {
			if err == nil || !strings.Contains(err.Error(), tt.werr) {
				t.Errorf("%d: expected error with %q, got %v", i, tt.werr, err)
			}
			if e != nil {
				e.Close()
			}
			continue
		}
		if err != nil {
			t.Errorf("%d: expected success, got error %v", i, err)
			continue
		}
		if len(e.Peers) != tt.wpeers {
			t.Errorf("%d: expected %d peers, got %d", i, tt.wpeers, len(e.Peers))
		}
		if len(e.Clients) != tt.wclients {
			t.Errorf("%d: expected %d peers, got %d", i, tt.wclients, len(e.Clients))
		}
		e.Close()
	}
}
Example #5
0
// RunEtcd starts an etcd server and runs it forever
func RunEtcd(etcdServerConfig *configapi.EtcdConfig) {
	cfg := embed.NewConfig()
	cfg.Debug = true
	cfg.Name = defaultName
	cfg.Dir = etcdServerConfig.StorageDir

	clientTLS := configapi.UseTLS(etcdServerConfig.ServingInfo)
	if clientTLS {
		cfg.ClientTLSInfo.CAFile = etcdServerConfig.ServingInfo.ClientCA
		cfg.ClientTLSInfo.CertFile = etcdServerConfig.ServingInfo.ServerCert.CertFile
		cfg.ClientTLSInfo.KeyFile = etcdServerConfig.ServingInfo.ServerCert.KeyFile
		cfg.ClientTLSInfo.ClientCertAuth = len(cfg.ClientTLSInfo.CAFile) > 0
	}
	u, err := types.NewURLs(addressToURLs(etcdServerConfig.ServingInfo.BindAddress, clientTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd peer URLs: %v", err)
	}
	cfg.LCUrls = []url.URL(u)

	peerTLS := configapi.UseTLS(etcdServerConfig.PeerServingInfo)
	if peerTLS {
		cfg.PeerTLSInfo.CAFile = etcdServerConfig.PeerServingInfo.ClientCA
		cfg.PeerTLSInfo.CertFile = etcdServerConfig.PeerServingInfo.ServerCert.CertFile
		cfg.PeerTLSInfo.KeyFile = etcdServerConfig.PeerServingInfo.ServerCert.KeyFile
		cfg.PeerTLSInfo.ClientCertAuth = len(cfg.PeerTLSInfo.CAFile) > 0
	}
	u, err = types.NewURLs(addressToURLs(etcdServerConfig.PeerServingInfo.BindAddress, peerTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd peer URLs: %v", err)
	}
	cfg.LPUrls = []url.URL(u)

	u, err = types.NewURLs(addressToURLs(etcdServerConfig.Address, clientTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd announce client URLs: %v", err)
	}
	cfg.ACUrls = []url.URL(u)

	u, err = types.NewURLs(addressToURLs(etcdServerConfig.PeerAddress, peerTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd announce peer URLs: %v", err)
	}
	cfg.APUrls = []url.URL(u)

	cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)

	osutil.HandleInterrupts()

	e, err := embed.StartEtcd(cfg)
	if err != nil {
		glog.Fatalf("Unable to start etcd: %v", err)
	}

	go func() {
		defer e.Close()

		select {
		case <-e.Server.ReadyNotify():
			glog.Infof("Started etcd at %s", etcdServerConfig.Address)
		case <-time.After(60 * time.Second):
			glog.Warning("etcd took too long to start, stopped")
			e.Server.Stop() // trigger a shutdown
		}
		glog.Fatalf("etcd has returned an error: %v", <-e.Err())
	}()
}