tune cluster ls: parallized and use tcp connect instead of https (#63)

This commit is contained in:
T. von Dein
2026-07-03 08:30:35 +02:00
parent b573d63c54
commit b51ee109f2
3 changed files with 59 additions and 51 deletions

View File

@@ -17,10 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package cfg
import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"os"
"strings"
@@ -185,42 +185,24 @@ func (conf *Config) SwitchCluster(name string) error {
// We do NOT use go-elasticsearch to check for cluster reachability,
// because at this stage, auth may not have been configured. So
// instead we just connect to the cluster using plan net/http, ignore
// HTTP response status and return true if we could just reach ith
// instead we just connect to the cluster using plan net/tcp
func (cluster *Cluster) IsReachable() (bool, error) {
ctx, cancel := context.WithTimeout(
context.Background(),
time.Duration(500)*time.Millisecond)
defer cancel()
timeout := 500 * time.Millisecond
req, err := http.NewRequestWithContext(
ctx,
"GET",
cluster.Uri,
nil,
)
url := strings.TrimPrefix(strings.TrimPrefix(cluster.Uri, "https://"), "http://")
host := strings.Split(url, "/")
if !strings.Contains(host[0], ":") {
host[0] += ":443"
}
conn, err := net.DialTimeout("tcp", host[0], timeout)
if err != nil {
return false, err
}
client := &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}
resp, err := client.Do(req)
if err != nil {
return false, err
}
if resp != nil {
// at this stage we do not care if the elasticsearch cluster
// accepts our request or if it's misconfigured in some way
return true, nil
}
return false, nil
return true, conn.Close()
}
func (conf *Config) SetupES() error {

View File

@@ -28,7 +28,7 @@ import (
)
const (
Version string = `v0.0.24`
Version string = `v0.0.25`
)
var (
@@ -137,6 +137,18 @@ func (conf *Config) Init() error {
return err
}
if err := conf.determineDefaultCluster(); err != nil {
return err
}
conf.HaveJQ = isJQinstalled()
conf.PrintDebug()
return nil
}
func (conf *Config) determineDefaultCluster() error {
if conf.CurrentCluster != "" {
// -C specified, set current cluster explicitly, no matter what the config says
current, exists := conf.Clusters[conf.CurrentCluster]
@@ -172,10 +184,6 @@ func (conf *Config) Init() error {
}
}
conf.HaveJQ = isJQinstalled()
conf.PrintDebug()
return nil
}

View File

@@ -31,44 +31,62 @@ import (
type ClusterIndices map[string]map[string]*types.IndicesRecord
func ClusterList(conf *cfg.Config) error {
table := printer.NewTable(conf, 5, len(conf.Clusters))
type clusterReachable struct {
reachable bool
err error
}
func ClusterList(conf *cfg.Config) error {
var mu sync.Mutex
var wg sync.WaitGroup
reachable := make(map[string]clusterReachable, len(conf.Clusters))
// check endpoints in parallel to speed things up
for name, cluster := range conf.Clusters {
wg.Add(1)
go func() {
defer wg.Done()
online, err := cluster.IsReachable()
mu.Lock()
reachable[name] = clusterReachable{reachable: online, err: err}
mu.Unlock()
}()
}
wg.Wait()
table := printer.NewTable(conf, 5, len(conf.Clusters))
table.Addheaders("cluster", "uri", "reachable", "current", "error")
idx := 0
for name, cluster := range conf.Clusters {
reachable := "no"
reachableStr := "no"
current := "no"
errmsg := ""
online, err := cluster.IsReachable()
if online {
reachable = printer.Colorize(conf, "green", "reachable")
if reachable[name].reachable {
reachableStr = printer.Colorize(conf, "green", "reachable")
}
if cluster.Default {
current = printer.Colorize(conf, "green", "yes")
if !online {
reachable = printer.Colorize(conf, "red", "no")
errmsg = err.Error()
if !reachable[name].reachable {
reachableStr = printer.Colorize(conf, "red", "no")
errmsg = reachable[name].err.Error()
}
}
table.Entries[idx] = []string{name, cluster.Uri, reachable, current, errmsg}
table.Entries[idx] = []string{name, cluster.Uri, reachableStr, current, errmsg}
idx++
}
table.Sort()
if err := table.Print(); err != nil {
return err
}
return nil
return table.Print()
}
// We're using goroutines here to parallelize API requests, since we