package elastic import ( "context" "crypto/tls" "fmt" "github.com/loveuer/nf/nft/log" es "github.com/olivere/elastic/v7" "github.com/spf13/cast" "net/http" "net/url" "strings" "time" ) var ( Client *es.Client ) const ( ExampleUri = "https://username:password@ip1:9200,ip2:9200?disable_sniff=false&health=false" ) func New(ctx context.Context, uri string) (*es.Client, error) { var ( err error ins *url.URL client *es.Client version string ) if ins, err = url.Parse(uri); err != nil { return nil, fmt.Errorf("invalid uri: %v\nexample uri: %s", err, ExampleUri) } if !(ins.Scheme == "http" || ins.Scheme == "https") { return nil, fmt.Errorf("invalid uri scheme: %v\nexample uri: %s", err, ExampleUri) } hosts := strings.Split(ins.Host, ",") if len(hosts) == 0 { return nil, fmt.Errorf("invalid uri hosts: %v\nexample uri: %s", err, ExampleUri) } opts := make([]es.ClientOptionFunc, 0) shouldHosts := make([]string, 0) oks := make([]string, 0) bads := make([]string, 0) for idx := range hosts { if len(hosts[idx]) == 0 { continue } opts = append(opts, es.SetURL(hosts[idx])) shouldHosts = append(shouldHosts, hosts[idx]) } if len(opts) == 0 { return nil, fmt.Errorf("invalid uri hosts: %v\nexample uri: %s", err, ExampleUri) } if ins.Scheme == "https" { opts = append(opts, es.SetScheme("https")) opts = append(opts, es.SetHttpClient( &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, }, )) } if ins.User != nil { username := ins.User.Username() password, _ := ins.User.Password() opts = append(opts, es.SetBasicAuth(username, password)) } if cast.ToBool(ins.Query().Get("disable_sniff")) { opts = append(opts, es.SetSniff(false)) } if cast.ToBool(ins.Query().Get("health")) { opts = append(opts, es.SetHealthcheckInterval(time.Minute)) opts = append(opts, es.SetHealthcheckTimeout(5*time.Second)) } else { opts = append(opts, es.SetHealthcheck(false)) } client, err = es.NewClient(opts...) for idx := range shouldHosts { if version, err = client.ElasticsearchVersion(shouldHosts[idx]); err != nil { bads = append(bads, shouldHosts[idx]) continue } oks = append(oks, shouldHosts[idx]) } switch len(oks) { case 0: return nil, fmt.Errorf("all nodes: %+v unavailable", shouldHosts) case len(shouldHosts): log.Info("connect to elastic[version: %s] success, all nodes: %+v available", version, shouldHosts) default: log.Warn("connect to elastic all nodes: %+v, err nodes: %v", shouldHosts, bads) } return client, err } func Init(ctx context.Context, uri string) (err error) { Client, err = New(ctx, uri) return err }