diff --git a/.golangci.yml b/.golangci.yml index 688152a..53f9569 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,9 +15,7 @@ linters: - canonicalheader - clickhouselint - containedctx - #- contextcheck - copyloopvar - #- cyclop - decorder - dogsled - dupword @@ -25,25 +23,19 @@ linters: - embeddedstructfieldcheck - errchkjson - errname - #- errorlint - exhaustive - exptostd - fatcontext - funcorder - #- funlen - ginkgolinter - gocheckcompilerdirectives - gochecknoinits - gochecksumtype - #- gocognit - gocritic - #- gocyclo - #- godoclint - goheader - gomoddirectives - gomodguard_v2 - goprintffuncname - #- gosec - gosmopolitan - grouper - iface @@ -58,7 +50,6 @@ linters: - misspell - modernize - nakedret - #- nestif - nilerr - nilnesserr - nlreturn @@ -67,12 +58,10 @@ linters: - paralleltest - perfsprint - prealloc - #- predeclared - promlinter - protogetter - reassign - recvcheck - #- revive - rowserrcheck - sloglint - spancheck @@ -107,4 +96,5 @@ linters: - fd - id - fn + - ds diff --git a/cmd/completion.go b/cmd/completion.go index 50a74ce..dba4323 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -24,6 +24,7 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/es" + "github.com/samber/lo" "github.com/urfave/cli/v3" ) @@ -55,9 +56,7 @@ func complete(conf *cfg.Config, cmd *cli.Command, what int) { case Crole: list, err = es.RoleNames(conf) case Ccluster: - for cluster := range conf.Clusters { - list = append(list, cluster) - } + list = lo.Keys(conf.Clusters) case Cdatastream: list, err = es.DatastreamNames(conf) case Capi: diff --git a/cmd/datastream.go b/cmd/datastream.go index 7f34b41..58dee5c 100644 --- a/cmd/datastream.go +++ b/cmd/datastream.go @@ -65,7 +65,7 @@ func DatastreamList(conf *cfg.Config) *cli.Command { }, &cli.StringSliceFlag{ Name: "filter", - Usage: "show only data streams matching the filter", + Usage: "show only data streams matching the filter regexp", Destination: &conf.Filter, Aliases: []string{"F"}, }, diff --git a/cmd/index.go b/cmd/index.go index fed99c9..4e4b4d6 100644 --- a/cmd/index.go +++ b/cmd/index.go @@ -86,7 +86,7 @@ func IndexList(conf *cfg.Config) *cli.Command { }, &cli.StringSliceFlag{ Name: "filter", - Usage: "show only indices matching the filter", + Usage: "show only indices matching the filter regexp", Destination: &conf.Filter, Aliases: []string{"F"}, }, @@ -239,10 +239,10 @@ func IndexFields(conf *cfg.Config) *cli.Command { Aliases: []string{"s"}, }, &cli.StringSliceFlag{ - Name: "type", - Usage: "show only fields of this type", + Name: "filter", + Usage: "show only fields matching this filter regexp.", Destination: &conf.Filter, - Aliases: []string{"t"}, + Aliases: []string{"F"}, }, }, diff --git a/cmd/roles.go b/cmd/roles.go index 88acb29..25332d2 100644 --- a/cmd/roles.go +++ b/cmd/roles.go @@ -52,7 +52,7 @@ func RoleList(conf *cfg.Config) *cli.Command { Name: "orphaned", Usage: "include only orphaned roles", Destination: &conf.Failed, - Aliases: []string{"o"}, + Aliases: []string{"O"}, }, }, diff --git a/go.mod b/go.mod index e87b72c..0b9c085 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ module codeberg.org/scip/esctl go 1.26 require ( - codeberg.org/scip/mapmap v0.0.2 github.com/MichaelMure/go-term-markdown v0.1.4 github.com/alecthomas/repr v0.5.3 github.com/charmbracelet/bubbles v1.0.0 @@ -32,6 +31,7 @@ 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/samber/lo v1.53.0 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 diff --git a/go.sum b/go.sum index 7f1e805..7638d1b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -codeberg.org/scip/mapmap v0.0.2 h1:0i61jOUwFmGVwPukrMzrx0Fi4T9Qru2nlmibuaJimBo= -codeberg.org/scip/mapmap v0.0.2/go.mod h1:/ojYo2P7dMA2FWEu+jHKmsKPeq5yDcCvXeHevqZd5OI= github.com/MichaelMure/go-term-markdown v0.1.4 h1:Ir3kBXDUtOX7dEv0EaQV8CNPpH+T7AfTh0eniMOtNcs= github.com/MichaelMure/go-term-markdown v0.1.4/go.mod h1:EhcA3+pKYnlUsxYKBJ5Sn1cTQmmBMjeNlpV8nRb+JxA= github.com/MichaelMure/go-term-text v0.3.1 h1:Kw9kZanyZWiCHOYu9v/8pWEgDQ6UVN9/ix2Vd2zzWf0= @@ -153,6 +151,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM= +github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/pkg/cfg/config.go b/pkg/cfg/config.go index 579282b..166031a 100644 --- a/pkg/cfg/config.go +++ b/pkg/cfg/config.go @@ -24,6 +24,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "time" "github.com/alecthomas/repr" @@ -79,16 +80,17 @@ type Config struct { Refresh bool // index copy: -r SourceIndices []string // index copy: -s - From, To, MaxItems int // search: flags - Filter []string // search: -F - Path string // search+doc sh: -p - Subhelp bool // search+doc sh: -H - Tail bool // search: -f [tail] - Or bool // search: -O - Range string // search: -r - TimestampFormat string // search: --timestamp-format - Explain bool // search: -e - Validate bool // search: --validate + From, To, MaxItems int // search: flags + Filter []string // search: -F + FilterRex []*regexp.Regexp // compiled .Filter + Path string // search+doc sh: -p + Subhelp bool // search+doc sh: -H + Tail bool // search: -f [tail] + Or bool // search: -O + Range string // search: -r + TimestampFormat string // search: --timestamp-format + Explain bool // search: -e + Validate bool // search: --validate SortBy string // sort: -k Ascending bool // sort: -a @@ -161,6 +163,8 @@ func (conf *Config) Init() error { return err } + conf.compileFilters() + conf.HaveJQ = isJQinstalled() conf.PrintDebug() @@ -303,6 +307,15 @@ func (conf *Config) determineDefaultCluster() error { return nil } +// compileFilters pre-compiles regexp filters +func (conf *Config) compileFilters() { + conf.FilterRex = make([]*regexp.Regexp, len(conf.Filter)) + + for i, f := range conf.Filter { + conf.FilterRex[i] = regexp.MustCompile(f) + } +} + func fileExists(filename string) bool { info, err := os.Stat(filename) if err != nil { diff --git a/pkg/es/cluster_util.go b/pkg/es/cluster_util.go index de7827c..8c8ff90 100644 --- a/pkg/es/cluster_util.go +++ b/pkg/es/cluster_util.go @@ -28,6 +28,7 @@ import ( "codeberg.org/scip/esctl/pkg/printer" "github.com/elastic/go-elasticsearch/v9/typedapi/cluster/health" "github.com/elastic/go-elasticsearch/v9/typedapi/types" + "github.com/samber/lo" ) const ( @@ -153,14 +154,12 @@ func findIlmErrors(conf *cfg.Config, leader, follower string) bool { } if len(failed[cluster]) > 0 { - idx := 0 table := printer.NewTable(conf).WithSize(2, len(failed[cluster])). WithHeaders("ilm errors on "+which, "errors") - for name, count := range failed[cluster] { - table.Entries[idx] = []any{name, count} - idx++ - } + table.Entries = lo.MapToSlice(failed[cluster], func(name string, count any) []any { + return []any{name, count} + }) table.Sort() @@ -227,16 +226,16 @@ func findIndicesOnlyOnLeader(conf *cfg.Config, indices ClusterIndices, leader, f return true } - idx := 0 table := printer.NewTable(conf).WithSize(3, len(indexOnlyOnLeader)). WithHeaders("index only on leader", "size", "docscount") - for name, index := range indexOnlyOnLeader { - name := printer.Colorize(conf, "red", name) - - table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} - idx++ - } + table.Entries = lo.MapToSlice(indexOnlyOnLeader, func(name string, index *types.IndicesRecord) []any { + return []any{ + printer.Colorize(conf, "red", name), + *index.DatasetSize, + *index.DocsCount, + } + }) table.Sort() @@ -277,16 +276,16 @@ func findOrphanedIndices(conf *cfg.Config, indices ClusterIndices, leader, follo return true } - idx := 0 table := printer.NewTable(conf).WithSize(3, len(orphaned)). WithHeaders("orphaned index on follower", "size", "docscount") - for name, index := range orphaned { - name := printer.Colorize(conf, "red", name) - - table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} - idx++ - } + table.Entries = lo.MapToSlice(orphaned, func(name string, index *types.IndicesRecord) []any { + return []any{ + printer.Colorize(conf, "red", name), + *index.DatasetSize, + *index.DocsCount, + } + }) table.Sort() @@ -313,16 +312,16 @@ func findFailedFollowerIndices(conf *cfg.Config, indices ClusterIndices, followe return true } - idx := 0 table := printer.NewTable(conf).WithSize(3, len(red)). WithHeaders("red index on follower", "size", "docscount") - for name, index := range red { - name := printer.Colorize(conf, "red", name) - - table.Entries[idx] = []any{name, *index.DatasetSize, *index.DocsCount} - idx++ - } + table.Entries = lo.MapToSlice(red, func(name string, index *types.IndicesRecord) []any { + return []any{ + printer.Colorize(conf, "red", name), + *index.DatasetSize, + *index.DocsCount, + } + }) table.Sort() diff --git a/pkg/es/datastream.go b/pkg/es/datastream.go index 7b27b79..e6a65a1 100644 --- a/pkg/es/datastream.go +++ b/pkg/es/datastream.go @@ -23,11 +23,11 @@ import ( "errors" "fmt" "log/slog" - "regexp" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" "github.com/elastic/go-elasticsearch/v9/typedapi/types" + "github.com/samber/lo" ) // DatastreamNames returns a list of datastream names for completion @@ -38,12 +38,9 @@ func DatastreamNames(conf *cfg.Config) ([]string, error) { return nil, fmt.Errorf("failed to get data streams: %w", esErrorString(err)) } - dss := make([]string, len(res.DataStreams)) - for idx, ds := range res.DataStreams { - dss[idx] = ds.Name - } - - return dss, nil + return lo.Map(res.DataStreams, func(d types.DataStream, _ int) string { + return d.Name + }), nil } // DatastreamList list datastreams @@ -228,29 +225,15 @@ func DatastreamRollover(conf *cfg.Config, ds string) error { // filterDatastreams return a filtered list of datastreams func filterDatastreams(conf *cfg.Config, list []types.DataStream) []types.DataStream { - selected := []types.DataStream{} - - for _, ds := range list { - if !conf.Hidden && ds.Hidden { - continue + return lo.Filter(list, func(ds types.DataStream, _ int) bool { + if ds.Hidden { + return conf.Hidden } - selected = append(selected, ds) - } - - if len(conf.Filter) == 0 { - return selected - } - - // we support just one filter here, for now - filter := *regexp.MustCompile(conf.Filter[0]) - newlist := []types.DataStream{} - - for _, ds := range selected { - if filter.MatchString(ds.Name) { - newlist = append(newlist, ds) + if len(conf.Filter) == 0 { + return true } - } - return newlist + return filterWithRex(conf, ds.Name) + }) } diff --git a/pkg/es/filter.go b/pkg/es/filter.go new file mode 100644 index 0000000..307362a --- /dev/null +++ b/pkg/es/filter.go @@ -0,0 +1,34 @@ +package es + +/* +Copyright © 2026 Finanz Informatik Technologie Service GmbH & Co KG +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 . +*/ + +import ( + "codeberg.org/scip/esctl/pkg/cfg" +) + +// filterWithRex returns true if ALL filters configured in conf.FilterRex match item. +func filterWithRex(conf *cfg.Config, item string) bool { + for _, r := range conf.FilterRex { + if !r.MatchString(item) { + return false + } + } + + return true +} diff --git a/pkg/es/index.go b/pkg/es/index.go index 2bebce4..5a0dfeb 100644 --- a/pkg/es/index.go +++ b/pkg/es/index.go @@ -24,20 +24,18 @@ import ( "errors" "fmt" "log/slog" - "regexp" - "slices" "strconv" "strings" "time" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" - "codeberg.org/scip/mapmap" "github.com/charmbracelet/lipgloss" "github.com/elastic/go-elasticsearch/v9/typedapi/cat/indices" "github.com/elastic/go-elasticsearch/v9/typedapi/esdsl" "github.com/elastic/go-elasticsearch/v9/typedapi/types" "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/healthstatus" + "github.com/samber/lo" ) // Diskusage stores disk usage details, since the API does not provide a struct for this @@ -65,12 +63,9 @@ func IndexNames(conf *cfg.Config) ([]string, error) { return nil, fmt.Errorf("failed to get indices: %w", esErrorString(err)) } - indices := make([]string, len(res)) - for idx, index := range res { - indices[idx] = *index.Index - } - - return indices, nil + return lo.Map(res, func(i types.IndicesRecord, _ int) string { + return *i.Index + }), nil } // IndexList lists indices @@ -127,13 +122,7 @@ func IndexShow(conf *cfg.Config, indexpattern string) error { slog.Debug("index show", "index", res) for name, index := range res { - fields := make([]string, len(index.Mappings.Properties)) - - idx := 0 - for field := range index.Mappings.Properties { - fields[idx] = field - idx++ - } + fields := lo.Keys(index.Mappings.Properties) table := printer.NewTable(conf).WithSize(2, 7). WithHeaders("index property", "value") @@ -275,7 +264,7 @@ func IndexFieldMappings(conf *cfg.Config, index string) error { continue case conf.Aggretable && !caps.Aggregatable: continue - case len(conf.Filter) > 0 && !slices.Contains(conf.Filter, fieldtype): + case len(conf.Filter) > 0 && !filterWithRex(conf, fieldtype): continue } @@ -362,13 +351,7 @@ func IndexDiskusage(conf *cfg.Config, index string) error { // filterIndices returns a filtered list of indices func filterIndices(conf *cfg.Config, list indices.Response) indices.Response { - var filter *regexp.Regexp - - if len(conf.Filter) > 0 { - filter = regexp.MustCompile(conf.Filter[0]) - } - - return mapmap.NewSlicer(list).MapSliceValuesImmutable(func(index types.IndicesRecord) bool { + return lo.Filter(list, func(index types.IndicesRecord, _ int) bool { if !conf.Partials && strings.HasPrefix(*index.Index, "partial-") { return false } @@ -377,12 +360,10 @@ func filterIndices(conf *cfg.Config, list indices.Response) indices.Response { return false } - if len(conf.Filter) > 0 { - if !filter.MatchString(*index.Index) { - return false - } + if len(conf.Filter) == 0 { + return true } - return true + return filterWithRex(conf, *index.Index) }) } diff --git a/pkg/es/index_alias.go b/pkg/es/index_alias.go index e9898ed..5709207 100644 --- a/pkg/es/index_alias.go +++ b/pkg/es/index_alias.go @@ -27,6 +27,7 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" + "github.com/samber/lo" ) // IndexAliasCreate create a new index alias @@ -79,15 +80,12 @@ func IndexAliasList(conf *cfg.Config) error { table := printer.NewTable(conf).WithSize(2, len(aliaslist)). WithHeaders("index", "alias") - idx := 0 - for index, aliases := range aliaslist { - table.Entries[idx] = []any{ + table.Entries = lo.MapToSlice(aliaslist, func(index string, aliases []string) []any { + return []any{ index, strings.Join(aliases, ","), } - - idx++ - } + }) table.Sort() diff --git a/pkg/es/index_template.go b/pkg/es/index_template.go index c3a203d..91375e7 100644 --- a/pkg/es/index_template.go +++ b/pkg/es/index_template.go @@ -30,9 +30,9 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" - "codeberg.org/scip/mapmap" "github.com/elastic/go-elasticsearch/v9/typedapi/esdsl" "github.com/elastic/go-elasticsearch/v9/typedapi/types" + "github.com/samber/lo" ) // IndexTemplateNames returns a list of index templates used for completion @@ -517,10 +517,10 @@ func modSettings(conf *cfg.Config) (map[string]json.RawMessage, error) { } // filterIndexTemplates filters index templates by name, index pattern -// or hidden flag, using mapmap.Slicer +// or hidden flag, using lo.Filter func filterIndexTemplates(conf *cfg.Config, nameFilter string, templates []types.IndexTemplateItem) []types.IndexTemplateItem { - return mapmap.NewSlicer(templates).MapSliceValuesImmutable(func(tpl types.IndexTemplateItem) bool { + return lo.Filter(templates, func(tpl types.IndexTemplateItem, _ int) bool { if !conf.Hidden && strings.HasPrefix(tpl.Name, ".") { return false } @@ -529,13 +529,15 @@ func filterIndexTemplates(conf *cfg.Config, nameFilter string, return false } - if len(conf.Filter) > 0 { - if !mapmap.NewSlicer(tpl.IndexTemplate.IndexPatterns). - FindSliceInSlice(conf.Filter, strings.Contains) { - return false - } + if len(conf.Filter) == 0 { + return true } - return true + return len( + lo.Filter( + tpl.IndexTemplate.IndexPatterns, + func(pattern string, _ int) bool { + return filterWithRex(conf, pattern) + })) > 0 }) } diff --git a/pkg/es/role.go b/pkg/es/role.go index 5abc1f0..e8e79a7 100644 --- a/pkg/es/role.go +++ b/pkg/es/role.go @@ -28,6 +28,10 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" "github.com/elastic/go-elasticsearch/v9/typedapi/types" + "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/clusterprivilege" + "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/indexprivilege" + "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/remoteclusterprivilege" + "github.com/samber/lo" ) // RoleNames returns a list of role names for completion @@ -54,15 +58,13 @@ func RoleList(conf *cfg.Config) error { table := printer.NewTable(conf).WithSize(3, len(res)). WithHeaders("role", "index roles", "cluster roles") - idx := 0 - for name, role := range res { - table.Entries[idx] = []any{ + table.Entries = lo.MapToSlice(res, func(name string, role types.Role) []any { + return []any{ name, role.Cluster, role.Indices, } - idx++ - } + }) table.Sort() @@ -134,18 +136,16 @@ func roleRemoteClusters(conf *cfg.Config, role types.Role) error { table := printer.NewTable(conf).WithSize(2, len(role.RemoteCluster)). WithHeaders("remote cluster", "privilege") - idx := 0 - - for _, priv := range role.RemoteCluster { - perms := []string{} - for _, perm := range priv.Privileges { - perms = append(perms, perm.Name) + table.Entries = lo.Map(role.RemoteCluster, func(priv types.RemoteClusterPrivileges, _ int) []any { + return []any{ + priv.Clusters, + lo.Map( + priv.Privileges, + func(perm remoteclusterprivilege.RemoteClusterPrivilege, _ int) string { + return perm.Name + }), } - - table.Entries[idx] = []any{priv.Clusters, perms} - - idx++ - } + }) table.Sort() @@ -161,11 +161,9 @@ func roleClusters(conf *cfg.Config, role types.Role) error { table := printer.NewTable(conf).WithSize(1, len(role.Cluster)). WithHeaders("cluster permissions") - idx := 0 - for _, cluster := range role.Cluster { - table.Entries[idx] = []any{cluster.Name} - idx++ - } + table.Entries = lo.Map(role.Cluster, func(cluster clusterprivilege.ClusterPrivilege, _ int) []any { + return []any{cluster.Name} + }) table.Sort() @@ -181,18 +179,17 @@ func roleRemoteIndices(conf *cfg.Config, role types.Role) error { table := printer.NewTable(conf).WithSize(3, len(role.RemoteIndices)). WithHeaders("remote index names", "index permissions", "allow restricted") - idx := 0 - - for _, priv := range role.RemoteIndices { - perms := []string{} - for _, perm := range priv.Privileges { - perms = append(perms, perm.Name) + table.Entries = lo.Map(role.RemoteIndices, func(priv types.RemoteIndicesPrivileges, _ int) []any { + return []any{ + priv.Names, + lo.Map( + priv.Privileges, + func(perm indexprivilege.IndexPrivilege, _ int) string { + return perm.Name + }), + *priv.AllowRestrictedIndices, } - - table.Entries[idx] = []any{priv.Names, perms, *priv.AllowRestrictedIndices} - - idx++ - } + }) table.Sort() @@ -208,18 +205,17 @@ func roleIndices(conf *cfg.Config, role types.Role) error { table := printer.NewTable(conf).WithSize(3, len(role.Indices)). WithHeaders("index names", "index permissions", "allow restricted") - idx := 0 - - for _, priv := range role.Indices { - perms := []string{} - for _, perm := range priv.Privileges { - perms = append(perms, perm.Name) + table.Entries = lo.Map(role.Indices, func(priv types.IndicesPrivileges, _ int) []any { + return []any{ + priv.Names, + lo.Map( + priv.Privileges, + func(perm indexprivilege.IndexPrivilege, _ int) string { + return perm.Name + }), + *priv.AllowRestrictedIndices, } - - table.Entries[idx] = []any{priv.Names, perms, *priv.AllowRestrictedIndices} - - idx++ - } + }) table.Sort() @@ -235,16 +231,13 @@ func roleApplications(conf *cfg.Config, role types.Role) error { table := printer.NewTable(conf).WithSize(3, len(role.Applications)). WithHeaders("application", "privileges", "resources") - idx := 0 - for _, priv := range role.Applications { - table.Entries[idx] = []any{ + table.Entries = lo.Map(role.Applications, func(priv types.ApplicationPrivileges, _ int) []any { + return []any{ priv.Application, priv.Privileges, priv.Resources, } - - idx++ - } + }) table.Sort() diff --git a/pkg/printer/cast.go b/pkg/printer/cast.go index a3386cf..95555e6 100644 --- a/pkg/printer/cast.go +++ b/pkg/printer/cast.go @@ -25,6 +25,8 @@ import ( "time" "github.com/elastic/go-elasticsearch/v9/typedapi/types" + "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/clusterprivilege" + "github.com/samber/lo" ) // stringer returns the string representation of different types of @@ -56,6 +58,14 @@ func stringer(cell any) string { return val.String() case []byte: return string(val) + case []clusterprivilege.ClusterPrivilege: + return strings.Join(lo.Map(val, func(p clusterprivilege.ClusterPrivilege, _ int) string { + return p.Name + }), ",") + case []types.IndicesPrivileges: + return strings.Join(lo.Map(val, func(p types.IndicesPrivileges, _ int) string { + return strings.Join(p.Names, "+") + }), ",") case nil: return "null" case *types.Float64: