initial commit

This commit is contained in:
2026-04-21 10:50:09 +02:00
parent dbf1d3601a
commit 2b21fa0e7e
13 changed files with 716 additions and 1 deletions

73
pkg/cfg/config.go Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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
}

36
pkg/es/aux.go Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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
}

72
pkg/es/search.go Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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
}

59
pkg/log/logger.go Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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)
}
}