github.com/thanos-io/thanos@v0.32.5/pkg/alert/config.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package alert 5 6 import ( 7 "net" 8 "net/url" 9 "strconv" 10 "strings" 11 "time" 12 13 "github.com/pkg/errors" 14 "github.com/prometheus/common/model" 15 "github.com/prometheus/prometheus/model/relabel" 16 "gopkg.in/yaml.v2" 17 18 "github.com/thanos-io/thanos/pkg/discovery/dns" 19 "github.com/thanos-io/thanos/pkg/httpconfig" 20 ) 21 22 type AlertingConfig struct { 23 Alertmanagers []AlertmanagerConfig `yaml:"alertmanagers"` 24 } 25 26 // AlertmanagerConfig represents a client to a cluster of Alertmanager endpoints. 27 type AlertmanagerConfig struct { 28 HTTPClientConfig httpconfig.ClientConfig `yaml:"http_config"` 29 EndpointsConfig httpconfig.EndpointsConfig `yaml:",inline"` 30 Timeout model.Duration `yaml:"timeout"` 31 APIVersion APIVersion `yaml:"api_version"` 32 } 33 34 // APIVersion represents the API version of the Alertmanager endpoint. 35 type APIVersion string 36 37 const ( 38 APIv1 APIVersion = "v1" 39 APIv2 APIVersion = "v2" 40 ) 41 42 var supportedAPIVersions = []APIVersion{ 43 APIv1, APIv2, 44 } 45 46 // UnmarshalYAML implements the yaml.Unmarshaler interface. 47 func (v *APIVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { 48 var s string 49 if err := unmarshal(&s); err != nil { 50 return errors.Wrap(err, "invalid Alertmanager API version") 51 } 52 53 for _, ver := range supportedAPIVersions { 54 if APIVersion(s) == ver { 55 *v = ver 56 return nil 57 } 58 } 59 return errors.Errorf("expected Alertmanager API version to be one of %v but got %q", supportedAPIVersions, s) 60 } 61 62 func DefaultAlertmanagerConfig() AlertmanagerConfig { 63 return AlertmanagerConfig{ 64 EndpointsConfig: httpconfig.EndpointsConfig{ 65 Scheme: "http", 66 StaticAddresses: []string{}, 67 FileSDConfigs: []httpconfig.FileSDConfig{}, 68 }, 69 Timeout: model.Duration(time.Second * 10), 70 APIVersion: APIv1, 71 } 72 } 73 74 // UnmarshalYAML implements the yaml.Unmarshaler interface. 75 func (c *AlertmanagerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 76 *c = DefaultAlertmanagerConfig() 77 type plain AlertmanagerConfig 78 return unmarshal((*plain)(c)) 79 } 80 81 // LoadAlertingConfig loads a list of AlertmanagerConfig from YAML data. 82 func LoadAlertingConfig(confYaml []byte) (AlertingConfig, error) { 83 var cfg AlertingConfig 84 if err := yaml.UnmarshalStrict(confYaml, &cfg); err != nil { 85 return cfg, err 86 } 87 return cfg, nil 88 } 89 90 // BuildAlertmanagerConfig initializes and returns an Alertmanager client configuration from a static address. 91 func BuildAlertmanagerConfig(address string, timeout time.Duration) (AlertmanagerConfig, error) { 92 parsed, err := url.Parse(address) 93 if err != nil { 94 return AlertmanagerConfig{}, err 95 } 96 97 scheme := parsed.Scheme 98 if scheme == "" { 99 return AlertmanagerConfig{}, errors.New("alertmanagers.url contains empty scheme") 100 } 101 102 host := parsed.Host 103 if host == "" { 104 return AlertmanagerConfig{}, errors.New("alertmanagers.url contains empty host") 105 } 106 107 for _, qType := range []dns.QType{dns.A, dns.SRV, dns.SRVNoA} { 108 prefix := string(qType) + "+" 109 if strings.HasPrefix(strings.ToLower(scheme), prefix) { 110 // Scheme is of the form "<dns type>+<http scheme>". 111 scheme = strings.TrimPrefix(scheme, prefix) 112 host = prefix + parsed.Host 113 if qType == dns.A { 114 if _, _, err := net.SplitHostPort(parsed.Host); err != nil { 115 // The host port could be missing. Append the defaultAlertmanagerPort. 116 host = host + ":" + strconv.Itoa(defaultAlertmanagerPort) 117 } 118 } 119 break 120 } 121 } 122 var basicAuth httpconfig.BasicAuth 123 if parsed.User != nil && parsed.User.String() != "" { 124 basicAuth.Username = parsed.User.Username() 125 pw, _ := parsed.User.Password() 126 basicAuth.Password = pw 127 } 128 129 return AlertmanagerConfig{ 130 HTTPClientConfig: httpconfig.ClientConfig{ 131 BasicAuth: basicAuth, 132 }, 133 EndpointsConfig: httpconfig.EndpointsConfig{ 134 PathPrefix: parsed.Path, 135 Scheme: scheme, 136 StaticAddresses: []string{host}, 137 }, 138 Timeout: model.Duration(timeout), 139 APIVersion: APIv1, 140 }, nil 141 } 142 143 // LoadRelabelConfigs loads a list of relabel.Config from YAML data. 144 func LoadRelabelConfigs(confYaml []byte) ([]*relabel.Config, error) { 145 var cfg []*relabel.Config 146 if err := yaml.UnmarshalStrict(confYaml, &cfg); err != nil { 147 return nil, err 148 } 149 return cfg, nil 150 }