mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-20 20:46:30 +00:00
149 lines
3.7 KiB
Go
149 lines
3.7 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
)
|
|
|
|
// ValidationError represents a configuration validation error.
|
|
type ValidationError struct {
|
|
Field string
|
|
Message string
|
|
}
|
|
|
|
func (e ValidationError) Error() string {
|
|
return fmt.Sprintf("config.%s: %s", e.Field, e.Message)
|
|
}
|
|
|
|
// ValidationErrors is a collection of validation errors.
|
|
type ValidationErrors []ValidationError
|
|
|
|
func (e ValidationErrors) Error() string {
|
|
if len(e) == 0 {
|
|
return ""
|
|
}
|
|
if len(e) == 1 {
|
|
return e[0].Error()
|
|
}
|
|
var b strings.Builder
|
|
b.WriteString("multiple configuration errors:\n")
|
|
for _, err := range e {
|
|
b.WriteString(" - ")
|
|
b.WriteString(err.Error())
|
|
b.WriteString("\n")
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
// Validate checks the configuration for errors and normalizes values.
|
|
func (c *Config) Validate() error {
|
|
var errs ValidationErrors
|
|
|
|
// Validate ReloadStrategy
|
|
switch c.ReloadStrategy {
|
|
case ReloadStrategyEnvVars, ReloadStrategyAnnotations:
|
|
// valid
|
|
case "":
|
|
c.ReloadStrategy = ReloadStrategyEnvVars
|
|
default:
|
|
errs = append(errs, ValidationError{
|
|
Field: "ReloadStrategy",
|
|
Message: fmt.Sprintf("invalid value %q, must be %q or %q", c.ReloadStrategy, ReloadStrategyEnvVars, ReloadStrategyAnnotations),
|
|
})
|
|
}
|
|
|
|
// Validate ArgoRolloutStrategy
|
|
switch c.ArgoRolloutStrategy {
|
|
case ArgoRolloutStrategyRestart, ArgoRolloutStrategyRollout:
|
|
// valid
|
|
case "":
|
|
c.ArgoRolloutStrategy = ArgoRolloutStrategyRollout
|
|
default:
|
|
errs = append(errs, ValidationError{
|
|
Field: "ArgoRolloutStrategy",
|
|
Message: fmt.Sprintf("invalid value %q, must be %q or %q", c.ArgoRolloutStrategy, ArgoRolloutStrategyRestart, ArgoRolloutStrategyRollout),
|
|
})
|
|
}
|
|
|
|
// Validate LogLevel
|
|
switch strings.ToLower(c.LogLevel) {
|
|
case "trace", "debug", "info", "warn", "warning", "error", "fatal", "panic", "":
|
|
// valid
|
|
default:
|
|
errs = append(errs, ValidationError{
|
|
Field: "LogLevel",
|
|
Message: fmt.Sprintf("invalid log level %q", c.LogLevel),
|
|
})
|
|
}
|
|
|
|
// Validate LogFormat
|
|
switch strings.ToLower(c.LogFormat) {
|
|
case "json", "":
|
|
// valid
|
|
default:
|
|
errs = append(errs, ValidationError{
|
|
Field: "LogFormat",
|
|
Message: fmt.Sprintf("invalid log format %q, must be \"json\" or empty", c.LogFormat),
|
|
})
|
|
}
|
|
|
|
// Normalize IgnoredResources to lowercase for consistent comparison
|
|
c.IgnoredResources = normalizeToLower(c.IgnoredResources)
|
|
|
|
// Normalize IgnoredWorkloads to lowercase
|
|
c.IgnoredWorkloads = normalizeToLower(c.IgnoredWorkloads)
|
|
|
|
if len(errs) > 0 {
|
|
return errs
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// normalizeToLower converts all strings in the slice to lowercase and removes empty strings.
|
|
func normalizeToLower(items []string) []string {
|
|
if len(items) == 0 {
|
|
return items
|
|
}
|
|
result := make([]string, 0, len(items))
|
|
for _, item := range items {
|
|
item = strings.TrimSpace(strings.ToLower(item))
|
|
if item != "" {
|
|
result = append(result, item)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ParseSelectors parses a slice of selector strings into label selectors.
|
|
func ParseSelectors(selectorStrings []string) ([]labels.Selector, error) {
|
|
if len(selectorStrings) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
selectors := make([]labels.Selector, 0, len(selectorStrings))
|
|
for _, s := range selectorStrings {
|
|
s = strings.TrimSpace(s)
|
|
if s == "" {
|
|
continue
|
|
}
|
|
selector, err := labels.Parse(s)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid selector %q: %w", s, err)
|
|
}
|
|
selectors = append(selectors, selector)
|
|
}
|
|
return selectors, nil
|
|
}
|
|
|
|
// MustParseSelectors parses selectors and panics on error.
|
|
// Use only when selectors are known to be valid (e.g., from validated config).
|
|
func MustParseSelectors(selectorStrings []string) []labels.Selector {
|
|
selectors, err := ParseSelectors(selectorStrings)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return selectors
|
|
}
|