171 lines
4.3 KiB
Go
171 lines
4.3 KiB
Go
|
package shim
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"log" //nolint:depguard // Allow exceptional but valid use of log here.
|
||
|
"os"
|
||
|
|
||
|
"github.com/BurntSushi/toml"
|
||
|
|
||
|
"github.com/influxdata/telegraf"
|
||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||
|
"github.com/influxdata/telegraf/plugins/processors"
|
||
|
)
|
||
|
|
||
|
type config struct {
|
||
|
Inputs map[string][]toml.Primitive
|
||
|
Processors map[string][]toml.Primitive
|
||
|
Outputs map[string][]toml.Primitive
|
||
|
}
|
||
|
|
||
|
type loadedConfig struct {
|
||
|
Input telegraf.Input
|
||
|
Processor telegraf.StreamingProcessor
|
||
|
Output telegraf.Output
|
||
|
}
|
||
|
|
||
|
// LoadConfig Adds plugins to the shim
|
||
|
func (s *Shim) LoadConfig(filePath *string) error {
|
||
|
conf, err := LoadConfig(filePath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if conf.Input != nil {
|
||
|
if err = s.AddInput(conf.Input); err != nil {
|
||
|
return fmt.Errorf("failed to add Input: %w", err)
|
||
|
}
|
||
|
} else if conf.Processor != nil {
|
||
|
if err = s.AddStreamingProcessor(conf.Processor); err != nil {
|
||
|
return fmt.Errorf("failed to add Processor: %w", err)
|
||
|
}
|
||
|
} else if conf.Output != nil {
|
||
|
if err = s.AddOutput(conf.Output); err != nil {
|
||
|
return fmt.Errorf("failed to add Output: %w", err)
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// LoadConfig loads the config and returns inputs that later need to be loaded.
|
||
|
func LoadConfig(filePath *string) (loaded loadedConfig, err error) {
|
||
|
var data string
|
||
|
conf := config{}
|
||
|
if filePath != nil && *filePath != "" {
|
||
|
b, err := os.ReadFile(*filePath)
|
||
|
if err != nil {
|
||
|
return loadedConfig{}, err
|
||
|
}
|
||
|
|
||
|
data = expandEnvVars(b)
|
||
|
} else {
|
||
|
conf = DefaultImportedPlugins()
|
||
|
}
|
||
|
|
||
|
md, err := toml.Decode(data, &conf)
|
||
|
if err != nil {
|
||
|
return loadedConfig{}, err
|
||
|
}
|
||
|
|
||
|
return createPluginsWithTomlConfig(md, conf)
|
||
|
}
|
||
|
|
||
|
func expandEnvVars(contents []byte) string {
|
||
|
return os.Expand(string(contents), getEnv)
|
||
|
}
|
||
|
|
||
|
func getEnv(key string) string {
|
||
|
v := os.Getenv(key)
|
||
|
|
||
|
return envVarEscaper.Replace(v)
|
||
|
}
|
||
|
|
||
|
func createPluginsWithTomlConfig(md toml.MetaData, conf config) (loadedConfig, error) {
|
||
|
loadedConf := loadedConfig{}
|
||
|
|
||
|
for name, primitives := range conf.Inputs {
|
||
|
creator, ok := inputs.Inputs[name]
|
||
|
if !ok {
|
||
|
return loadedConf, errors.New("unknown input " + name)
|
||
|
}
|
||
|
|
||
|
plugin := creator()
|
||
|
if len(primitives) > 0 {
|
||
|
primitive := primitives[0]
|
||
|
if err := md.PrimitiveDecode(primitive, plugin); err != nil {
|
||
|
return loadedConf, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
loadedConf.Input = plugin
|
||
|
break
|
||
|
}
|
||
|
|
||
|
for name, primitives := range conf.Processors {
|
||
|
creator, ok := processors.Processors[name]
|
||
|
if !ok {
|
||
|
return loadedConf, errors.New("unknown processor " + name)
|
||
|
}
|
||
|
|
||
|
plugin := creator()
|
||
|
if len(primitives) > 0 {
|
||
|
primitive := primitives[0]
|
||
|
var p telegraf.PluginDescriber = plugin
|
||
|
if processor, ok := plugin.(processors.HasUnwrap); ok {
|
||
|
p = processor.Unwrap()
|
||
|
}
|
||
|
if err := md.PrimitiveDecode(primitive, p); err != nil {
|
||
|
return loadedConf, err
|
||
|
}
|
||
|
}
|
||
|
loadedConf.Processor = plugin
|
||
|
break
|
||
|
}
|
||
|
|
||
|
for name, primitives := range conf.Outputs {
|
||
|
creator, ok := outputs.Outputs[name]
|
||
|
if !ok {
|
||
|
return loadedConf, errors.New("unknown output " + name)
|
||
|
}
|
||
|
|
||
|
plugin := creator()
|
||
|
if len(primitives) > 0 {
|
||
|
primitive := primitives[0]
|
||
|
if err := md.PrimitiveDecode(primitive, plugin); err != nil {
|
||
|
return loadedConf, err
|
||
|
}
|
||
|
}
|
||
|
loadedConf.Output = plugin
|
||
|
break
|
||
|
}
|
||
|
return loadedConf, nil
|
||
|
}
|
||
|
|
||
|
// DefaultImportedPlugins defaults to whatever plugins happen to be loaded and
|
||
|
// have registered themselves with the registry. This makes loading plugins
|
||
|
// without having to define a config dead easy.
|
||
|
func DefaultImportedPlugins() config {
|
||
|
conf := config{
|
||
|
Inputs: make(map[string][]toml.Primitive, len(inputs.Inputs)),
|
||
|
Processors: make(map[string][]toml.Primitive, len(processors.Processors)),
|
||
|
Outputs: make(map[string][]toml.Primitive, len(outputs.Outputs)),
|
||
|
}
|
||
|
for name := range inputs.Inputs {
|
||
|
log.Println("No config found. Loading default config for plugin", name)
|
||
|
conf.Inputs[name] = make([]toml.Primitive, 0)
|
||
|
return conf
|
||
|
}
|
||
|
for name := range processors.Processors {
|
||
|
log.Println("No config found. Loading default config for plugin", name)
|
||
|
conf.Processors[name] = make([]toml.Primitive, 0)
|
||
|
return conf
|
||
|
}
|
||
|
for name := range outputs.Outputs {
|
||
|
log.Println("No config found. Loading default config for plugin", name)
|
||
|
conf.Outputs[name] = make([]toml.Primitive, 0)
|
||
|
return conf
|
||
|
}
|
||
|
return conf
|
||
|
}
|