diff --git a/NOTICE.txt b/NOTICE.txt index 76189f17cce..c40525550dc 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -20797,37 +20797,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -Dependency : github.com/joeshaw/multierror -Version: v0.0.0-20140124173710-69b34d4ec901 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/joeshaw/multierror@v0.0.0-20140124173710-69b34d4ec901/LICENSE: - -The MIT License (MIT) - -Copyright (c) 2014 Joe Shaw - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------------------- Dependency : github.com/jonboulle/clockwork Version: v0.2.2 diff --git a/auditbeat/helper/hasher/hasher.go b/auditbeat/helper/hasher/hasher.go index d0612ab731d..7eac11b264c 100644 --- a/auditbeat/helper/hasher/hasher.go +++ b/auditbeat/helper/hasher/hasher.go @@ -23,6 +23,7 @@ import ( "crypto/sha256" "crypto/sha512" "encoding/hex" + "errors" "fmt" "hash" "io" @@ -32,7 +33,6 @@ import ( "github.com/cespare/xxhash/v2" "github.com/dustin/go-humanize" - "github.com/joeshaw/multierror" "golang.org/x/crypto/blake2b" "golang.org/x/crypto/sha3" "golang.org/x/time/rate" @@ -138,7 +138,7 @@ type Config struct { // Validate validates the config. func (c *Config) Validate() error { - var errs multierror.Errors + var errs []error for _, ht := range c.HashTypes { if !ht.IsValid() { @@ -160,7 +160,7 @@ func (c *Config) Validate() error { errs = append(errs, fmt.Errorf("invalid scan_rate_per_sec value: %w", err)) } - return errs.Err() + return errors.Join(errs...) } // FileHasher hashes the contents of files. diff --git a/auditbeat/module/auditd/config.go b/auditbeat/module/auditd/config.go index 6762a3924a9..32ca4413528 100644 --- a/auditbeat/module/auditd/config.go +++ b/auditbeat/module/auditd/config.go @@ -22,6 +22,7 @@ package auditd import ( "bufio" "bytes" + "errors" "fmt" "io" "os" @@ -30,8 +31,6 @@ import ( "strings" "time" - "github.com/joeshaw/multierror" - "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/go-libaudit/v2/rule" "github.com/elastic/go-libaudit/v2/rule/flags" @@ -93,7 +92,7 @@ var defaultConfig = Config{ // Validate validates the rules specified in the config. func (c *Config) Validate() error { - var errs multierror.Errors + var errs []error err := c.loadRules() if err != nil { errs = append(errs, err) @@ -115,7 +114,7 @@ func (c *Config) Validate() error { "'%v' (use unicast, multicast, or don't set a value)", c.SocketType)) } - return errs.Err() + return errors.Join(errs...) } // Rules returns a list of rules specified in the config. @@ -191,7 +190,7 @@ func (c Config) failureMode() (uint32, error) { // errors will be logged as warnings and any successfully parsed rules will be // returned. func readRules(reader io.Reader, source string, knownRules ruleSet, log *logp.Logger) (rules []auditRule, err error) { - var errs multierror.Errors + var errs []error s := bufio.NewScanner(reader) for lineNum := 1; s.Scan(); lineNum++ { @@ -229,9 +228,9 @@ func readRules(reader io.Reader, source string, knownRules ruleSet, log *logp.Lo if len(errs) != 0 { if log == nil { - return nil, fmt.Errorf("failed loading rules: %w", errs.Err()) + return nil, fmt.Errorf("failed loading rules: %w", errors.Join(errs...)) } - log.Warnf("errors loading rules: %v", errs.Err()) + log.Warnf("errors loading rules: %v", errors.Join(errs...)) } return rules, nil } diff --git a/auditbeat/module/file_integrity/config.go b/auditbeat/module/file_integrity/config.go index db934b02789..182463ebdd4 100644 --- a/auditbeat/module/file_integrity/config.go +++ b/auditbeat/module/file_integrity/config.go @@ -28,7 +28,6 @@ import ( "strings" "github.com/dustin/go-humanize" - "github.com/joeshaw/multierror" "github.com/elastic/beats/v7/libbeat/common/match" ) @@ -131,7 +130,7 @@ func (c *Config) Validate() error { sort.Strings(c.Paths) c.Paths = deduplicate(c.Paths) - var errs multierror.Errors + var errs []error var err error nextHash: @@ -187,7 +186,7 @@ nextHash: errs = append(errs, errors.New("backend can only be specified on linux")) } - return errs.Err() + return errors.Join(errs...) } // deduplicate deduplicates the given sorted string slice. The returned slice diff --git a/auditbeat/module/file_integrity/config_test.go b/auditbeat/module/file_integrity/config_test.go index 6104a01cfb8..725c73eac00 100644 --- a/auditbeat/module/file_integrity/config_test.go +++ b/auditbeat/module/file_integrity/config_test.go @@ -24,7 +24,6 @@ import ( "regexp/syntax" "testing" - "github.com/joeshaw/multierror" "github.com/stretchr/testify/assert" conf "github.com/elastic/elastic-agent-libs/config" @@ -85,11 +84,13 @@ func TestConfigInvalid(t *testing.T) { t.Fatal("expected ucfg.Error") } - merr, ok := ucfgErr.Reason().(*multierror.MultiError) + merr, ok := ucfgErr.Reason().(interface { + Unwrap() []error + }) if !ok { - t.Fatal("expected MultiError") + t.Fatal("expected slice error unwrapper") } - assert.Len(t, merr.Errors, 4) + assert.Len(t, merr.Unwrap(), 4) config, err = conf.NewConfigFrom(map[string]interface{}{ "paths": []string{"/usr/bin"}, diff --git a/auditbeat/module/file_integrity/fileinfo_posix.go b/auditbeat/module/file_integrity/fileinfo_posix.go index d87c8fc4e20..dd654a20e89 100644 --- a/auditbeat/module/file_integrity/fileinfo_posix.go +++ b/auditbeat/module/file_integrity/fileinfo_posix.go @@ -21,13 +21,13 @@ package file_integrity import ( "bytes" + "errors" "fmt" "os" "os/user" "strconv" "syscall" - "github.com/joeshaw/multierror" "github.com/pkg/xattr" ) @@ -61,7 +61,7 @@ func NewMetadata(path string, info os.FileInfo) (*Metadata, error) { } // Lookup UID and GID - var errs multierror.Errors + var errs []error owner, err := user.LookupId(strconv.Itoa(int(fileInfo.UID))) if err != nil { errs = append(errs, err) @@ -81,7 +81,7 @@ func NewMetadata(path string, info os.FileInfo) (*Metadata, error) { errs = append(errs, err) } - return fileInfo, errs.Err() + return fileInfo, errors.Join(errs...) } func fillExtendedAttributes(md *Metadata, path string) { diff --git a/auditbeat/module/file_integrity/fileinfo_windows.go b/auditbeat/module/file_integrity/fileinfo_windows.go index 0ab8055b5fb..8f8caec8b40 100644 --- a/auditbeat/module/file_integrity/fileinfo_windows.go +++ b/auditbeat/module/file_integrity/fileinfo_windows.go @@ -20,14 +20,13 @@ package file_integrity import ( + "errors" "fmt" "os" "syscall" "time" "unsafe" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/common/file" ) @@ -40,12 +39,12 @@ func NewMetadata(path string, info os.FileInfo) (*Metadata, error) { return nil, fmt.Errorf("unexpected fileinfo sys type %T for %v", info.Sys(), path) } - var errs multierror.Errors + var errs []error state := file.GetOSState(info) fileInfo := &Metadata{ - Inode: uint64(state.IdxHi<<32 + state.IdxLo), + Inode: state.IdxHi<<32 + state.IdxLo, Mode: info.Mode(), Size: uint64(info.Size()), MTime: time.Unix(0, attrs.LastWriteTime.Nanoseconds()).UTC(), @@ -73,7 +72,7 @@ func NewMetadata(path string, info os.FileInfo) (*Metadata, error) { if fileInfo.Origin, err = GetFileOrigin(path); err != nil { errs = append(errs, fmt.Errorf("GetFileOrigin failed: %w", err)) } - return fileInfo, errs.Err() + return fileInfo, errors.Join(errs...) } // fileOwner returns the SID and name (domain\user) of the file's owner. @@ -89,10 +88,11 @@ func fileOwner(path string) (sid, owner string, err error) { OwnerSecurityInformation, &securityID, nil, nil, nil, &securityDescriptor); err != nil { return "", "", fmt.Errorf("failed on GetSecurityInfo for %v: %w", path, err) } + //nolint:errcheck // ignore defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(securityDescriptor))) // Convert SID to a string and lookup the username. - var errs multierror.Errors + var errs []error sid, err = securityID.String() if err != nil { errs = append(errs, err) @@ -105,5 +105,5 @@ func fileOwner(path string) (sid, owner string, err error) { owner = fmt.Sprintf(`%s\%s`, domain, account) } - return sid, owner, errs.Err() + return sid, owner, errors.Join(errs...) } diff --git a/auditbeat/module/file_integrity/monitor/recursive.go b/auditbeat/module/file_integrity/monitor/recursive.go index 6cdb98f8464..aac80af46ad 100644 --- a/auditbeat/module/file_integrity/monitor/recursive.go +++ b/auditbeat/module/file_integrity/monitor/recursive.go @@ -18,12 +18,12 @@ package monitor import ( + "errors" "fmt" "os" "path/filepath" "github.com/fsnotify/fsnotify" - "github.com/joeshaw/multierror" "github.com/elastic/elastic-agent-libs/logp" ) @@ -113,7 +113,7 @@ func (watcher *recursiveWatcher) addRecursive(path string) error { return nil } - var errs multierror.Errors + var errs []error if err := watcher.watchFile(path, nil); err != nil { errs = append(errs, fmt.Errorf("failed adding watcher to '%s': %w", path, err)) } @@ -147,7 +147,7 @@ func (watcher *recursiveWatcher) addRecursive(path string) error { if err != nil { errs = append(errs, fmt.Errorf("failed to walk path '%s': %w", path, err)) } - return errs.Err() + return errors.Join(errs...) } func (watcher *recursiveWatcher) close() error { diff --git a/auditbeat/tracing/perfevent.go b/auditbeat/tracing/perfevent.go index 36f595aa676..0aae609a01f 100644 --- a/auditbeat/tracing/perfevent.go +++ b/auditbeat/tracing/perfevent.go @@ -29,7 +29,6 @@ import ( "time" "unsafe" - "github.com/joeshaw/multierror" "golang.org/x/sys/unix" "github.com/elastic/go-perf" @@ -336,7 +335,7 @@ func (c *PerfChannel) Close() error { defer close(c.errC) defer close(c.lostC) } - var errs multierror.Errors + var errs []error for _, ev := range c.events { if err := ev.Disable(); err != nil { errs = append(errs, fmt.Errorf("failed to disable event channel: %w", err)) @@ -345,7 +344,7 @@ func (c *PerfChannel) Close() error { errs = append(errs, fmt.Errorf("failed to close event channel: %w", err)) } } - return errs.Err() + return errors.Join(errs...) } // doneWrapperContext is a custom context.Context that is tailored to diff --git a/auditbeat/tracing/tracefs.go b/auditbeat/tracing/tracefs.go index 532eb75ca45..77ed5600293 100644 --- a/auditbeat/tracing/tracefs.go +++ b/auditbeat/tracing/tracefs.go @@ -21,14 +21,13 @@ package tracing import ( "bufio" + "errors" "fmt" "os" "path/filepath" "regexp" "strconv" "strings" - - "github.com/joeshaw/multierror" ) const ( @@ -53,7 +52,7 @@ type TraceFS struct { // It autodetects a tracefs mounted on /sys/kernel/tracing or via // debugfs at /sys/kernel/debug/tracing. func NewTraceFS() (*TraceFS, error) { - var errs multierror.Errors + var errs []error ptr, err := NewTraceFSWithPath(traceFSPath) if err != nil { errs = append(errs, err) @@ -64,7 +63,7 @@ func NewTraceFS() (*TraceFS, error) { errs = nil } } - return ptr, errs.Err() + return ptr, errors.Join(errs...) } // NewTraceFSWithPath creates a new accessor for the event tracing feature diff --git a/dev-tools/mage/integtest.go b/dev-tools/mage/integtest.go index 0b881a21e49..323853a1691 100644 --- a/dev-tools/mage/integtest.go +++ b/dev-tools/mage/integtest.go @@ -24,7 +24,6 @@ import ( "path/filepath" "strconv" - "github.com/joeshaw/multierror" "github.com/magefile/mage/mg" ) @@ -115,7 +114,7 @@ func (steps IntegrationTestSteps) Teardown(env map[string]string) error { } func (steps IntegrationTestSteps) teardownFrom(start int, env map[string]string) error { - var errs multierror.Errors + var errs []error for i := start; i >= 0; i-- { if mg.Verbose() { fmt.Printf("Teardown %s...\n", steps[i].Name()) @@ -124,7 +123,7 @@ func (steps IntegrationTestSteps) teardownFrom(start int, env map[string]string) errs = append(errs, fmt.Errorf("%s teardown failed: %w", steps[i].Name(), err)) } } - return errs.Err() + return errors.Join(errs...) } // IntegrationTester is interface used by the actual test runner. @@ -287,7 +286,9 @@ func (r *IntegrationRunner) Test(mageTarget string, test func() error) (err erro inTeardown := false defer func() { if recoverErr := recover(); recoverErr != nil { - err = recoverErr.(error) + if rerr, ok := recoverErr.(error); ok { + err = rerr + } if !inTeardown { // ignore errors _ = r.steps.Teardown(r.env) @@ -317,13 +318,13 @@ func (r *IntegrationRunner) Test(mageTarget string, test func() error) (err erro // Test runs the test on each runner and collects the errors. func (r IntegrationRunners) Test(mageTarget string, test func() error) error { - var errs multierror.Errors + var errs []error for _, runner := range r { if err := runner.Test(mageTarget, test); err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } func passThroughEnvs(env map[string]string, passthrough ...string) { diff --git a/dev-tools/mage/modules.go b/dev-tools/mage/modules.go index 14b7f7ab118..b41c68d6201 100644 --- a/dev-tools/mage/modules.go +++ b/dev-tools/mage/modules.go @@ -18,13 +18,12 @@ package mage import ( + "errors" "fmt" - "io/ioutil" "os" "path/filepath" "strings" - "github.com/joeshaw/multierror" "gopkg.in/yaml.v2" ) @@ -54,7 +53,7 @@ func GenerateDirModulesD() error { } moduleName := parts[1] - config, err := ioutil.ReadFile(f) + config, err := os.ReadFile(f) if err != nil { return err } @@ -68,7 +67,7 @@ func GenerateDirModulesD() error { } target := filepath.Join("modules.d", moduleName+".yml.disabled") - err = ioutil.WriteFile(createDir(target), []byte(data), 0644) + err = os.WriteFile(createDir(target), []byte(data), 0644) if err != nil { return err } @@ -100,7 +99,7 @@ func ValidateDirModulesDDatasetsDisabled() error { if err != nil { return err } - var errs multierror.Errors + var errs []error for path, cfg := range cfgs { // A config.yml is a list of module configurations. for modIdx, mod := range cfg { @@ -118,7 +117,7 @@ func ValidateDirModulesDDatasetsDisabled() error { } } } - return errs.Err() + return errors.Join(errs...) } func loadModulesD() (modules map[string][]moduleDefinition, err error) { @@ -128,7 +127,7 @@ func loadModulesD() (modules map[string][]moduleDefinition, err error) { } modules = make(map[string][]moduleDefinition, len(files)) for _, file := range files { - contents, err := ioutil.ReadFile(file) + contents, err := os.ReadFile(file) if err != nil { return nil, fmt.Errorf("reading %s: %w", file, err) } diff --git a/filebeat/fileset/pipelines.go b/filebeat/fileset/pipelines.go index c58a7c13edc..434ec8e7137 100644 --- a/filebeat/fileset/pipelines.go +++ b/filebeat/fileset/pipelines.go @@ -19,11 +19,10 @@ package fileset import ( "encoding/json" + "errors" "fmt" "strings" - "github.com/joeshaw/multierror" - "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/version" ) @@ -100,14 +99,14 @@ func (reg *ModuleRegistry) LoadPipelines(esClient PipelineLoader, overwrite bool // Rollback pipelines and return errors // TODO: Instead of attempting to load all pipelines and then rolling back loaded ones when there's an // error, validate all pipelines before loading any of them. This requires https://github.com/elastic/elasticsearch/issues/35495. - errs := multierror.Errors{err} + errs := []error{err} for _, pipelineID := range pipelineIDsLoaded { err = DeletePipeline(esClient, pipelineID) if err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } } } diff --git a/go.mod b/go.mod index 3e2fe304b67..c9fd7c5aa3f 100644 --- a/go.mod +++ b/go.mod @@ -100,7 +100,6 @@ require ( github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd - github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 github.com/jonboulle/clockwork v0.2.2 github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd github.com/jpillora/backoff v1.0.0 // indirect diff --git a/go.sum b/go.sum index ba2722f5baa..7817e64e754 100644 --- a/go.sum +++ b/go.sum @@ -640,8 +640,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= diff --git a/libbeat/cfgfile/list.go b/libbeat/cfgfile/list.go index 3a9e3429d29..3def249856d 100644 --- a/libbeat/cfgfile/list.go +++ b/libbeat/cfgfile/list.go @@ -22,7 +22,6 @@ import ( "fmt" "sync" - "github.com/joeshaw/multierror" "github.com/mitchellh/hashstructure" "github.com/elastic/beats/v7/libbeat/beat" @@ -85,7 +84,7 @@ func (r *RunnerList) Reload(configs []*reload.ConfigWithMeta) error { r.mutex.Lock() defer r.mutex.Unlock() - var errs multierror.Errors + var errs []error startList := map[uint64]*reload.ConfigWithMeta{} stopList := r.copyRunnerList() @@ -179,7 +178,7 @@ func (r *RunnerList) Reload(configs []*reload.ConfigWithMeta) error { // above it is done asynchronously. moduleRunning.Set(int64(len(r.runners))) - return errs.Err() + return errors.Join(errs...) } // Stop all runners diff --git a/libbeat/cfgfile/reload.go b/libbeat/cfgfile/reload.go index 930bd56eafd..ee3f0d58fac 100644 --- a/libbeat/cfgfile/reload.go +++ b/libbeat/cfgfile/reload.go @@ -18,13 +18,12 @@ package cfgfile import ( + "errors" "fmt" "path/filepath" "sync" "time" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common/reload" "github.com/elastic/elastic-agent-libs/config" @@ -262,7 +261,7 @@ func (rl *Reloader) Load(runnerFactory RunnerFactory) { func (rl *Reloader) loadConfigs(files []string) ([]*reload.ConfigWithMeta, error) { // Load all config objects result := []*reload.ConfigWithMeta{} - var errs multierror.Errors + var errs []error for _, file := range files { configs, err := LoadList(file) if err != nil { @@ -276,7 +275,7 @@ func (rl *Reloader) loadConfigs(files []string) ([]*reload.ConfigWithMeta, error } } - return result, errs.Err() + return result, errors.Join(errs...) } // Stop stops the reloader and waits for all modules to properly stop diff --git a/libbeat/common/cfgwarn/removed.go b/libbeat/common/cfgwarn/removed.go index 84144c8d984..3de5754cd49 100644 --- a/libbeat/common/cfgwarn/removed.go +++ b/libbeat/common/cfgwarn/removed.go @@ -18,23 +18,22 @@ package cfgwarn import ( + "errors" "fmt" "strings" - "github.com/joeshaw/multierror" - "github.com/elastic/elastic-agent-libs/config" ) func checkRemovedSettings(cfg *config.C, settings ...string) error { - var errs multierror.Errors + var errs []error for _, setting := range settings { if err := checkRemovedSetting(cfg, setting); err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } func checkRemovedSetting(cfg *config.C, setting string) error { diff --git a/libbeat/common/cfgwarn/removed_test.go b/libbeat/common/cfgwarn/removed_test.go index 50ebb6eefd0..8e0c674c355 100644 --- a/libbeat/common/cfgwarn/removed_test.go +++ b/libbeat/common/cfgwarn/removed_test.go @@ -21,7 +21,6 @@ import ( "errors" "testing" - "github.com/joeshaw/multierror" "github.com/stretchr/testify/assert" "github.com/elastic/elastic-agent-libs/config" @@ -93,7 +92,7 @@ func TestRemovedSettings(t *testing.T) { cfg: config.MustNewConfigFrom(map[string]interface{}{ "hello.world": "ok", }), - expected: multierror.Errors{errors.New("setting 'hello' has been removed")}.Err(), + expected: errors.Join(errors.New("setting 'hello' has been removed")), }, { name: "multiple obsolete settings", @@ -102,10 +101,10 @@ func TestRemovedSettings(t *testing.T) { "hello.world": "ok", "bad": "true", }), - expected: multierror.Errors{ + expected: errors.Join( errors.New("setting 'hello' has been removed"), errors.New("setting 'bad' has been removed"), - }.Err(), + ), }, { name: "multiple obsolete settings not on first level", @@ -114,10 +113,10 @@ func TestRemovedSettings(t *testing.T) { "filebeat.prospectors": "ok", "filebeat.config.prospectors": map[string]interface{}{"ok": "ok1"}, }), - expected: multierror.Errors{ + expected: errors.Join( errors.New("setting 'filebeat.config.prospectors' has been removed"), errors.New("setting 'filebeat.prospectors' has been removed"), - }.Err(), + ), }, } diff --git a/libbeat/common/schema/mapstriface/mapstriface.go b/libbeat/common/schema/mapstriface/mapstriface.go index d06119a5bf0..508072822e8 100644 --- a/libbeat/common/schema/mapstriface/mapstriface.go +++ b/libbeat/common/schema/mapstriface/mapstriface.go @@ -76,8 +76,6 @@ import ( "fmt" "time" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/schema" "github.com/elastic/elastic-agent-libs/logp" @@ -92,13 +90,13 @@ type ConvMap struct { } // Map drills down in the data dictionary by using the key -func (convMap ConvMap) Map(key string, event mapstr.M, data map[string]interface{}) multierror.Errors { +func (convMap ConvMap) Map(key string, event mapstr.M, data map[string]interface{}) []error { d, err := mapstr.M(data).GetValue(convMap.Key) if err != nil { err := schema.NewKeyNotFoundError(convMap.Key) err.Optional = convMap.Optional err.Required = convMap.Required - return multierror.Errors{err} + return []error{err} } switch subData := d.(type) { case map[string]interface{}, mapstr.M: @@ -116,7 +114,7 @@ func (convMap ConvMap) Map(key string, event mapstr.M, data map[string]interface msg := fmt.Sprintf("expected dictionary, found %T", subData) err := schema.NewWrongFormatError(convMap.Key, msg) logp.Err("%s", err.Error()) - return multierror.Errors{err} + return []error{err} } } diff --git a/libbeat/common/schema/mapstriface/mapstriface_test.go b/libbeat/common/schema/mapstriface/mapstriface_test.go index a96a15ba0c8..9a357a735f7 100644 --- a/libbeat/common/schema/mapstriface/mapstriface_test.go +++ b/libbeat/common/schema/mapstriface/mapstriface_test.go @@ -19,6 +19,7 @@ package mapstriface import ( "encoding/json" + "errors" "testing" "time" @@ -244,9 +245,10 @@ func TestFullFieldPathInErrors(t *testing.T) { } _, errs := c.Schema.ApplyTo(mapstr.M{}, c.Input) - assert.Error(t, errs.Err(), c.Description) + assert.NotEmpty(t, errs, c.Description) if assert.Equal(t, 1, len(errs), c.Description) { - keyErr, ok := errs[0].(s.KeyError) + var keyErr s.KeyError + ok := errors.As(errs[0], &keyErr) if assert.True(t, ok, c.Description) { assert.Equal(t, c.Expected, keyErr.Key(), c.Description) } diff --git a/libbeat/common/schema/mapstrstr/mapstrstr_test.go b/libbeat/common/schema/mapstrstr/mapstrstr_test.go index acd77a62c6d..1d2e58c57ff 100644 --- a/libbeat/common/schema/mapstrstr/mapstrstr_test.go +++ b/libbeat/common/schema/mapstrstr/mapstrstr_test.go @@ -18,6 +18,7 @@ package mapstrstr import ( + "errors" "testing" "time" @@ -124,9 +125,10 @@ func TestKeyInErrors(t *testing.T) { } _, errs := c.Schema.ApplyTo(mapstr.M{}, c.Input) - assert.Error(t, errs.Err(), c.Description) + assert.NotEmpty(t, errs, c.Description) if assert.Equal(t, 1, len(errs), c.Description) { - keyErr, ok := errs[0].(s.KeyError) + var keyErr s.KeyError + ok := errors.As(errs[0], &keyErr) if assert.True(t, ok, c.Description) { assert.Equal(t, c.Expected, keyErr.Key(), c.Description) } diff --git a/libbeat/common/schema/options.go b/libbeat/common/schema/options.go index de69b851cfc..6905c4f6b4c 100644 --- a/libbeat/common/schema/options.go +++ b/libbeat/common/schema/options.go @@ -18,7 +18,7 @@ package schema import ( - "github.com/joeshaw/multierror" + "errors" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -27,50 +27,53 @@ import ( var DefaultApplyOptions = []ApplyOption{AllRequired} // ApplyOption modifies the result of Apply -type ApplyOption func(mapstr.M, multierror.Errors) (mapstr.M, multierror.Errors) +type ApplyOption func(mapstr.M, []error) (mapstr.M, []error) // AllRequired considers any missing field as an error, except if explicitly // set as optional -func AllRequired(event mapstr.M, errors multierror.Errors) (mapstr.M, multierror.Errors) { +func AllRequired(event mapstr.M, errs []error) (mapstr.M, []error) { k := 0 - for i, err := range errors { - if err, ok := err.(*KeyNotFoundError); ok { - if err.Optional { + for i, err := range errs { + var keyErr *KeyNotFoundError + if errors.As(err, &keyErr) { + if keyErr.Optional { continue } } - errors[k] = errors[i] + errs[k] = errs[i] k++ } - return event, errors[:k] + return event, errs[:k] } // FailOnRequired considers missing fields as an error only if they are set // as required -func FailOnRequired(event mapstr.M, errors multierror.Errors) (mapstr.M, multierror.Errors) { +func FailOnRequired(event mapstr.M, errs []error) (mapstr.M, []error) { k := 0 - for i, err := range errors { - if err, ok := err.(*KeyNotFoundError); ok { - if !err.Required { + for i, err := range errs { + var keyErr *KeyNotFoundError + if errors.As(err, &keyErr) { + if !keyErr.Required { continue } } - errors[k] = errors[i] + errs[k] = errs[i] k++ } - return event, errors[:k] + return event, errs[:k] } // NotFoundKeys calls a function with the list of missing keys as parameter func NotFoundKeys(cb func(keys []string)) ApplyOption { - return func(event mapstr.M, errors multierror.Errors) (mapstr.M, multierror.Errors) { + return func(event mapstr.M, errs []error) (mapstr.M, []error) { var keys []string - for _, err := range errors { - if err, ok := err.(*KeyNotFoundError); ok { - keys = append(keys, err.Key()) + for _, err := range errs { + var keyErr *KeyNotFoundError + if errors.As(err, &keyErr) { + keys = append(keys, keyErr.Key()) } } cb(keys) - return event, errors + return event, errs } } diff --git a/libbeat/common/schema/options_test.go b/libbeat/common/schema/options_test.go index 3b99117f313..2eac62dc0a9 100644 --- a/libbeat/common/schema/options_test.go +++ b/libbeat/common/schema/options_test.go @@ -22,7 +22,6 @@ import ( "errors" - "github.com/joeshaw/multierror" "github.com/stretchr/testify/assert" "github.com/elastic/elastic-agent-libs/mapstr" @@ -32,19 +31,19 @@ func TestApplyOptions(t *testing.T) { cases := []struct { Description string Options []ApplyOption - Errors multierror.Errors + Errors []error ExpectError bool }{ { "all fields required, no error", []ApplyOption{AllRequired}, - multierror.Errors{}, + nil, false, }, { "all fields required, an error", []ApplyOption{AllRequired}, - multierror.Errors{ + []error{ NewKeyNotFoundError("foo"), }, true, @@ -52,7 +51,7 @@ func TestApplyOptions(t *testing.T) { { "all fields required, some other error, it should fail", []ApplyOption{AllRequired}, - multierror.Errors{ + []error{ errors.New("something bad happened"), }, true, @@ -60,7 +59,7 @@ func TestApplyOptions(t *testing.T) { { "all fields required, an error, collecting missing keys doesn't alter result", []ApplyOption{NotFoundKeys(func([]string) {}), AllRequired}, - multierror.Errors{ + []error{ NewKeyNotFoundError("foo"), }, true, @@ -68,7 +67,7 @@ func TestApplyOptions(t *testing.T) { { "fail on required, an error, not required", []ApplyOption{FailOnRequired}, - multierror.Errors{ + []error{ &KeyNotFoundError{errorKey: errorKey{"foo"}, Required: false}, }, false, @@ -76,7 +75,7 @@ func TestApplyOptions(t *testing.T) { { "fail on required, an error, required", []ApplyOption{FailOnRequired}, - multierror.Errors{ + []error{ &KeyNotFoundError{errorKey: errorKey{"foo"}, Required: true}, }, true, @@ -84,7 +83,7 @@ func TestApplyOptions(t *testing.T) { { "fail on required, some other error, it should fail", []ApplyOption{FailOnRequired}, - multierror.Errors{ + []error{ errors.New("something bad happened"), }, true, @@ -98,9 +97,9 @@ func TestApplyOptions(t *testing.T) { event, errors = opt(event, errors) } if c.ExpectError { - assert.Error(t, errors.Err(), c.Description) + assert.NotEmpty(t, errors, c.Description) } else { - assert.NoError(t, errors.Err(), c.Description) + assert.Empty(t, errors, c.Description) } } } @@ -108,31 +107,31 @@ func TestApplyOptions(t *testing.T) { func TestNotFoundKeys(t *testing.T) { cases := []struct { Description string - Errors multierror.Errors + Errors []error Expected []string }{ { "empty errors, no key", - multierror.Errors{}, + nil, []string{}, }, { "key not found error", - multierror.Errors{ + []error{ NewKeyNotFoundError("foo"), }, []string{"foo"}, }, { "only another error, so no key", - multierror.Errors{ + []error{ NewWrongFormatError("foo", ""), }, []string{}, }, { "two errors, only one is key not found", - multierror.Errors{ + []error{ NewKeyNotFoundError("foo"), NewWrongFormatError("bar", ""), }, diff --git a/libbeat/common/schema/schema.go b/libbeat/common/schema/schema.go index ad95ee64492..511fbf9dc79 100644 --- a/libbeat/common/schema/schema.go +++ b/libbeat/common/schema/schema.go @@ -18,7 +18,7 @@ package schema import ( - "github.com/joeshaw/multierror" + "errors" "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" @@ -33,7 +33,7 @@ type Schema map[string]Mapper type Mapper interface { // Map applies the Mapper conversion on the data and adds the result // to the event on the key. - Map(key string, event mapstr.M, data map[string]interface{}) multierror.Errors + Map(key string, event mapstr.M, data map[string]interface{}) []error HasKey(key string) bool } @@ -52,18 +52,19 @@ type Converter func(key string, data map[string]interface{}) (interface{}, error // Map applies the conversion on the data and adds the result // to the event on the key. -func (conv Conv) Map(key string, event mapstr.M, data map[string]interface{}) multierror.Errors { +func (conv Conv) Map(key string, event mapstr.M, data map[string]interface{}) []error { value, err := conv.Func(conv.Key, data) if err != nil { - if err, keyNotFound := err.(*KeyNotFoundError); keyNotFound { - err.Optional = conv.Optional - err.Required = conv.Required + var keyErr *KeyNotFoundError + if errors.As(err, &keyErr) { + keyErr.Optional = conv.Optional + keyErr.Required = conv.Required } if conv.IgnoreAllErrors { logp.Debug("schema", "ignoring error for key %q: %s", key, err) return nil } - return multierror.Errors{err} + return []error{err} } event[key] = value return nil @@ -77,7 +78,7 @@ func (conv Conv) HasKey(key string) bool { type Object map[string]Mapper // Map applies the schema for an object -func (o Object) Map(key string, event mapstr.M, data map[string]interface{}) multierror.Errors { +func (o Object) Map(key string, event mapstr.M, data map[string]interface{}) []error { subEvent := mapstr.M{} errs := applySchemaToEvent(subEvent, data, o) event[key] = subEvent @@ -90,7 +91,7 @@ func (o Object) HasKey(key string) bool { // ApplyTo adds the fields extracted from data, converted using the schema, to the // event map. -func (s Schema) ApplyTo(event mapstr.M, data map[string]interface{}, opts ...ApplyOption) (mapstr.M, multierror.Errors) { +func (s Schema) ApplyTo(event mapstr.M, data map[string]interface{}, opts ...ApplyOption) (mapstr.M, []error) { if len(opts) == 0 { opts = DefaultApplyOptions } @@ -103,8 +104,8 @@ func (s Schema) ApplyTo(event mapstr.M, data map[string]interface{}, opts ...App // Apply converts the fields extracted from data, using the schema, into a new map and reports back the errors. func (s Schema) Apply(data map[string]interface{}, opts ...ApplyOption) (mapstr.M, error) { - event, errors := s.ApplyTo(mapstr.M{}, data, opts...) - return event, errors.Err() + event, errs := s.ApplyTo(mapstr.M{}, data, opts...) + return event, errors.Join(errs...) } // HasKey checks if the key is part of the schema @@ -121,11 +122,12 @@ func hasKey(key string, mappers map[string]Mapper) bool { return false } -func applySchemaToEvent(event mapstr.M, data map[string]interface{}, conversions map[string]Mapper) multierror.Errors { - var errs multierror.Errors +func applySchemaToEvent(event mapstr.M, data map[string]interface{}, conversions map[string]Mapper) []error { + var errs []error for key, mapper := range conversions { - errors := mapper.Map(key, event, data) - errs = append(errs, errors...) + if err := mapper.Map(key, event, data); err != nil { + errs = append(errs, err...) + } } return errs } diff --git a/libbeat/dashboards/kibana_loader.go b/libbeat/dashboards/kibana_loader.go index 3320f996a2a..1062262c7f7 100644 --- a/libbeat/dashboards/kibana_loader.go +++ b/libbeat/dashboards/kibana_loader.go @@ -20,14 +20,13 @@ package dashboards import ( "context" "encoding/json" + "errors" "fmt" "net/url" "os" "path/filepath" "time" - "github.com/joeshaw/multierror" - beatversion "github.com/elastic/beats/v7/libbeat/version" "github.com/elastic/elastic-agent-libs/config" "github.com/elastic/elastic-agent-libs/kibana" @@ -130,7 +129,7 @@ func (loader KibanaLoader) ImportIndex(pattern mapstr.M) error { return fmt.Errorf("kibana version must be at least %s", minimumRequiredVersionSavedObjects.String()) } - var errs multierror.Errors + var errs []error params := url.Values{} params.Set("overwrite", "true") @@ -143,7 +142,7 @@ func (loader KibanaLoader) ImportIndex(pattern mapstr.M) error { if err != nil { errs = append(errs, fmt.Errorf("error loading index pattern: %w", err)) } - return errs.Err() + return errors.Join(errs...) } // ImportDashboard imports the dashboard file diff --git a/libbeat/mapping/field.go b/libbeat/mapping/field.go index c1264db26d2..b4128cb926a 100644 --- a/libbeat/mapping/field.go +++ b/libbeat/mapping/field.go @@ -22,8 +22,6 @@ import ( "fmt" "strings" - "github.com/joeshaw/multierror" - "github.com/elastic/elastic-agent-libs/mapstr" "github.com/elastic/go-ucfg/yaml" ) @@ -442,14 +440,14 @@ func ConcatFields(a, b Fields) (Fields, error) { } func (f Fields) conflicts(fields Fields) error { - var errs multierror.Errors + var errs []error for _, key := range fields.GetKeys() { keys := strings.Split(key, ".") if err := f.canConcat(key, keys); err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } // canConcat checks if the given string can be concatenated to the existing fields f diff --git a/libbeat/mapping/field_test.go b/libbeat/mapping/field_test.go index 933a0f8444e..4769ee35a2c 100644 --- a/libbeat/mapping/field_test.go +++ b/libbeat/mapping/field_test.go @@ -454,7 +454,7 @@ func TestFieldConcat(t *testing.T) { "duplicates fail": { a: Fields{{Name: "a"}}, b: Fields{{Name: "a"}}, - err: "1 error: fields contain key ", + err: "fields contain key ", }, "nested with common prefix": { a: Fields{{ @@ -495,7 +495,7 @@ func TestFieldConcat(t *testing.T) { Name: "a", Fields: Fields{{Name: "c"}}, }}, - err: "1 error: fields contain key ", + err: "fields contain key ", }, "a is prefix of b": { a: Fields{{Name: "a"}}, @@ -503,7 +503,7 @@ func TestFieldConcat(t *testing.T) { Name: "a", Fields: Fields{{Name: "b"}}, }}, - err: "1 error: fields contain non object node conflicting with key ", + err: "fields contain non object node conflicting with key ", }, "a is object and prefix of b": { a: Fields{{Name: "a", Type: "object"}}, @@ -522,7 +522,7 @@ func TestFieldConcat(t *testing.T) { Fields: Fields{{Name: "b"}}, }}, b: Fields{{Name: "a"}}, - err: "1 error: fields contain key ", + err: "fields contain key ", }, "multiple errors": { a: Fields{ @@ -536,7 +536,7 @@ func TestFieldConcat(t *testing.T) { {Name: "foo", Fields: Fields{{Name: "b", Fields: Fields{{Name: "c"}}}}}, }, - err: "2 errors: fields contain key ; fields contain non object node conflicting with key ", + err: "fields contain key \nfields contain non object node conflicting with key ", }, } diff --git a/libbeat/processors/processor.go b/libbeat/processors/processor.go index d1f84aee33e..05346f34cc5 100644 --- a/libbeat/processors/processor.go +++ b/libbeat/processors/processor.go @@ -18,11 +18,10 @@ package processors import ( + "errors" "fmt" "strings" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/elastic-agent-libs/logp" @@ -148,14 +147,14 @@ func (procs *Processors) All() []beat.Processor { } func (procs *Processors) Close() error { - var errs multierror.Errors + var errs []error for _, p := range procs.List { err := Close(p) if err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } // Run executes the all processors serially and returns the event and possibly diff --git a/libbeat/processors/util/netinfo.go b/libbeat/processors/util/netinfo.go index d4e694e5fa4..a472220f032 100644 --- a/libbeat/processors/util/netinfo.go +++ b/libbeat/processors/util/netinfo.go @@ -18,10 +18,9 @@ package util import ( + "errors" "net" "sort" - - "github.com/joeshaw/multierror" ) // GetNetInfo returns lists of IPs and MACs for the machine it is executed on. @@ -33,7 +32,7 @@ func GetNetInfo() (ipList []string, hwList []string, err error) { } // Keep track of all errors - var errs multierror.Errors + var errs []error for _, i := range ifaces { // Skip loopback interfaces @@ -62,7 +61,7 @@ func GetNetInfo() (ipList []string, hwList []string, err error) { } } - return ipList, unique(hwList), errs.Err() + return ipList, unique(hwList), errors.Join(errs...) } // formatHardwareAddr formats hardware addresses according to the ECS spec. diff --git a/libbeat/publisher/processing/processors.go b/libbeat/publisher/processing/processors.go index a3fe42c88da..e5a33741a3f 100644 --- a/libbeat/publisher/processing/processors.go +++ b/libbeat/publisher/processing/processors.go @@ -18,13 +18,12 @@ package processing import ( + "errors" "fmt" "strings" "sync" "time" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/outputs/codec/json" @@ -90,14 +89,14 @@ func (p *group) Close() error { if p == nil { return nil } - var errs multierror.Errors + var errs []error for _, processor := range p.list { err := processors.Close(processor) if err != nil { errs = append(errs, err) } } - return errs.Err() + return errors.Join(errs...) } func (p *group) String() string { diff --git a/metricbeat/helper/socket/ptable.go b/metricbeat/helper/socket/ptable.go index 67197d7f38a..158ff1fed0a 100644 --- a/metricbeat/helper/socket/ptable.go +++ b/metricbeat/helper/socket/ptable.go @@ -20,11 +20,11 @@ package socket import ( + "errors" "os" "strconv" "strings" - "github.com/joeshaw/multierror" "github.com/prometheus/procfs" ) @@ -86,7 +86,7 @@ func (t *ProcTable) Refresh() error { return err } - var errs multierror.Errors + var errs []error inodes := map[uint32]*Proc{} cachedProcs := make(map[int]*Proc, len(procs)) for _, pi := range procs { @@ -125,7 +125,7 @@ func (t *ProcTable) Refresh() error { t.procs = cachedProcs t.inodes = inodes - return errs.Err() + return errors.Join(errs...) } func (t *ProcTable) accessibleProcs() ([]procfs.Proc, error) { diff --git a/metricbeat/mb/builders.go b/metricbeat/mb/builders.go index 4c55e3e3944..37256633851 100644 --- a/metricbeat/mb/builders.go +++ b/metricbeat/mb/builders.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/gofrs/uuid/v5" - "github.com/joeshaw/multierror" conf "github.com/elastic/elastic-agent-libs/config" "github.com/elastic/elastic-agent-libs/logp" @@ -108,7 +107,7 @@ func createModule(r *Register, bm BaseModule) (Module, error) { func initMetricSets(r *Register, m Module) ([]MetricSet, error) { var ( - errs multierror.Errors + errs []error ) bms, err := newBaseMetricSets(r, m) @@ -151,7 +150,7 @@ func initMetricSets(r *Register, m Module) ([]MetricSet, error) { metricsets = append(metricsets, metricSet) } - return metricsets, errs.Err() + return metricsets, errors.Join(errs...) } // newBaseMetricSets creates a new BaseMetricSet for all MetricSets defined diff --git a/metricbeat/module/apache/status/data.go b/metricbeat/module/apache/status/data.go index a1c8e0e6663..b2036785c7d 100644 --- a/metricbeat/module/apache/status/data.go +++ b/metricbeat/module/apache/status/data.go @@ -19,6 +19,7 @@ package status import ( "bufio" + "errors" "regexp" "strings" @@ -28,10 +29,10 @@ import ( ) var ( - scoreboardRegexp = regexp.MustCompile("(Scoreboard):\\s+((_|S|R|W|K|D|C|L|G|I|\\.)+)") + scoreboardRegexp = regexp.MustCompile(`(Scoreboard):\s+((_|S|R|W|K|D|C|L|G|I|\.)+)`) // This should match: "CPUSystem: .01" - matchNumber = regexp.MustCompile("(^[0-9a-zA-Z ]+):\\s+(\\d*\\.?\\d+)") + matchNumber = regexp.MustCompile(`(^[0-9a-zA-Z ]+):\s+(\d*\.?\d+)`) schema = s.Schema{ "total_accesses": c.Int("Total Accesses"), @@ -102,8 +103,8 @@ func applySchema(event mapstr.M, fullEvent map[string]interface{}) error { if _, found := fullEvent["ServerUptimeSeconds"]; !found { applicableSchema = schemaOld } - _, err := applicableSchema.ApplyTo(event, fullEvent) - return err.Err() + _, errs := applicableSchema.ApplyTo(event, fullEvent) + return errors.Join(errs...) } // Map body to MapStr diff --git a/metricbeat/module/elasticsearch/ccr/data.go b/metricbeat/module/elasticsearch/ccr/data.go index 5301f6e217c..c4ab21d8713 100644 --- a/metricbeat/module/elasticsearch/ccr/data.go +++ b/metricbeat/module/elasticsearch/ccr/data.go @@ -19,13 +19,12 @@ package ccr import ( "encoding/json" + "errors" "fmt" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/elastic-agent-libs/mapstr" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/mb" @@ -142,7 +141,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return fmt.Errorf("failure parsing Elasticsearch CCR Stats API response: %w", err) } - var errs multierror.Errors + var errs []error for _, followerIndex := range data.FollowStats.Indices { for _, followerShard := range followerIndex.Shards { event := mb.Event{} @@ -169,5 +168,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX } } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/enrich/data.go b/metricbeat/module/elasticsearch/enrich/data.go index e400160698c..4722ec83006 100644 --- a/metricbeat/module/elasticsearch/enrich/data.go +++ b/metricbeat/module/elasticsearch/enrich/data.go @@ -25,8 +25,6 @@ import ( "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/elastic-agent-libs/mapstr" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/mb" @@ -77,7 +75,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return fmt.Errorf("failure parsing Elasticsearch Enrich Stats API response: %w", err) } - var errs multierror.Errors + var errs []error for _, stat := range data.CoordinatorStats { event := mb.Event{} @@ -157,5 +155,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX r.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/index/data.go b/metricbeat/module/elasticsearch/index/data.go index d8bec4939d6..d73126d3e25 100644 --- a/metricbeat/module/elasticsearch/index/data.go +++ b/metricbeat/module/elasticsearch/index/data.go @@ -19,10 +19,9 @@ package index import ( "encoding/json" + "errors" "fmt" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/metricbeat/helper" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/beats/v7/metricbeat/mb" @@ -190,7 +189,7 @@ func eventsMapping(r mb.ReporterV2, httpClient *helper.HTTP, info elasticsearch. return fmt.Errorf("failure parsing Indices Stats Elasticsearch API response: %w", err) } - var errs multierror.Errors + var errs []error for name := range indicesStats.Indices { event := mb.Event{ ModuleFields: mapstr.M{}, @@ -234,7 +233,7 @@ func eventsMapping(r mb.ReporterV2, httpClient *helper.HTTP, info elasticsearch. r.Event(event) } - return errs.Err() + return errors.Join(errs...) } func parseAPIResponse(content []byte, indicesStats *stats) error { @@ -308,8 +307,15 @@ func getIndexStatus(shards map[string]interface{}) (string, error) { shard := mapstr.M(s) - isPrimary := shard["primary"].(bool) - state := shard["state"].(string) + isPrimary, ok := shard["primary"].(bool) + if !ok { + return "", fmt.Errorf("%v.shards[primary] is not a bool", indexName) + } + + state, ok := shard["state"].(string) + if !ok { + return "", fmt.Errorf("%v.shards[state] is not a string", indexName) + } if isPrimary { areAllPrimariesStarted = areAllPrimariesStarted && (state == "STARTED") @@ -357,8 +363,15 @@ func getIndexShardStats(shards mapstr.M) (*shardStats, error) { shard := mapstr.M(s) - isPrimary := shard["primary"].(bool) - state := shard["state"].(string) + isPrimary, ok := shard["primary"].(bool) + if !ok { + return nil, fmt.Errorf("%v.shards[primary] is not a bool", indexName) + } + + state, ok := shard["state"].(string) + if !ok { + return nil, fmt.Errorf("%v.shards[state] is not a string", indexName) + } if isPrimary { primaries++ diff --git a/metricbeat/module/elasticsearch/index_recovery/data.go b/metricbeat/module/elasticsearch/index_recovery/data.go index c71b17e56e6..67bc2c90cc4 100644 --- a/metricbeat/module/elasticsearch/index_recovery/data.go +++ b/metricbeat/module/elasticsearch/index_recovery/data.go @@ -19,11 +19,10 @@ package index_recovery import ( "encoding/json" + "errors" "fmt" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/helper/elastic" @@ -97,7 +96,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return fmt.Errorf("failure parsing Elasticsearch Recovery API response: %w", err) } - var errs multierror.Errors + var errs []error for indexName, d := range data { shards, ok := d["shards"] if !ok { @@ -133,5 +132,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX r.Event(event) } } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/ml_job/data.go b/metricbeat/module/elasticsearch/ml_job/data.go index 7954d106b25..c70647dc7a2 100644 --- a/metricbeat/module/elasticsearch/ml_job/data.go +++ b/metricbeat/module/elasticsearch/ml_job/data.go @@ -19,10 +19,9 @@ package ml_job import ( "encoding/json" + "errors" "fmt" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/elastic-agent-libs/mapstr" @@ -61,7 +60,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return fmt.Errorf("failure parsing Elasticsearch ML Job Stats API response: %w", err) } - var errs multierror.Errors + var errs []error for _, job := range jobsData.Jobs { if err := elastic.FixTimestampField(job, "data_counts.earliest_record_timestamp"); err != nil { @@ -83,7 +82,12 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX event.ModuleFields.Put("cluster.id", info.ClusterID) if node, exists := job["node"]; exists { - nodeHash := node.(map[string]interface{}) + nodeHash, ok := node.(map[string]interface{}) + if !ok { + errs = append(errs, errors.New("job[node] is not a map")) + continue + } + event.ModuleFields.Put("node.id", nodeHash["id"]) event.ModuleFields.Put("node.name", nodeHash["name"]) } @@ -100,5 +104,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX r.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/node/data.go b/metricbeat/module/elasticsearch/node/data.go index 4576cc4ac88..78fea5cfe43 100644 --- a/metricbeat/module/elasticsearch/node/data.go +++ b/metricbeat/module/elasticsearch/node/data.go @@ -19,13 +19,12 @@ package node import ( "encoding/json" + "errors" "fmt" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/elastic-agent-libs/mapstr" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/mb" @@ -74,7 +73,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return fmt.Errorf("failure parsing Elasticsearch Node Stats API response: %w", err) } - var errs multierror.Errors + var errs []error for id, node := range nodesStruct.Nodes { event := mb.Event{} @@ -103,5 +102,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX r.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/node_stats/data.go b/metricbeat/module/elasticsearch/node_stats/data.go index 2673baa3b06..95a462d077c 100644 --- a/metricbeat/module/elasticsearch/node_stats/data.go +++ b/metricbeat/module/elasticsearch/node_stats/data.go @@ -19,13 +19,12 @@ package node_stats import ( "encoding/json" + "errors" "fmt" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/elastic-agent-libs/mapstr" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/mb" @@ -375,7 +374,7 @@ func eventsMapping(r mb.ReporterV2, m elasticsearch.MetricSetAPI, info elasticse return err } - var errs multierror.Errors + var errs []error for nodeID, node := range nodeData.Nodes { isMaster := nodeID == masterNodeID @@ -452,5 +451,5 @@ func eventsMapping(r mb.ReporterV2, m elasticsearch.MetricSetAPI, info elasticse r.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/pending_tasks/data.go b/metricbeat/module/elasticsearch/pending_tasks/data.go index a75c2dea6b6..ba22f012302 100644 --- a/metricbeat/module/elasticsearch/pending_tasks/data.go +++ b/metricbeat/module/elasticsearch/pending_tasks/data.go @@ -19,10 +19,9 @@ package pending_tasks import ( "encoding/json" + "errors" "fmt" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/helper/elastic" @@ -54,7 +53,7 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX return elastic.MakeErrorForMissingField("tasks", elastic.Elasticsearch) } - var errs multierror.Errors + var errs []error for _, task := range tasksStruct.Tasks { event := mb.Event{} @@ -81,5 +80,5 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX r.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/metricbeat/module/elasticsearch/shard/data.go b/metricbeat/module/elasticsearch/shard/data.go index e2c211035fb..65b38b31277 100644 --- a/metricbeat/module/elasticsearch/shard/data.go +++ b/metricbeat/module/elasticsearch/shard/data.go @@ -19,6 +19,7 @@ package shard import ( "encoding/json" + "errors" "strconv" "github.com/elastic/beats/v7/metricbeat/helper/elastic" @@ -26,8 +27,6 @@ import ( "fmt" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/mb" @@ -65,7 +64,7 @@ func eventsMapping(r mb.ReporterV2, content []byte, isXpack bool) error { return fmt.Errorf("failure parsing Elasticsearch Cluster State API response: %w", err) } - var errs multierror.Errors + var errs []error for _, index := range stateData.RoutingTable.Indices { for _, shards := range index.Shards { for i, shard := range shards { @@ -146,7 +145,7 @@ func eventsMapping(r mb.ReporterV2, content []byte, isXpack bool) error { } } - return errs.Err() + return errors.Join(errs...) } func getSourceNode(nodeID string, stateData *stateStruct) (mapstr.M, error) { diff --git a/metricbeat/module/jolokia/jmx/data.go b/metricbeat/module/jolokia/jmx/data.go index 59498764cf9..accc2145d4d 100644 --- a/metricbeat/module/jolokia/jmx/data.go +++ b/metricbeat/module/jolokia/jmx/data.go @@ -18,11 +18,10 @@ package jmx import ( + "errors" "fmt" "strings" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" @@ -120,7 +119,7 @@ func eventMapping(entries []Entry, mapping AttributeMapping) ([]mapstr.M, error) // Generate a different event for each wildcard mbean, and and additional one // for non-wildcard requested mbeans, group them by event name if defined mbeanEvents := make(map[eventKey]mapstr.M) - var errs multierror.Errors + var errs []error for _, v := range entries { if v.Value == nil || v.Request.Attribute == nil { @@ -136,11 +135,13 @@ func eventMapping(entries []Entry, mapping AttributeMapping) ([]mapstr.M, error) errs = append(errs, err) } case map[string]interface{}: - constructEvents(entryValues, v, mbeanEvents, mapping, errs) + errs = constructEvents(entryValues, v, mbeanEvents, mapping, errs) } case []interface{}: - entryValues := v.Value.(map[string]interface{}) - constructEvents(entryValues, v, mbeanEvents, mapping, errs) + entryValues, ok := v.Value.(map[string]interface{}) + if ok { + errs = constructEvents(entryValues, v, mbeanEvents, mapping, errs) + } } } @@ -149,10 +150,10 @@ func eventMapping(entries []Entry, mapping AttributeMapping) ([]mapstr.M, error) events = append(events, event) } - return events, errs.Err() + return events, errors.Join(errs...) } -func constructEvents(entryValues map[string]interface{}, v Entry, mbeanEvents map[eventKey]mapstr.M, mapping AttributeMapping, errs multierror.Errors) { +func constructEvents(entryValues map[string]interface{}, v Entry, mbeanEvents map[eventKey]mapstr.M, mapping AttributeMapping, errs []error) []error { hasWildcard := strings.Contains(v.Request.Mbean, "*") for attribute, value := range entryValues { if !hasWildcard { @@ -180,6 +181,7 @@ func constructEvents(entryValues map[string]interface{}, v Entry, mbeanEvents ma } } } + return errs } func selectEvent(events map[eventKey]mapstr.M, key eventKey) mapstr.M { diff --git a/packetbeat/module/pipeline.go b/packetbeat/module/pipeline.go index c90f0adda76..74bb7d36b45 100644 --- a/packetbeat/module/pipeline.go +++ b/packetbeat/module/pipeline.go @@ -26,7 +26,6 @@ import ( "path/filepath" "strings" - "github.com/joeshaw/multierror" "gopkg.in/yaml.v2" "github.com/elastic/beats/v7/filebeat/fileset" @@ -141,14 +140,14 @@ func load(esClient *eslegclient.Connection, pipelines []pipeline, overwritePipel } if err != nil { - errs := multierror.Errors{err} + errs := []error{err} for _, id := range loaded { err = fileset.DeletePipeline(esClient, id) if err != nil { errs = append(errs, err) } } - return nil, errs.Err() + return nil, errors.Join(errs...) } return loaded, nil } @@ -182,6 +181,7 @@ func applyTemplates(prefix string, version string, filename string, original []b if err != nil { return nil, fmt.Errorf("failed to sanitize the YAML pipeline file: %s: %w", filename, err) } + //nolint:errcheck // ignore content = newContent.(map[string]interface{}) default: return nil, fmt.Errorf("unsupported extension '%s' for pipeline file: %s", extension, filename) diff --git a/winlogbeat/config/config.go b/winlogbeat/config/config.go index 08ea6822a32..d5dced5efb4 100644 --- a/winlogbeat/config/config.go +++ b/winlogbeat/config/config.go @@ -19,11 +19,10 @@ package config import ( + "errors" "fmt" "time" - "github.com/joeshaw/multierror" - conf "github.com/elastic/elastic-agent-libs/config" ) @@ -49,12 +48,12 @@ type WinlogbeatConfig struct { // Validate validates the WinlogbeatConfig data and returns an error describing // all problems or nil if there are none. func (ebc WinlogbeatConfig) Validate() error { - var errs multierror.Errors + var errs []error if len(ebc.EventLogs) == 0 { errs = append(errs, fmt.Errorf("at least one event log must be "+ "configured as part of event_logs")) } - return errs.Err() + return errors.Join(errs...) } diff --git a/winlogbeat/config/config_test.go b/winlogbeat/config/config_test.go index 2efd501336c..2ca49808804 100644 --- a/winlogbeat/config/config_test.go +++ b/winlogbeat/config/config_test.go @@ -60,8 +60,7 @@ func TestConfigValidate(t *testing.T) { }, { WinlogbeatConfig{}, - "1 error: at least one event log must be configured as part of " + - "event_logs", + "at least one event log must be configured as part of event_logs", }, } diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index 43654284218..4b6e9f7b50e 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -32,7 +32,6 @@ import ( "syscall" "time" - "github.com/joeshaw/multierror" "github.com/rcrowley/go-metrics" "golang.org/x/sys/windows" @@ -142,7 +141,7 @@ var defaultWinEventLogConfig = winEventLogConfig{ // Validate validates the winEventLogConfig data and returns an error describing // any problems or nil. func (c *winEventLogConfig) Validate() error { - var errs multierror.Errors + var errs []error if c.XMLQuery != "" { if c.ID == "" { @@ -170,7 +169,7 @@ func (c *winEventLogConfig) Validate() error { errs = append(errs, fmt.Errorf("event log is missing a 'name'")) } - return errs.Err() + return errors.Join(errs...) } // Validate that winEventLog implements the EventLog interface. diff --git a/winlogbeat/module/pipeline.go b/winlogbeat/module/pipeline.go index 3ddc4f10f11..8e36703c92e 100644 --- a/winlogbeat/module/pipeline.go +++ b/winlogbeat/module/pipeline.go @@ -27,7 +27,6 @@ import ( "path/filepath" "strings" - "github.com/joeshaw/multierror" "gopkg.in/yaml.v2" "github.com/elastic/beats/v7/filebeat/fileset" @@ -167,14 +166,14 @@ func load(esClient *eslegclient.Connection, pipelines []pipeline, overwritePipel } if err != nil { - errs := multierror.Errors{err} + errs := []error{err} for _, id := range loaded { err = fileset.DeletePipeline(esClient, id) if err != nil { errs = append(errs, err) } } - return nil, errs.Err() + return nil, errors.Join(errs...) } return loaded, nil } @@ -208,6 +207,7 @@ func applyTemplates(prefix string, version string, filename string, original []b if err != nil { return nil, fmt.Errorf("failed to sanitize the YAML pipeline file: %s: %w", filename, err) } + //nolint:errcheck // ignore content = newContent.(map[string]interface{}) default: return nil, fmt.Errorf("unsupported extension '%s' for pipeline file: %s", extension, filename) diff --git a/winlogbeat/sys/wineventlog/query.go b/winlogbeat/sys/wineventlog/query.go index c48208f38fa..13a51cb0ac6 100644 --- a/winlogbeat/sys/wineventlog/query.go +++ b/winlogbeat/sys/wineventlog/query.go @@ -19,14 +19,13 @@ package wineventlog import ( "bytes" + "errors" "fmt" "regexp" "strconv" "strings" "text/template" "time" - - "github.com/joeshaw/multierror" ) const ( @@ -73,7 +72,7 @@ type Query struct { // Build builds a query from the given parameters. The query is returned as a // XML string and can be used with Subscribe function. func (q Query) Build() (string, error) { - var errs multierror.Errors + var errs []error if q.Log == "" { errs = append(errs, fmt.Errorf("empty log name")) } @@ -91,7 +90,7 @@ func (q Query) Build() (string, error) { } } if len(errs) > 0 { - return "", errs.Err() + return "", errors.Join(errs...) } return executeTemplate(queryTemplate, qp) } diff --git a/x-pack/auditbeat/module/system/host/host.go b/x-pack/auditbeat/module/system/host/host.go index 8ea3a899de2..e9edbf08cc5 100644 --- a/x-pack/auditbeat/module/system/host/host.go +++ b/x-pack/auditbeat/module/system/host/host.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/binary" "encoding/gob" + "errors" "fmt" "io" "math" @@ -16,7 +17,6 @@ import ( "time" "github.com/cespare/xxhash/v2" - "github.com/joeshaw/multierror" "github.com/elastic/beats/v7/auditbeat/ab" "github.com/elastic/beats/v7/auditbeat/datastore" @@ -117,7 +117,6 @@ func (host *Host) changeDetectionHash() uint64 { return h.Sum64() } -//nolint:errcheck // All checks are for mapstr.Put. func (host *Host) toMapStr() mapstr.M { mapstr := mapstr.M{ // https://github.com/elastic/ecs#-host-fields @@ -289,7 +288,6 @@ func (ms *MetricSet) reportChanges(report mb.ReporterV2) error { var events []mb.Event // Report ID changes as a separate, special event. - //nolint:errcheck // All checks are for mapstr.Put. if ms.lastHost.Info.UniqueID != currentHost.Info.UniqueID { /* Issue two events - one for the host with the old ID, one for the new @@ -510,7 +508,7 @@ func getNetInfo() ([]net.IP, []net.HardwareAddr, error) { } // Keep track of all errors - var errs multierror.Errors + var errs []error for _, i := range ifaces { // Skip loopback interfaces @@ -546,5 +544,5 @@ func getNetInfo() ([]net.IP, []net.HardwareAddr, error) { } } - return append(ipv4List, ipv6List...), hwList, errs.Err() + return append(ipv4List, ipv6List...), hwList, errors.Join(errs...) } diff --git a/x-pack/auditbeat/module/system/package/package.go b/x-pack/auditbeat/module/system/package/package.go index 14aaadfdc56..90c976f68a5 100644 --- a/x-pack/auditbeat/module/system/package/package.go +++ b/x-pack/auditbeat/module/system/package/package.go @@ -25,7 +25,6 @@ import ( "github.com/cespare/xxhash/v2" "github.com/gofrs/uuid/v5" - "github.com/joeshaw/multierror" "go.etcd.io/bbolt" "github.com/elastic/beats/v7/auditbeat/ab" @@ -255,7 +254,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Close cleans up the MetricSet when it finishes. func (ms *MetricSet) Close() error { - var errs multierror.Errors + var errs []error errs = append(errs, closeDataset()) @@ -263,7 +262,7 @@ func (ms *MetricSet) Close() error { errs = append(errs, ms.bucket.Close()) } - return errs.Err() + return errors.Join(errs...) } // Fetch collects data about the host. It is invoked periodically. diff --git a/x-pack/auditbeat/module/system/socket/helper/loopback.go b/x-pack/auditbeat/module/system/socket/helper/loopback.go index 79512c602bc..c723d27d6a3 100644 --- a/x-pack/auditbeat/module/system/socket/helper/loopback.go +++ b/x-pack/auditbeat/module/system/socket/helper/loopback.go @@ -7,14 +7,13 @@ package helper import ( + "crypto/rand" "errors" "fmt" - "math/rand" "net" "time" "unsafe" - "github.com/joeshaw/multierror" "golang.org/x/sys/unix" ) @@ -81,7 +80,10 @@ func NewIPv6Loopback() (lo IPv6Loopback, err error) { func (lo *IPv6Loopback) AddRandomAddress() (addr net.IP, err error) { addr = make(net.IP, 16) addr[0] = 0xFD - rand.Read(addr[1:]) + _, err = rand.Read(addr[1:]) + if err != nil { + return nil, fmt.Errorf("rand.Read failed: %w", err) + } var req in6Ifreq copy(req.addr[:], addr) req.ifindex = lo.ifreq.index @@ -106,7 +108,7 @@ func (lo *IPv6Loopback) AddRandomAddress() (addr net.IP, err error) { if err = unix.Bind(fd, &bindAddr); err == nil { break } - if errno, ok := err.(unix.Errno); !ok || errno != unix.EADDRNOTAVAIL { + if !errors.Is(err, unix.EADDRNOTAVAIL) { break } time.Sleep(time.Millisecond * time.Duration(i)) @@ -119,7 +121,7 @@ func (lo *IPv6Loopback) AddRandomAddress() (addr net.IP, err error) { // Cleanup removes the addresses registered to this loopback. func (lo *IPv6Loopback) Cleanup() error { - var errs multierror.Errors + var errs []error var req in6Ifreq req.ifindex = lo.ifreq.index req.prefix = 128 @@ -133,5 +135,5 @@ func (lo *IPv6Loopback) Cleanup() error { if lo.fd != -1 { unix.Close(lo.fd) } - return errs.Err() + return errors.Join(errs...) } diff --git a/x-pack/auditbeat/module/system/socket/kprobes.go b/x-pack/auditbeat/module/system/socket/kprobes.go index a8781345991..d468cfa9599 100644 --- a/x-pack/auditbeat/module/system/socket/kprobes.go +++ b/x-pack/auditbeat/module/system/socket/kprobes.go @@ -12,8 +12,6 @@ import ( "strings" "unsafe" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/auditbeat/tracing" "github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper" "github.com/elastic/elastic-agent-libs/mapstr" @@ -59,19 +57,19 @@ func (p *probeInstaller) Install(pdef helper.ProbeDef) (format tracing.ProbeForm if decoder, err = pdef.Decoder(format); err != nil { return format, decoder, fmt.Errorf("failed to create decoder: %w", err) } - return + return format, decoder, nil } // UninstallInstalled uninstalls the probes installed by Install. func (p *probeInstaller) UninstallInstalled() error { - var errs multierror.Errors + var errs []error for _, probe := range p.installed { if err := p.traceFS.RemoveKProbe(probe); err != nil { errs = append(errs, err) } } p.installed = nil - return errs.Err() + return errors.Join(errs...) } // UninstallIf uninstalls all probes in the system that met the condition. @@ -80,7 +78,7 @@ func (p *probeInstaller) UninstallIf(condition helper.ProbeCondition) error { if err != nil { return fmt.Errorf("failed to list installed kprobes: %w", err) } - var errs multierror.Errors + var errs []error for _, probe := range kprobes { if condition(probe) { if err := p.traceFS.RemoveKProbe(probe); err != nil { @@ -88,7 +86,7 @@ func (p *probeInstaller) UninstallIf(condition helper.ProbeCondition) error { } } } - return errs.Err() + return errors.Join(errs...) } // WithGroup sets a custom group to probes before they are installed. diff --git a/x-pack/auditbeat/module/system/socket/state.go b/x-pack/auditbeat/module/system/socket/state.go index 347c5385921..2db1f18c28e 100644 --- a/x-pack/auditbeat/module/system/socket/state.go +++ b/x-pack/auditbeat/module/system/socket/state.go @@ -17,7 +17,6 @@ import ( "sync/atomic" "time" - "github.com/joeshaw/multierror" "golang.org/x/sys/unix" "github.com/elastic/beats/v7/auditbeat/tracing" @@ -974,7 +973,7 @@ func (f *flow) toEvent(final bool) (ev mb.Event, err error) { "complete": f.complete, }, } - var errs multierror.Errors + var errs []error rootPut := func(key string, value interface{}) { if _, err := root.Put(key, value); err != nil { errs = append(errs, err) @@ -1042,7 +1041,7 @@ func (f *flow) toEvent(final bool) (ev mb.Event, err error) { return mb.Event{ RootFields: root, MetricSetFields: metricset, - }, errs.Err() + }, errors.Join(errs...) } func (s *state) SyncClocks(kernelNanos, userNanos uint64) error { diff --git a/x-pack/auditbeat/module/system/user/user.go b/x-pack/auditbeat/module/system/user/user.go index f48019af572..f984d39310e 100644 --- a/x-pack/auditbeat/module/system/user/user.go +++ b/x-pack/auditbeat/module/system/user/user.go @@ -21,7 +21,6 @@ import ( "github.com/cespare/xxhash/v2" "github.com/gofrs/uuid/v5" - "github.com/joeshaw/multierror" "github.com/elastic/beats/v7/auditbeat/ab" "github.com/elastic/beats/v7/auditbeat/datastore" @@ -326,7 +325,7 @@ func (ms *MetricSet) Fetch(report mb.ReporterV2) { // reportState reports all existing users on the system. func (ms *MetricSet) reportState(report mb.ReporterV2) error { - var errs multierror.Errors + var errs []error ms.lastState = time.Now() users, err := GetUsers(ms.config.DetectPasswordChanges) @@ -369,12 +368,12 @@ func (ms *MetricSet) reportState(report mb.ReporterV2) error { } } - return errs.Err() + return errors.Join(errs...) } // reportChanges detects and reports any changes to users on this system since the last call. func (ms *MetricSet) reportChanges(report mb.ReporterV2) error { - var errs multierror.Errors + var errs []error currentTime := time.Now() // If this is not the first call to Fetch/reportChanges, @@ -403,10 +402,12 @@ func (ms *MetricSet) reportChanges(report mb.ReporterV2) error { // Check for changes to users missingUserMap := make(map[string](*User)) for _, missingUser := range missingFromCache { + //nolint:errcheck // ignore missingUserMap[missingUser.(*User).UID] = missingUser.(*User) } for _, userFromCache := range newInCache { + //nolint:errcheck // ignore newUser := userFromCache.(*User) oldUser, found := missingUserMap[newUser.UID] @@ -460,7 +461,7 @@ func (ms *MetricSet) reportChanges(report mb.ReporterV2) error { } } - return errs.Err() + return errors.Join(errs...) } func (ms *MetricSet) userEvent(user *User, eventType string, action eventAction) mb.Event { diff --git a/x-pack/auditbeat/module/system/user/users_linux.go b/x-pack/auditbeat/module/system/user/users_linux.go index e104fc1333b..adaf14b49cd 100644 --- a/x-pack/auditbeat/module/system/user/users_linux.go +++ b/x-pack/auditbeat/module/system/user/users_linux.go @@ -18,6 +18,7 @@ import "C" import ( "crypto/sha512" + "errors" "fmt" "os/user" "runtime" @@ -25,8 +26,6 @@ import ( "strings" "syscall" "time" - - "github.com/joeshaw/multierror" ) var epoch = time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) @@ -34,7 +33,7 @@ var epoch = time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) // GetUsers retrieves a list of users using information from // /etc/passwd, /etc/group, and - if configured - /etc/shadow. func GetUsers(readPasswords bool) ([]*User, error) { - var errs multierror.Errors + var errs []error // We are using a number of thread sensitive C functions in // this file, most importantly setpwent/getpwent/endpwent and @@ -61,7 +60,7 @@ func GetUsers(readPasswords bool) ([]*User, error) { } } - return users, errs.Err() + return users, errors.Join(errs...) } func readPasswdFile(readPasswords bool) ([]*User, error) { @@ -80,7 +79,7 @@ func readPasswdFile(readPasswords bool) ([]*User, error) { if passwd == nil { // getpwent() can return ENOENT even when there is no error, // see https://github.com/systemd/systemd/issues/9585. - if err != nil && err != syscall.ENOENT { + if err != nil && !errors.Is(err, syscall.ENOENT) { return users, fmt.Errorf("error getting user: %w", err) } diff --git a/x-pack/filebeat/input/o365audit/input.go b/x-pack/filebeat/input/o365audit/input.go index b01ba98ac90..11e7c1222cc 100644 --- a/x-pack/filebeat/input/o365audit/input.go +++ b/x-pack/filebeat/input/o365audit/input.go @@ -7,11 +7,11 @@ package o365audit import ( "context" "encoding/json" + "errors" "fmt" "time" "github.com/Azure/go-autorest/autorest" - "github.com/joeshaw/multierror" v2 "github.com/elastic/beats/v7/filebeat/input/v2" cursor "github.com/elastic/beats/v7/filebeat/input/v2/input-cursor" @@ -117,7 +117,8 @@ func (inp *o365input) Run( if err == nil { break } - if ctx.Cancelation.Err() != err && err != context.Canceled { + //nolint:errorlint // ignore + if ctx.Cancelation.Err() != err && !errors.Is(err, context.Canceled) { msg := mapstr.M{} msg.Put("error.message", err.Error()) msg.Put("event.kind", "pipeline_error") @@ -125,9 +126,12 @@ func (inp *o365input) Run( Timestamp: time.Now(), Fields: msg, } - publisher.Publish(event, nil) + if err := publisher.Publish(event, nil); err != nil { + ctx.Logger.Errorf("publisher.Publish failed: %v", err) + } ctx.Logger.Errorf("Input failed: %v", err) ctx.Logger.Infof("Restarting in %v", inp.config.API.ErrorRetryInterval) + //nolint:errcheck // ignore timed.Wait(ctx.Cancelation, inp.config.API.ErrorRetryInterval) } } @@ -140,7 +144,10 @@ func (inp *o365input) runOnce( cursor cursor.Cursor, publisher cursor.Publisher, ) error { - stream := src.(*stream) + stream, ok := src.(*stream) + if !ok { + return errors.New("unable to cast src to stream") + } tenantID, contentType := stream.tenantID, stream.contentType log := ctx.Logger.With("tenantID", tenantID, "contentType", contentType) @@ -239,7 +246,7 @@ func (env apiEnvironment) ReportAPIError(err apiError) poll.Action { } func (env apiEnvironment) toBeatEvent(raw json.RawMessage, doc mapstr.M) beat.Event { - var errs multierror.Errors + var errs []error ts, err := getDateKey(doc, "CreationTime", apiDateFormats) if err != nil { ts = time.Now() @@ -257,6 +264,7 @@ func (env apiEnvironment) toBeatEvent(raw json.RawMessage, doc mapstr.M) beat.Ev } } if env.Config.PreserveOriginalEvent { + //nolint:errcheck // ignore b.PutValue("event.original", string(raw)) } if len(errs) > 0 { @@ -264,6 +272,7 @@ func (env apiEnvironment) toBeatEvent(raw json.RawMessage, doc mapstr.M) beat.Ev for idx, e := range errs { msgs[idx] = e.Error() } + //nolint:errcheck // ignore b.PutValue("error.message", msgs) } return b diff --git a/x-pack/functionbeat/function/core/coordinator.go b/x-pack/functionbeat/function/core/coordinator.go index b7cf2e716be..50e771ba996 100644 --- a/x-pack/functionbeat/function/core/coordinator.go +++ b/x-pack/functionbeat/function/core/coordinator.go @@ -6,10 +6,9 @@ package core import ( "context" + "errors" "fmt" - "github.com/joeshaw/multierror" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/elastic-agent-libs/logp" ) @@ -68,14 +67,14 @@ func (r *Coordinator) Run(ctx context.Context, t telemetry.T) error { // Wait for goroutine to complete and aggregate any errors from the goroutine and // raise them back to the main program. - var errors multierror.Errors + var errs []error for range r.runners { err := <-results if err != nil { - errors = append(errors, err) + errs = append(errs, err) } } - return errors.Err() + return errors.Join(errs...) } func (r *Coordinator) runFunc( diff --git a/x-pack/libbeat/management/managerV2.go b/x-pack/libbeat/management/managerV2.go index e39b394bf2b..2ffa7f1c807 100644 --- a/x-pack/libbeat/management/managerV2.go +++ b/x-pack/libbeat/management/managerV2.go @@ -14,7 +14,6 @@ import ( "syscall" "time" - "github.com/joeshaw/multierror" "go.uber.org/zap/zapcore" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -682,9 +681,14 @@ func (cm *BeatV2Manager) reload(units map[unitKey]*agentUnit) { // in v2 only a single input type will be started per component, so we don't need to // worry about getting multiple re-loaders (we just need the one for the type) if err := cm.reloadInputs(inputUnits); err != nil { - merror := &multierror.MultiError{} - if errors.As(err, &merror) { - for _, err := range merror.Errors { + // reloadInputs wraps the multierror so we have to call Unwrap + wr := errors.Unwrap(err) + + //nolint:errorlint // ignore + if u, ok := wr.(interface { + Unwrap() []error + }); ok { + for _, err := range u.Unwrap() { unitErr := cfgfile.UnitError{} if errors.As(err, &unitErr) { unitErrors[unitErr.UnitID] = append(unitErrors[unitErr.UnitID], unitErr.Err) @@ -824,17 +828,17 @@ func (cm *BeatV2Manager) reloadInputs(inputUnits []*agentUnit) error { } if err := obj.Reload(inputBeatCfgs); err != nil { - merror := &multierror.MultiError{} - realErrors := multierror.Errors{} + var errs []error // At the moment this logic is tightly bound to the current RunnerList // implementation from libbeat/cfgfile/list.go and Input.loadStates from // filebeat/input/log/input.go. // If they change the way they report errors, this will break. - // TODO (Tiago): update all layers to use the most recent features from - // the standard library errors package. - if errors.As(err, &merror) { - for _, err := range merror.Errors { + //nolint:errorlint // ignore + if u, ok := err.(interface { + Unwrap() []error + }); ok { + for _, err := range u.Unwrap() { causeErr := errors.Unwrap(err) // A Log input is only marked as finished when all events it // produced are acked by the acker so when we see this error, @@ -850,12 +854,12 @@ func (cm *BeatV2Manager) reloadInputs(inputUnits []*agentUnit) error { } // This is an error that cannot be ignored, so we report it - realErrors = append(realErrors, err) + errs = append(errs, err) } } - if len(realErrors) != 0 { - return fmt.Errorf("failed to reload inputs: %w", realErrors.Err()) + if len(errs) != 0 { + return fmt.Errorf("failed to reload inputs: %w", errors.Join(errs...)) } } else { // If there was no error reloading input and forceReload was diff --git a/x-pack/libbeat/management/managerV2_test.go b/x-pack/libbeat/management/managerV2_test.go index f1b32b15d82..f76bda8e1ff 100644 --- a/x-pack/libbeat/management/managerV2_test.go +++ b/x-pack/libbeat/management/managerV2_test.go @@ -12,7 +12,6 @@ import ( "testing" "time" - "github.com/joeshaw/multierror" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" "google.golang.org/grpc" @@ -411,14 +410,14 @@ func TestErrorPerUnit(t *testing.T) { r.MustRegisterOutput(output) inputs := &mockReloadable{ ReloadFn: func(configs []*reload.ConfigWithMeta) error { - errs := multierror.Errors{} + var errs []error for _, input := range configs { errs = append(errs, cfgfile.UnitError{ UnitID: input.InputUnitID, Err: errors.New(errorMessages[input.InputUnitID]), }) } - return errs.Err() + return errors.Join(errs...) }, } r.MustRegisterInput(inputs) diff --git a/x-pack/metricbeat/module/enterprisesearch/health/data.go b/x-pack/metricbeat/module/enterprisesearch/health/data.go index 318f9fa0598..24cc7b643fe 100644 --- a/x-pack/metricbeat/module/enterprisesearch/health/data.go +++ b/x-pack/metricbeat/module/enterprisesearch/health/data.go @@ -9,8 +9,6 @@ import ( "errors" "fmt" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/helper/elastic" @@ -81,7 +79,7 @@ func eventMapping(report mb.ReporterV2, input []byte, isXpack bool) error { if err != nil { return err } - var errs multierror.Errors + var errs []error // All events need to have a cluster_uuid to work with Stack Monitoring event := mb.Event{ @@ -131,5 +129,5 @@ func eventMapping(report mb.ReporterV2, input []byte, isXpack bool) error { report.Event(event) } - return errs.Err() + return errors.Join(errs...) } diff --git a/x-pack/metricbeat/module/enterprisesearch/stats/data.go b/x-pack/metricbeat/module/enterprisesearch/stats/data.go index cd1ebd13dc3..1de2934118b 100644 --- a/x-pack/metricbeat/module/enterprisesearch/stats/data.go +++ b/x-pack/metricbeat/module/enterprisesearch/stats/data.go @@ -9,8 +9,6 @@ import ( "errors" "fmt" - "github.com/joeshaw/multierror" - s "github.com/elastic/beats/v7/libbeat/common/schema" c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface" "github.com/elastic/beats/v7/metricbeat/helper/elastic" @@ -163,7 +161,7 @@ func eventMapping(report mb.ReporterV2, input []byte, isXpack bool) error { if err != nil { return err } - var errs multierror.Errors + var errs []error // All events need to have a cluster_uuid to work with Stack Monitoring event := mb.Event{ @@ -201,5 +199,5 @@ func eventMapping(report mb.ReporterV2, input []byte, isXpack bool) error { report.Event(event) } - return errs.Err() + return errors.Join(errs...) }