diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b516e7b8792..4f7c465c76f 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -238,6 +238,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Fix 'make setup' instructions for a new beat {pull}24944[24944] - Fix out of date FreeBSD vagrantbox. {pull}25652[25652] - Fix handling of `file_selectors` in aws-s3 input. {pull}25792[25792] +- Fix ILM alias creation when write alias exists and initial index does not exist {pull}26143[26143] - Include date separator in the filename prefix of `dateRotator` to make sure nothing gets purged accidentally {pull}26176[26176] *Auditbeat* diff --git a/libbeat/idxmgmt/ilm/client_handler.go b/libbeat/idxmgmt/ilm/client_handler.go index 12b739c9946..d17af457ef4 100644 --- a/libbeat/idxmgmt/ilm/client_handler.go +++ b/libbeat/idxmgmt/ilm/client_handler.go @@ -191,19 +191,18 @@ func (h *ESClientHandler) CreateAlias(alias Alias) error { } // Note: actual aliases are accessible via the index - status, res, err := h.client.Request("PUT", "/"+firstIndex, "", nil, body) - if status == 400 { - // HasAlias fails if there is an index with the same name, that is - // what we want to check here. - _, err := h.HasAlias(alias.Name) - if err != nil { + if _, res, err := h.client.Request("PUT", "/"+firstIndex, "", nil, body); err != nil { + // Creating the index may fail for multiple reasons, e.g. because + // the index exists, or because the write alias exists and points + // to another index. + if ok, err := h.HasAlias(alias.Name); err != nil { + // HasAlias fails if there is an index with the same name. return err + } else if ok { + return errOf(ErrAliasAlreadyExists) } - return errOf(ErrAliasAlreadyExists) - } else if err != nil { return wrapErrf(err, ErrAliasCreateFailed, "failed to create alias: %s", res) } - return nil } diff --git a/libbeat/idxmgmt/ilm/client_handler_integration_test.go b/libbeat/idxmgmt/ilm/client_handler_integration_test.go index 936eb35dcd8..9471da7c9cf 100644 --- a/libbeat/idxmgmt/ilm/client_handler_integration_test.go +++ b/libbeat/idxmgmt/ilm/client_handler_integration_test.go @@ -136,13 +136,44 @@ func TestESClientHandler_Alias(t *testing.T) { assert.True(t, b) }) - t.Run("second create", func(t *testing.T) { + t.Run("create index exists", func(t *testing.T) { alias := makeAlias("esch-alias-2create") h := newESClientHandler(t) err := h.CreateAlias(alias) assert.NoError(t, err) + // Second time around creating the alias, ErrAliasAlreadyExists is returned: + // the initial index already exists and the write alias points to it. + err = h.CreateAlias(alias) + require.Error(t, err) + assert.Equal(t, ilm.ErrAliasAlreadyExists, ilm.ErrReason(err)) + + b, err := h.HasAlias(alias.Name) + assert.NoError(t, err) + assert.True(t, b) + }) + + t.Run("create alias exists", func(t *testing.T) { + alias := makeAlias("esch-alias-2create") + alias.Pattern = "000001" // no date math, so we get predictable index names + h := newESClientHandler(t) + + err := h.CreateAlias(alias) + assert.NoError(t, err) + + // Rollover, so write alias points at -000002. + es := newRawESClient(t) + _, _, err = es.Request("POST", "/"+alias.Name+"/_rollover", "", nil, nil) + require.NoError(t, err) + + // Delete -000001, simulating ILM delete. + _, _, err = es.Request("DELETE", "/"+alias.Name+"-"+alias.Pattern, "", nil, nil) + require.NoError(t, err) + + // Second time around creating the alias, ErrAliasAlreadyExists is returned: + // initial index does not exist, but the write alias exists and points to + // another index. err = h.CreateAlias(alias) require.Error(t, err) assert.Equal(t, ilm.ErrAliasAlreadyExists, ilm.ErrReason(err))