src/go/plugin/go.d/agent/discovery/sd/pipeline/config.go
// SPDX-License-Identifier: GPL-3.0-or-later
package pipeline
import (
"errors"
"fmt"
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/confgroup"
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/dockerd"
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/kubernetes"
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/netlisteners"
)
type Config struct {
Source string `yaml:"-"`
ConfigDefaults confgroup.Registry `yaml:"-"`
Disabled bool `yaml:"disabled"`
Name string `yaml:"name"`
Discover []DiscoveryConfig `yaml:"discover"`
Classify []ClassifyRuleConfig `yaml:"classify"`
Compose []ComposeRuleConfig `yaml:"compose"`
}
type DiscoveryConfig struct {
Discoverer string `yaml:"discoverer"`
NetListeners netlisteners.Config `yaml:"net_listeners"`
Docker dockerd.Config `yaml:"docker"`
K8s []kubernetes.Config `yaml:"k8s"`
}
type ClassifyRuleConfig struct {
Name string `yaml:"name"`
Selector string `yaml:"selector"` // mandatory
Tags string `yaml:"tags"` // mandatory
Match []struct {
Tags string `yaml:"tags"` // mandatory
Expr string `yaml:"expr"` // mandatory
} `yaml:"match"` // mandatory, at least 1
}
type ComposeRuleConfig struct {
Name string `yaml:"name"` // optional
Selector string `yaml:"selector"` // mandatory
Config []struct {
Selector string `yaml:"selector"` // mandatory
Template string `yaml:"template"` // mandatory
} `yaml:"config"` // mandatory, at least 1
}
func validateConfig(cfg Config) error {
if cfg.Name == "" {
return errors.New("'name' not set")
}
if err := validateDiscoveryConfig(cfg.Discover); err != nil {
return fmt.Errorf("discover config: %v", err)
}
if err := validateClassifyConfig(cfg.Classify); err != nil {
return fmt.Errorf("classify rules: %v", err)
}
if err := validateComposeConfig(cfg.Compose); err != nil {
return fmt.Errorf("compose rules: %v", err)
}
return nil
}
func validateDiscoveryConfig(config []DiscoveryConfig) error {
if len(config) == 0 {
return errors.New("no discoverers, must be at least one")
}
for _, cfg := range config {
switch cfg.Discoverer {
case "net_listeners", "docker", "k8s":
default:
return fmt.Errorf("unknown discoverer: '%s'", cfg.Discoverer)
}
}
return nil
}
func validateClassifyConfig(rules []ClassifyRuleConfig) error {
if len(rules) == 0 {
return errors.New("empty config, need least 1 rule")
}
for i, rule := range rules {
i++
if rule.Selector == "" {
return fmt.Errorf("'rule[%s][%d]->selector' not set", rule.Name, i)
}
if rule.Tags == "" {
return fmt.Errorf("'rule[%s][%d]->tags' not set", rule.Name, i)
}
if len(rule.Match) == 0 {
return fmt.Errorf("'rule[%s][%d]->match' not set, need at least 1 rule match", rule.Name, i)
}
for j, match := range rule.Match {
j++
if match.Tags == "" {
return fmt.Errorf("'rule[%s][%d]->match[%d]->tags' not set", rule.Name, i, j)
}
if match.Expr == "" {
return fmt.Errorf("'rule[%s][%d]->match[%d]->expr' not set", rule.Name, i, j)
}
}
}
return nil
}
func validateComposeConfig(rules []ComposeRuleConfig) error {
if len(rules) == 0 {
return errors.New("empty config, need least 1 rule")
}
for i, rule := range rules {
i++
if rule.Selector == "" {
return fmt.Errorf("'rule[%s][%d]->selector' not set", rule.Name, i)
}
if len(rule.Config) == 0 {
return fmt.Errorf("'rule[%s][%d]->config' not set", rule.Name, i)
}
for j, conf := range rule.Config {
j++
if conf.Selector == "" {
return fmt.Errorf("'rule[%s][%d]->config[%d]->selector' not set", rule.Name, i, j)
}
if conf.Template == "" {
return fmt.Errorf("'rule[%s][%d]->config[%d]->template' not set", rule.Name, i, j)
}
}
}
return nil
}