mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-08 12:08:41 -05:00
Support Elasticsearch v9 alongside v8 (#35781)
This commit is contained in:
@@ -240,6 +240,21 @@ jobs:
|
||||
artifact-name: postgres-server-test-logs
|
||||
save-timing-cache: true
|
||||
|
||||
test-elasticsearch-v8:
|
||||
name: Elasticsearch v8 Compatibility
|
||||
needs: go
|
||||
uses: ./.github/workflows/server-test-template.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
name: Elasticsearch v8 Compatibility
|
||||
datasource: postgres://mmuser:mostest@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10
|
||||
drivername: postgres
|
||||
logsartifact: elasticsearch-v8-server-test-logs
|
||||
go-version: ${{ needs.go.outputs.version }}
|
||||
fips-enabled: false
|
||||
elasticsearch-version: "8.9.0"
|
||||
test-target: "test-server-elasticsearch"
|
||||
|
||||
test-postgres-normal-fips:
|
||||
# Always run on pushes to master/release branches.
|
||||
# For PRs, run when the branch name contains "fips" or any go.mod was changed.
|
||||
|
||||
@@ -33,6 +33,14 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
elasticsearch-version:
|
||||
required: false
|
||||
type: string
|
||||
default: "9.0.0"
|
||||
test-target:
|
||||
required: false
|
||||
type: string
|
||||
default: "test-server"
|
||||
# -- Test sharding inputs (leave defaults for non-sharded callers) --
|
||||
shard-index:
|
||||
required: false
|
||||
@@ -98,6 +106,7 @@ jobs:
|
||||
|
||||
- name: Run docker compose
|
||||
env:
|
||||
ELASTICSEARCH_VERSION: ${{ inputs.elasticsearch-version }}
|
||||
POSTGRES_PASSWORD: ${{ inputs.fips-enabled && 'mostest-fips-test' || 'mostest' }}
|
||||
run: |
|
||||
cd server/build
|
||||
@@ -166,11 +175,11 @@ jobs:
|
||||
env:
|
||||
BUILD_IMAGE: ${{ steps.build.outputs.BUILD_IMAGE }}
|
||||
run: |
|
||||
if [[ ${{ github.ref_name }} == 'master' && ${{ inputs.fullyparallel }} != true ]]; then
|
||||
if [[ ${{ github.ref_name }} == 'master' && ${{ inputs.fullyparallel }} != true && "${{ inputs.test-target }}" == "test-server" ]]; then
|
||||
export RACE_MODE="-race"
|
||||
fi
|
||||
|
||||
MAKE_ARGS="test-server${RACE_MODE} BUILD_NUMBER=${GITHUB_HEAD_REF}-${GITHUB_RUN_ID}"
|
||||
MAKE_ARGS="${{ inputs.test-target }}${RACE_MODE} BUILD_NUMBER=${GITHUB_HEAD_REF}-${GITHUB_RUN_ID}"
|
||||
DOCKER_CMD="make ${MAKE_ARGS}"
|
||||
|
||||
# When sharding is active, use the multi-run wrapper script
|
||||
|
||||
+10
-1
@@ -1,4 +1,4 @@
|
||||
.PHONY: build package run stop run-client run-server run-node run-haserver stop-haserver stop-client stop-server restart restart-server restart-client restart-haserver start-docker update-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-freebsd build-windows package-prep package-linux package-osx package-windows internal-test-web-client vet run-server-for-web-client-tests diff-config prepackaged-plugins prepackaged-binaries test-server test-server-ee test-server-quick test-server-race test-mmctl-unit test-mmctl-e2e test-mmctl test-mmctl-coverage mmctl-build mmctl-docs new-migration migrations-extract test-public mocks-public run-server-faketime
|
||||
.PHONY: build package run stop run-client run-server run-node run-haserver stop-haserver stop-client stop-server restart restart-server restart-client restart-haserver start-docker update-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-freebsd build-windows package-prep package-linux package-osx package-windows internal-test-web-client vet run-server-for-web-client-tests diff-config prepackaged-plugins prepackaged-binaries test-server test-server-ee test-server-elasticsearch test-server-quick test-server-race test-mmctl-unit test-mmctl-e2e test-mmctl test-mmctl-coverage mmctl-build mmctl-docs new-migration migrations-extract test-public mocks-public run-server-faketime
|
||||
|
||||
ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -495,6 +495,15 @@ test-server-ee: check-prereqs-enterprise start-docker gotestsum ## Runs EE tests
|
||||
@echo Running only EE tests
|
||||
$(GOBIN)/gotestsum --packages="$(EE_PACKAGES)" -- $(GOFLAGS) -timeout=20m
|
||||
|
||||
ES_PACKAGES=$(shell $(GO) list ./enterprise/elasticsearch/...)
|
||||
|
||||
test-server-elasticsearch: export GOTESTSUM_FORMAT := $(GOTESTSUM_FORMAT)
|
||||
test-server-elasticsearch: export GOTESTSUM_JUNITFILE := $(GOTESTSUM_JUNITFILE)
|
||||
test-server-elasticsearch: export GOTESTSUM_JSONFILE := $(GOTESTSUM_JSONFILE)
|
||||
test-server-elasticsearch: check-prereqs-enterprise start-docker gotestsum ## Runs Elasticsearch tests.
|
||||
@echo Running only Elasticsearch tests
|
||||
$(GOBIN)/gotestsum --rerun-fails=3 --packages="$(ES_PACKAGES)" -- $(GOFLAGS) -timeout=20m
|
||||
|
||||
test-server-quick: export GOTESTSUM_FORMAT := $(GOTESTSUM_FORMAT)
|
||||
test-server-quick: export GOTESTSUM_JUNITFILE := $(GOTESTSUM_JUNITFILE)
|
||||
test-server-quick: export GOTESTSUM_JSONFILE := $(GOTESTSUM_JSONFILE)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG ELASTICSEARCH_VERSION=8.9.0
|
||||
FROM mattermostdevelopment/mattermost-elasticsearch:${ELASTICSEARCH_VERSION}
|
||||
ARG ELASTICSEARCH_VERSION=9.0.0
|
||||
FROM docker.elastic.co/elasticsearch/elasticsearch:${ELASTICSEARCH_VERSION}
|
||||
|
||||
RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch analysis-nori analysis-kuromoji analysis-smartcn
|
||||
RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch analysis-icu analysis-nori analysis-kuromoji analysis-smartcn
|
||||
|
||||
@@ -59,6 +59,8 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile.elasticsearch
|
||||
args:
|
||||
ELASTICSEARCH_VERSION: ${ELASTICSEARCH_VERSION:-9.0.0}
|
||||
networks:
|
||||
- mm-test
|
||||
environment:
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.enterprise for license information.
|
||||
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
elastic "github.com/elastic/go-elasticsearch/v8"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newTestClient(t *testing.T, handler http.Handler) *elastic.TypedClient {
|
||||
t.Helper()
|
||||
ts := httptest.NewServer(handler)
|
||||
t.Cleanup(ts.Close)
|
||||
|
||||
client, err := elastic.NewTypedClient(elastic.Config{
|
||||
Addresses: []string{ts.URL},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return client
|
||||
}
|
||||
|
||||
func infoHandler(version string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("X-Elastic-Product", "Elasticsearch")
|
||||
fmt.Fprintf(w, `{"cluster_name":"test","version":{"number":%q,"build_flavor":"default","build_hash":"abc","build_date":"2024-01-01","build_snapshot":false,"build_type":"docker","lucene_version":"9.0.0","minimum_wire_compatibility_version":"7.0.0","minimum_index_compatibility_version":"7.0.0"}}`, version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
version string
|
||||
wantVersion string
|
||||
wantMajor int
|
||||
wantErrID string
|
||||
}{
|
||||
{
|
||||
name: "ES 8 is supported",
|
||||
version: "8.9.0",
|
||||
wantVersion: "8.9.0",
|
||||
wantMajor: 8,
|
||||
},
|
||||
{
|
||||
name: "ES 9 is supported",
|
||||
version: "9.0.0",
|
||||
wantVersion: "9.0.0",
|
||||
wantMajor: 9,
|
||||
},
|
||||
{
|
||||
name: "ES 7 is too old",
|
||||
version: "7.17.0",
|
||||
wantErrID: "ent.elasticsearch.min_version.app_error",
|
||||
},
|
||||
{
|
||||
name: "ES 10 is too new",
|
||||
version: "10.0.0",
|
||||
wantErrID: "ent.elasticsearch.max_version.app_error",
|
||||
},
|
||||
{
|
||||
name: "invalid version string",
|
||||
version: "invalid",
|
||||
wantErrID: "ent.elasticsearch.start.parse_server_version.app_error",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
client := newTestClient(t, infoHandler(tc.version))
|
||||
version, major, appErr := checkVersion(client)
|
||||
if tc.wantErrID != "" {
|
||||
require.NotNil(t, appErr)
|
||||
assert.Equal(t, tc.wantErrID, appErr.Id)
|
||||
} else {
|
||||
require.Nil(t, appErr)
|
||||
assert.Equal(t, tc.wantVersion, version)
|
||||
assert.Equal(t, tc.wantMajor, major)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckVersionConnectionError(t *testing.T) {
|
||||
ts := httptest.NewServer(http.NotFoundHandler())
|
||||
ts.Close() // close immediately to force connection error
|
||||
|
||||
client, err := elastic.NewTypedClient(elastic.Config{
|
||||
Addresses: []string{ts.URL},
|
||||
MaxRetries: 0,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, appErr := checkVersion(client)
|
||||
require.NotNil(t, appErr)
|
||||
assert.Equal(t, "ent.elasticsearch.start.get_server_version.app_error", appErr.Id)
|
||||
}
|
||||
@@ -32,7 +32,8 @@ import (
|
||||
"github.com/elastic/go-elasticsearch/v8/typedapi/types/enums/sortorder"
|
||||
)
|
||||
|
||||
const elasticsearchMaxVersion = 8
|
||||
const elasticsearchMinVersion = 8
|
||||
const elasticsearchMaxVersion = 9
|
||||
|
||||
var (
|
||||
purgeIndexListAllowedIndexes = []string{common.IndexBaseChannels}
|
||||
@@ -93,7 +94,7 @@ func (es *ElasticsearchInterfaceImpl) IsIndexingSync() bool {
|
||||
|
||||
// fetchServerInfo retrieves and stores the server version and plugins from the given client.
|
||||
func (es *ElasticsearchInterfaceImpl) fetchServerInfo(client *elastic.TypedClient) *model.AppError {
|
||||
version, major, appErr := checkMaxVersion(client)
|
||||
version, major, appErr := checkVersion(client)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
@@ -2110,19 +2111,22 @@ func (es *ElasticsearchInterfaceImpl) DeleteFilesBatch(rctx request.CTX, endTime
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkMaxVersion(client *elastic.TypedClient) (string, int, *model.AppError) {
|
||||
func checkVersion(client *elastic.TypedClient) (string, int, *model.AppError) {
|
||||
resp, err := client.API.Core.Info().Do(context.Background())
|
||||
if err != nil {
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkMaxVersion", "ent.elasticsearch.start.get_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusInternalServerError).Wrap(err)
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkVersion", "ent.elasticsearch.start.get_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
major, _, _, esErr := common.GetVersionComponents(resp.Version.Int)
|
||||
if esErr != nil {
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkMaxVersion", "ent.elasticsearch.start.parse_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusInternalServerError).Wrap(err)
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkVersion", "ent.elasticsearch.start.parse_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusInternalServerError).Wrap(esErr)
|
||||
}
|
||||
|
||||
if major < elasticsearchMinVersion {
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkVersion", "ent.elasticsearch.min_version.app_error", map[string]any{"Version": major, "MinVersion": elasticsearchMinVersion, "Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusBadRequest)
|
||||
}
|
||||
if major > elasticsearchMaxVersion {
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkMaxVersion", "ent.elasticsearch.max_version.app_error", map[string]any{"Version": major, "MaxVersion": elasticsearchMaxVersion, "Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusBadRequest)
|
||||
return "", 0, model.NewAppError("Elasticsearch.checkVersion", "ent.elasticsearch.max_version.app_error", map[string]any{"Version": major, "MaxVersion": elasticsearchMaxVersion, "Backend": model.ElasticsearchSettingsESBackend}, "", http.StatusBadRequest)
|
||||
}
|
||||
return resp.Version.Int, major, nil
|
||||
}
|
||||
|
||||
@@ -9332,6 +9332,10 @@
|
||||
"id": "ent.elasticsearch.max_version.app_error",
|
||||
"translation": "{{.Backend}} version {{.Version}} is higher than max supported version of {{.MaxVersion}}"
|
||||
},
|
||||
{
|
||||
"id": "ent.elasticsearch.min_version.app_error",
|
||||
"translation": "{{.Backend}} version {{.Version}} is lower than min supported version of {{.MinVersion}}"
|
||||
},
|
||||
{
|
||||
"id": "ent.elasticsearch.not_started.error",
|
||||
"translation": "{{.Backend}} is not started"
|
||||
|
||||
Reference in New Issue
Block a user