From f27f9157fb4913f9df1f8d3b227c8706d5584552 Mon Sep 17 00:00:00 2001 From: "T. von Dein" Date: Tue, 28 Apr 2026 13:43:13 +0200 Subject: [PATCH] add "cluster ls", put "status" into "cluster status" (#5) --- cmd/cluster.go | 43 +++++++++++++++++++++++++++++++++ cmd/health.go | 42 -------------------------------- cmd/root.go | 8 +++++-- go.mod | 1 + go.sum | 2 ++ pkg/cfg/config.go | 3 ++- pkg/es/aux.go | 50 -------------------------------------- pkg/es/cluster.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 95 deletions(-) delete mode 100644 cmd/health.go delete mode 100644 pkg/es/aux.go diff --git a/cmd/cluster.go b/cmd/cluster.go index 5432d40..00f1cb9 100644 --- a/cmd/cluster.go +++ b/cmd/cluster.go @@ -34,6 +34,49 @@ func Cluster(conf *cfg.Config) *cli.Command { Commands: []*cli.Command{ Compare(conf), + Status(conf), + List(conf), + }, + } +} + +func List(conf *cfg.Config) *cli.Command { + return &cli.Command{ + Name: "list", + Usage: "list configured clusters", + Aliases: []string{"ls"}, + + Action: func(ctx context.Context, cmd *cli.Command) error { + if err := es.List(conf); err != nil { + return err + } + + return nil + }, + } +} + +func Status(conf *cfg.Config) *cli.Command { + return &cli.Command{ + Name: "status", + Usage: "show cluster status", + Aliases: []string{"s"}, + + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "all", + Usage: "show status of all clusters", + Destination: &conf.All, + Aliases: []string{"a"}, + }, + }, + + Action: func(ctx context.Context, cmd *cli.Command) error { + if err := es.Status(conf); err != nil { + return err + } + + return nil }, } } diff --git a/cmd/health.go b/cmd/health.go deleted file mode 100644 index 6d13025..0000000 --- a/cmd/health.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright © 2026 Thomas von Dein - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -package cmd - -import ( - "context" - - "codeberg.org/scip/esctl/pkg/cfg" - "codeberg.org/scip/esctl/pkg/es" - - "github.com/urfave/cli/v3" -) - -func Status(conf *cfg.Config) *cli.Command { - return &cli.Command{ - Name: "status", - Usage: "show ES status", - Aliases: []string{"s"}, - Action: func(ctx context.Context, cmd *cli.Command) error { - if err := es.Health(conf); err != nil { - return err - } - - return nil - }, - } -} diff --git a/cmd/root.go b/cmd/root.go index aa21150..c7ea297 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -72,7 +72,6 @@ func Main() int { }, Commands: []*cli.Command{ - Status(conf), Search(conf), Index(conf), Snapshot(conf), @@ -81,7 +80,12 @@ func Main() int { Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) { if err := conf.Init(); err != nil { - return nil, err + if len(os.Args) > 1 { + return nil, err + } else { + fmt.Println(cmd.UsageText) + return nil, nil + } } log.Init(conf) diff --git a/go.mod b/go.mod index 55f7cbd..c1df583 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect golang.org/x/sys v0.42.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d4e1dd4..a9b1be6 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/ go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/pkg/cfg/config.go b/pkg/cfg/config.go index 67d575a..5a21757 100644 --- a/pkg/cfg/config.go +++ b/pkg/cfg/config.go @@ -30,7 +30,7 @@ import ( ) const ( - Version string = `v0.0.2` + Version string = `v0.0.3` ) type Cluster struct { @@ -49,6 +49,7 @@ type Config struct { From, To, MaxItems int // search: flags Filter []string // search: -F Exclude string // cluster compare: -e (regexp) + All bool // cluster status: -a } func NewConfig() *Config { diff --git a/pkg/es/aux.go b/pkg/es/aux.go deleted file mode 100644 index ef0bacd..0000000 --- a/pkg/es/aux.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright © 2026 Thomas von Dein - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -package es - -import ( - "context" - "fmt" - "log" - "log/slog" - - "codeberg.org/scip/esctl/pkg/cfg" -) - -func Health(conf *cfg.Config) error { - res, err := conf.DefaultCluster.ES.Cluster.Health().Do(context.Background()) - if err != nil { - log.Fatalf("Error getting health: %s", err) - } - - slog.Debug("ES result", "cluster health", res) - - table := NewTable(2, 5) - - table.headers = []string{bold("SETTING"), bold("STATUS")} - - table.entries = [][]string{ - {"Cluster Name", Colorize(*&res.Status.Name, res.ClusterName)}, - {"Active Shards", fmt.Sprintf("%d", res.ActiveShards)}, - {"Active Primary Shards", fmt.Sprintf("%d", res.ActivePrimaryShards)}, - {"Indicies", fmt.Sprintf("%d", len(res.Indices))}, - {"Nodes", fmt.Sprintf("%d", res.NumberOfNodes)}, - } - - table.PrintMarkdown() - return nil -} diff --git a/pkg/es/cluster.go b/pkg/es/cluster.go index a6bf21c..6990079 100644 --- a/pkg/es/cluster.go +++ b/pkg/es/cluster.go @@ -19,6 +19,8 @@ package es import ( "context" "fmt" + "log" + "log/slog" "regexp" "codeberg.org/scip/esctl/pkg/cfg" @@ -57,6 +59,65 @@ func ClusterCompare(conf *cfg.Config, leader, follower string) error { return nil } +func List(conf *cfg.Config) error { + table := NewTable(2, len(conf.Clusters)) + table.Addheaders("cluster", "uri") + + idx := 0 + for name, cluster := range conf.Clusters { + table.entries[idx] = []string{name, cluster.Uri} + idx++ + } + + table.PrintMarkdown() + + return nil +} + +func Status(conf *cfg.Config) error { + clusters := []string{} + + if conf.All { + for key, _ := range conf.Clusters { + clusters = append(clusters, key) + } + } else { + clusters = []string{"default"} + } + + for _, cluster := range clusters { + es := conf.DefaultCluster.ES + if cluster != "default" { + es = conf.Clusters[cluster].ES + } + + res, err := es.Cluster.Health(). + Header("content-type", "application/json"). + Header("accept", "application/json"). + Do(context.Background()) + if err != nil { + log.Fatalf("Error getting health: %s", err) + } + + slog.Debug("ES result", "cluster health", res) + + table := NewTable(2, 5) + table.Addheaders(cluster, "status") + + table.entries = [][]string{ + {"Cluster Name", Colorize(*&res.Status.Name, res.ClusterName)}, + {"Active Shards", fmt.Sprintf("%d", res.ActiveShards)}, + {"Active Primary Shards", fmt.Sprintf("%d", res.ActivePrimaryShards)}, + {"Indicies", fmt.Sprintf("%d", len(res.Indices))}, + {"Nodes", fmt.Sprintf("%d", res.NumberOfNodes)}, + } + + table.PrintMarkdown() + } + + return nil +} + // look for indicies only on leader func findIndicesOnlyOnMaster(conf *cfg.Config, indices ClusterIndices, leader, follower string) { exclude := regexp.MustCompile(DefaultExclude)