func (c *Client) DiscoverNodes() error {
	var conns []*Connection
	nodes, err := c.getNodesInfo()
	if err != nil {
		if debugLogger != nil {
			debugLogger.Logf("Error getting nodes info: %s\n", err)
		}
		return fmt.Errorf("discovery: get nodes: %s", err)
	}
	for _, node := range nodes {
		var (
			isDataNode   bool
			isIngestNode bool
		)
		roles := append(node.Roles[:0:0], node.Roles...)
		sort.Strings(roles)
		if i := sort.SearchStrings(roles, "data"); i < len(roles) && roles[i] == "data" {
			isDataNode = true
		}
		if i := sort.SearchStrings(roles, "ingest"); i < len(roles) && roles[i] == "ingest" {
			isIngestNode = true
		}
		if debugLogger != nil {
			var skip string
			if !isDataNode || !isIngestNode {
				skip = "; [SKIP]"
			}
			debugLogger.Logf("Discovered node [%s]; %s; roles=%s%s\n", node.Name, node.URL, node.Roles, skip)
		}
		if !isDataNode || !isIngestNode {
			continue
		}
		conns = append(conns, &Connection{
			URL:        node.URL,
			ID:         node.ID,
			Name:       node.Name,
			Roles:      node.Roles,
			Attributes: node.Attributes,
		})
	}
	c.Lock()
	defer c.Unlock()
	if lockable, ok := c.pool.(sync.Locker); ok {
		lockable.Lock()
		defer lockable.Unlock()
	}
	if c.poolFunc != nil {
		c.pool = c.poolFunc(conns, c.selector)
	} else {
		c.pool, err = NewConnectionPool(conns, c.selector)
		if err != nil {
			return err
		}
	}
	return nil
}
DiscoverNodes reloads the client connections by fetching information from the cluster.
package estransport
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"sync"
	"time"
)
type Discoverable interface {
	DiscoverNodes() error
}
type nodeInfo struct {
	ID         string
	Name       string
	URL        *url.URL
	Roles      []string
	Attributes map[string]interface{}
	HTTP       struct {
		PublishAddress string `json:"publish_address"`
	}
}