Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support camelcase matchLabels and matchExpressions in TA config #3418

Merged
merged 10 commits into from
Jan 29, 2025
Prev Previous commit
Next Next commit
using mapstructure for flexible unmarshalling
davidhaja committed Nov 5, 2024
commit b082525ab8795771a8bd181e42f7280207bc831c
125 changes: 39 additions & 86 deletions cmd/otel-allocator/config/config.go
Original file line number Diff line number Diff line change
@@ -21,16 +21,16 @@ import (
"fmt"
"io/fs"
"os"
"strings"
"reflect"
"time"

"dario.cat/mergo"
"github.com/go-logr/logr"
yaml "github.com/goccy/go-yaml"
"github.com/mitchellh/mapstructure"
"github.com/prometheus/common/model"
promconfig "github.com/prometheus/prometheus/config"
_ "github.com/prometheus/prometheus/discovery/install"
"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
@@ -41,7 +41,7 @@ import (

const (
DefaultResyncTime = 5 * time.Minute
DefaultConfigFilePath string = "/conf/targetallocator.yaml"
DefaultConfigFilePath string = "../../conf/targetallocator.yaml"
DefaultCRScrapeInterval model.Duration = model.Duration(time.Second * 30)
DefaultAllocationStrategy = "consistent-hashing"
DefaultFilterStrategy = "relabel-config"
@@ -77,11 +77,6 @@ type HTTPSServerConfig struct {
TLSKeyFilePath string `yaml:"tls_key_file_path,omitempty"`
}

type LabeLSelectorPaths struct {
MatchLabelsPath string
MatchExpressionsPath string
}

func LoadFromFile(file string, target *Config) error {
return unmarshal(target, file)
}
@@ -155,92 +150,55 @@ func LoadFromCLI(target *Config, flagSet *pflag.FlagSet) error {
return nil
}

// readPath extracts value from specific YAMLPath.
func readPath(p string, yamlFile []byte, f interface{}) error {
path, err := yaml.PathString(p)
if err != nil {
return err
}
if err := path.Read(strings.NewReader(string(yamlFile)), f); err != nil {
return err
}
return nil
}

func readLabelSelectorPaths(ps LabeLSelectorPaths, yamlFile []byte, f *metav1.LabelSelector) (bool, error) {
founderrs := 0

if err := readPath(ps.MatchLabelsPath, yamlFile, &f.MatchLabels); err != nil {
if !errors.Is(err, yaml.ErrNotFoundNode) {
return false, err
func StringToModelDurationHookFunc() mapstructure.DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
founderrs += 1
}
if err := readPath(ps.MatchExpressionsPath, yamlFile, &f.MatchExpressions); err != nil {
if !errors.Is(err, yaml.ErrNotFoundNode) {
return false, err
}
founderrs += 1
}

return founderrs < 2, nil
}

func flexibleLabelSelector(yamlFile []byte, fieldPathsMap map[*metav1.LabelSelector]LabeLSelectorPaths) error {
for f, ps := range fieldPathsMap {
tmpls := metav1.LabelSelector{}

found, err := readLabelSelectorPaths(ps, yamlFile, &tmpls)
if err != nil {
return err
if t != reflect.TypeOf(model.Duration(5)) {
return data, nil
}

if found {
if err := mergo.Merge(f, tmpls, mergo.WithOverride); err != nil {
return err
}
}
// Convert it by parsing
return time.ParseDuration(data.(string))
}
return nil
}

func flexibleCollectorSelector(yamlFile []byte, cfg *Config) error {
collectorSelectorFieldPathsMap := map[*metav1.LabelSelector]LabeLSelectorPaths{
cfg.CollectorSelector: {
MatchLabelsPath: "$.collector_selector.matchlabels",
MatchExpressionsPath: "$.collector_selector.matchexpressions",
},
func decodeSubConfig(t interface{}, dc mapstructure.DecoderConfig) error {
dec, decError := mapstructure.NewDecoder(&dc)
if decError != nil {
return decError
}

if err := flexibleLabelSelector(yamlFile, collectorSelectorFieldPathsMap); err != nil {
if err := dec.Decode(t); err != nil {
return err
}
return nil
}

func flexiblePrometheusCR(yamlFile []byte, cfg *Config) error {
prometheusCRFieldPathsMap := map[*metav1.LabelSelector]LabeLSelectorPaths{
cfg.PrometheusCR.PodMonitorSelector: {
MatchLabelsPath: "$.prometheus_cr.pod_monitor_selector.matchlabels",
MatchExpressionsPath: "$.prometheus_cr.pod_monitor_selector.matchexpressions",
},
cfg.PrometheusCR.ServiceMonitorSelector: {
MatchLabelsPath: "$.prometheus_cr.service_monitor_selector.matchlabels",
MatchExpressionsPath: "$.prometheus_cr.service_monitor_selector.matchexpressions",
},
cfg.PrometheusCR.ServiceMonitorNamespaceSelector: {
MatchLabelsPath: "$.prometheus_cr.service_monitor_namespace_selector.matchlabels",
MatchExpressionsPath: "$.prometheus_cr.service_monitor_namespace_selector.matchexpressions",
},
cfg.PrometheusCR.PodMonitorNamespaceSelector: {
MatchLabelsPath: "$.prometheus_cr.pod_monitor_namespace_selector.matchlabels",
MatchExpressionsPath: "$.prometheus_cr.pod_monitor_namespace_selector.matchexpressions",
},
func flexibleUnmarshal(yamlFile []byte, cfg *Config) error {
t := make(map[string]interface{})
if err := yaml.Unmarshal(yamlFile, &t); err != nil {
return fmt.Errorf("error unmarshaling YAML: %w", err)
}

if err := flexibleLabelSelector(yamlFile, prometheusCRFieldPathsMap); err != nil {
return err
if t["collector_selector"] != nil {
dc := mapstructure.DecoderConfig{TagName: "yaml", Result: cfg.CollectorSelector}
if err := decodeSubConfig(t["collector_selector"], dc); err != nil {
return err
}
}

if t["prometheus_cr"] != nil {
dc := mapstructure.DecoderConfig{TagName: "yaml", Result: &cfg.PrometheusCR, DecodeHook: StringToModelDurationHookFunc()}
if err := decodeSubConfig(t["prometheus_cr"], dc); err != nil {
return err
}
}

return nil
}

@@ -249,16 +207,11 @@ func unmarshal(cfg *Config, configFile string) error {
if err != nil {
return err
}

if err = yaml.Unmarshal(yamlFile, cfg); err != nil {
return fmt.Errorf("error unmarshaling YAML: %w", err)
}

if err := flexibleCollectorSelector(yamlFile, cfg); err != nil {
return err
}

if err := flexiblePrometheusCR(yamlFile, cfg); err != nil {
if err := flexibleUnmarshal(yamlFile, cfg); err != nil {
return err
}

5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ require (
github.com/gin-gonic/gin v1.10.0
github.com/go-kit/log v0.2.1
github.com/go-logr/logr v1.4.2
github.com/goccy/go-yaml v1.13.4
github.com/google/uuid v1.6.0
github.com/json-iterator/go v1.1.12
github.com/mitchellh/mapstructure v1.5.0
@@ -94,7 +93,7 @@ require (
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
@@ -116,7 +115,7 @@ require (
github.com/go-openapi/validate v0.24.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-resty/resty/v2 v2.13.1 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
10 changes: 4 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -165,8 +165,8 @@ github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
@@ -229,8 +229,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g=
github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -240,8 +240,6 @@ github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-yaml v1.13.4 h1:XOnLX9GqT+kH/gB7YzCMUiDBFU9B7pm3HZz6kyeDPkk=
github.com/goccy/go-yaml v1.13.4/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=