diff --git a/TODO.md b/TODO.md index 87ad16a..f42e3bb 100644 --- a/TODO.md +++ b/TODO.md @@ -11,3 +11,5 @@ https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-data-stream also exclude data stream backing indices from index ls + +- table any2string diff --git a/cmd/root.go b/cmd/root.go index 4f95c8c..2eac0a1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -89,7 +89,7 @@ func Main() int { Name: "output", Aliases: []string{"o"}, Value: "", - Usage: "output mode (tsv, markdown, json, yaml) default: tsv", + Usage: "output mode (tsv, json, yaml) default: tsv", Destination: &conf.Output, }, &cli.StringFlag{ diff --git a/go.mod b/go.mod index e8116bb..152498b 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,8 @@ go 1.25.8 require ( github.com/MichaelMure/go-term-markdown v0.1.4 github.com/alecthomas/repr v0.5.2 + github.com/charmbracelet/bubbles v1.0.0 + github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/lipgloss v1.1.0 github.com/chzyer/readline v1.5.1 github.com/dustin/go-humanize v1.0.1 @@ -29,10 +31,11 @@ require ( github.com/go-openapi/spec v0.22.5 github.com/go-openapi/swag/loading v0.26.1 github.com/mattn/go-isatty v0.0.22 - github.com/olekukonko/tablewriter v1.1.4 + github.com/seeruk/go-wordwrap v0.0.0-20191208221741-14ec4aac9550 github.com/tidwall/gjson v1.19.0 github.com/tlinden/yadu v0.1.3 github.com/urfave/cli/v3 v3.10.1-0.20260623012112-f980ca84bf65 + golang.org/x/term v0.44.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -40,9 +43,6 @@ require ( github.com/MichaelMure/go-term-text v0.3.1 // indirect github.com/alecthomas/chroma v0.7.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charmbracelet/bubbles v1.0.0 // indirect - github.com/charmbracelet/bubbletea v1.3.10 // indirect github.com/charmbracelet/colorprofile v0.4.1 // indirect github.com/charmbracelet/x/ansi v0.11.6 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect @@ -69,7 +69,6 @@ require ( github.com/go-openapi/swag/typeutils v0.26.1 // indirect github.com/go-openapi/swag/yamlutils v0.26.1 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect - github.com/goccy/go-json v0.10.6 // indirect github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 // indirect github.com/google/uuid v1.6.0 // indirect github.com/kyokomi/emoji/v2 v2.2.8 // indirect @@ -81,11 +80,7 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect - github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect - github.com/olekukonko/errors v1.2.0 // indirect - github.com/olekukonko/ll v0.1.8 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/seeruk/go-wordwrap v0.0.0-20191208221741-14ec4aac9550 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect @@ -94,10 +89,8 @@ require ( go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 // indirect golang.org/x/net v0.55.0 // indirect golang.org/x/sys v0.46.0 // indirect - golang.org/x/term v0.44.0 // indirect golang.org/x/text v0.37.0 // indirect ) diff --git a/go.sum b/go.sum index 2918b3b..5f7026b 100644 --- a/go.sum +++ b/go.sum @@ -14,28 +14,18 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= @@ -114,8 +104,6 @@ github.com/go-openapi/testify/v2 v2.5.1 h1:TMdhCaw8fUNraVSf3Omoob1dO/AzBfhtFAPW0 github.com/go-openapi/testify/v2 v2.5.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= -github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 h1:Qxs3bNRWe8GTcKMxYOSXm0jx6j0de8XUtb/fsP3GZ0I= github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -154,14 +142,6 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= -github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= -github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= -github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= -github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.1.8 h1:ysHCJRGHYKzmBSdz9w5AySztx7lG8SQY+naTGYUbsz8= -github.com/olekukonko/ll v0.1.8/go.mod h1:RPRC6UcscfFZgjo1nulkfMH5IM0QAYim0LfnMvUuozw= -github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= -github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -189,8 +169,6 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY= github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA= -github.com/urfave/cli/v3 v3.9.1-0.20260524212652-be8b79d0c8de h1:ESKPiS7inVoBnv4FmgGNZdjWBI/wmvaragoyD3D9nM4= -github.com/urfave/cli/v3 v3.9.1-0.20260524212652-be8b79d0c8de/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/urfave/cli/v3 v3.10.1-0.20260623012112-f980ca84bf65 h1:NXitXXO9DupDLEFj8hIyYtsubRxSFTp5JXqohElT0nU= github.com/urfave/cli/v3 v3.10.1-0.20260623012112-f980ca84bf65/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= @@ -223,8 +201,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= diff --git a/pkg/es/ccr.go b/pkg/es/ccr.go index 788fd95..ca7c5a4 100644 --- a/pkg/es/ccr.go +++ b/pkg/es/ccr.go @@ -113,11 +113,11 @@ func CcrRemoteInfo(conf *cfg.Config, index string) error { table := printer.NewTable(conf, 2, 5) table.Addheaders("ccr remote property", "value") - table.Entries = [][]string{ + table.Entries = [][]any{ {"Remote Cluster", remote}, {"CCR Mode", mode}, - {"Connected", fmt.Sprintf("%t", info.Connected)}, - {"Num Proxy Sockets Connected", fmt.Sprintf("%d", info.NumProxySocketsConnected)}, + {"Connected", info.Connected}, + {"Num Proxy Sockets Connected", info.NumProxySocketsConnected}, {"Proxy Address", info.ProxyAddress}, } diff --git a/pkg/es/ccr_follower.go b/pkg/es/ccr_follower.go index e324142..e8bb674 100644 --- a/pkg/es/ccr_follower.go +++ b/pkg/es/ccr_follower.go @@ -164,16 +164,16 @@ func CcrFollowerShow(conf *cfg.Config, index string) error { table := printer.NewTable(conf, 2, 9) table.Addheaders("ccr follower property", "value") - table.Entries = [][]string{ + table.Entries = [][]any{ {"name", index}, {"remote_cluster", follower.RemoteCluster}, - {"leader_checkpoint", fmt.Sprintf("%d", follower.LeaderGlobalCheckpoint)}, - {"follower_checkpoint", fmt.Sprintf("%d", follower.FollowerGlobalCheckpoint)}, - {"bytes_read", fmt.Sprintf("%d", follower.BytesRead)}, - {"failed_read_requests", fmt.Sprintf("%d", follower.FailedReadRequests)}, - {"failed_write_requests", fmt.Sprintf("%d", follower.FailedWriteRequests)}, - {"successful_read_requests", fmt.Sprintf("%d", follower.SuccessfulReadRequests)}, - {"successful_write_requests", fmt.Sprintf("%d", follower.SuccessfulWriteRequests)}, + {"leader_checkpoint", follower.LeaderGlobalCheckpoint}, + {"follower_checkpoint", follower.FollowerGlobalCheckpoint}, + {"bytes_read", follower.BytesRead}, + {"failed_read_requests", follower.FailedReadRequests}, + {"failed_write_requests", follower.FailedWriteRequests}, + {"successful_read_requests", follower.SuccessfulReadRequests}, + {"successful_write_requests", follower.SuccessfulWriteRequests}, } if err := table.Print(); err != nil { diff --git a/pkg/es/cluster.go b/pkg/es/cluster.go index 8895e50..ac8904b 100644 --- a/pkg/es/cluster.go +++ b/pkg/es/cluster.go @@ -81,7 +81,7 @@ func ClusterList(conf *cfg.Config) error { } } - table.Entries[idx] = []string{name, cluster.Uri, reachableStr, current, errmsg} + table.Entries[idx] = []any{name, cluster.Uri, reachableStr, current, errmsg} idx++ } @@ -190,25 +190,25 @@ func ClusterStatus(conf *cfg.Config) error { table := printer.NewTable(conf, 2, 7) table.Addheaders(conf.DefaultCluster.Name, "status") - table.Entries = [][]string{ + table.Entries = [][]any{ {"Cluster Name", res.health.ClusterName}, {"ES Status", printer.Colorize(conf, res.health.Status.Name, res.health.Status.Name)}, {"ES Version", res.info.Version.Int}, - {"Is Leader", fmt.Sprintf("%t", isleader)}, - {"Active Shards", fmt.Sprintf("%d", res.health.ActiveShards)}, - {"Active Primary Shards", fmt.Sprintf("%d", res.health.ActivePrimaryShards)}, - {"Unassigned Shards", fmt.Sprintf("%d", res.health.UnassignedShards)}, - {"Unassigned Primary Shards", fmt.Sprintf("%d", res.health.UnassignedPrimaryShards)}, - {"Pending Tasks", fmt.Sprintf("%d", res.health.NumberOfPendingTasks)}, - {"Nodes", fmt.Sprintf("%d", res.health.NumberOfNodes)}, - {"Red Indices", fmt.Sprintf("%d", redindices)}, - {"Long Running Tasks", fmt.Sprintf("%d", longtasks)}, + {"Is Leader", isleader}, + {"Active Shards", res.health.ActiveShards}, + {"Active Primary Shards", res.health.ActivePrimaryShards}, + {"Unassigned Shards", res.health.UnassignedShards}, + {"Unassigned Primary Shards", res.health.UnassignedPrimaryShards}, + {"Pending Tasks", res.health.NumberOfPendingTasks}, + {"Nodes", res.health.NumberOfNodes}, + {"Red Indices", redindices}, + {"Long Running Tasks", longtasks}, } if !isleader && res.ccr != nil { - table.Entries = append(table.Entries, [][]string{ + table.Entries = append(table.Entries, [][]any{ {"AutoFollow (success/failed indices)", ccrfollowing}, - {"Followed Indices", fmt.Sprintf("%d", len(res.ccr.FollowStats.Indices))}, + {"Followed Indices", len(res.ccr.FollowStats.Indices)}, }...) } @@ -219,15 +219,15 @@ func ClusterStatus(conf *cfg.Config) error { if res.health.Status.Name != "green" { for name, indicator := range res.healthreport.Indicators { if indicator.Status != "green" { - table.Entries = append(table.Entries, []string{ + table.Entries = append(table.Entries, []any{ printer.Colorize(conf, indicator.Status, "Bad health "+name), indicator.Symptom, }) for _, diag := range indicator.Diagnosis { - table.Entries = append(table.Entries, []string{" -> cause", diag.Cause}) + table.Entries = append(table.Entries, []any{" -> cause", diag.Cause}) for resource, items := range diag.AffectedResources { - table.Entries = append(table.Entries, []string{" -> affected " + resource, strings.Join(items, ",")}) + table.Entries = append(table.Entries, []any{" -> affected " + resource, strings.Join(items, ",")}) } } } @@ -255,13 +255,13 @@ func gatherClusterStats(conf *cfg.Config, clusterstats *clusterstats.Response, t clusterstats.Nodes.Jvm.Versions[0].VmVersion}, " ") } - table.Entries = append(table.Entries, [][]string{ - {"Indicies", fmt.Sprintf("%d", clusterstats.Indices.Count)}, - {"Docs", fmt.Sprintf("%d", clusterstats.Indices.Docs.Count)}, - {"Total Size", humanize.Bytes(uint64(clusterstats.Indices.Docs.TotalSizeInBytes))}, - {"Total Queries", fmt.Sprintf("%d", querycount)}, - {"Shards Primaries", fmt.Sprintf("%d", clusterstats.Indices.Shards.Primaries)}, - {"Shards Total", fmt.Sprintf("%d", clusterstats.Indices.Shards.Total)}, + table.Entries = append(table.Entries, [][]any{ + {"Indicies", clusterstats.Indices.Count}, + {"Docs", clusterstats.Indices.Docs.Count}, + {"Total Size", printer.Bytes(clusterstats.Indices.Docs.TotalSizeInBytes)}, + {"Total Queries", "%d", querycount}, + {"Shards Primaries", clusterstats.Indices.Shards.Primaries}, + {"Shards Total", clusterstats.Indices.Shards.Total}, {"Storage", fmt.Sprintf( "%s/%s", humanize.Bytes(uint64(clusterstats.Indices.Store.SizeInBytes)), @@ -272,11 +272,11 @@ func gatherClusterStats(conf *cfg.Config, clusterstats *clusterstats.Response, t humanize.Bytes(uint64(clusterstats.Nodes.Jvm.Mem.HeapUsedInBytes)), humanize.Bytes(uint64(clusterstats.Nodes.Jvm.Mem.HeapMaxInBytes)), )}, - {"JVM Threads", fmt.Sprintf("%d", clusterstats.Nodes.Jvm.Threads)}, + {"JVM Threads", clusterstats.Nodes.Jvm.Threads}, {"JVM Version", vmversion}, - {"CPUs", fmt.Sprintf("%d", clusterstats.Nodes.Os.AllocatedProcessors)}, + {"CPUs", clusterstats.Nodes.Os.AllocatedProcessors}, {"CPU Usage", fmt.Sprintf("%d%%", clusterstats.Nodes.Process.Cpu.Percent)}, - {"Open FDs", fmt.Sprintf("%d", clusterstats.Nodes.Process.OpenFileDescriptors.Avg)}, + {"Open FDs", clusterstats.Nodes.Process.OpenFileDescriptors.Avg}, }...) return table diff --git a/pkg/es/cluster_settings.go b/pkg/es/cluster_settings.go index e2a1d77..8941221 100644 --- a/pkg/es/cluster_settings.go +++ b/pkg/es/cluster_settings.go @@ -40,7 +40,7 @@ func ClusterSettingsList(conf *cfg.Config) error { table := printer.NewTable(conf, 2, 0) table.Addheaders("setting", "value") - entries := [][]string{} + entries := [][]any{} settingshash := res.Persistent // == map[string]json.RawMessage @@ -52,7 +52,7 @@ func ClusterSettingsList(conf *cfg.Config) error { } for topic, val := range settingshash { - entries = append(entries, []string{topic, string(val)}) + entries = append(entries, []any{topic, string(val)}) } table.Entries = entries diff --git a/pkg/es/cluster_util.go b/pkg/es/cluster_util.go index 8800c92..e72115e 100644 --- a/pkg/es/cluster_util.go +++ b/pkg/es/cluster_util.go @@ -72,27 +72,27 @@ func checkClusterStatus(conf *cfg.Config, leader, follower string) bool { table.Addheaders("setting", "leader:"+leader, "follower:"+follower) - table.Entries = [][]string{ + table.Entries = [][]any{ {"Cluster Name", status[leader].ClusterName, status[follower].ClusterName}, {"Cluster Status", printer.Colorize(conf, status[leader].Status.Name, status[leader].Status.Name), printer.Colorize(conf, status[follower].Status.Name, status[follower].Status.Name), }, {"Active Shards", - fmt.Sprintf("%d", status[leader].ActiveShards), - fmt.Sprintf("%d", status[follower].ActiveShards), + status[leader].ActiveShards, + status[follower].ActiveShards, }, {"Active Primary Shards", - fmt.Sprintf("%d", status[leader].ActivePrimaryShards), - fmt.Sprintf("%d", status[follower].ActivePrimaryShards), + status[leader].ActivePrimaryShards, + status[follower].ActivePrimaryShards, }, {"Indicies", - fmt.Sprintf("%d", len(status[leader].Indices)), - fmt.Sprintf("%d", len(status[follower].Indices)), + len(status[leader].Indices), + len(status[follower].Indices), }, {"Nodes", - fmt.Sprintf("%d", status[leader].NumberOfNodes), - fmt.Sprintf("%d", status[follower].NumberOfNodes), + status[leader].NumberOfNodes, + status[follower].NumberOfNodes, }, } @@ -112,7 +112,7 @@ func checkClusterStatus(conf *cfg.Config, leader, follower string) bool { // finds indices on both clusters which have ilm errors func findIlmErrors(conf *cfg.Config, leader, follower string) bool { - failed := map[string]map[string]string{} + failed := map[string]map[string]any{} for _, cluster := range []string{leader, follower} { ilm, err := conf.Clusters[cluster].ES().Ilm.ExplainLifecycle("_all"). @@ -123,13 +123,13 @@ func findIlmErrors(conf *cfg.Config, leader, follower string) bool { return false } - failed[cluster] = map[string]string{} + failed[cluster] = map[string]any{} for name, ilmstate := range ilm.Indices { count := ilmstate.(*types.LifecycleExplainManaged).FailedStepRetryCount if count != nil && *count > 0 { - failed[cluster][name] = fmt.Sprintf("%d", *count) + failed[cluster][name] = *count } } } @@ -150,7 +150,7 @@ func findIlmErrors(conf *cfg.Config, leader, follower string) bool { table.Addheaders("ilm errors on "+which, "errors") for name, count := range failed[cluster] { - table.Entries[idx] = []string{name, count} + table.Entries[idx] = []any{name, count} idx++ } @@ -222,7 +222,7 @@ func findIndicesOnlyOnLeader(conf *cfg.Config, indices ClusterIndices, leader, f for name, index := range indexOnlyOnLeader { name := printer.Colorize(conf, "red", name) - table.Entries[idx] = []string{name, *index.DatasetSize, *index.DocsCount} + table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} idx++ } @@ -270,7 +270,7 @@ func findOrphanedIndices(conf *cfg.Config, indices ClusterIndices, leader, follo for name, index := range orphaned { name := printer.Colorize(conf, "red", name) - table.Entries[idx] = []string{name, *index.DatasetSize, *index.DocsCount} + table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} idx++ } @@ -304,7 +304,7 @@ func findFailedFollowerIndices(conf *cfg.Config, indices ClusterIndices, followe for name, index := range red { name := printer.Colorize(conf, "red", name) - table.Entries[idx] = []string{name, *index.DatasetSize, *index.DocsCount} + table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} idx++ } diff --git a/pkg/es/datastream.go b/pkg/es/datastream.go index a0a1a83..78b1e18 100644 --- a/pkg/es/datastream.go +++ b/pkg/es/datastream.go @@ -25,7 +25,6 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" - "github.com/dustin/go-humanize" "github.com/elastic/go-elasticsearch/v9/typedapi/types" ) @@ -73,13 +72,13 @@ func DatastreamList(conf *cfg.Config) error { policy = *ds.IlmPolicy } - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ name, policy, - fmt.Sprintf("%t", ds.Hidden), - fmt.Sprintf("%t", *ds.System), - fmt.Sprintf("%t", *ds.Replicated), - fmt.Sprintf("%d", ds.Generation), + ds.Hidden, + *ds.System, + *ds.Replicated, + ds.Generation, ds.TimestampField.Name, } @@ -156,18 +155,18 @@ func DatastreamShow(conf *cfg.Config, dsname string) error { policy = *ds.IlmPolicy } - table.Entries = [][]string{ + table.Entries = [][]any{ {"name", name}, {"ilm policy", policy}, - {"hidden", fmt.Sprintf("%t", ds.Hidden)}, - {"system", fmt.Sprintf("%t", *ds.System)}, - {"replicated", fmt.Sprintf("%t", *ds.Replicated)}, - {"generation", fmt.Sprintf("%d", ds.Generation)}, + {"hidden", ds.Hidden}, + {"system", *ds.System}, + {"replicated", *ds.Replicated}, + {"generation", ds.Generation}, {"timestamp field", ds.TimestampField.Name}, - {"backing indices", fmt.Sprintf("%d", stats.BackingIndices)}, - {"size", humanize.Bytes(uint64(stats.TotalStoreSizeBytes))}, - {"shards-failed", fmt.Sprintf("%d", stats.Shards_.Failed)}, - {"shards-successful", fmt.Sprintf("%d", stats.Shards_.Successful)}, + {"backing indices", stats.BackingIndices}, + {"size", printer.Bytes(stats.TotalStoreSizeBytes)}, + {"shards-failed", stats.Shards_.Failed}, + {"shards-successful", stats.Shards_.Successful}, } if err := table.Print(); err != nil { @@ -183,10 +182,10 @@ func DatastreamShow(conf *cfg.Config, dsname string) error { policy = *ds.IlmPolicy } - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ index.IndexName, index.IndexUuid, - fmt.Sprintf("%t", *index.PreferIlm), + *index.PreferIlm, policy, index.ManagedBy.Name, } @@ -235,10 +234,10 @@ func DatastreamRollover(conf *cfg.Config, ds string) error { table := printer.NewTable(conf, 2, 5) table.Addheaders("rollover response", "value") - table.Entries = [][]string{ - {"acknowledged", fmt.Sprintf("%t", res.Acknowledged)}, - {"rolled over", fmt.Sprintf("%t", res.RolledOver)}, - {"shards acknowledged", fmt.Sprintf("%t", res.ShardsAcknowledged)}, + table.Entries = [][]any{ + {"acknowledged", res.Acknowledged}, + {"rolled over", res.RolledOver}, + {"shards acknowledged", res.ShardsAcknowledged}, {"old index", res.OldIndex}, {"new index", res.NewIndex}, } diff --git a/pkg/es/ilm.go b/pkg/es/ilm.go index b0fbd08..e82067d 100644 --- a/pkg/es/ilm.go +++ b/pkg/es/ilm.go @@ -129,7 +129,7 @@ func IlmShow(conf *cfg.Config, policy string) error { table := printer.NewTable(conf, 2, 5) table.Addheaders("ilm policy setting", "value") - table.Entries = [][]string{ + table.Entries = [][]any{ {"policy", policy}, {"hot phase", ilmPhaseString(ilm.Policy.Phases.Hot, false)}, {"warm phase", ilmPhaseString(ilm.Policy.Phases.Warm, false)}, @@ -291,17 +291,17 @@ func IlmExplain(conf *cfg.Config, index string) error { return fmt.Errorf("failed to unmarshal step info: %w", err) } - table.Entries = [][]string{ + table.Entries = [][]any{ {"index", ilm.Index}, {"ilm policy", *ilm.Policy}, {"action", *ilm.Action}, - {"age", fmt.Sprintf("%s", ilm.Age)}, - {"managed", fmt.Sprintf("%t", ilm.Managed)}, + {"age", ilm.Age}, + {"managed", ilm.Managed}, {"phase", *ilm.Phase}, {"phase execution", ilmPhaseString(ilm.PhaseExecution.PhaseDefinition, false)}, {"step", *ilm.Step}, {"failed step", *ilm.FailedStep}, - {"failed step retry count", fmt.Sprintf("%d", ilm.FailedStepRetryCount)}, + {"failed step retry count", ilm.FailedStepRetryCount}, } if err := table.Print(); err != nil { diff --git a/pkg/es/ilm_forecast.go b/pkg/es/ilm_forecast.go index 569bf2d..63d9faa 100644 --- a/pkg/es/ilm_forecast.go +++ b/pkg/es/ilm_forecast.go @@ -119,13 +119,13 @@ func IlmForecastList(conf *cfg.Config, filter string) error { virtualAge := virtualAge(&phase) - row := []string{ + row := []any{ phase.index, - humanize.Bytes(uint64(phase.size)), + printer.Bytes(phase.size), formatDuration(phase.age), formatDuration(virtualAge), formatDuration(phase.minage), - humanize.Bytes(uint64(phase.minsize)), + printer.Bytes(phase.minsize), phase.currentPhase, phase.nextPhase, } diff --git a/pkg/es/index.go b/pkg/es/index.go index be8a6d4..2d16ef6 100644 --- a/pkg/es/index.go +++ b/pkg/es/index.go @@ -118,7 +118,7 @@ func IndexList(conf *cfg.Config) error { for idx, index := range list { name := printer.Colorize(conf, *index.Health, *index.Index) - table.Entries[idx] = []string{name, *index.DatasetSize, *index.DocsCount} + table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} if idx == size-1 { break @@ -156,18 +156,18 @@ func IndexShow(conf *cfg.Config, indexpattern string) error { created := time.Unix(ts/1000, 0) - table.Entries = [][]string{ + table.Entries = [][]any{ {"name", name}, {"replicas", *index.Settings.Index.NumberOfReplicas}, {"shards", *index.Settings.Index.NumberOfShards}, - {"created", created.Format("2006-01-02 15:04:05")}, + {"created", created}, {"uuid", *index.Settings.Index.Uuid}, {"version", *index.Settings.Index.Version.Created}, - {"fields", strings.Join(fields, ",")}, + {"fields", fields}, } if index.Settings.Index.Lifecycle != nil { - table.Entries = append(table.Entries, [][]string{ + table.Entries = append(table.Entries, [][]any{ {"ilm policy", *index.Settings.Index.Lifecycle.Name}, {"ilm rollover alias", *index.Settings.Index.Lifecycle.RolloverAlias}, }...) @@ -283,14 +283,14 @@ func IndexAllocation(conf *cfg.Config, index string) error { roles[idx] = role.Name } - table.Entries = [][]string{ + table.Entries = [][]any{ {"Index", index}, {"Current node", currentNode.Name}, {"Current k8s node", currentNode.Attributes["k8s_node_name"]}, {"Current node address", currentNode.TransportAddress}, {"Current node id", currentNode.Id}, - {"Current node weight", fmt.Sprintf("%d", currentNode.WeightRanking)}, - {"Current node roles", strings.Join(roles, ",")}, + {"Current node weight", currentNode.WeightRanking}, + {"Current node roles", roles}, {"Can rebalance cluster", res.CanRebalanceCluster.Name}, {"Can rebalance to another node", res.CanRebalanceToOtherNode.Name}, {"Can remain on current node", res.CanRemainOnCurrentNode.Name}, @@ -344,10 +344,11 @@ func IndexFields(conf *cfg.Config, index string) error { continue } - table.Entries = append(table.Entries, []string{name, fieldtype, - fmt.Sprintf("%t", caps.Searchable), - fmt.Sprintf("%t", caps.Aggregatable), - fmt.Sprintf("%t", *caps.MetadataField)}) + table.AddRow(name, fieldtype, + caps.Searchable, + caps.Aggregatable, + *caps.MetadataField) + break } diff --git a/pkg/es/index_alias.go b/pkg/es/index_alias.go index 0f0f49c..0745488 100644 --- a/pkg/es/index_alias.go +++ b/pkg/es/index_alias.go @@ -78,7 +78,7 @@ func IndexAliasList(conf *cfg.Config) error { idx := 0 for index, aliases := range aliaslist { - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ index, strings.Join(aliases, ","), } @@ -117,10 +117,10 @@ func IndexAliasRollover(conf *cfg.Config, alias string) error { table := printer.NewTable(conf, 2, 5) table.Addheaders("rollover response", "value") - table.Entries = [][]string{ - {"acknowledged", fmt.Sprintf("%t", res.Acknowledged)}, - {"rolled over", fmt.Sprintf("%t", res.RolledOver)}, - {"shards acknowledged", fmt.Sprintf("%t", res.ShardsAcknowledged)}, + table.Entries = [][]any{ + {"acknowledged", res.Acknowledged}, + {"rolled over", res.RolledOver}, + {"shards acknowledged", res.ShardsAcknowledged}, {"old index", res.OldIndex}, {"new index", res.NewIndex}, } diff --git a/pkg/es/index_template.go b/pkg/es/index_template.go index 85fcaa7..55a546f 100644 --- a/pkg/es/index_template.go +++ b/pkg/es/index_template.go @@ -51,11 +51,7 @@ func IndexTemplateList(conf *cfg.Config) error { return fmt.Errorf("failed to unmarshal meta json data: %w", err) } - table.Entries[idx] = []string{ - tpl.Name, - string(desc), - fmt.Sprintf("%d", tpl.IndexTemplate.Priority), - } + table.Entries[idx] = []any{tpl.Name, desc, tpl.IndexTemplate.Priority} } table.Sort() @@ -94,13 +90,13 @@ func IndexTemplateShow(conf *cfg.Config, tplname string) error { aliases = append(aliases, alias) } - table.Entries = [][]string{ + table.Entries = [][]any{ {"name", tpl.Name}, - {"description", string(desc)}, - {"index patterns", strings.Join(tpl.IndexTemplate.IndexPatterns, ",")}, - {"composed of", strings.Join(tpl.IndexTemplate.ComposedOf, ",")}, - {"data stream enabled", fmt.Sprintf("%t", hasds)}, - {"aliases", strings.Join(aliases, ",")}, + {"description", desc}, + {"index patterns", tpl.IndexTemplate.IndexPatterns}, + {"composed of", tpl.IndexTemplate.ComposedOf}, + {"data stream enabled", hasds}, + {"aliases", aliases}, } if err := table.Print(); err != nil { @@ -136,9 +132,7 @@ func IndexTemplateShow(conf *cfg.Config, tplname string) error { typeval = val.Type } - table.Entries = append(table.Entries, []string{ - name, typeval, - }) + table.AddRow(name, typeval) } fmt.Println() @@ -414,12 +408,7 @@ func rolloverAliasIndexTemplate(conf *cfg.Config, name string) error { return err } - table.Entries = append(table.Entries, []string{ - alias, - fmt.Sprintf("%t", res.RolledOver), - fmt.Sprintf("%t", res.Acknowledged), - res.NewIndex, - }) + table.AddRow(alias, res.RolledOver, res.Acknowledged, res.NewIndex) if err := table.Print(); err != nil { return err diff --git a/pkg/es/index_template_settings.go b/pkg/es/index_template_settings.go index 92df17c..d28da25 100644 --- a/pkg/es/index_template_settings.go +++ b/pkg/es/index_template_settings.go @@ -52,7 +52,7 @@ func getIndexTemplateSettings(conf *cfg.Config, tplname string, table *printer.T tpl := data.IndexTemplates[0].IndexTemplate.Template.Settings for topic, val := range tpl { - table.Entries = append(table.Entries, []string{topic, fmt.Sprintf("%v", val)}) + table.AddRow(topic, val) } return nil diff --git a/pkg/es/license.go b/pkg/es/license.go index 1d8eb63..cf74e1f 100644 --- a/pkg/es/license.go +++ b/pkg/es/license.go @@ -54,11 +54,11 @@ func LicenseShow(conf *cfg.Config) error { maxunits = fmt.Sprintf("%d", *lic.MaxResourceUnits) } - table.Entries = [][]string{ + table.Entries = [][]any{ {"UID", lic.Uid}, {"Issued to", lic.IssuedTo}, {"Expires", expire}, - {"Issued", lic.IssueDate.(string)}, + {"Issued", lic.IssueDate}, {"Max nodes", maxnodes}, {"Max resource units", maxunits}, {"Type", lic.Type.Name}, diff --git a/pkg/es/node.go b/pkg/es/node.go index d9874b8..bfa930c 100644 --- a/pkg/es/node.go +++ b/pkg/es/node.go @@ -41,14 +41,14 @@ func NodeList(conf *cfg.Config) error { table.Addheaders("name", "ip", "load1m", "load5m", "load15m", "ram %", "heap %") for idx, node := range nodes { - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ *node.Name, *node.Ip, *node.Load1M, *node.Load5M, *node.Load15M, - node.RamPercent.(string), - node.HeapPercent.(string), + node.RamPercent, + node.HeapPercent, } } @@ -113,25 +113,25 @@ func NodeShow(conf *cfg.Config, nodename string) error { k8snode := info.Attributes["k8s_node_name"] - table.Entries = [][]string{ + table.Entries = [][]any{ {"Id", id}, {"Name", nodename}, {"Kubernetes node", k8snode}, {"Ip address", info.Ip}, {"Node rank", *stat.AdaptiveSelection[id].Rank}, {"JVM", info.Jvm.VmName + " " + info.Jvm.Version}, - {"JVM Started", time.UnixMilli(info.Jvm.StartTimeInMillis).String()}, + {"JVM Started", time.UnixMilli(info.Jvm.StartTimeInMillis)}, {"OS", info.Os.PrettyName + " " + info.Os.Version}, - {"Node roles", strings.Join(roles, ",")}, + {"Node roles", roles}, {"Node version", info.Version}, - {"HTTP clients", fmt.Sprintf("%d", *stat.Http.CurrentOpen)}, - {"CPUs", fmt.Sprintf("%d", *info.Os.AllocatedProcessors)}, + {"HTTP clients", *stat.Http.CurrentOpen}, + {"CPUs", *info.Os.AllocatedProcessors}, {"Load 15m/5m/1m", fmt.Sprintf("%.2f/%.2f/%.2f", stat.Os.Cpu.LoadAverage["15m"], stat.Os.Cpu.LoadAverage["5m"], stat.Os.Cpu.LoadAverage["1m"], )}, - {"Open FD's", fmt.Sprintf("%d", *stat.Process.OpenFileDescriptors)}, + {"Open FD's", *stat.Process.OpenFileDescriptors}, {"Response time avg", fmt.Sprintf("%dns", *stat.AdaptiveSelection[id].AvgResponseTimeNs)}, {"Memory usage (used/avail)", humanize.Bytes(uint64(*stat.Os.Mem.UsedInBytes)) + " / " + humanize.Bytes(uint64(*stat.Os.Mem.TotalInBytes))}, @@ -139,7 +139,7 @@ func NodeShow(conf *cfg.Config, nodename string) error { if len(stat.Fs.Data) > 0 { fs := stat.Fs.Data[0] - table.Entries = append(table.Entries, [][]string{ + table.Entries = append(table.Entries, [][]any{ {"Storage usage (used/avail)", humanize.Bytes(uint64(*fs.AvailableInBytes)) + " / " + humanize.Bytes(uint64(*fs.TotalInBytes))}, {"Storage mount", *fs.Mount}, diff --git a/pkg/es/role.go b/pkg/es/role.go index ffff478..357e1c1 100644 --- a/pkg/es/role.go +++ b/pkg/es/role.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "log/slog" - "strings" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" @@ -58,10 +57,10 @@ func RoleList(conf *cfg.Config) error { idx := 0 for name, role := range res { - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ name, - fmt.Sprintf("%d", len(role.Cluster)), - fmt.Sprintf("%d", len(role.Indices)), + role.Cluster, + role.Indices, } idx++ } @@ -140,10 +139,8 @@ func roleRemoteClusters(conf *cfg.Config, role types.Role) error { perms = append(perms, perm.Name) } - table.Entries[idx] = []string{ - strings.Join(priv.Clusters, ","), - strings.Join(perms, ","), - } + table.Entries[idx] = []any{priv.Clusters, perms} + idx++ } @@ -160,7 +157,7 @@ func roleClusters(conf *cfg.Config, role types.Role) error { table.Addheaders("cluster rights") idx := 0 for _, cluster := range role.Cluster { - table.Entries[idx] = []string{cluster.Name} + table.Entries[idx] = []any{cluster.Name} idx++ } @@ -182,11 +179,7 @@ func roleRemoteIndices(conf *cfg.Config, role types.Role) error { perms = append(perms, perm.Name) } - table.Entries[idx] = []string{ - strings.Join(priv.Names, ", "), - strings.Join(perms, ", "), - fmt.Sprintf("%t", *priv.AllowRestrictedIndices), - } + table.Entries[idx] = []any{priv.Names, perms, *priv.AllowRestrictedIndices} idx++ } @@ -209,11 +202,7 @@ func roleIndices(conf *cfg.Config, role types.Role) error { perms = append(perms, perm.Name) } - table.Entries[idx] = []string{ - strings.Join(priv.Names, ", "), - strings.Join(perms, ", "), - fmt.Sprintf("%t", *priv.AllowRestrictedIndices), - } + table.Entries[idx] = []any{priv.Names, perms, *priv.AllowRestrictedIndices} idx++ } @@ -231,10 +220,10 @@ func roleApplications(conf *cfg.Config, role types.Role) error { table.Addheaders("application", "privileges", "resources") idx := 0 for _, priv := range role.Applications { - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ priv.Application, - strings.Join(priv.Privileges, ", "), - strings.Join(priv.Resources, ", "), + priv.Privileges, + priv.Resources, } idx++ diff --git a/pkg/es/role_diff.go b/pkg/es/role_diff.go index bb5898c..838a5a8 100644 --- a/pkg/es/role_diff.go +++ b/pkg/es/role_diff.go @@ -229,7 +229,7 @@ func RoleDiff(conf *cfg.Config, csvfile, role string) error { defined = printer.Colorize(conf, "red", "undefined") } - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ row.name, deployed, defined, diff --git a/pkg/es/shard.go b/pkg/es/shard.go index 24395fa..2e6de38 100644 --- a/pkg/es/shard.go +++ b/pkg/es/shard.go @@ -107,7 +107,7 @@ func printShards(conf *cfg.Config, shardlist shards.Response) error { for idx, shard := range shardlist { name := colorzizeShard(conf, *shard.State, *shard.Index) - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ name, *shard.Shard, resolvePrirep(*shard.Prirep), diff --git a/pkg/es/snapshot.go b/pkg/es/snapshot.go index 2ef680c..b7144b9 100644 --- a/pkg/es/snapshot.go +++ b/pkg/es/snapshot.go @@ -88,7 +88,7 @@ func SnapshotList(conf *cfg.Config) error { table.Addheaders("name", "index", "start", "orphaned", "status") for idx, snap := range snapshots { - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ snap.Name, snap.Forindex, snap.Start, @@ -122,20 +122,20 @@ func SnapshotShow(conf *cfg.Config, snapshot string) error { snap := res.Snapshots[0] - table.Entries = [][]string{ + table.Entries = [][]any{ {"snapshot", snapshot}, {"uuid", snap.Uuid}, {"repository", *snap.Repository}, - {"version_id", fmt.Sprintf("%d", snap.VersionId)}, + {"version_id", snap.VersionId}, {"version", *snap.Version}, - {"include_global_state", fmt.Sprintf("%t", *snap.IncludeGlobalState)}, + {"include_global_state", *snap.IncludeGlobalState}, {"state", *snap.State}, - {"start_time", fmt.Sprintf("%s", snap.StartTime)}, - {"end_time", fmt.Sprintf("%s", snap.EndTime)}, - {"duration_in_millis", fmt.Sprintf("%d", *snap.DurationInMillis)}, - {"shards-total", fmt.Sprintf("%d", snap.Shards.Total)}, - {"shards-failed", fmt.Sprintf("%d", snap.Shards.Failed)}, - {"shards-successful", fmt.Sprintf("%d", snap.Shards.Successful)}, + {"start_time", snap.StartTime}, + {"end_time", snap.EndTime}, + {"duration_in_millis", *snap.DurationInMillis}, + {"shards-total", snap.Shards.Total}, + {"shards-failed", snap.Shards.Failed}, + {"shards-successful", snap.Shards.Successful}, } if err := table.Print(); err != nil { diff --git a/pkg/es/task.go b/pkg/es/task.go index 640bdb6..ebba906 100644 --- a/pkg/es/task.go +++ b/pkg/es/task.go @@ -49,10 +49,10 @@ func TaskList(conf *cfg.Config) error { ts = time.Unix(int64(epc/1000), 0) } - table.Entries[idx] = []string{ + table.Entries[idx] = []any{ *task.TaskId, *task.Action, - ts.Format("2006-01-02T15:04:05"), + ts, *task.RunningTime, *task.Node, *task.Type, diff --git a/pkg/printer/bytes.go b/pkg/printer/bytes.go new file mode 100644 index 0000000..cae3c58 --- /dev/null +++ b/pkg/printer/bytes.go @@ -0,0 +1,31 @@ +/* +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 printer + +import "github.com/dustin/go-humanize" + +type ByteSize struct { + size uint64 +} + +func Bytes(size int64) ByteSize { + return ByteSize{size: uint64(size)} +} + +func (b *ByteSize) String() string { + return humanize.Bytes(b.size) +} diff --git a/pkg/printer/cast.go b/pkg/printer/cast.go new file mode 100644 index 0000000..40ad367 --- /dev/null +++ b/pkg/printer/cast.go @@ -0,0 +1,97 @@ +/* +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 printer + +import ( + "fmt" + "strconv" + "strings" + "time" + + "github.com/elastic/go-elasticsearch/v9/typedapi/types" +) + +func any2string(in any) string { + switch val := in.(type) { + case string: + return val + case bool: + return strconv.FormatBool(val) + case int64: + return strconv.FormatInt(val, 10) + case int: + return strconv.Itoa(val) + case float64: + return fmt.Sprintf("%.2f", val) + case []string: + return strings.Join(val, ",") + case ByteSize: + return val.String() + case time.Time: + return val.Format("2006-01-02 15:04:05") + case []byte: + return string(val) + case types.DateTime, types.Percentage: + return val.(string) + case nil: + return "null" + } + + return "" +} + +func (data *Table) preprocessRows() { + if data.processed { + // only do it once + return + } + + // convert entries to strings + data.rows = make([][]string, len(data.Entries)) + for rowidx, entries := range data.Entries { + data.rows[rowidx] = make([]string, len(entries)) + + for colidx, entry := range data.Entries[rowidx] { + data.rows[rowidx][colidx] = any2string(entry) + } + } + + // determine header lenght's + for idx, head := range data.Headers { + data.lenHeaders[idx] = visibleLen(head) + } + + // determine max width per column + for _, entries := range data.rows { + currentWidth := 0 + for idx, entry := range entries { + length := visibleLen(entry) + + if data.lenHeaders[idx] < length { + if length > currentWidth+data.maxwidth { + data.lenHeaders[idx] = data.maxwidth - currentWidth + } else { + data.lenHeaders[idx] = length + } + } + + currentWidth += data.lenHeaders[idx] + } + } + + data.processed = true +} diff --git a/pkg/printer/table.go b/pkg/printer/table.go index 363c97f..26020a2 100644 --- a/pkg/printer/table.go +++ b/pkg/printer/table.go @@ -25,18 +25,17 @@ import ( "strings" "codeberg.org/scip/esctl/pkg/cfg" - "github.com/olekukonko/tablewriter" - "github.com/olekukonko/tablewriter/renderer" - "github.com/olekukonko/tablewriter/tw" "github.com/seeruk/go-wordwrap" "gopkg.in/yaml.v3" ) type Table struct { - Mode string // table, markdown, json + Mode string // tsv, json, yaml Headers []string - Entries [][]string + Entries [][]any + rows [][]string // representation used for printing + processed bool lenHeaders []int alignInts bool maxwidth int @@ -46,7 +45,7 @@ func NewTable(conf *cfg.Config, columns, rows int) *Table { table := Table{Mode: conf.Output, maxwidth: cfg.GetTermWidth()} table.Headers = make([]string, columns) - table.Entries = make([][]string, rows) + table.Entries = make([][]any, rows) table.lenHeaders = make([]int, columns) table.alignInts = conf.AlignInts @@ -62,7 +61,7 @@ func NewTableEmpty(conf *cfg.Config) *Table { func (table *Table) WithHeaders(headers ...string) *Table { count := len(headers) - table.Entries = [][]string{} + table.Entries = [][]any{} table.lenHeaders = make([]int, count) table.Headers = make([]string, count) @@ -73,8 +72,6 @@ func (table *Table) WithHeaders(headers ...string) *Table { func (data *Table) Print() error { switch data.Mode { - case "markdown", "md": - return data.PrintMarkdown() case "json": return data.PrintJSON() case "yaml": @@ -89,11 +86,11 @@ var ( ) // needed for json and yaml output -func (data *Table) toMap() []map[string]string { - raw := make([]map[string]string, len(data.Entries)) +func (data *Table) toMap() []map[string]any { + raw := make([]map[string]any, len(data.Entries)) for idx, entries := range data.Entries { - raw[idx] = make(map[string]string, len(data.Headers)) + raw[idx] = make(map[string]any, len(data.Headers)) for eidx, entry := range entries { raw[idx][data.Headers[eidx]] = entry } @@ -128,31 +125,9 @@ func (data *Table) PrintJSON() error { return nil } -// Well. tablewriter should be able to print in TSV mode, but it -// doesn't work because of the various ansic color escapes we're -// using. Therefore we do it the hard way and use our own TSV printer. func (data *Table) PrintTSV() error { - // determine lenght's - for idx, head := range data.Headers { - data.lenHeaders[idx] = visibleLen(head) - } - - for _, entries := range data.Entries { - currentWidth := 0 - for idx, entry := range entries { - length := visibleLen(entry) - - if data.lenHeaders[idx] < length { - if length > currentWidth+data.maxwidth { - data.lenHeaders[idx] = data.maxwidth - currentWidth - } else { - data.lenHeaders[idx] = length - } - } - - currentWidth += data.lenHeaders[idx] - } - } + // length's, convert cell types + data.preprocessRows() // output headers for idx, header := range data.Headers { @@ -169,7 +144,7 @@ func (data *Table) PrintTSV() error { } fmt.Println() - for _, entries := range data.Entries { + for _, entries := range data.rows { currentWidth := 0 for idx, entry := range entries { @@ -213,130 +188,16 @@ func (data *Table) PrintTSV() error { return nil } -func (data *Table) PrintTabularFail() error { - OFS := " " - - tableString := &strings.Builder{} - - styleTSV := tw.NewSymbolCustom("space").WithColumn("\t") - - table := tablewriter.NewTable(tableString, - tablewriter.WithRenderer( - renderer.NewBlueprint(tw.Rendition{ - Borders: tw.BorderNone, - Symbols: styleTSV, - Settings: tw.Settings{ - Separators: tw.SeparatorsNone, - Lines: tw.LinesNone, - }, - })), - tablewriter.WithConfig(tablewriter.Config{ - Header: tw.CellConfig{ - Formatting: tw.CellFormatting{ - AutoFormat: tw.Off, - }, - Padding: tw.CellPadding{Global: tw.Padding{Left: "", Right: OFS}}, - }, - Row: tw.CellConfig{ - Formatting: tw.CellFormatting{ - AutoWrap: tw.WrapNone, - Alignment: tw.AlignLeft, - }, - Padding: tw.CellPadding{Global: tw.Padding{Right: OFS}}, - }, - - Debug: true, - }), - ) - - table.Header(data.Headers) - - if err := table.Bulk(data.Entries); err != nil { - return fmt.Errorf("failed to add data to table renderer: %s", err) - } - - if err := table.Render(); err != nil { - return fmt.Errorf("failed to render table: %s", err) - } - - // we need to trim our output here, because tablewriter appends - // excess whitespace to our rows. - cleanedString := &strings.Builder{} - - for _, row := range strings.Split(strings.TrimSpace(tableString.String()), "\n") { - cleanedString.WriteString(strings.TrimSpace(row)) - cleanedString.WriteString("\n") - } - - fmt.Println(cleanedString.String()) - - return nil -} - -func (data *Table) PrintMarkdown() error { - tableString := &strings.Builder{} - - table := tablewriter.NewTable(tableString, - tablewriter.WithRenderer( - renderer.NewBlueprint( - tw.Rendition{ - Borders: tw.Border{ - Left: tw.On, - Right: tw.On, - Top: tw.Off, - Bottom: tw.Off, - }, - Settings: tw.Settings{ - Separators: tw.Separators{ - ShowHeader: tw.On, - ShowFooter: tw.Off, - BetweenRows: tw.Off, - BetweenColumns: 0, - }, - }, - Symbols: tw.NewSymbols(tw.StyleMarkdown), - })), - - tablewriter.WithConfig( - tablewriter.Config{ - Header: tw.CellConfig{ - Formatting: tw.CellFormatting{ - Alignment: tw.AlignLeft, - AutoFormat: tw.Off, - }, - }, - Row: tw.CellConfig{ - Formatting: tw.CellFormatting{ - Alignment: tw.AlignLeft, - }, - }, - }, - ), - ) - - table.Header(data.Headers) - - if err := table.Bulk(data.Entries); err != nil { - return fmt.Errorf("failed to add data to table renderer: %s", err) - } - - if err := table.Render(); err != nil { - return fmt.Errorf("failed to render table: %s", err) - } - - fmt.Println(tableString.String()) - - return nil -} - func (data *Table) Sort() { // sanity checks if len(data.Entries) == 0 { return } - sort.Slice(data.Entries, func(i, j int) bool { - return data.Entries[i][0] < data.Entries[j][0] + data.preprocessRows() + + sort.Slice(data.rows, func(i, j int) bool { + return data.rows[i][0] < data.rows[j][0] }) } @@ -351,7 +212,7 @@ func (data *Table) Addheaders(headers ...string) { } } -func (data *Table) AddRow(fields ...string) { +func (data *Table) AddRow(fields ...any) { data.Entries = append(data.Entries, fields) }