netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/agent/discovery/sd/pipeline/config.go

Summary

Maintainability
A
2 hrs
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package pipeline

import (
    "errors"
    "fmt"

    "github.com/netdata/netdata/go/go.d.plugin/agent/confgroup"
    "github.com/netdata/netdata/go/go.d.plugin/agent/discovery/sd/discoverer/dockerd"
    "github.com/netdata/netdata/go/go.d.plugin/agent/discovery/sd/discoverer/kubernetes"
    "github.com/netdata/netdata/go/go.d.plugin/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
}