mirror of
https://codeberg.org/scip/esctl.git
synced 2026-08-24 04:54:18 +02:00
enhanced default cluster selection, add 'cluster switch', overhaul json header setting (#47)
This commit is contained in:
@@ -17,25 +17,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"github.com/alecthomas/repr"
|
||||
"github.com/elastic/elastic-transport-go/v8/elastictransport"
|
||||
"github.com/elastic/go-elasticsearch/v9"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
Version string = `v0.0.20`
|
||||
Version string = `v0.0.21`
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -43,11 +36,6 @@ var (
|
||||
APIVERSION, GOVERSION, BUILD, COMMIT, BRANCH string
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
Uri, User, Pass string
|
||||
ES *elasticsearch.TypedClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ConfigFile string // -c
|
||||
CurrentCluster string // -C
|
||||
@@ -119,8 +107,12 @@ func NewConfig() *Config {
|
||||
return &Config{Clusters: map[string]*Cluster{}}
|
||||
}
|
||||
|
||||
func getDefaultPath() string {
|
||||
return filepath.Join([]string{os.Getenv("HOME"), ".config", "esctl", "config.yaml"}...)
|
||||
}
|
||||
|
||||
func (conf *Config) Init() error {
|
||||
DefaultConfig := os.Getenv("HOME") + "/.config/esctl/config.yaml"
|
||||
DefaultConfig := getDefaultPath()
|
||||
|
||||
switch {
|
||||
case fileExists(DefaultConfig):
|
||||
@@ -141,29 +133,35 @@ func (conf *Config) Init() error {
|
||||
}
|
||||
|
||||
if conf.CurrentCluster != "" {
|
||||
// -C specified, set current cluster explicitly, no matter what the config says
|
||||
current, exists := conf.Clusters[conf.CurrentCluster]
|
||||
if !exists {
|
||||
return fmt.Errorf("no cluster with alias %s configured", conf.CurrentCluster)
|
||||
} else {
|
||||
conf.DefaultCluster = current
|
||||
|
||||
// disable all others
|
||||
for _, cluster := range conf.Clusters {
|
||||
cluster.Default = false
|
||||
}
|
||||
|
||||
conf.DefaultCluster.Default = true
|
||||
}
|
||||
} else {
|
||||
// we need to determine ourselfes
|
||||
if len(conf.Clusters) == 1 {
|
||||
// ok, just one cluster configured, use this, of course
|
||||
for name, cluster := range conf.Clusters {
|
||||
conf.DefaultCluster = cluster
|
||||
conf.CurrentCluster = name
|
||||
conf.DefaultCluster.Default = true
|
||||
}
|
||||
} else {
|
||||
// multiple ones exists, look if one is set as default
|
||||
for name, cluster := range conf.Clusters {
|
||||
_, err := cluster.ES.Cluster.Health().
|
||||
Header("content-type", "application/json").
|
||||
Header("accept", "application/json").
|
||||
Do(context.Background())
|
||||
|
||||
if err == nil {
|
||||
if cluster.Default {
|
||||
conf.DefaultCluster = cluster
|
||||
conf.CurrentCluster = name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,86 +248,21 @@ func (conf *Config) LoadConfig() error {
|
||||
if len(newconf.Clusters) > 0 {
|
||||
conf.Clusters = newconf.Clusters
|
||||
|
||||
_, exists := conf.Clusters["default"]
|
||||
if !exists {
|
||||
// no "default", just use the first we stumble upon
|
||||
for _, cluster := range conf.Clusters {
|
||||
for _, cluster := range conf.Clusters {
|
||||
if cluster.Default {
|
||||
conf.DefaultCluster = cluster
|
||||
break
|
||||
}
|
||||
} else {
|
||||
conf.DefaultCluster = newconf.Clusters["default"]
|
||||
}
|
||||
|
||||
if conf.DefaultCluster == nil {
|
||||
conf.DefaultCluster = &Cluster{}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (conf *Config) getTransport() elastictransport.Option {
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
|
||||
if conf.DebugHTTP {
|
||||
return elastictransport.WithTransport(
|
||||
&DebugTransport{Transport: transport},
|
||||
)
|
||||
}
|
||||
|
||||
return elastictransport.WithTransport(transport)
|
||||
}
|
||||
|
||||
func (conf *Config) SetupES() error {
|
||||
for _, cluster := range conf.Clusters {
|
||||
es, err := elasticsearch.NewTyped(
|
||||
elasticsearch.WithAddresses(cluster.Uri),
|
||||
elasticsearch.WithBasicAuth(cluster.User, cluster.Pass),
|
||||
elasticsearch.WithTransportOptions(conf.getTransport()),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setup elasticsearch connection: %w", err)
|
||||
}
|
||||
|
||||
cluster.ES = es
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// used to print uri, path and body of a request made by the go-client
|
||||
type DebugTransport struct {
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *DebugTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
content := ""
|
||||
contentline := ""
|
||||
|
||||
if req.ContentLength > 0 {
|
||||
buf := new(bytes.Buffer)
|
||||
body, _ := req.GetBody()
|
||||
|
||||
_, err := buf.ReadFrom(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pretty bytes.Buffer
|
||||
err = json.Indent(&pretty, buf.Bytes(), "", "\t")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("json parse error: %s", err)
|
||||
}
|
||||
|
||||
content = pretty.String()
|
||||
contentline = buf.String()
|
||||
}
|
||||
|
||||
slog.Info("req", "host", req.URL.Host, "uri", req.URL.Path, "body", content, "bodyline", contentline)
|
||||
|
||||
return t.Transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user