mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-27 14:37:17 +00:00
refactor: expose decision engine in public pkg
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
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),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
c.IgnoredResources = normalizeToLower(c.IgnoredResources)
|
||||
|
||||
// Normalize ignored workloads to canonical Kind values (e.g., "cronjobs" -> "CronJob")
|
||||
c.IgnoredWorkloads = normalizeToLower(c.IgnoredWorkloads)
|
||||
normalizedWorkloads := make([]string, 0, len(c.IgnoredWorkloads))
|
||||
for _, w := range c.IgnoredWorkloads {
|
||||
kind, err := workload.KindFromString(w)
|
||||
if err != nil {
|
||||
errs = append(
|
||||
errs, ValidationError{
|
||||
Field: "IgnoredWorkloads",
|
||||
Message: fmt.Sprintf("unknown workload type %q", w),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
normalizedWorkloads = append(normalizedWorkloads, string(kind))
|
||||
}
|
||||
}
|
||||
c.IgnoredWorkloads = normalizedWorkloads
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user