From 6b1b26a946e0d3c8c3b95c4f822eb82c4e83bae3 Mon Sep 17 00:00:00 2001 From: Dan Panzarella Date: Fri, 23 Jun 2023 16:27:27 -0400 Subject: [PATCH 01/13] Adds delivery module tests (#2692) (#2728) --- internal/pkg/api/handleFileDelivery.go | 5 +- internal/pkg/api/handleFileDelivery_test.go | 432 ++++++++++++++++++++ internal/pkg/api/handleUpload_test.go | 26 +- internal/pkg/file/delivery/delivery_test.go | 303 ++++++++++++++ internal/pkg/file/delivery/es.go | 3 + 5 files changed, 757 insertions(+), 12 deletions(-) create mode 100644 internal/pkg/api/handleFileDelivery_test.go create mode 100644 internal/pkg/file/delivery/delivery_test.go diff --git a/internal/pkg/api/handleFileDelivery.go b/internal/pkg/api/handleFileDelivery.go index 439a41b4f..62c6b63db 100644 --- a/internal/pkg/api/handleFileDelivery.go +++ b/internal/pkg/api/handleFileDelivery.go @@ -9,7 +9,6 @@ import ( "net/http" "strconv" - "github.com/elastic/fleet-server/v7/internal/pkg/apikey" "github.com/elastic/fleet-server/v7/internal/pkg/bulk" "github.com/elastic/fleet-server/v7/internal/pkg/cache" "github.com/elastic/fleet-server/v7/internal/pkg/config" @@ -26,7 +25,6 @@ type FileDeliveryT struct { chunkClient *elasticsearch.Client deliverer *delivery.Deliverer authAgent func(*http.Request, *string, bulk.Bulk, cache.Cache) (*model.Agent, error) // injectable for testing purposes - authAPIKey func(*http.Request, bulk.Bulk, cache.Cache) (*apikey.APIKey, error) // as above } func NewFileDeliveryT(cfg *config.Server, bulker bulk.Bulk, chunkClient *elasticsearch.Client, cache cache.Cache) *FileDeliveryT { @@ -41,12 +39,11 @@ func NewFileDeliveryT(cfg *config.Server, bulker bulk.Bulk, chunkClient *elastic cache: cache, deliverer: delivery.New(chunkClient, bulker, maxFileSize), authAgent: authAgent, - authAPIKey: authAPIKey, } } func (ft *FileDeliveryT) handleSendFile(zlog zerolog.Logger, w http.ResponseWriter, r *http.Request, fileID string) error { - agent, err := authAgent(r, nil, ft.bulker, ft.cache) + agent, err := ft.authAgent(r, nil, ft.bulker, ft.cache) if err != nil { return err } diff --git a/internal/pkg/api/handleFileDelivery_test.go b/internal/pkg/api/handleFileDelivery_test.go new file mode 100644 index 000000000..35a0578b5 --- /dev/null +++ b/internal/pkg/api/handleFileDelivery_test.go @@ -0,0 +1,432 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build !integration + +package api + +import ( + "encoding/hex" + "errors" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/elastic/fleet-server/v7/internal/pkg/bulk" + "github.com/elastic/fleet-server/v7/internal/pkg/cache" + "github.com/elastic/fleet-server/v7/internal/pkg/config" + "github.com/elastic/fleet-server/v7/internal/pkg/es" + "github.com/elastic/fleet-server/v7/internal/pkg/file" + "github.com/elastic/fleet-server/v7/internal/pkg/file/delivery" + "github.com/elastic/fleet-server/v7/internal/pkg/model" + + itesting "github.com/elastic/fleet-server/v7/internal/pkg/testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +var ( + isFileMetaSearch = mock.MatchedBy(func(idx string) bool { + return strings.HasPrefix(idx, fmt.Sprintf(delivery.FileHeaderIndexPattern, "")) + }) + isFileChunkSearch = mock.MatchedBy(func(idx string) bool { + return strings.HasPrefix(idx, fmt.Sprintf(delivery.FileDataIndexPattern, "")) + }) +) + +func TestFileDeliveryRouteDisallowedMethods(t *testing.T) { + hr, _, _, fakebulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + fakebulk.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{}, nil) + + disallowed := []string{ + http.MethodPost, + http.MethodDelete, + http.MethodPut, + } + + for _, method := range disallowed { + t.Run("filedelivery"+method, func(t *testing.T) { + hr.ServeHTTP(rec, httptest.NewRequest(method, "/api/fleet/file/X", nil)) + assert.Equal(t, http.StatusMethodNotAllowed, rec.Code) + }) + } +} + +func TestFileDeliveryRouteGetMissingFile(t *testing.T) { + hr, _, _, fakebulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + fakebulk.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{}, nil) + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + assert.Equal(t, http.StatusNotFound, rec.Code) +} + +// if metadata exists, but no chunks, file should be 404 +func TestFileDeliveryNoChunks(t *testing.T) { + hr, _, _, fakebulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + + fakebulk.On("Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: "X", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "test.txt", + "mime_type": "text/plain", + "Meta": { + "target_agents": ["someagent"], + "action_id": "" + }, + "size": 256 + } + }`), + }, + }, + }, + }, nil, + ).Once() + fakebulk.On("Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{}, + }, + }, nil, + ) + + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + assert.Equal(t, http.StatusNotFound, rec.Code) +} + +func TestFileDelivery(t *testing.T) { + hr, _, tx, bulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + + bulk.On("Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{{ + ID: "X", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "somefile", + "mime_type": "application/octet-stream", + "Meta": { + "target_agents": ["someagent"], + "action_id": "" + }, + "size": 2 + } + }`), + }}, + }, + }, nil, + ) + bulk.On("Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: "X.0", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileDataIndexPattern, "endpoint"), + Fields: map[string]interface{}{ + file.FieldBaseID: []interface{}{"X"}, + file.FieldLast: []interface{}{true}, + }, + }, + }, + }, + }, nil, + ) + + tx.Response = sendBodyBytes(hexDecode("A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD")) + + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + + bulk.AssertCalled(t, "Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything) + bulk.AssertCalled(t, "Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything) + + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, []byte{0xAB, 0xCD}, rec.Body.Bytes()) +} + +func TestFileDeliveryMultipleChunks(t *testing.T) { + hr, _, tx, bulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + + bulk.On("Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{{ + ID: "X", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "somefile", + "mime_type": "application/octet-stream", + "Meta": { + "target_agents": ["someagent"], + "action_id": "" + }, + "size": 4 + } + }`), + }}, + }, + }, nil, + ) + bulk.On("Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: "X.0", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileDataIndexPattern, "endpoint"), + Fields: map[string]interface{}{ + file.FieldBaseID: []interface{}{"X"}, + }, + }, + { + ID: "X.1", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileDataIndexPattern, "endpoint"), + Fields: map[string]interface{}{ + file.FieldBaseID: []interface{}{"X"}, + file.FieldLast: []interface{}{true}, + }, + }, + }, + }, + }, nil, + ) + + mockChunks := []string{ + "A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD", + "A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E31685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142EF01", + } + + tx.RoundTripFn = func(req *http.Request) (*http.Response, error) { + if strings.HasSuffix(req.URL.Path, "X.0") { + return sendBodyBytes(hexDecode(mockChunks[0])), nil + } else if strings.HasSuffix(req.URL.Path, "X.1") { + return sendBodyBytes(hexDecode(mockChunks[1])), nil + } else { + return nil, errors.New("invalid chunk index!") + } + } + + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + + require.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, []byte{0xAB, 0xCD, 0xEF, 0x01}, rec.Body.Bytes()) +} + +func TestFileDeliverySetsHeaders(t *testing.T) { + hr, _, tx, bulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + + bulk.On("Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{{ + ID: "X", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "test.csv", + "mime_type": "text/csv", + "Meta": { + "target_agents": ["someagent"], + "action_id": "" + }, + "size": 4 + } + }`), + }}, + }, + }, nil, + ) + bulk.On("Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: "X.0", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileDataIndexPattern, "endpoint"), + Fields: map[string]interface{}{ + file.FieldBaseID: []interface{}{"X"}, + file.FieldLast: []interface{}{true}, + }, + }, + }, + }, + }, nil, + ) + tx.Response = sendBodyBytes(hexDecode("A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD")) + + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + + require.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, "text/csv", rec.Header().Get("Content-Type")) + assert.Equal(t, "4", rec.Header().Get("Content-Length")) + assert.Empty(t, rec.Header().Get("X-File-SHA2")) +} + +func TestFileDeliverySetsHashWhenPresent(t *testing.T) { + hr, _, tx, bulk := prepareFileDeliveryMock(t) + rec := httptest.NewRecorder() + + bulk.On("Search", mock.Anything, isFileMetaSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{{ + ID: "X", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "test.csv", + "mime_type": "text/csv", + "Meta": { + "target_agents": ["someagent"], + "action_id": "" + }, + "size": 4, + "hash": { + "sha256": "deadbeef" + } + } + }`), + }}, + }, + }, nil, + ) + bulk.On("Search", mock.Anything, isFileChunkSearch, mock.Anything, mock.Anything, mock.Anything).Return( + &es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: "X.0", + SeqNo: 1, + Version: 1, + Index: fmt.Sprintf(delivery.FileDataIndexPattern, "endpoint"), + Fields: map[string]interface{}{ + file.FieldBaseID: []interface{}{"X"}, + file.FieldLast: []interface{}{true}, + }, + }, + }, + }, + }, nil, + ) + tx.Response = sendBodyBytes(hexDecode("A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD")) + + hr.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/fleet/file/X", nil)) + + require.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, "deadbeef", rec.Header().Get("X-File-SHA2")) +} + +/* + Helpers and mocks +*/ + +// prepareUploaderMock sets up common dependencies and registers upload routes to a returned router +func prepareFileDeliveryMock(t *testing.T) (http.Handler, apiServer, *MockTransport, *itesting.MockBulk) { + // chunk index operations skip the bulker in order to send binary docs directly + // so a mock *elasticsearch.Client needs to be be prepared + mockES, tx := mockESClient(t) + + fakebulk := itesting.NewMockBulk() + fakebulk.On("Client", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(mockES, nil) + + c, err := cache.New(config.Cache{NumCounters: 100, MaxCost: 100000}) + require.NoError(t, err) + + si := apiServer{ + ft: &FileDeliveryT{ + bulker: fakebulk, + chunkClient: mockES, + cache: c, + deliverer: delivery.New(mockES, fakebulk, maxFileSize), + authAgent: func(r *http.Request, id *string, bulker bulk.Bulk, c cache.Cache) (*model.Agent, error) { + return &model.Agent{ + ESDocument: model.ESDocument{ + Id: "foo", + }, + Agent: &model.AgentMetadata{ + ID: "foo", + }, + }, nil + }, + }, + } + + return Handler(&si), si, tx, fakebulk +} + +func hexDecode(s string) []byte { + data, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return data +} diff --git a/internal/pkg/api/handleUpload_test.go b/internal/pkg/api/handleUpload_test.go index de033bdb1..e919184fd 100644 --- a/internal/pkg/api/handleUpload_test.go +++ b/internal/pkg/api/handleUpload_test.go @@ -11,6 +11,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "io" "io/ioutil" "net/http" "net/http/httptest" @@ -857,7 +858,7 @@ func TestUploadCompleteIncorrectTransitHash(t *testing.T) { func prepareUploaderMock(t *testing.T) (http.Handler, apiServer, *itesting.MockBulk) { // chunk index operations skip the bulker in order to send binary docs directly // so a mock *elasticsearch.Client needs to be be prepared - es := mockESClient(t) + es, _ := mockESClient(t) fakebulk := itesting.NewMockBulk() fakebulk.On("Create", @@ -1024,13 +1025,9 @@ func (t *MockTransport) RoundTrip(req *http.Request) (*http.Response, error) { return t.RoundTripFn(req) } -func mockESClient(t *testing.T) *elasticsearch.Client { +func mockESClient(t *testing.T) (*elasticsearch.Client, *MockTransport) { mocktrans := MockTransport{ - Response: &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(`{}`)), - Header: http.Header{"X-Elastic-Product": []string{"Elasticsearch"}}, - }, + Response: sendBodyString("{}"), //nolint:bodyclose // nopcloser is used, linter does not see it } mocktrans.RoundTripFn = func(req *http.Request) (*http.Response, error) { return mocktrans.Response, nil } @@ -1038,5 +1035,18 @@ func mockESClient(t *testing.T) *elasticsearch.Client { Transport: &mocktrans, }) require.NoError(t, err) - return client + return client, &mocktrans +} + +func sendBodyString(body string) *http.Response { return sendBody(strings.NewReader(body)) } +func sendBodyBytes(body []byte) *http.Response { return sendBody(bytes.NewReader(body)) } +func sendBody(body io.Reader) *http.Response { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(body), + Header: http.Header{ + "X-Elastic-Product": []string{"Elasticsearch"}, + "Content-Type": []string{"application/cbor"}, + }, + } } diff --git a/internal/pkg/file/delivery/delivery_test.go b/internal/pkg/file/delivery/delivery_test.go new file mode 100644 index 000000000..7f680cf07 --- /dev/null +++ b/internal/pkg/file/delivery/delivery_test.go @@ -0,0 +1,303 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package delivery + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/elastic/fleet-server/v7/internal/pkg/es" + "github.com/elastic/fleet-server/v7/internal/pkg/file" + itesting "github.com/elastic/fleet-server/v7/internal/pkg/testing" + "github.com/elastic/go-elasticsearch/v8" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +// cbor decoding and encoding tools can be helpful for examining or changing the test data here +// https://cbor.me/ may be helpful in verifying the shapes of the data + +func TestFindFile(t *testing.T) { + fakeBulk := itesting.NewMockBulk() + + agentID := "abcagent" + fileID := "xyzfile" + + fakeBulk.Mock.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: fileID, + Index: fmt.Sprintf(FileHeaderIndexPattern, "endpoint"), + Source: []byte(`{ + "file": { + "created": "2023-06-05T15:23:37.499Z", + "Status": "READY", + "Updated": "2023-06-05T15:23:37.499Z", + "name": "test.txt", + "mime_type": "text/plain", + "Meta": { + "target_agents": ["` + agentID + `"], + "action_id": "" + }, + "size": 256, + "hash": { + "sha256": "b94276997f744bab637c2e937bb349947bc2c3b6c6397feb5b252c6928c7799b" + } + } + }`), + }, + }, + }, + }, nil) + + d := New(nil, fakeBulk, -1) + + info, err := d.FindFileForAgent(context.Background(), fileID, agentID) + require.NoError(t, err) + + assert.NotNil(t, info.File.Hash) + assert.Equal(t, "READY", info.File.Status) +} + +func TestFindFileHandlesNoResults(t *testing.T) { + fakeBulk := itesting.NewMockBulk() + + // handles case where ES does not return an error, simply no results + fakeBulk.Mock.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{}, + }, + }, nil) + + d := New(nil, fakeBulk, -1) + + _, err := d.FindFileForAgent(context.Background(), "somefile", "anyagent") + assert.ErrorIs(t, ErrNoFile, err) +} + +func TestLocateChunks(t *testing.T) { + fakeBulk := itesting.NewMockBulk() + + baseID := "somefile" + + fakeBulk.Mock.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{ + { + ID: baseID + ".0", + Index: "", + Source: []byte(""), + Fields: map[string]interface{}{ + "bid": []interface{}{baseID}, + }, + }, + { + ID: baseID + ".1", + Index: "", + Source: []byte(""), + Fields: map[string]interface{}{ + "bid": []interface{}{baseID}, + "last": []interface{}{true}, + }, + }, + }, + }, + }, nil) + + d := New(nil, fakeBulk, -1) + + chunks, err := d.LocateChunks(context.Background(), zerolog.Logger{}, baseID) + require.NoError(t, err) + + assert.Len(t, chunks, 2) +} + +func TestLocateChunksEmpty(t *testing.T) { + fakeBulk := itesting.NewMockBulk() + + fakeBulk.Mock.On("Search", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&es.ResultT{ + HitsT: es.HitsT{ + Hits: []es.HitT{}, + }, + }, nil) + + d := New(nil, fakeBulk, -1) + + _, err := d.LocateChunks(context.Background(), zerolog.Logger{}, "afile") + assert.Error(t, err) +} + +func TestSendFile(t *testing.T) { + buf := bytes.NewBuffer(nil) + + fakeBulk := itesting.NewMockBulk() + esClient, esMock := mockESClient(t) + + const fileID = "xyz" + chunks := []file.ChunkInfo{ + {Index: fmt.Sprintf(FileDataIndexPattern, "endpoint"), ID: fileID + ".0"}, + } + // Chunk data from a tiny PNG, as a full CBOR document + esMock.Response = sendBodyBytes(hexDecode("bf665f696e64657878212e666c6565742d66696c6564656c69766572792d646174612d656e64706f696e74635f6964654142432e30685f76657273696f6e02675f7365715f6e6f016d5f7072696d6172795f7465726d0165666f756e64f5666669656c6473bf64646174619f586789504e470d0a1a0a0000000d494844520000010000000100010300000066bc3a2500000003504c5445b5d0d0630416ea0000001f494441546881edc1010d000000c2a0f74f6d0e37a00000000000000000be0d210000019a60e1d50000000049454e44ae426082ffffff")) //nolint:bodyclose // nopcloser is used, linter does not see it + d := New(esClient, fakeBulk, -1) + err := d.SendFile(context.Background(), zerolog.Logger{}, buf, chunks, fileID) + require.NoError(t, err) + + // the byte string is the bare PNG file data + assert.Equal(t, hexDecode("89504e470d0a1a0a0000000d494844520000010000000100010300000066bc3a2500000003504c5445b5d0d0630416ea0000001f494441546881edc1010d000000c2a0f74f6d0e37a00000000000000000be0d210000019a60e1d50000000049454e44ae426082"), buf.Bytes()) +} + +// sending a file that spans more than 1 chunk +func TestSendFileMultipleChunks(t *testing.T) { + buf := bytes.NewBuffer(nil) + + fakeBulk := itesting.NewMockBulk() + esClient, esMock := mockESClient(t) + + const fileID = "xyz" + chunks := []file.ChunkInfo{ + {Index: fmt.Sprintf(FileDataIndexPattern, "endpoint"), ID: fileID + ".0"}, + {Index: fmt.Sprintf(FileDataIndexPattern, "endpoint"), ID: fileID + ".1"}, + } + + mockChunks := []string{ + "A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD", + "A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E31685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142EF01", + } + + esMock.RoundTripFn = func(req *http.Request) (*http.Response, error) { + if strings.HasSuffix(req.URL.Path, fileID+".0") { + return sendBodyBytes(hexDecode(mockChunks[0])), nil + } else if strings.HasSuffix(req.URL.Path, fileID+".1") { + return sendBodyBytes(hexDecode(mockChunks[1])), nil + } else { + return nil, errors.New("invalid chunk index!") + } + } + + d := New(esClient, fakeBulk, -1) + err := d.SendFile(context.Background(), zerolog.Logger{}, buf, chunks, fileID) + require.NoError(t, err) + + // the collective bytes sent (0xabcd in first chunk, 0xef01 in second) + assert.Equal(t, hexDecode("abcdef01"), buf.Bytes()) +} + +// when chunks may be located in different backing indices behind an alias or data stream, they should be fetched from the backing index directly +func TestSendFileMultipleChunksUsesBackingIndex(t *testing.T) { + buf := bytes.NewBuffer(nil) + + fakeBulk := itesting.NewMockBulk() + esClient, esMock := mockESClient(t) + + const fileID = "xyz" + + idx1 := fmt.Sprintf(FileDataIndexPattern, "endpoint") + "-0001" + idx2 := fmt.Sprintf(FileDataIndexPattern, "endpoint") + "-0002" + chunks := []file.ChunkInfo{ + {Index: idx1, ID: fileID + ".0"}, + {Index: idx2, ID: fileID + ".1"}, + } + + mockData := hexDecode("A7665F696E64657878212E666C6565742D66696C6564656C69766572792D646174612D656E64706F696E74635F69646578797A2E30685F76657273696F6E01675F7365715F6E6F016D5F7072696D6172795F7465726D0165666F756E64F5666669656C6473A164646174618142ABCD") + + esMock.RoundTripFn = func(req *http.Request) (*http.Response, error) { + parts := strings.Split(req.URL.Path, "/") // ["", ".fleet-filedelivery-data-endpoint-0001", "_doc", "xyz.1"] + + if parts[3] == fileID+".0" { + assert.Equal(t, idx1, parts[1]) + } else if parts[3] == fileID+".1" { + assert.Equal(t, idx2, parts[1]) + } else { + return nil, errors.New("invalid chunk index!") + } + + return sendBodyBytes(mockData), nil + } + + d := New(esClient, fakeBulk, -1) + err := d.SendFile(context.Background(), zerolog.Logger{}, buf, chunks, fileID) + require.NoError(t, err) +} + +/* + Setup to convert a *elasticsearch.Client as a harmless mock + by replacing the Transport to nowhere +*/ + +type MockTransport struct { + Response *http.Response + RoundTripFn func(req *http.Request) (*http.Response, error) +} + +func (t *MockTransport) RoundTrip(req *http.Request) (*http.Response, error) { + return t.RoundTripFn(req) +} + +func mockESClient(t *testing.T) (*elasticsearch.Client, *MockTransport) { + mocktrans := MockTransport{ + Response: sendBodyString(""), //nolint:bodyclose // nopcloser is used, linter does not see it + } + + mocktrans.RoundTripFn = func(req *http.Request) (*http.Response, error) { return mocktrans.Response, nil } + client, err := elasticsearch.NewClient(elasticsearch.Config{ + Transport: &mocktrans, + }) + require.NoError(t, err) + return client, &mocktrans +} + +func sendBodyString(body string) *http.Response { return sendBody(strings.NewReader(body)) } +func sendBodyBytes(body []byte) *http.Response { return sendBody(bytes.NewReader(body)) } +func sendBody(body io.Reader) *http.Response { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(body), + Header: http.Header{ + "X-Elastic-Product": []string{"Elasticsearch"}, + "Content-Type": []string{"application/cbor"}, + }, + } +} + +// helper to turn hex data strings into bytes +func hexDecode(s string) []byte { + data, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return data +} diff --git a/internal/pkg/file/delivery/es.go b/internal/pkg/file/delivery/es.go index 3dda02b81..6f224189c 100644 --- a/internal/pkg/file/delivery/es.go +++ b/internal/pkg/file/delivery/es.go @@ -13,6 +13,7 @@ import ( "github.com/elastic/fleet-server/v7/internal/pkg/bulk" "github.com/elastic/fleet-server/v7/internal/pkg/dsl" "github.com/elastic/fleet-server/v7/internal/pkg/es" + "github.com/elastic/fleet-server/v7/internal/pkg/file" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/go-elasticsearch/v8/esapi" ) @@ -24,6 +25,7 @@ const ( FieldDocID = "_id" FieldTargetAgents = "file.Meta.target_agents" + FieldStatus = "file.Status" ) var ( @@ -36,6 +38,7 @@ func prepareQueryMetaByIDAndAgent() *dsl.Tmpl { node := root.Query().Bool().Must() node.Term(FieldDocID, tmpl.Bind(FieldDocID), nil) node.Term(FieldTargetAgents, tmpl.Bind("target_agents"), nil) + node.Term(FieldStatus, file.StatusDone, nil) tmpl.MustResolve(root) return tmpl } From f1976f7117de48a4cf591e0d9fa1c8f7a6d87983 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Fri, 30 Jun 2023 04:20:48 -0400 Subject: [PATCH 02/13] [updatecli] update elastic stack version for testing 8.9.0-bbb2ee5d-SNAPSHOT (#2732) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adds delivery module tests (#2692) * [Release] add-backport-next (#2721) * [Release] update version (#2720) Co-authored-by: Anderson Queiroz * Revert "[Release] update version (#2720)" (#2730) This reverts commit 331112b16439ccfcef7883e49baf5ac325515601. * add the trigger package-registry pipeline (#2729) * package step (#2651) * test the trigger step * test condition for trigger step * revert test condition for trigger step and add comment with TODO step for the future * fix condition * matrix test * matrix test2 * matrix test3 * fix the version path * platform and matrix test * platform and matrix test * platform and matrix test * platform and matrix test * update script permissions * fix values * fix platform type and add debug info * add package part * fix package part add publish part * add add_bin_path * add variable SETUP_GVM_VERSION * fix go module names * fix for loop for install packages * add ubuntu images * fix step keys * fix images * delete provider setting * change the image options * change the image options * change the image options * change gvm version * try to debug make error * add debur info into the package script * troubleshoot the script * troubleshoot the script * troubleshoot the script * troubleshoot the image * troubleshoot the image * revert the image * change the gcp image * change the gcp image * change the gcp image * add GO_VERSION * add debug to the comman.bash script * add debug to the comman.bash script * debug comman.bash script * debug comman.bash script * debug comman.bash script * debug comman.bash script * debug comman.bash script * revert common.bash and run_with_go_ver * revert common.bash and run_with_go_ver * change image * correct path * add google_cloud_auth * test * Update .buildkite/scripts/common.sh Co-authored-by: Mario Rodriguez Molins * Update .buildkite/scripts/common.sh Co-authored-by: Mario Rodriguez Molins * Update .buildkite/scripts/common.sh Co-authored-by: Mario Rodriguez Molins * optimize the package.sh * Update .buildkite/scripts/package.sh Co-authored-by: Mario Rodriguez Molins * change the getting the bucket name * change the condition and dependency to run the stage * add '--no-pager' to the 'git log' command --------- Co-authored-by: Mario Rodriguez Molins * chore: Updated to content "" in file "dev-tools/integration/.env" Made with ❤️️ by updatecli * chore: Updated to content "" in file "dev-tools/integration/.env" Made with ❤️️ by updatecli * chore: Updated to content "" in file "dev-tools/integration/.env" Made with ❤️️ by updatecli * chore: Updated to content "" in file "dev-tools/integration/.env" Made with ❤️️ by updatecli * chore: Updated to content "" in file "dev-tools/integration/.env" Made with ❤️️ by updatecli --------- Co-authored-by: Dan Panzarella Co-authored-by: Elastic Machine Co-authored-by: Anderson Queiroz Co-authored-by: Jaime Soriano Pastor Co-authored-by: sharbuz <87968844+sharbuz@users.noreply.github.com> Co-authored-by: Mario Rodriguez Molins Co-authored-by: apmmachine Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .buildkite/hooks/post-checkout | 1 + .buildkite/hooks/pre-command | 9 +++++++ .buildkite/hooks/pre-exit | 7 ++++++ .buildkite/pipeline.package.mbp.yml | 38 +++++++++++++++++++++++------ .buildkite/pipeline.yml | 17 ++++++++----- .buildkite/scripts/common.sh | 28 +++++++++++++++++++++ .buildkite/scripts/package.sh | 35 ++++++++++++++++++++++++++ .mergify.yml | 13 ++++++++++ dev-tools/integration/.env | 2 +- 9 files changed, 135 insertions(+), 15 deletions(-) create mode 100755 .buildkite/scripts/package.sh diff --git a/.buildkite/hooks/post-checkout b/.buildkite/hooks/post-checkout index 104970d82..0d95535b6 100644 --- a/.buildkite/hooks/post-checkout +++ b/.buildkite/hooks/post-checkout @@ -47,6 +47,7 @@ MERGE_BRANCH="pr_merge_${PR_ID}" checkout_merge "${TARGET_BRANCH}" "${PR_COMMIT}" "${MERGE_BRANCH}" echo "Commit information" + git --no-pager log --format=%B -n 1 # Ensure buildkite groups are rendered diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index e1fc865d1..fbdd6d925 100755 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -7,6 +7,7 @@ source .buildkite/scripts/common.sh DOCKER_REGISTRY_SECRET_PATH="kv/ci-shared/platform-ingest/docker_registry_prod" EC_KEY_SECRET_PATH="kv/ci-shared/platform-ingest/platform-ingest-ec-prod" PRIVATE_CI_GCS_CREDENTIALS_PATH="kv/ci-shared/platform-ingest/private_ci_artifacts_gcs_credentials" +JOB_GCS_BUCKET_SECRET_PATH="kv/ci-shared/platform-ingest/fleet_gcs_bucket" if [[ "$BUILDKITE_PIPELINE_SLUG" == "fleet-server" ]]; then if [[ "$BUILDKITE_STEP_KEY" == "publish" || "$BUILDKITE_STEP_KEY" == "cloud-e2e-test" ]]; then @@ -24,4 +25,12 @@ fi if [[ "$BUILDKITE_PIPELINE_SLUG" == "fleet-server" && "$BUILDKITE_STEP_KEY" == "release-test" ]]; then export PRIVATE_CI_GCS_CREDENTIALS_SECRET=$(retry 5 vault kv get -field plaintext ${PRIVATE_CI_GCS_CREDENTIALS_PATH}) + export JOB_GCS_BUCKET=$(retry 5 vault kv get -field plaintext ${JOB_GCS_BUCKET_SECRET_PATH}) fi + +if [[ "$BUILDKITE_PIPELINE_SLUG" == "fleet-server-package-mbp" ]]; then + if [[ "$BUILDKITE_STEP_KEY" == "package-x86-64" || "$BUILDKITE_STEP_KEY" == "package-arm" ]]; then + export PRIVATE_CI_GCS_CREDENTIALS_SECRET=$(retry 5 vault kv get -field plaintext ${PRIVATE_CI_GCS_CREDENTIALS_PATH}) + export JOB_GCS_BUCKET=$(retry 5 vault kv get -field plaintext ${JOB_GCS_BUCKET_SECRET_PATH}) + fi +fi \ No newline at end of file diff --git a/.buildkite/hooks/pre-exit b/.buildkite/hooks/pre-exit index c2b6750c1..0aa33dcf6 100755 --- a/.buildkite/hooks/pre-exit +++ b/.buildkite/hooks/pre-exit @@ -14,3 +14,10 @@ if [[ "$BUILDKITE_PIPELINE_SLUG" == "fleet-server" && "$BUILDKITE_STEP_KEY" == " unset GOOGLE_APPLICATIONS_CREDENTIALS cleanup fi + +if [[ "$BUILDKITE_PIPELINE_SLUG" == "fleet-server-package-mbp" ]]; then + if [[ "$BUILDKITE_STEP_KEY" == "package-x86-64" || "$BUILDKITE_STEP_KEY" == "package-arm" ]]; then + unset GOOGLE_APPLICATIONS_CREDENTIALS + cleanup + fi +fi diff --git a/.buildkite/pipeline.package.mbp.yml b/.buildkite/pipeline.package.mbp.yml index 57fc59234..b9251491f 100644 --- a/.buildkite/pipeline.package.mbp.yml +++ b/.buildkite/pipeline.package.mbp.yml @@ -1,12 +1,34 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/buildkite/pipeline-schema/main/schema.json name: "fleet server package mbp" -steps: - - label: ":pipeline: test step" - command: echo "test-pipeline" +env: + REPO: 'fleet-server' + JOB_GCS_BUCKET: 'fleet-ci-artifacts' + SETUP_GVM_VERSION: 'v0.3.0' - - group: "test group" +steps: + - group: "Package and Publish" + key: "package-publish" steps: - - label: "step1 of the group" - command: echo "step1 of the group" + - label: "Package Ubuntu-20 x86_64" + key: "package-x86-64" + command: ".buildkite/scripts/package.sh {{matrix.type}}" + agents: + provider: "gcp" + image: "family/core-ubuntu-2004" + matrix: + setup: + type: + - "snapshot" + - "staging" - - label: "step2 of the group" - command: echo "step2 of the group" \ No newline at end of file + - label: "Package Ubuntu-20 aarch64" + key: "package-arm" + command: ".buildkite/scripts/package.sh {{matrix.type}}" + agents: + provider: "aws" + image: "core-ubuntu-2004-aarch64" + matrix: + setup: + type: + - "snapshot" + - "staging" diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index e5ea3ab54..9dfe48d8a 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -10,7 +10,6 @@ env: DOCKER_IMAGE_GIT_TAG: "temp-${BUILDKITE_BRANCH}" # needs to rename after tests GO_AGENT_IMAGE: "golang:1.20.5" TERRAFORM_VERSION: '1.4.6' - JOB_GCS_BUCKET: 'fleet-ci-artifacts' steps: - group: "Check and build" @@ -74,7 +73,7 @@ steps: - step: "int-test" allow_failure: false - - label: "Cloud e2e Test" + - label: ":gcloud: Cloud e2e Test" key: "cloud-e2e-test" command: ".buildkite/scripts/cloud_e2e_test.sh" agents: @@ -124,14 +123,20 @@ steps: - label: ":jenkins: Release - Package Registry Distribution" key: "release-package-registry" - command: echo "Triggering the Jenkins Job 'release-package-registry-distribution'..." + trigger: "package-registry-release-package-registry-distribution" + build: + branch: "main" + meta_data: + DOCKER_TAG: "${BUILDKITE_TAG}" + if: "build.env('BUILDKITE_TAG') != ''" depends_on: - step: "release-test" allow_failure: false - - label: ":jenkins: Downstream - Package" + - trigger: "fleet-server-package-mbp" + label: ":esbuild: Downstream - Package" key: "downstream-package" - command: echo "Triggering the Jenkins Job 'fleet-server/fleet-server-package-mbp/env.JOB_BASE_NAME'..." + if: "build.env('BUILDKITE_BRANCH') != '' && build.env('BUILDKITE_TAG') == '' && build.env('BUILDKITE_PULL_REQUEST') == ''" depends_on: - step: "release-package-registry" - allow_failure: false + allow_failure: false \ No newline at end of file diff --git a/.buildkite/scripts/common.sh b/.buildkite/scripts/common.sh index 259054058..d09cc5a72 100755 --- a/.buildkite/scripts/common.sh +++ b/.buildkite/scripts/common.sh @@ -94,6 +94,34 @@ upload_packages_to_gcp_bucket() { done } +upload_mbp_packages_to_gcp_bucket() { + local pattern=${1} + local type=${2} + local baseUri="gs://${JOB_GCS_BUCKET}/jobs/buildkite" #TODO: needs to delete the "/buildkite" part after the migration from Jenkins + local bucketUri="" + + if [[ ${type} == "snapshot" ]]; then + bucketUri="${baseUri}"/commits/${BUILDKITE_COMMIT} + else + bucketUri="${baseUri}"/${type}/${BUILDKITE_COMMIT} + fi + gsutil -m -q cp -a public-read -r ${pattern} "${bucketUri}" +} + +with_mage() { + local install_packages=( + "github.com/magefile/mage" + "github.com/elastic/go-licenser" + "golang.org/x/tools/cmd/goimports" + "github.com/jstemmer/go-junit-report" + "gotest.tools/gotestsum" + ) + + for pkg in "${install_packages[@]}"; do + go install "${pkg}@latest" + done +} + cleanup() { echo "Deleting temporal files..." cd ${WORKSPACE} diff --git a/.buildkite/scripts/package.sh b/.buildkite/scripts/package.sh new file mode 100755 index 000000000..be1cea776 --- /dev/null +++ b/.buildkite/scripts/package.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -euo pipefail + +source .buildkite/scripts/common.sh + +VERSION=$(awk '/const DefaultVersion/{print $NF}' version/version.go | tr -d '"') +PLATFORM_TYPE=$(uname -m) +MATRIX_TYPE="$1" +INFRA_REPO="https://github.com/repos/elastic/infra/contents" + +if [[ ${BUILDKITE_BRANCH} == "main" && ${MATRIX_TYPE} == "staging" ]]; then + echo "INFO: staging artifacts for the main branch are not required." + exit 0 +fi + +PLATFORMS="" +PACKAGES="" +if [[ ${PLATFORM_TYPE} == "arm" || ${PLATFORM_TYPE} == "aarch64" ]]; then + PLATFORMS="linux/arm64" + PACKAGES="docker" +fi + +add_bin_path +with_go +with_mage + +if [[ ${MATRIX_TYPE} == "staging" ]]; then + make release +else + make SNAPSHOT=true release +fi + +google_cloud_auth +upload_mbp_packages_to_gcp_bucket "build/distributions/" "${MATRIX_TYPE}" diff --git a/.mergify.yml b/.mergify.yml index 7ca86c680..594c25693 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -155,3 +155,16 @@ pull_request_rules: labels: - "backport" title: "[{{ destination_branch }}](backport #{{ number }}) {{ title }}" + - name: backport patches to 8.9 branch + conditions: + - merged + - label=backport-v8.9.0 + actions: + backport: + assignees: + - "{{ author }}" + branches: + - "8.9" + labels: + - "backport" + title: "[{{ destination_branch }}](backport #{{ number }}) {{ title }}" diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 0dd1a500f..570ee654f 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-0032a096-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-bbb2ee5d-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From dda011ed1e05bdd22c2a25ce855a7528fd30e271 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:51:55 -0400 Subject: [PATCH 03/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 570ee654f..fd45ab3af 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-bbb2ee5d-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-dd1f0db2-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 4cfc825934f4feffaf0eb8a6fcd595cf719fa4d1 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Mon, 3 Jul 2023 11:48:59 -0400 Subject: [PATCH 04/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2761) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index fd45ab3af..93c3a8de4 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-dd1f0db2-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-024bad78-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 399d02ce10f73d5eb7e01268ed329df9a85f6d2a Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Tue, 4 Jul 2023 11:49:51 -0400 Subject: [PATCH 05/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 93c3a8de4..c7fbb4b70 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-024bad78-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-872b2eab-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 5b7ceb0c95f5f1998512195c349fa8146d7c7871 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:55:08 -0400 Subject: [PATCH 06/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index c7fbb4b70..74d8e515f 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-872b2eab-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-55dfeb9a-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From a90bd61e1bedbabfb37f3b5055ae38fdf7f887d0 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:53:47 -0400 Subject: [PATCH 07/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2773) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 74d8e515f..19cd472eb 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-55dfeb9a-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-0f1ee255-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From e18decb1235f828e82cae313e7b443ce37d0486d Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Wed, 12 Jul 2023 11:51:50 -0400 Subject: [PATCH 08/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2779) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 19cd472eb..b5fbb188c 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-0f1ee255-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-a302929e-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From c8bbea4889cdce0a5934200ddadc51cdb53af116 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:56:12 -0400 Subject: [PATCH 09/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2784) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index b5fbb188c..6d8095259 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-a302929e-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-53fadbe2-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 2955afb9608412fcc93817802046a20c49eb27e3 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:52:31 -0400 Subject: [PATCH 10/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 6d8095259..14834450f 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-53fadbe2-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-905e99b1-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 1de82f02000ec679c7abf2ff1af759f803e05c84 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:51:11 -0400 Subject: [PATCH 11/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2794) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 14834450f..f08d01a24 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-905e99b1-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-6fafc4ad-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From 64158931241420c6ff074ac14be576a91fcfeebf Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:00:01 -0400 Subject: [PATCH 12/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2796) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index f08d01a24..84593eed1 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-6fafc4ad-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-446d2070-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file From a18a2e64b5854e5de49a8ae7b6a011007ff34230 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:56:29 -0400 Subject: [PATCH 13/13] chore: Updated to content "" in file "dev-tools/integration/.env" (#2801) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made with ❤️️ by updatecli Co-authored-by: apmmachine --- dev-tools/integration/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/integration/.env b/dev-tools/integration/.env index 84593eed1..b6b1b7112 100644 --- a/dev-tools/integration/.env +++ b/dev-tools/integration/.env @@ -1,4 +1,4 @@ -ELASTICSEARCH_VERSION=8.9.0-446d2070-SNAPSHOT +ELASTICSEARCH_VERSION=8.9.0-164e5e60-SNAPSHOT ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=changeme TEST_ELASTICSEARCH_HOSTS=localhost:9200 \ No newline at end of file