diff --git a/.gitignore b/.gitignore index 5b90e79..444ce48 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ go.work.sum # env file .env +esctl diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..719e4ae --- /dev/null +++ b/Makefile @@ -0,0 +1,87 @@ +# 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 . + +# +# no need to modify anything below +tool = esctl +VERSION = $(shell grep VERSION config.go | head -1 | cut -d '"' -f2) +archs = darwin freebsd linux windows +PREFIX = /usr/local +UID = root +GID = 0 +HAVE_POD := $(shell pod2text -h 2>/dev/null) + +all: buildlocal + + +buildlocal: + CGO_LDFLAGS='-static' go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o $(tool) + strip $(tool) + +install: buildlocal + install -d -o $(UID) -g $(GID) $(PREFIX)/bin + install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1 + install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/ + install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/ + +clean: + rm -rf $(tool) coverage.out testdata t/out + +test: clean + mkdir -p t/out + go test ./... $(ARGS) + +testlint: test lint + +lint: + golangci-lint run + +lint-full: + golangci-lint run --enable-all --exclude-use-default --disable exhaustivestruct,exhaustruct,depguard,interfacer,deadcode,golint,structcheck,scopelint,varcheck,ifshort,maligned,nosnakecase,godot,funlen,gofumpt,cyclop,noctx,gochecknoglobals,paralleltest + +testfuzzy: clean + go test -fuzz ./... $(ARGS) + +singletest: + @echo "Call like this: make singletest TEST=TestPrepareColumns ARGS=-v" + go test -run $(TEST) $(ARGS) + +cover-report: + go test ./... -cover -coverprofile=coverage.out + go tool cover -html=coverage.out + +goupdate: + go get -t -u=patch ./... + +buildall: + ./mkrel.sh $(tool) $(VERSION) + +release: + gh release create v$(VERSION) --generate-notes + +show-versions: buildlocal + @echo "### esctl version:" + @./gfn -V + + @echo + @echo "### go module versions:" + @go list -m all + + @echo + @echo "### go version used for building:" + @grep -m 1 go go.mod + +# lint: +# golangci-lint run -p bugs -p unused diff --git a/README.md b/README.md index 04e234b..9189e98 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,99 @@ # esctl -Elasticsearch CLI \ No newline at end of file +Elasticsearch CLI + +## Usage + +```console +NAME: + esctl - manage elasticsearch from cli + +USAGE: + esctl [global options] [command [command options]] + +VERSION: + v0.0.1 + +COMMANDS: + health show ES health + search, / search within an index + help, h Shows a list of commands or help for one command + +GLOBAL OPTIONS: + --debug, -d enable debugging [$ES_DEBUG] + --help, -h show help + --version, -v print the version +``` + +Configure `esctl` with environment variables: + +- `ES_URI`: elasticsearch uri +- `ES_USER`: username +- `ES_PASS`: password + +## Introduction + +FIXME + +## Installation + +The tool does not have any dependencies. Just download the binary for +your platform from the releases page and you're good to go. + +### Installation using a pre-compiled binary + +You can use [stew](https://github.com/marwanhawari/stew) to install esctl: +```default +stew install https://codeberg.org/scip/esctl +``` + +Or go to the [latest release page](https://codeberg.org/scip/esctl/releases/) +and look for your OS and platform. There are two options to install the binary: + +Directly download the binary for your platform, +e.g. `esctl-linux-amd64-0.0.2`, rename it to `esctl` (or whatever +you like more!) and put it into your bin dir (e.g. `$HOME/bin` or as +root to `/usr/local/bin`). + +Be sure to verify the signature of the binary file. For this also +download the matching `esctl-linux-amd64-0.0.2.sha256` file and: + +```shell +cat esctl-linux-amd64-0.0.2.sha25 && sha256sum esctl-linux-amd64-0.0.2 +``` +You should see the same SHA256 hash. + +You may also download a binary tarball for your platform, e.g. +`esctl-linux-amd64-0.0.2.tar.gz`, unpack and install it. GNU Make is +required for this: + +```shell +tar xvfz esctl-linux-amd64-0.0.2.tar.gz +cd esctl-linux-amd64-0.0.2 +sudo make install +``` + +### Installation from source + +Check out the repository and execute `go build`, then copy the +compiled binary to your `$PATH`. + +Or, if you have GNU Make installed, just execute: + +```default +make +sudo make install +``` + +# Report bugs + +[Please open an issue](https://codeberg.org/scip/esctl/issues). Thanks! + +# License + +This work is licensed under the terms of the General Public Licens +version 3. + +# Author + +Copyleft (c) 2026 Thomas von Dein diff --git a/cmd/health.go b/cmd/health.go new file mode 100644 index 0000000..a82dc7d --- /dev/null +++ b/cmd/health.go @@ -0,0 +1,41 @@ +/* +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 Health(conf *cfg.Config) *cli.Command { + return &cli.Command{ + Name: "health", + Usage: "show ES health", + 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 new file mode 100644 index 0000000..f66f6c9 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,74 @@ +/* +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" + "fmt" + "os" + + "codeberg.org/scip/esctl/pkg/cfg" + "codeberg.org/scip/esctl/pkg/log" + + "github.com/urfave/cli/v3" +) + +func Finish(err error) int { + if err != nil { + fmt.Fprintln(os.Stderr, "Error: ", err.Error()) + return 1 + } + + return 0 +} + +func Main() int { + conf, err := cfg.Init() + if err != nil { + return Finish(err) + } + + cmd := &cli.Command{ + Name: "esctl", + Usage: "manage elasticsearch from cli", + Version: cfg.Version, + EnableShellCompletion: true, + + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "debug", + Aliases: []string{"d"}, + Value: false, + Usage: "enable debugging", + Sources: cli.EnvVars("ES_DEBUG"), + Destination: &conf.Debug, + }, + }, + + Commands: []*cli.Command{ + Health(conf), + Search(conf), + }, + + Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) { + log.Init(conf) + return nil, nil + }, + } + + return Finish(cmd.Run(context.Background(), os.Args)) +} diff --git a/cmd/search.go b/cmd/search.go new file mode 100644 index 0000000..0bfc3d2 --- /dev/null +++ b/cmd/search.go @@ -0,0 +1,72 @@ +/* +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 Search(conf *cfg.Config) *cli.Command { + return &cli.Command{ + Name: "search", + Aliases: []string{"/"}, + Usage: "search within an index", + UsageText: "search [options] ", + + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "index", + Usage: "index to search within", + Sources: cli.EnvVars("ES_INDEX"), + Destination: &conf.Index, + }, + &cli.IntFlag{ + Name: "from", + Usage: "show results FROM (default 0)", + Destination: &conf.From, + Value: 0, + Aliases: []string{"f"}, + }, + &cli.IntFlag{ + Name: "to", + Usage: "show results to (default 10)", + Destination: &conf.To, + Value: 10, + Aliases: []string{"t"}, + }, + &cli.StringSliceFlag{ + Name: "filter", + Usage: "additional filters. format: key=value", + Destination: &conf.Filter, + Aliases: []string{"F"}, + }, + }, + + Action: func(ctx context.Context, cmd *cli.Command) error { + if err := es.Search(conf, cmd.Args().Get(0)); err != nil { + return err + } + + return nil + }, + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d1f0f75 --- /dev/null +++ b/go.mod @@ -0,0 +1,37 @@ +// 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 . +module codeberg.org/scip/esctl + +go 1.24 + +require ( + github.com/alecthomas/repr v0.5.2 // indirect + github.com/elastic/elastic-transport-go/v8 v8.11.0 // indirect + github.com/elastic/go-elasticsearch/v9 v9.3.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/lmittmann/tint v1.1.3 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect + github.com/tlinden/yadu v0.1.3 // indirect + github.com/urfave/cli/v3 v3.8.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + 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/sys v0.28.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2306ef2 --- /dev/null +++ b/go.sum @@ -0,0 +1,40 @@ +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/elastic/elastic-transport-go/v8 v8.9.0 h1:KeT/2P54F0xS0S8Y3Pf+tFDg4HmBgReQMB+BMz8dDAs= +github.com/elastic/elastic-transport-go/v8 v8.9.0/go.mod h1:ssMTvNS2hwf7CaiGsRRsx4gQHFZ/jS/DkLcISxekWzc= +github.com/elastic/elastic-transport-go/v8 v8.11.0 h1:taYmqC2M6+fZt/+W+ENYh/W5L9+KrlJGOSbEJs8egWc= +github.com/elastic/elastic-transport-go/v8 v8.11.0/go.mod h1:DZQ0szCNywc9F+C9l/Kkd4n69SvJVj0I3yK1Of7s3l8= +github.com/elastic/go-elasticsearch/v9 v9.3.2 h1:nvtvfN/Gsp/rzUPz/9yILwDAsYJ3s5L0VmhR16zPKCA= +github.com/elastic/go-elasticsearch/v9 v9.3.2/go.mod h1:ubKUMJCJbX5V/gW5MIn2NQZyaEZ61ubXwJmD5UMNrM8= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/lmittmann/tint v1.1.3 h1:Hv4EaHWXQr+GTFnOU4VKf8UvAtZgn0VuKT+G0wFlO3I= +github.com/lmittmann/tint v1.1.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +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.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI= +github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +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/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= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..222b8a9 --- /dev/null +++ b/main.go @@ -0,0 +1,27 @@ +/* +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 main + +import ( + "os" + + "codeberg.org/scip/esctl/cmd" +) + +func main() { + os.Exit(cmd.Main()) +} diff --git a/pkg/cfg/config.go b/pkg/cfg/config.go new file mode 100644 index 0000000..e21a6ba --- /dev/null +++ b/pkg/cfg/config.go @@ -0,0 +1,73 @@ +/* +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 cfg + +import ( + "crypto/tls" + "errors" + "net/http" + "os" + + "github.com/elastic/elastic-transport-go/v8/elastictransport" + "github.com/elastic/go-elasticsearch/v9" +) + +const ( + Version string = `v0.0.1` +) + +type Config struct { + Uri, User, Pass string + ES *elasticsearch.TypedClient + Debug bool + From, To int + Index string + Filter []string +} + +func Init() (*Config, error) { + cfg := Config{ + Uri: os.Getenv("ES_URI"), + User: os.Getenv("ES_USER"), + Pass: os.Getenv("ES_PASS"), + } + + switch { + case cfg.Uri == "": + return nil, errors.New("ES_URI unset") + case cfg.User == "": + return nil, errors.New("ES_USER unset") + case cfg.Pass == "": + return nil, errors.New("ES_PASS unset") + } + + es, _ := elasticsearch.NewTyped( + elasticsearch.WithAddresses(cfg.Uri), + elasticsearch.WithBasicAuth(cfg.User, cfg.Pass), + elasticsearch.WithTransportOptions( + elastictransport.WithTransport( + &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + ), + ), + ) + + cfg.ES = es + + return &cfg, nil +} diff --git a/pkg/es/aux.go b/pkg/es/aux.go new file mode 100644 index 0000000..05fe721 --- /dev/null +++ b/pkg/es/aux.go @@ -0,0 +1,36 @@ +/* +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" + "log" + "log/slog" + + "codeberg.org/scip/esctl/pkg/cfg" +) + +func Health(conf *cfg.Config) error { + res, err := conf.ES.Cluster.Health().Do(context.Background()) + if err != nil { + log.Fatalf("Error getting health: %s", err) + } + + slog.Info("ES result", "cluster health", res) + + return nil +} diff --git a/pkg/es/search.go b/pkg/es/search.go new file mode 100644 index 0000000..fe7b76b --- /dev/null +++ b/pkg/es/search.go @@ -0,0 +1,72 @@ +/* +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" + "strings" + + "codeberg.org/scip/esctl/pkg/cfg" + "github.com/elastic/go-elasticsearch/v9/typedapi/core/search" + "github.com/elastic/go-elasticsearch/v9/typedapi/esdsl" + "github.com/elastic/go-elasticsearch/v9/typedapi/types" +) + +/* +Execute an ES search. + + q is the actual search query given as arg to the 'search' cmd + additional filters can be given as -F key=value +*/ +func Search(conf *cfg.Config, q string) error { + query := esdsl.NewBoolQuery(). + Must(esdsl.NewMatchQuery("message", q)) + + filters := make([]types.QueryVariant, len(conf.Filter)) + + for idx, filter := range conf.Filter { + parts := strings.Split(filter, "=") + if len(parts) != 2 { + return fmt.Errorf("invalid filter spec: %s, expecting key=value", filter) + } + + filters[idx] = esdsl.NewTermQuery(parts[0], esdsl.NewFieldValue().String(parts[1])) + } + + if len(filters) > 0 { + query.Filter(filters...) + } + + res, err := conf.ES.Search(). + Index(conf.Index). + Request(&search.Request{ + Query: query.QueryCaster(), + From: &conf.From, + Size: &conf.To, + }). + Do(context.Background()) + if err != nil { + return fmt.Errorf("Error running search (esdsl): %s", err) + } + + for _, hit := range res.Hits.Hits { + fmt.Printf("%s\n", hit.Source_) + } + + return nil +} diff --git a/pkg/log/logger.go b/pkg/log/logger.go new file mode 100644 index 0000000..c65791f --- /dev/null +++ b/pkg/log/logger.go @@ -0,0 +1,59 @@ +/* +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 log + +import ( + "log/slog" + "os" + "runtime/debug" + + "codeberg.org/scip/esctl/pkg/cfg" + "github.com/mattn/go-isatty" + "github.com/tlinden/yadu" +) + +const LevelNotice = slog.Level(2) + +func Init(conf *cfg.Config) { + logLevel := &slog.LevelVar{} + + opts := &yadu.Options{ + Level: logLevel, + AddSource: true, + NoColor: !isatty.IsTerminal(os.Stdout.Fd()), + } + + buildInfo, _ := debug.ReadBuildInfo() + + handler := yadu.NewHandler(os.Stdout, opts) + debuglogger := slog.New(handler).With( + slog.Group("program_info", + slog.String("version", cfg.Version), + slog.String("go_version", buildInfo.GoVersion), + ), + ) + + slog.SetDefault(debuglogger) + + switch conf.Debug { + case true: + logLevel.Set(slog.LevelDebug) + + default: + logLevel.Set(slog.LevelInfo) + } +}