| 76 | } |
| 77 | |
| 78 | func New(id string, cfg *Config) (*Etcd, error) { |
| 79 | if len(id) == 0 { |
| 80 | return nil, errors.New("id must NOT be a empty string") |
| 81 | } |
| 82 | |
| 83 | clientConfig := clientv3.Config{ |
| 84 | Endpoints: cfg.Addrs, |
| 85 | DialTimeout: defaultDialTimeout, |
| 86 | Logger: logger.Get(), |
| 87 | } |
| 88 | |
| 89 | if cfg.TLS.Enable { |
| 90 | tlsInfo := transport.TLSInfo{ |
| 91 | CertFile: cfg.TLS.CertFile, |
| 92 | KeyFile: cfg.TLS.KeyFile, |
| 93 | TrustedCAFile: cfg.TLS.TrustedCAFile, |
| 94 | } |
| 95 | tlsConfig, err := tlsInfo.ClientConfig() |
| 96 | if err != nil { |
| 97 | return nil, err |
| 98 | } |
| 99 | |
| 100 | clientConfig.TLS = tlsConfig |
| 101 | } |
| 102 | if cfg.Username != "" && cfg.Password != "" { |
| 103 | clientConfig.Username = cfg.Username |
| 104 | clientConfig.Password = cfg.Password |
| 105 | } |
| 106 | |
| 107 | client, err := clientv3.New(clientConfig) |
| 108 | if err != nil { |
| 109 | return nil, err |
| 110 | } |
| 111 | |
| 112 | electPath := defaultElectPath |
| 113 | if cfg.ElectPath != "" { |
| 114 | electPath = cfg.ElectPath |
| 115 | } |
| 116 | e := &Etcd{ |
| 117 | myID: id, |
| 118 | electPath: electPath, |
| 119 | client: client, |
| 120 | kv: clientv3.NewKV(client), |
| 121 | quitCh: make(chan struct{}), |
| 122 | electionCh: make(chan *concurrency.Election), |
| 123 | leaderChangeCh: make(chan bool), |
| 124 | } |
| 125 | e.isReady.Store(false) |
| 126 | e.wg.Add(2) |
| 127 | go e.electLoop(context.Background()) |
| 128 | go e.observeLeaderEvent(context.Background()) |
| 129 | return e, nil |
| 130 | } |
| 131 | |
| 132 | func (e *Etcd) ID() string { |
| 133 | return e.myID |