Replace olivere/elastic with REST API client, add OpenSearch support (#37411)
Drops `github.com/olivere/elastic/v7` (unmaintained) and replaces it
with a small in-house wrapper that speaks the Elasticsearch REST API
directly via `net/http`. The subset used by Gitea (`_cluster/health`,
`_bulk`, `_doc`, `_delete_by_query`, `_refresh`, `_search`, `HEAD`/`PUT`
index) is stable across the targeted servers, so no client library is
needed.
**Targets tested**
- Elasticsearch 7, 8, 9
- OpenSearch 1, 2, 3
**Why not `go-elasticsearch`?**
The official client enforces an `X-Elastic-Product` server-identity
check that OpenSearch deliberately fails, which would force shipping a
transport shim to defeat it. Going direct over `net/http` removes that
fight along with several MB of transitive deps (`elastic-transport-go`,
`go.opentelemetry.io/otel{,/metric,/trace}`, `auto/sdk`, `easyjson`,
`intern`, `logr`, `stdr`).
Replaces: #30755
Fixes: https://github.com/go-gitea/gitea/issues/30752
---
This PR was written with the help of Claude Opus 4.7
---------
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
@@ -6,14 +6,11 @@ package elasticsearch
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/olivere/elastic/v7"
|
||||
)
|
||||
|
||||
// VersionedIndexName returns the full index name with version
|
||||
// VersionedIndexName returns the full index name with version suffix.
|
||||
func (i *Indexer) VersionedIndexName() string {
|
||||
return versionedIndexName(i.indexName, i.version)
|
||||
}
|
||||
@@ -26,41 +23,10 @@ func versionedIndexName(indexName string, version int) string {
|
||||
return fmt.Sprintf("%s.v%d", indexName, version)
|
||||
}
|
||||
|
||||
func (i *Indexer) createIndex(ctx context.Context) error {
|
||||
createIndex, err := i.Client.CreateIndex(i.VersionedIndexName()).BodyString(i.mapping).Do(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !createIndex.Acknowledged {
|
||||
return fmt.Errorf("create index %s with %s failed", i.VersionedIndexName(), i.mapping)
|
||||
}
|
||||
|
||||
i.checkOldIndexes(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Indexer) initClient() (*elastic.Client, error) {
|
||||
opts := []elastic.ClientOptionFunc{
|
||||
elastic.SetURL(i.url),
|
||||
elastic.SetSniff(false),
|
||||
elastic.SetHealthcheckInterval(10 * time.Second),
|
||||
elastic.SetGzip(false),
|
||||
}
|
||||
|
||||
logger := log.GetLogger(log.DEFAULT)
|
||||
|
||||
opts = append(opts, elastic.SetTraceLog(&log.PrintfLogger{Logf: logger.Trace}))
|
||||
opts = append(opts, elastic.SetInfoLog(&log.PrintfLogger{Logf: logger.Info}))
|
||||
opts = append(opts, elastic.SetErrorLog(&log.PrintfLogger{Logf: logger.Error}))
|
||||
|
||||
return elastic.NewClient(opts...)
|
||||
}
|
||||
|
||||
func (i *Indexer) checkOldIndexes(ctx context.Context) {
|
||||
for v := 0; v < i.version; v++ {
|
||||
for v := range i.version {
|
||||
indexName := versionedIndexName(i.indexName, v)
|
||||
exists, err := i.Client.IndexExists(indexName).Do(ctx)
|
||||
exists, err := i.indexExists(ctx, indexName)
|
||||
if err == nil && exists {
|
||||
log.Warn("Found older elasticsearch index named %q, Gitea will keep the old NOT DELETED. You can delete the old version after the upgrade succeed.", indexName)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user