ask for pass if missing or use env pass, add token support (#60)

This commit is contained in:
T. von Dein
2026-07-01 10:58:39 +02:00
parent f5c8a23589
commit 6436bcfb22
6 changed files with 258 additions and 171 deletions

View File

@@ -17,7 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package es
import (
"context"
"fmt"
"log/slog"
"strings"
@@ -38,32 +37,33 @@ import (
type ClusterIndices map[string]map[string]*types.IndicesRecord
func ClusterList(conf *cfg.Config) error {
table := printer.NewTable(conf, 4, len(conf.Clusters))
table := printer.NewTable(conf, 5, len(conf.Clusters))
table.Addheaders("cluster", "uri", "reachable", "current")
table.Addheaders("cluster", "uri", "reachable", "current", "error")
idx := 0
for name, cluster := range conf.Clusters {
reachable := "no"
current := "no"
errmsg := ""
_, err := cluster.ES().Cluster.Health().
Do(context.Background())
online, err := cluster.IsReachable()
if err == nil {
if online {
reachable = printer.Colorize(conf, "green", "reachable")
}
if cluster.Default {
current = printer.Colorize(conf, "green", "yes")
if err != nil {
if !online {
reachable = printer.Colorize(conf, "red", "no")
errmsg = err.Error()
}
}
table.Entries[idx] = []string{name, cluster.Uri, reachable, current}
table.Entries[idx] = []string{name, cluster.Uri, reachable, current, errmsg}
idx++
}
@@ -79,134 +79,120 @@ func ClusterList(conf *cfg.Config) error {
// We're using goroutines here to parallelize API requests, since we
// have to do 3 of'em for each cluster. This speeds things up.
func ClusterStatus(conf *cfg.Config) error {
clusters := []string{}
gocount := 5
if conf.Verbose {
gocount++
}
if conf.All {
for key := range conf.Clusters {
clusters = append(clusters, key)
}
} else {
clusters = []string{"default"}
es := conf.DefaultCluster.ES()
responses := make(chan apiResponse, gocount)
wg := &sync.WaitGroup{}
wg.Add(gocount)
go getApiData(es, wg, responses, "health")
go getApiData(es, wg, responses, "info")
go getApiData(es, wg, responses, "ccrstats")
go getApiData(es, wg, responses, "indices")
go getApiData(es, wg, responses, "tasks")
if conf.Verbose {
go getApiData(es, wg, responses, "stats")
}
for _, cluster := range clusters {
es := conf.DefaultCluster.ES()
if cluster != "default" {
es = conf.Clusters[cluster].ES()
wg.Wait()
var clusterhealth *health.Response
var info *info.Response
var ccrstats *stats.Response
var clusterstats *clusterstats.Response
var indexstats *indices.Response
var taskstatus *tasks.Response
for i := 0; i < gocount; i++ {
r := <-responses
if r.error != nil {
return r.error
}
responses := make(chan apiResponse, gocount)
wg := &sync.WaitGroup{}
wg.Add(gocount)
go getApiData(es, wg, responses, "health")
go getApiData(es, wg, responses, "info")
go getApiData(es, wg, responses, "ccrstats")
go getApiData(es, wg, responses, "indices")
go getApiData(es, wg, responses, "tasks")
if conf.Verbose {
go getApiData(es, wg, responses, "stats")
switch r.which {
case ResponseHealth:
clusterhealth = r.health
case ResponseCcr:
ccrstats = r.ccr
case ResponseInfo:
info = r.info
case ResponseStats:
clusterstats = r.stats
case ResponseIndices:
indexstats = r.indices
case ResponseTasks:
taskstatus = r.tasks
}
}
wg.Wait()
slog.Debug("ES result", "cluster health", clusterhealth)
var clusterhealth *health.Response
var info *info.Response
var ccrstats *stats.Response
var clusterstats *clusterstats.Response
var indexstats *indices.Response
var taskstatus *tasks.Response
isleader := len(ccrstats.AutoFollowStats.AutoFollowedClusters) == 0
for i := 0; i < gocount; i++ {
r := <-responses
ccrfollowing := ""
if len(ccrstats.AutoFollowStats.AutoFollowedClusters) > 0 {
// is following another cluster
ccrfollowing = fmt.Sprintf("%s (%d/%d)",
ccrstats.AutoFollowStats.AutoFollowedClusters[0].ClusterName,
ccrstats.AutoFollowStats.NumberOfSuccessfulFollowIndices,
ccrstats.AutoFollowStats.NumberOfFailedFollowIndices,
)
}
if r.error != nil {
return r.error
}
switch r.which {
case ResponseHealth:
clusterhealth = r.health
case ResponseCcr:
ccrstats = r.ccr
case ResponseInfo:
info = r.info
case ResponseStats:
clusterstats = r.stats
case ResponseIndices:
indexstats = r.indices
case ResponseTasks:
taskstatus = r.tasks
}
// look for red indices, if any
redindices := 0
for _, index := range *indexstats {
if *index.Health == "red" {
redindices++
}
}
slog.Debug("ES result", "cluster health", clusterhealth)
isleader := len(ccrstats.AutoFollowStats.AutoFollowedClusters) == 0
ccrfollowing := ""
if len(ccrstats.AutoFollowStats.AutoFollowedClusters) > 0 {
// is following another cluster
ccrfollowing = fmt.Sprintf("%s (%d/%d)",
ccrstats.AutoFollowStats.AutoFollowedClusters[0].ClusterName,
ccrstats.AutoFollowStats.NumberOfSuccessfulFollowIndices,
ccrstats.AutoFollowStats.NumberOfFailedFollowIndices,
)
// look for long running tasks
longtasks := 0
for _, task := range *taskstatus {
if strings.Contains(*task.RunningTime, "d") {
longtasks++
}
}
// look for red indices, if any
redindices := 0
for _, index := range *indexstats {
if *index.Health == "red" {
redindices++
}
}
table := printer.NewTable(conf, 2, 7)
table.Addheaders(conf.DefaultCluster.Name, "status")
// look for long running tasks
longtasks := 0
for _, task := range *taskstatus {
if strings.Contains(*task.RunningTime, "d") {
longtasks++
}
}
table.Entries = [][]string{
{"Cluster Name", clusterhealth.ClusterName},
{"ES Status", printer.Colorize(conf, clusterhealth.Status.Name, clusterhealth.Status.Name)},
{"ES Version", info.Version.Int},
{"Is Leader", fmt.Sprintf("%t", isleader)},
{"Active Shards", fmt.Sprintf("%d", clusterhealth.ActiveShards)},
{"Active Primary Shards", fmt.Sprintf("%d", clusterhealth.ActivePrimaryShards)},
{"Unassigned Shards", fmt.Sprintf("%d", clusterhealth.UnassignedShards)},
{"Unassigned Primary Shards", fmt.Sprintf("%d", clusterhealth.UnassignedPrimaryShards)},
{"Pending Tasks", fmt.Sprintf("%d", clusterhealth.NumberOfPendingTasks)},
{"Nodes", fmt.Sprintf("%d", clusterhealth.NumberOfNodes)},
{"Red Indices", fmt.Sprintf("%d", redindices)},
{"Long Running Tasks", fmt.Sprintf("%d", longtasks)},
}
table := printer.NewTable(conf, 2, 7)
table.Addheaders(cluster, "status")
if !isleader {
table.Entries = append(table.Entries, [][]string{
{"AutoFollow (success/failed indices)", ccrfollowing},
{"Followed Indices", fmt.Sprintf("%d", len(ccrstats.FollowStats.Indices))},
}...)
}
table.Entries = [][]string{
{"Cluster Name", clusterhealth.ClusterName},
{"ES Status", printer.Colorize(conf, clusterhealth.Status.Name, clusterhealth.Status.Name)},
{"ES Version", info.Version.Int},
{"Is Leader", fmt.Sprintf("%t", isleader)},
{"Active Shards", fmt.Sprintf("%d", clusterhealth.ActiveShards)},
{"Active Primary Shards", fmt.Sprintf("%d", clusterhealth.ActivePrimaryShards)},
{"Unassigned Shards", fmt.Sprintf("%d", clusterhealth.UnassignedShards)},
{"Unassigned Primary Shards", fmt.Sprintf("%d", clusterhealth.UnassignedPrimaryShards)},
{"Pending Tasks", fmt.Sprintf("%d", clusterhealth.NumberOfPendingTasks)},
{"Nodes", fmt.Sprintf("%d", clusterhealth.NumberOfNodes)},
{"Red Indices", fmt.Sprintf("%d", redindices)},
{"Long Running Tasks", fmt.Sprintf("%d", longtasks)},
}
if conf.Verbose {
table = gatherClusterStats(conf, clusterstats, table)
}
if !isleader {
table.Entries = append(table.Entries, [][]string{
{"AutoFollow (success/failed indices)", ccrfollowing},
{"Followed Indices", fmt.Sprintf("%d", len(ccrstats.FollowStats.Indices))},
}...)
}
if conf.Verbose {
table = gatherClusterStats(conf, clusterstats, table)
}
if err := table.Print(); err != nil {
return err
}
if err := table.Print(); err != nil {
return err
}
return nil