package util12import "flag"34// DefaultConfigFromFlags will load default values into cfg by5// retrieving default values that are registered as flags.6//7// cfg must implement either PrefixedConfigFlags or ConfigFlags.8func DefaultConfigFromFlags(cfg interface{}) interface{} {9// This function is super ugly but is required for mixing the combination10// of mechanisms for providing default for config structs that are used11// across both Prometheus (via UnmarshalYAML and assigning the default object)12// and Cortex (via RegisterFlags*).13//14// The issue stems from default values assigned via RegisterFlags being set15// at *registration* time, not *flag parse* time. For example, this16// flag:17//18// fs.BoolVar(&enabled, "enabled", true, "enable everything")19//20// Sets enabled to true as soon as fs.BoolVar is called. Normally this is21// fine, but with how Prometheus implements UnmarshalYAML, these defaults22// get overridden:23//24// func (c *Config) UnmarshalYAML(unmarshal func(v interface{}) error) error {25// *c = DefaultConfig // <-- !! overrides defaults from flags !!26// type plain Config27// return unmarshal((*plain)(c))28// }29//30// The solution to this is to make sure that the DefaultConfig object contains31// the defaults that are set up through registering flags. Unfortunately, the32// best way to do this is this function that creates a temporary flagset just for33// the sake of collecting default values.34//35// This function should be used like so:36//37// var DefaultConfig = *DefaultConfigFromFlags(&Config{}).(*Config)3839fs := flag.NewFlagSet("DefaultConfigFromFlags", flag.PanicOnError)4041if v, ok := cfg.(PrefixedConfigFlags); ok {42v.RegisterFlagsWithPrefix("", fs)43} else if v, ok := cfg.(ConfigFlags); ok {44v.RegisterFlags(fs)45} else {46panic("config does not implement PrefixedConfigFlags or ConfigFlags")47}4849return cfg50}5152// ConfigFlags is an interface that will register flags that can control53// some object.54type ConfigFlags interface {55RegisterFlags(f *flag.FlagSet)56}5758// PrefixedConfigFlags is an interface that, given a prefix for flags59// and a flagset, will register flags that can control some object.60type PrefixedConfigFlags interface {61RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet)62}636465