Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ otherwise no tag is added. {issue}42208[42208] {pull}42403[42403]
- Journald `include_matches.match` now accepts `+` to represent a logical disjunction (OR) {issue}40185[40185] {pull}42517[42517]
- The journald input is now generally available. {pull}42107[42107]
- Add metrics for number of events and pages published by HTTPJSON input. {issue}42340[42340] {pull}42442[42442]
- Filestram take over now supports taking over states from other Filestream inputs and dynamic loading of inputs (autodiscover and Elastic-Agent). {issue}42472[42472] {issue}42884[42884] {pull}42624[42624]
- Filestram take over now supports taking over states from other Filestream inputs and dynamic loading of inputs (autodiscover and Elastic-Agent). There is a new syntax for the configuration, but the previous one can still be used. {issue}42472[42472] {issue}42884[42884] {pull}42624[42624]
Comment thread
belimawr marked this conversation as resolved.
Outdated
- Add `etw` input fallback to attach an already existing session. {pull}42847[42847]
- Update CEL mito extensions to v1.17.0. {pull}42851[42851]
- Winlog input now can report its status to Elastic-Agent {pull}43089[43089]
Expand Down
5 changes: 4 additions & 1 deletion docs/reference/filebeat/filebeat-input-filestream.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,16 @@ The `take over` mode can work correctly only if the source (taken from) inputs a
`take_over.enabled: true` requires the `filestream` to have a unique ID.
::::


This `take over` mode was created to enable smooth migration from
deprecated `log` inputs to the new `filestream` inputs and to allow
changing `filestream` input IDs without data re-ingestion.

See [*Migrate `log` input configurations to `filestream`*](/reference/filebeat/migrate-to-filestream.md) for more details about the migration process.

The previous configuration format `take_over: true`, while
discouraged, is still supported to migrate state from the `log` input
Comment thread
belimawr marked this conversation as resolved.
Outdated
to `filestream`.
Comment thread
belimawr marked this conversation as resolved.

Comment thread
mauri870 marked this conversation as resolved.
::::{warning}
The `take over` mode is still in beta, however, it should be generally safe to use.
::::
Expand Down
4 changes: 3 additions & 1 deletion filebeat/input/filestream/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ type config struct {
IgnoreOlder time.Duration `config:"ignore_older"`
IgnoreInactive ignoreInactiveType `config:"ignore_inactive"`
Rotation *conf.Namespace `config:"rotation"`
TakeOver takeOverConfig `config:"take_over"`

// TakeOver is parsed independently from the rest of this struct, see
// 'GetTakeOverConfig' on internal/input-logfile/manager.go
TakeOver takeOverConfig `config:"-"`
// AllowIDDuplication is used by InputManager.Create
// (see internal/input-logfile/manager.go).
AllowIDDuplication bool `config:"allow_deprecated_id_duplication"`
Expand Down
84 changes: 84 additions & 0 deletions filebeat/input/filestream/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
require.NoError(t, err, "could not create input configuration")
inputs = append(inputs, cfg)
}
err := logp.DevelopmentSetup(logp.ToObserverOutput())

Check failure on line 231 in filebeat/input/filestream/config_test.go

View workflow job for this annotation

GitHub Actions / lint (macos-latest)

SA1019: logp.DevelopmentSetup is deprecated: Prefer using localized loggers. Use logp.NewDevelopmentLogger. (staticcheck)
require.NoError(t, err, "could not setup log for development")

err = ValidateInputIDs(inputs, logp.L())
Expand All @@ -239,3 +239,87 @@
})
}
}

func TestTakeOverCfg(t *testing.T) {
testCases := map[string]struct {
cfgYAML string
takeOverCfg takeOverConfig
expectErr bool
}{
"legacy mode enabled": {
cfgYAML: `
take_over: true`,
takeOverCfg: takeOverConfig{
Enabled: true,
},
},
"legacy mode disabled": {
cfgYAML: `
take_over: false`,
takeOverCfg: takeOverConfig{
Enabled: false,
},
},
"new mode enabled": {
cfgYAML: `
take_over:
enabled: true`,
takeOverCfg: takeOverConfig{
Enabled: true,
},
},
"new mode disabled": {
cfgYAML: `
take_over:
enabled: false`,
takeOverCfg: takeOverConfig{
Enabled: false,
},
},
"new mode with IDs": {
cfgYAML: `
take_over:
enabled: false
from_ids: ["foo", "bar"]`,
takeOverCfg: takeOverConfig{
Enabled: false,
FromIDs: []string{"foo", "bar"},
},
},
"take_over not defined": {
cfgYAML: "",
expectErr: false,
},
"invalid config": {
cfgYAML: "take_over.enabled: 42",
expectErr: true,
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
// It is required to have 'paths' set, so set it here for all tests
cfg := conf.MustNewConfigFrom(tc.cfgYAML)
err := cfg.SetChild("paths", -1, conf.MustNewConfigFrom(`["foo"]`))
if err != nil {
t.Fatalf("cannot set 'paths' in config: %s", err)
}
Comment thread
belimawr marked this conversation as resolved.
Outdated

_, inp, err := configure(cfg, logp.NewNopLogger())
if tc.expectErr {
require.Error(t, err, "expecting error when parsing config")
Comment thread
AndersonQ marked this conversation as resolved.
Outdated
require.Nil(t, inp, "returned filestream must be nil on error")
return
} else {
require.NoError(t, err, "expecting the config to be successfully parsed")
Comment thread
AndersonQ marked this conversation as resolved.
Outdated
}

f, ok := inp.(*filestream)
if !ok {
t.Fatalf("expecting type filestream, got %T", inp)
}
Comment thread
belimawr marked this conversation as resolved.
Outdated

assert.Equal(t, tc.takeOverCfg, f.takeOver, "take over config does not match")
})
}
}
7 changes: 7 additions & 0 deletions filebeat/input/filestream/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@
return nil, nil, err
}

takeOverEnabled, fromIDs, err := loginp.GetTakeOverConfig(cfg, log)
if err != nil {
return nil, nil, err
}
config.TakeOver.Enabled = takeOverEnabled
config.TakeOver.FromIDs = fromIDs

prospector, err := newProspector(config, log)
if err != nil {
return nil, nil, fmt.Errorf("cannot create prospector: %w", err)
Expand Down Expand Up @@ -393,7 +400,7 @@
continue
}

metrics.BytesProcessed.Add(uint64(message.Bytes))

Check failure on line 403 in filebeat/input/filestream/input.go

View workflow job for this annotation

GitHub Actions / lint (macos-latest)

G115: integer overflow conversion int -> uint64 (gosec)

// add "take_over" tag if `take_over` is set to true
if inp.takeOver.Enabled {
Expand Down
56 changes: 53 additions & 3 deletions filebeat/input/filestream/internal/input-logfile/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
if err != nil {
store.Release()
cim.shutdown()
return fmt.Errorf("Can not start registry cleanup process: %w", err)

Check failure on line 134 in filebeat/input/filestream/internal/input-logfile/manager.go

View workflow job for this annotation

GitHub Actions / lint (macos-latest)

ST1005: error strings should not be capitalized (staticcheck)
}

return nil
Expand All @@ -156,9 +156,9 @@
HarvesterLimit uint64 `config:"harvester_limit"`
AllowIDDuplication bool `config:"allow_deprecated_id_duplication"`
TakeOver struct {
Enabled bool `config:"enabled"`
FromIDs []string `config:"from_ids"`
} `config:"take_over"`
Enabled bool
FromIDs []string
} `config:"-"`
}{
CleanInactive: cim.DefaultCleanTimeout,
}
Expand All @@ -167,6 +167,13 @@
return nil, err
}

takeOverEnabled, fromIDs, err := GetTakeOverConfig(config, cim.Logger)
if err != nil {
return nil, err
}
settings.TakeOver.Enabled = takeOverEnabled
settings.TakeOver.FromIDs = fromIDs

if settings.ID == "" {
cim.Logger.Warn("filestream input without ID is discouraged, please add an ID and restart Filebeat")
}
Expand Down Expand Up @@ -325,3 +332,46 @@
func (i *sourceIdentifier) MatchesInput(id string) bool {
return strings.HasPrefix(id, i.prefix)
}

// GetTakeOverConfig returns the take over configuration as two independent
// values. In the YAML they're defined as 'take_over.enabled' and
// 'take_over.from_ids', respectively.
// It can handle both formats: the single boolean (`take_over: true|false`) and
// the object (show above). On error false, nil and the error are returned
func GetTakeOverConfig(cfg *conf.C, logger *logp.Logger) (bool, []string, error) {
Comment thread
mauri870 marked this conversation as resolved.
Outdated
// This is never going to return an error because the config path
// is a single element. Anyways, we still handle it.
Comment thread
belimawr marked this conversation as resolved.
Outdated
hasTakeOver, err := cfg.Has("take_over", -1)
if err != nil {
return false, nil, fmt.Errorf("cannot assert if 'take_over' is present: %w", err)
}
if hasTakeOver {
legacyEnabled, legacyErr := cfg.Bool("take_over", -1)
if legacyErr != nil {
// Try again with the new type
takeOverCfg, err := cfg.Child("take_over", -1)
// if there is an error now, then the config is definitely invalid
if err != nil {
return false, nil, errors.New("cannot parse the 'take_over' field")
}

// This is copied from filebeat/input/filestream/config.go
takeOver := struct {
Enabled bool `config:"enabled"`
FromIDs []string `config:"from_ids"`
}{}
if err := takeOverCfg.Unpack(&takeOver); err != nil {
return false, nil, err
}

return takeOver.Enabled, takeOver.FromIDs, nil
} else {
if legacyEnabled {
logger.Warn("using 'take_over: true' is deprecated, use the new format: 'take_over.enabled: true'")
}
return legacyEnabled, nil, nil
}
}
Comment thread
belimawr marked this conversation as resolved.
Outdated

return false, nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,65 @@ func newBufferLogger() (*logp.Logger, *bytes.Buffer) {
}))
return log, buf
}

func TestGetTakeOverConfig(t *testing.T) {
testCases := map[string]struct {
cfgYAML string
enabled bool
fromIDs []string
expectErr bool
}{
"legacy mode enabled": {
cfgYAML: `
take_over: true`,
enabled: true,
},
"legacy mode disabled": {
cfgYAML: `
take_over: false`,
enabled: false,
},
"new mode enabled": {
cfgYAML: `
take_over:
enabled: true`,
enabled: true,
},
"new mode disabled": {
cfgYAML: `
take_over:
enabled: false`,
enabled: false,
},
"new mode with IDs": {
cfgYAML: `
take_over:
enabled: true
from_ids: ["foo", "bar"]`,
enabled: true,
fromIDs: []string{"foo", "bar"},
},
"take_over not defined": {
cfgYAML: "",
expectErr: false,
},
"invalid config": {
cfgYAML: "take_over.enabled: 42",
expectErr: true,
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
enabled, fromIDs, err := GetTakeOverConfig(config.MustNewConfigFrom(tc.cfgYAML), logp.NewNopLogger())
if tc.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}

assert.Equal(t, tc.enabled, enabled, "wrong value for enabled")
assert.Equal(t, tc.fromIDs, fromIDs, "wrong value for from_ids")
})
}
}
1 change: 0 additions & 1 deletion filebeat/input/v2/compat/compat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ paths:
prospector:
scanner:
symlinks: true
take_over: true
Comment thread
belimawr marked this conversation as resolved.
type: test
`, inputID)

Expand Down
10 changes: 10 additions & 0 deletions filebeat/tests/integration/filestream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,11 @@
"expected-registry-happy-path.json"),
"Entries in the registry are different from the expectation",
)

deprecationLog := "using 'take_over: true' is deprecated, use the new format: 'take_over.enabled: true'"
if filebeat.LogContains(deprecationLog) {
t.Fatalf("deprecation log %q must not be present when using the new syntax", deprecationLog)
}
}

func TestFilestreamTakeOverFromLogInput(t *testing.T) {
Expand Down Expand Up @@ -655,6 +660,11 @@
"expected-registry-happy-path-log-input.json"),
"Entries in the registry are different from the expectation",
)

deprecationLog := "using 'take_over: true' is deprecated, use the new format: 'take_over.enabled: true'"
if !filebeat.LogContains(deprecationLog) {
t.Fatalf("did not find the deprecation log %q", deprecationLog)
}
}

func requireRegistryEntryRemoved(t *testing.T, workDir, identity string) {
Expand Down Expand Up @@ -731,7 +741,7 @@
func waitForEOF(t *testing.T, filebeat *integration.BeatProc, files []string) {
for _, path := range files {
if runtime.GOOS == "windows" {
path = strings.Replace(path, `\`, `\\`, -1)

Check failure on line 744 in filebeat/tests/integration/filestream_test.go

View workflow job for this annotation

GitHub Actions / lint (macos-latest)

QF1004: could use strings.ReplaceAll instead (staticcheck)
}
eofMsg := fmt.Sprintf("End of file reached: %s; Backoff now.", path)

Expand All @@ -750,7 +760,7 @@
func waitForDidnotChange(t *testing.T, filebeat *integration.BeatProc, files []string) {
for _, path := range files {
if runtime.GOOS == "windows" {
path = strings.Replace(path, `\`, `\\`, -1)

Check failure on line 763 in filebeat/tests/integration/filestream_test.go

View workflow job for this annotation

GitHub Actions / lint (macos-latest)

QF1004: could use strings.ReplaceAll instead (staticcheck)
}
eofMsg := fmt.Sprintf("File didn't change: %s", path)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ filebeat.inputs:
- {{.testdata}}/take-over/*.log
{{ if .takeOver }}
id: take-over-from-log-input
take_over:
enabled: true
take_over: true
file_identity.fingerprint: ~
prospector:
scanner:
Expand Down
Loading