diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index f313a5121c3..f818a846ac8 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -370,6 +370,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Added the `max_cached_sessions` option to the script processor. {pull}19562[19562] - Add support for DNS over TLS for the dns_processor. {pull}19321[19321] - Set index.max_docvalue_fields_search in index template to increase value to 200 fields. {issue}20215[20215] +- Add leader election for Kubernetes autodiscover. {pull}20281[20281] - Add capability of enriching process metadata with contianer id also for non-privileged containers in `add_process_metadata` processor. {pull}19767[19767] *Auditbeat* diff --git a/deploy/kubernetes/metricbeat-kubernetes.yaml b/deploy/kubernetes/metricbeat-kubernetes.yaml index bc687dfac9d..32cd5568025 100644 --- a/deploy/kubernetes/metricbeat-kubernetes.yaml +++ b/deploy/kubernetes/metricbeat-kubernetes.yaml @@ -367,6 +367,12 @@ rules: - "/metrics" verbs: - get +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - '*' --- apiVersion: v1 kind: ServiceAccount diff --git a/deploy/kubernetes/metricbeat/metricbeat-role.yaml b/deploy/kubernetes/metricbeat/metricbeat-role.yaml index 152f9c4e9de..3f802c2bcf2 100644 --- a/deploy/kubernetes/metricbeat/metricbeat-role.yaml +++ b/deploy/kubernetes/metricbeat/metricbeat-role.yaml @@ -33,3 +33,9 @@ rules: - "/metrics" verbs: - get +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - '*' diff --git a/go.mod b/go.mod index 8055fffdf5d..71acd2ff53f 100644 --- a/go.mod +++ b/go.mod @@ -167,7 +167,7 @@ require ( golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae golang.org/x/text v0.3.2 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 - golang.org/x/tools v0.0.0-20200701041122-1837592efa10 + golang.org/x/tools v0.0.0-20200806022845-90696ccdc692 google.golang.org/api v0.15.0 google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb google.golang.org/grpc v1.29.1 diff --git a/libbeat/autodiscover/autodiscover.go b/libbeat/autodiscover/autodiscover.go index e26a2521c16..ce175b65072 100644 --- a/libbeat/autodiscover/autodiscover.go +++ b/libbeat/autodiscover/autodiscover.go @@ -83,7 +83,7 @@ func NewAutodiscover( // Init providers var providers []Provider for _, providerCfg := range config.Providers { - provider, err := Registry.BuildProvider(bus, providerCfg, keystore) + provider, err := Registry.BuildProvider(name, bus, providerCfg, keystore) if err != nil { return nil, errors.Wrap(err, "error in autodiscover provider settings") } diff --git a/libbeat/autodiscover/autodiscover_test.go b/libbeat/autodiscover/autodiscover_test.go index deec66ece8e..49dc50509e6 100644 --- a/libbeat/autodiscover/autodiscover_test.go +++ b/libbeat/autodiscover/autodiscover_test.go @@ -140,7 +140,7 @@ func TestAutodiscover(t *testing.T) { // Register mock autodiscover provider busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { + Registry.AddProvider("mock", func(beatName string, b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b @@ -259,7 +259,7 @@ func TestAutodiscoverHash(t *testing.T) { busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { + Registry.AddProvider("mock", func(beatName string, b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b @@ -323,7 +323,7 @@ func TestAutodiscoverWithConfigCheckFailures(t *testing.T) { // Register mock autodiscover provider busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { + Registry.AddProvider("mock", func(beatName string, b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b diff --git a/libbeat/autodiscover/provider.go b/libbeat/autodiscover/provider.go index 510e09ab4bf..ce4a0c50423 100644 --- a/libbeat/autodiscover/provider.go +++ b/libbeat/autodiscover/provider.go @@ -35,7 +35,7 @@ type Provider interface { } // ProviderBuilder creates a new provider based on the given config and returns it -type ProviderBuilder func(bus.Bus, uuid.UUID, *common.Config, keystore.Keystore) (Provider, error) +type ProviderBuilder func(string, bus.Bus, uuid.UUID, *common.Config, keystore.Keystore) (Provider, error) // AddProvider registers a new ProviderBuilder func (r *registry) AddProvider(name string, provider ProviderBuilder) error { @@ -70,7 +70,7 @@ func (r *registry) GetProvider(name string) ProviderBuilder { } // BuildProvider reads provider configuration and instantiate one -func (r *registry) BuildProvider(bus bus.Bus, c *common.Config, keystore keystore.Keystore) (Provider, error) { +func (r *registry) BuildProvider(beatName string, bus bus.Bus, c *common.Config, keystore keystore.Keystore) (Provider, error) { var config ProviderConfig err := c.Unpack(&config) if err != nil { @@ -87,5 +87,5 @@ func (r *registry) BuildProvider(bus bus.Bus, c *common.Config, keystore keystor return nil, err } - return builder(bus, uuid, c, keystore) + return builder(beatName, bus, uuid, c, keystore) } diff --git a/libbeat/autodiscover/providers/docker/docker.go b/libbeat/autodiscover/providers/docker/docker.go index 553b981177e..2680eab54b3 100644 --- a/libbeat/autodiscover/providers/docker/docker.go +++ b/libbeat/autodiscover/providers/docker/docker.go @@ -59,7 +59,13 @@ type Provider struct { } // AutodiscoverBuilder builds and returns an autodiscover provider -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { +func AutodiscoverBuilder( + beatName string, + bus bus.Bus, + uuid uuid.UUID, + c *common.Config, + keystore keystore.Keystore, +) (autodiscover.Provider, error) { logger := logp.NewLogger("docker") errWrap := func(err error) error { diff --git a/libbeat/autodiscover/providers/docker/docker_integration_test.go b/libbeat/autodiscover/providers/docker/docker_integration_test.go index 5d6baaa0b83..bbb2bc979bc 100644 --- a/libbeat/autodiscover/providers/docker/docker_integration_test.go +++ b/libbeat/autodiscover/providers/docker/docker_integration_test.go @@ -56,7 +56,7 @@ func TestDockerStart(t *testing.T) { s := &template.MapperSettings{nil, nil} config.Templates = *s k, _ := keystore.NewFileKeystore("test") - provider, err := AutodiscoverBuilder(bus, UUID, common.MustNewConfigFrom(config), k) + provider, err := AutodiscoverBuilder("mockBeat", bus, UUID, common.MustNewConfigFrom(config), k) if err != nil { t.Fatal(err) } diff --git a/libbeat/autodiscover/providers/jolokia/jolokia.go b/libbeat/autodiscover/providers/jolokia/jolokia.go index 5a8876a011a..928c1cc8e78 100644 --- a/libbeat/autodiscover/providers/jolokia/jolokia.go +++ b/libbeat/autodiscover/providers/jolokia/jolokia.go @@ -53,7 +53,13 @@ type Provider struct { // AutodiscoverBuilder builds a Jolokia Discovery autodiscover provider, it fails if // there is some problem with the configuration -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { +func AutodiscoverBuilder( + beatName string, + bus bus.Bus, + uuid uuid.UUID, + c *common.Config, + keystore keystore.Keystore, +) (autodiscover.Provider, error) { errWrap := func(err error) error { return errors.Wrap(err, "error setting up jolokia autodiscover provider") } diff --git a/libbeat/autodiscover/providers/kubernetes/config.go b/libbeat/autodiscover/providers/kubernetes/config.go index a1ec2db5dd5..84672659f74 100644 --- a/libbeat/autodiscover/providers/kubernetes/config.go +++ b/libbeat/autodiscover/providers/kubernetes/config.go @@ -44,6 +44,9 @@ type Config struct { // Scope can be either node or cluster. Scope string `config:"scope"` Resource string `config:"resource"` + // Unique identifies if this provider enables its templates only when it is elected as leader in a k8s cluster + Unique bool `config:"unique"` + LeaderLease string `config:"leader_lease"` Prefix string `config:"prefix"` Hints *common.Config `config:"hints"` @@ -60,6 +63,7 @@ func defaultConfig() *Config { Resource: "pod", CleanupTimeout: 60 * time.Second, Prefix: "co.elastic", + Unique: false, } } @@ -98,6 +102,9 @@ func (c *Config) Validate() error { if c.Scope != "node" && c.Scope != "cluster" { return fmt.Errorf("invalid `scope` configured. supported values are `node` and `cluster`") } + if c.Unique && c.Scope != "cluster" { + logp.L().Warnf("can only set `unique` when scope is `cluster`") + } return nil } diff --git a/libbeat/autodiscover/providers/kubernetes/kubernetes.go b/libbeat/autodiscover/providers/kubernetes/kubernetes.go index e1a2cb02ee0..190c646ef0c 100644 --- a/libbeat/autodiscover/providers/kubernetes/kubernetes.go +++ b/libbeat/autodiscover/providers/kubernetes/kubernetes.go @@ -20,7 +20,14 @@ package kubernetes import ( + "context" "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8s "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/leaderelection/resourcelock" "github.com/gofrs/uuid" "github.com/pkg/errors" @@ -47,19 +54,45 @@ type Eventer interface { Stop() } +// EventManager allows defining ways in which kubernetes resource events are observed and processed +type EventManager interface { + GenerateHints(event bus.Event) bus.Event + Start() + Stop() +} + // Provider implements autodiscover provider for docker containers type Provider struct { - config *Config - bus bus.Bus - templates template.Mapper - builders autodiscover.Builders - appenders autodiscover.Appenders - logger *logp.Logger - eventer Eventer + config *Config + bus bus.Bus + templates template.Mapper + builders autodiscover.Builders + appenders autodiscover.Appenders + logger *logp.Logger + eventManager EventManager +} + +// eventerManager implements start/stop methods for autodiscover provider with resource eventer +type eventerManager struct { + eventer Eventer + logger *logp.Logger +} + +// leaderElectionManager implements start/stop methods for autodiscover provider with leaderElection +type leaderElectionManager struct { + leaderElection leaderelection.LeaderElectionConfig + cancelLeaderElection context.CancelFunc + logger *logp.Logger } // AutodiscoverBuilder builds and returns an autodiscover provider -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { +func AutodiscoverBuilder( + beatName string, + bus bus.Bus, + uuid uuid.UUID, + c *common.Config, + keystore keystore.Keystore, +) (autodiscover.Provider, error) { logger := logp.NewLogger("autodiscover") errWrap := func(err error) error { @@ -67,6 +100,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore } config := defaultConfig() + config.LeaderLease = fmt.Sprintf("%v-cluster-leader", beatName) err := c.Unpack(&config) if err != nil { return nil, errWrap(err) @@ -103,15 +137,10 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore logger: logger, } - switch config.Resource { - case "pod": - p.eventer, err = NewPodEventer(uuid, c, client, p.publish) - case "node": - p.eventer, err = NewNodeEventer(uuid, c, client, p.publish) - case "service": - p.eventer, err = NewServiceEventer(uuid, c, client, p.publish) - default: - return nil, fmt.Errorf("unsupported autodiscover resource %s", config.Resource) + if p.config.Unique { + p.eventManager, err = NewLeaderElectionManager(uuid, config, client, p.startLeading, p.stopLeading, logger) + } else { + p.eventManager, err = NewEventerManager(uuid, c, config, client, p.publish) } if err != nil { @@ -123,14 +152,12 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore // Start for Runner interface. func (p *Provider) Start() { - if err := p.eventer.Start(); err != nil { - p.logger.Errorf("Error starting kubernetes autodiscover provider: %s", err) - } + p.eventManager.Start() } // Stop signals the stop channel to force the watch loop routine to stop. func (p *Provider) Stop() { - p.eventer.Stop() + p.eventManager.Stop() } // String returns a description of kubernetes autodiscover provider. @@ -144,7 +171,7 @@ func (p *Provider) publish(event bus.Event) { event["config"] = config } else { // If there isn't a default template then attempt to use builders - e := p.eventer.GenerateHints(event) + e := p.eventManager.GenerateHints(event) if config := p.builders.GetConfig(e); config != nil { event["config"] = config } @@ -154,3 +181,149 @@ func (p *Provider) publish(event bus.Event) { p.appenders.Append(event) p.bus.Publish(event) } + +func (p *Provider) startLeading(uuid string, eventID string) { + event := bus.Event{ + "start": true, + "provider": uuid, + "id": eventID, + "unique": "true", + } + if config := p.templates.GetConfig(event); config != nil { + event["config"] = config + } + p.bus.Publish(event) +} + +func (p *Provider) stopLeading(uuid string, eventID string) { + event := bus.Event{ + "stop": true, + "provider": uuid, + "id": eventID, + "unique": "true", + } + if config := p.templates.GetConfig(event); config != nil { + event["config"] = config + } + p.bus.Publish(event) +} + +func NewEventerManager( + uuid uuid.UUID, + c *common.Config, + cfg *Config, + client k8s.Interface, + publish func(event bus.Event), +) (EventManager, error) { + var err error + em := &eventerManager{} + switch cfg.Resource { + case "pod": + em.eventer, err = NewPodEventer(uuid, c, client, publish) + case "node": + em.eventer, err = NewNodeEventer(uuid, c, client, publish) + case "service": + em.eventer, err = NewServiceEventer(uuid, c, client, publish) + default: + return nil, fmt.Errorf("unsupported autodiscover resource %s", cfg.Resource) + } + + if err != nil { + return nil, err + } + return em, nil +} + +func NewLeaderElectionManager( + uuid uuid.UUID, + cfg *Config, + client k8s.Interface, + startLeading func(uuid string, eventID string), + stopLeading func(uuid string, eventID string), + logger *logp.Logger, +) (EventManager, error) { + lem := &leaderElectionManager{logger: logger} + var id string + if cfg.Node != "" { + id = "beats-leader-" + cfg.Node + } else { + id = "beats-leader-" + uuid.String() + } + lease := metav1.ObjectMeta{ + Name: cfg.LeaderLease, + Namespace: "default", + } + metaUID := lease.GetObjectMeta().GetUID() + lem.leaderElection = leaderelection.LeaderElectionConfig{ + Lock: &resourcelock.LeaseLock{ + LeaseMeta: lease, + Client: client.CoordinationV1(), + LockConfig: resourcelock.ResourceLockConfig{ + Identity: id, + }, + }, + ReleaseOnCancel: true, + LeaseDuration: 15 * time.Second, + RenewDeadline: 10 * time.Second, + RetryPeriod: 2 * time.Second, + Callbacks: leaderelection.LeaderCallbacks{ + OnStartedLeading: func(ctx context.Context) { + logger.Debugf("leader election lock GAINED, id %v", id) + eventID := fmt.Sprintf("%v-%v", metaUID, time.Now().UnixNano()) + startLeading(uuid.String(), eventID) + }, + OnStoppedLeading: func() { + logger.Debugf("leader election lock LOST, id %v", id) + eventID := fmt.Sprintf("%v-%v", metaUID, time.Now().UnixNano()) + stopLeading(uuid.String(), eventID) + }, + }, + } + return lem, nil +} + +// Start for EventManager interface. +func (p *eventerManager) Start() { + if err := p.eventer.Start(); err != nil { + p.logger.Errorf("Error starting kubernetes autodiscover provider: %s", err) + } +} + +// Stop signals the stop channel to force the watch loop routine to stop. +func (p *eventerManager) Stop() { + p.eventer.Stop() +} + +// GenerateHints for EventManager interface. +func (p *eventerManager) GenerateHints(event bus.Event) bus.Event { + return p.eventer.GenerateHints(event) +} + +// Start for EventManager interface. +func (p *leaderElectionManager) Start() { + ctx, cancel := context.WithCancel(context.TODO()) + p.cancelLeaderElection = cancel + p.startLeaderElector(ctx, p.leaderElection) +} + +// Stop signals the stop channel to force the leader election loop routine to stop. +func (p *leaderElectionManager) Stop() { + if p.cancelLeaderElection != nil { + p.cancelLeaderElection() + } +} + +// GenerateHints for EventManager interface. +func (p *leaderElectionManager) GenerateHints(event bus.Event) bus.Event { + return event +} + +// startLeaderElector starts a Leader Elector in the background with the provided config +func (p *leaderElectionManager) startLeaderElector(ctx context.Context, lec leaderelection.LeaderElectionConfig) { + le, err := leaderelection.NewLeaderElector(lec) + if err != nil { + p.logger.Errorf("error while creating Leader Elector: %v", err) + } + p.logger.Debugf("Starting Leader Elector") + go le.Run(ctx) +} diff --git a/libbeat/autodiscover/providers/kubernetes/node_test.go b/libbeat/autodiscover/providers/kubernetes/node_test.go index 736bd153cf2..8c29c008fc8 100644 --- a/libbeat/autodiscover/providers/kubernetes/node_test.go +++ b/libbeat/autodiscover/providers/kubernetes/node_test.go @@ -246,8 +246,9 @@ func TestEmitEvent_Node(t *testing.T) { } metaGen := metadata.NewNodeMetadataGenerator(common.NewConfig(), nil) + config := defaultConfig() p := &Provider{ - config: defaultConfig(), + config: config, bus: bus.New(logp.NewLogger("bus"), "test"), templates: mapper, logger: logp.NewLogger("kubernetes"), @@ -261,7 +262,7 @@ func TestEmitEvent_Node(t *testing.T) { logger: logp.NewLogger("kubernetes.no"), } - p.eventer = no + p.eventManager = NewMockNodeEventerManager(no) listener := p.bus.Subscribe() @@ -279,6 +280,12 @@ func TestEmitEvent_Node(t *testing.T) { } } +func NewMockNodeEventerManager(no *node) EventManager { + em := &eventerManager{} + em.eventer = no + return em +} + func TestNode_isUpdated(t *testing.T) { tests := []struct { old *kubernetes.Node diff --git a/libbeat/autodiscover/providers/kubernetes/pod_test.go b/libbeat/autodiscover/providers/kubernetes/pod_test.go index f22bfc64cea..0e435fda4c5 100644 --- a/libbeat/autodiscover/providers/kubernetes/pod_test.go +++ b/libbeat/autodiscover/providers/kubernetes/pod_test.go @@ -1013,7 +1013,7 @@ func TestEmitEvent(t *testing.T) { logger: logp.NewLogger("kubernetes.pod"), } - p.eventer = pod + p.eventManager = NewMockPodEventerManager(pod) listener := p.bus.Subscribe() @@ -1034,6 +1034,12 @@ func TestEmitEvent(t *testing.T) { } } +func NewMockPodEventerManager(pod *pod) EventManager { + em := &eventerManager{} + em.eventer = pod + return em +} + func getNestedAnnotations(in common.MapStr) common.MapStr { out := common.MapStr{} diff --git a/libbeat/autodiscover/providers/kubernetes/service_test.go b/libbeat/autodiscover/providers/kubernetes/service_test.go index 7ead61fc3a0..c45c691f75e 100644 --- a/libbeat/autodiscover/providers/kubernetes/service_test.go +++ b/libbeat/autodiscover/providers/kubernetes/service_test.go @@ -414,8 +414,7 @@ func TestEmitEvent_Service(t *testing.T) { logger: logp.NewLogger("kubernetes.service"), } - p.eventer = service - + p.eventManager = NewMockServiceEventerManager(service) listener := p.bus.Subscribe() service.emit(test.Service, test.Flag) @@ -431,3 +430,9 @@ func TestEmitEvent_Service(t *testing.T) { }) } } + +func NewMockServiceEventerManager(svc *service) EventManager { + em := &eventerManager{} + em.eventer = svc + return em +} diff --git a/libbeat/docs/shared-autodiscover.asciidoc b/libbeat/docs/shared-autodiscover.asciidoc index 7c59b9f8452..c7993c29bef 100644 --- a/libbeat/docs/shared-autodiscover.asciidoc +++ b/libbeat/docs/shared-autodiscover.asciidoc @@ -242,6 +242,40 @@ running configuration for a container, 60s by default. include_labels: ["nodelabel2"] ------------------------------------------------------------------------------------- +`unique`:: (Optional) Defaults to `false`. Marking an autodiscover provider as unique results into + making the provider to enable the provided templates only when it will gain the leader lease. + This setting can only be combined with `cluster` scope. When `unique` is enabled enabled, `resource` + and `add_resource_metadata` settings are not taken into account. +`leader_lease`:: (Optional) Defaults to `{beatname_lc}-cluster-leader`. This will be name of the lock lease. + One can monitor the status of the lease with `kubectl describe lease beats-cluster-leader`. + Different Beats that refer to the same leader lease will be competetitors in holding the lease + and only one will be elected as leader each time. Example: + +["source","yaml",subs="attributes"] +------------------------------------------------------------------------------------- +metricbeat.autodiscover: + providers: + - type: kubernetes + scope: cluster + node: ${NODE_NAME} + unique: true + identifier: leader-election-metricbeat + templates: + - config: + - module: kubernetes + hosts: ["kube-state-metrics:8080"] + period: 10s + add_metadata: true + metricsets: + - state_node +------------------------------------------------------------------------------------- + +The above configuration when deployed on one or more Metribceat instances will enable `state_node` +metricset only for the Metricbeat instance that will gain the leader lease/lock. With this deployment +strategy we can ensure that cluster-wide metricsets are only enabled by one Beat instance when +deploying a Beat as Daemonset. + + include::../../{beatname_lc}/docs/autodiscover-kubernetes-config.asciidoc[] ifdef::autodiscoverJolokia[] diff --git a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go index 06b153626fe..029a54d5403 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go @@ -37,7 +37,13 @@ type Provider struct { } // AutodiscoverBuilder is the main builder for this provider. -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { +func AutodiscoverBuilder( + beatName string, + bus bus.Bus, + uuid uuid.UUID, + c *common.Config, + keystore keystore.Keystore, +) (autodiscover.Provider, error) { cfgwarn.Experimental("aws_ec2 autodiscover is experimental") config := awsauto.DefaultConfig() diff --git a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go index 54021a8db88..b0617baad4d 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go @@ -39,7 +39,13 @@ type Provider struct { } // AutodiscoverBuilder is the main builder for this provider. -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { +func AutodiscoverBuilder( + beatName string, + bus bus.Bus, + uuid uuid.UUID, + c *common.Config, + keystore keystore.Keystore, +) (autodiscover.Provider, error) { cfgwarn.Experimental("aws_elb autodiscover is experimental") config := awsauto.DefaultConfig()