128 lines
3.6 KiB
Go
128 lines
3.6 KiB
Go
// Licensed to Elasticsearch B.V. under one or more contributor
|
|
// license agreements. See the NOTICE file distributed with
|
|
// this work for additional information regarding copyright
|
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
|
// the Apache License, Version 2.0 (the "License"); you may
|
|
// not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package template
|
|
|
|
import (
|
|
"github.com/elastic/beats/libbeat/common"
|
|
"github.com/elastic/beats/libbeat/common/bus"
|
|
"github.com/elastic/beats/libbeat/conditions"
|
|
"github.com/elastic/beats/libbeat/logp"
|
|
"github.com/elastic/go-ucfg"
|
|
)
|
|
|
|
// Mapper maps config templates with conditions, if a match happens on a discover event
|
|
// the given template will be used as config
|
|
type Mapper []*ConditionMap
|
|
|
|
// ConditionMap maps a condition to the configs to use when it's triggered
|
|
type ConditionMap struct {
|
|
Condition conditions.Condition
|
|
Configs []*common.Config
|
|
}
|
|
|
|
// MapperSettings holds user settings to build Mapper
|
|
type MapperSettings []*struct {
|
|
ConditionConfig *conditions.Config `config:"condition"`
|
|
Configs []*common.Config `config:"config"`
|
|
}
|
|
|
|
// NewConfigMapper builds a template Mapper from given settings
|
|
func NewConfigMapper(configs MapperSettings) (*Mapper, error) {
|
|
var mapper Mapper
|
|
for _, c := range configs {
|
|
condition, err := conditions.NewCondition(c.ConditionConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mapper = append(mapper, &ConditionMap{
|
|
Condition: condition,
|
|
Configs: c.Configs,
|
|
})
|
|
}
|
|
|
|
return &mapper, nil
|
|
}
|
|
|
|
// Event adapts MapStr to processors.ValuesMap interface
|
|
type Event common.MapStr
|
|
|
|
// GetValue extracts given key from an Event
|
|
func (e Event) GetValue(key string) (interface{}, error) {
|
|
val, err := common.MapStr(e).GetValue(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return val, nil
|
|
}
|
|
|
|
// GetConfig returns a matching Config if any, nil otherwise
|
|
func (c *Mapper) GetConfig(event bus.Event) []*common.Config {
|
|
var result []*common.Config
|
|
|
|
for _, mapping := range *c {
|
|
if mapping.Configs != nil && !mapping.Condition.Check(Event(event)) {
|
|
continue
|
|
}
|
|
|
|
configs := ApplyConfigTemplate(event, mapping.Configs)
|
|
if configs != nil {
|
|
result = append(result, configs...)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ApplyConfigTemplate takes a set of templated configs and applys information in an event map
|
|
func ApplyConfigTemplate(event bus.Event, configs []*common.Config) []*common.Config {
|
|
var result []*common.Config
|
|
// unpack input
|
|
vars, err := ucfg.NewFrom(map[string]interface{}{
|
|
"data": event,
|
|
})
|
|
if err != nil {
|
|
logp.Err("Error building config: %v", err)
|
|
}
|
|
opts := []ucfg.Option{
|
|
ucfg.PathSep("."),
|
|
ucfg.Env(vars),
|
|
ucfg.ResolveEnv,
|
|
ucfg.VarExp,
|
|
}
|
|
for _, config := range configs {
|
|
c, err := ucfg.NewFrom(config, opts...)
|
|
if err != nil {
|
|
logp.Err("Error parsing config: %v", err)
|
|
continue
|
|
}
|
|
// Unpack config to process any vars in the template:
|
|
var unpacked map[string]interface{}
|
|
c.Unpack(&unpacked, opts...)
|
|
if err != nil {
|
|
logp.Err("Error unpacking config: %v", err)
|
|
continue
|
|
}
|
|
// Repack again:
|
|
res, err := common.NewConfigFrom(unpacked)
|
|
if err != nil {
|
|
logp.Err("Error creating config from unpack: %v", err)
|
|
continue
|
|
}
|
|
result = append(result, res)
|
|
}
|
|
return result
|
|
}
|