Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/util/defaults.go
4093 views
1
package util
2
3
import "flag"
4
5
// DefaultConfigFromFlags will load default values into cfg by
6
// retrieving default values that are registered as flags.
7
//
8
// cfg must implement either PrefixedConfigFlags or ConfigFlags.
9
func DefaultConfigFromFlags(cfg interface{}) interface{} {
10
// This function is super ugly but is required for mixing the combination
11
// of mechanisms for providing default for config structs that are used
12
// across both Prometheus (via UnmarshalYAML and assigning the default object)
13
// and Cortex (via RegisterFlags*).
14
//
15
// The issue stems from default values assigned via RegisterFlags being set
16
// at *registration* time, not *flag parse* time. For example, this
17
// flag:
18
//
19
// fs.BoolVar(&enabled, "enabled", true, "enable everything")
20
//
21
// Sets enabled to true as soon as fs.BoolVar is called. Normally this is
22
// fine, but with how Prometheus implements UnmarshalYAML, these defaults
23
// get overridden:
24
//
25
// func (c *Config) UnmarshalYAML(unmarshal func(v interface{}) error) error {
26
// *c = DefaultConfig // <-- !! overrides defaults from flags !!
27
// type plain Config
28
// return unmarshal((*plain)(c))
29
// }
30
//
31
// The solution to this is to make sure that the DefaultConfig object contains
32
// the defaults that are set up through registering flags. Unfortunately, the
33
// best way to do this is this function that creates a temporary flagset just for
34
// the sake of collecting default values.
35
//
36
// This function should be used like so:
37
//
38
// var DefaultConfig = *DefaultConfigFromFlags(&Config{}).(*Config)
39
40
fs := flag.NewFlagSet("DefaultConfigFromFlags", flag.PanicOnError)
41
42
if v, ok := cfg.(PrefixedConfigFlags); ok {
43
v.RegisterFlagsWithPrefix("", fs)
44
} else if v, ok := cfg.(ConfigFlags); ok {
45
v.RegisterFlags(fs)
46
} else {
47
panic("config does not implement PrefixedConfigFlags or ConfigFlags")
48
}
49
50
return cfg
51
}
52
53
// ConfigFlags is an interface that will register flags that can control
54
// some object.
55
type ConfigFlags interface {
56
RegisterFlags(f *flag.FlagSet)
57
}
58
59
// PrefixedConfigFlags is an interface that, given a prefix for flags
60
// and a flagset, will register flags that can control some object.
61
type PrefixedConfigFlags interface {
62
RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet)
63
}
64
65