1// Copyright 2015 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package config 15 16import ( 17 "encoding/json" 18 "fmt" 19 "io/ioutil" 20 "net/url" 21 "path/filepath" 22 "regexp" 23 "strings" 24 "time" 25 26 "github.com/aws/aws-sdk-go/aws/ec2metadata" 27 "github.com/aws/aws-sdk-go/aws/session" 28 "github.com/prometheus/common/model" 29 "gopkg.in/yaml.v2" 30) 31 32var ( 33 patFileSDName = regexp.MustCompile(`^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$`) 34 patRulePath = regexp.MustCompile(`^[^*]*(\*[^/]*)?$`) 35 relabelTarget = regexp.MustCompile(`^(?:(?:[a-zA-Z_]|\$(?:\{\w+\}|\w+))+\w*)+$`) 36) 37 38// Load parses the YAML input s into a Config. 39func Load(s string) (*Config, error) { 40 cfg := &Config{} 41 // If the entire config body is empty the UnmarshalYAML method is 42 // never called. We thus have to set the DefaultConfig at the entry 43 // point as well. 44 *cfg = DefaultConfig 45 46 err := yaml.Unmarshal([]byte(s), cfg) 47 if err != nil { 48 return nil, err 49 } 50 cfg.original = s 51 return cfg, nil 52} 53 54// LoadFile parses the given YAML file into a Config. 55func LoadFile(filename string) (*Config, error) { 56 content, err := ioutil.ReadFile(filename) 57 if err != nil { 58 return nil, err 59 } 60 cfg, err := Load(string(content)) 61 if err != nil { 62 return nil, err 63 } 64 resolveFilepaths(filepath.Dir(filename), cfg) 65 return cfg, nil 66} 67 68// The defaults applied before parsing the respective config sections. 69var ( 70 // DefaultConfig is the default top-level configuration. 71 DefaultConfig = Config{ 72 GlobalConfig: DefaultGlobalConfig, 73 } 74 75 // DefaultGlobalConfig is the default global configuration. 76 DefaultGlobalConfig = GlobalConfig{ 77 ScrapeInterval: model.Duration(1 * time.Minute), 78 ScrapeTimeout: model.Duration(10 * time.Second), 79 EvaluationInterval: model.Duration(1 * time.Minute), 80 } 81 82 // DefaultScrapeConfig is the default scrape configuration. 83 DefaultScrapeConfig = ScrapeConfig{ 84 // ScrapeTimeout and ScrapeInterval default to the 85 // configured globals. 86 MetricsPath: "/metrics", 87 Scheme: "http", 88 HonorLabels: false, 89 } 90 91 // DefaultAlertmanagerConfig is the default alertmanager configuration. 92 DefaultAlertmanagerConfig = AlertmanagerConfig{ 93 Scheme: "http", 94 Timeout: 10 * time.Second, 95 } 96 97 // DefaultRelabelConfig is the default Relabel configuration. 98 DefaultRelabelConfig = RelabelConfig{ 99 Action: RelabelReplace, 100 Separator: ";", 101 Regex: MustNewRegexp("(.*)"), 102 Replacement: "$1", 103 } 104 105 // DefaultDNSSDConfig is the default DNS SD configuration. 106 DefaultDNSSDConfig = DNSSDConfig{ 107 RefreshInterval: model.Duration(30 * time.Second), 108 Type: "SRV", 109 } 110 111 // DefaultFileSDConfig is the default file SD configuration. 112 DefaultFileSDConfig = FileSDConfig{ 113 RefreshInterval: model.Duration(5 * time.Minute), 114 } 115 116 // DefaultConsulSDConfig is the default Consul SD configuration. 117 DefaultConsulSDConfig = ConsulSDConfig{ 118 TagSeparator: ",", 119 Scheme: "http", 120 } 121 122 // DefaultServersetSDConfig is the default Serverset SD configuration. 123 DefaultServersetSDConfig = ServersetSDConfig{ 124 Timeout: model.Duration(10 * time.Second), 125 } 126 127 // DefaultNerveSDConfig is the default Nerve SD configuration. 128 DefaultNerveSDConfig = NerveSDConfig{ 129 Timeout: model.Duration(10 * time.Second), 130 } 131 132 // DefaultMarathonSDConfig is the default Marathon SD configuration. 133 DefaultMarathonSDConfig = MarathonSDConfig{ 134 Timeout: model.Duration(30 * time.Second), 135 RefreshInterval: model.Duration(30 * time.Second), 136 } 137 138 // DefaultKubernetesSDConfig is the default Kubernetes SD configuration 139 DefaultKubernetesSDConfig = KubernetesSDConfig{} 140 141 // DefaultGCESDConfig is the default EC2 SD configuration. 142 DefaultGCESDConfig = GCESDConfig{ 143 Port: 80, 144 TagSeparator: ",", 145 RefreshInterval: model.Duration(60 * time.Second), 146 } 147 148 // DefaultEC2SDConfig is the default EC2 SD configuration. 149 DefaultEC2SDConfig = EC2SDConfig{ 150 Port: 80, 151 RefreshInterval: model.Duration(60 * time.Second), 152 } 153 154 // DefaultOpenstackSDConfig is the default OpenStack SD configuration. 155 DefaultOpenstackSDConfig = OpenstackSDConfig{ 156 Port: 80, 157 RefreshInterval: model.Duration(60 * time.Second), 158 } 159 160 // DefaultAzureSDConfig is the default Azure SD configuration. 161 DefaultAzureSDConfig = AzureSDConfig{ 162 Port: 80, 163 RefreshInterval: model.Duration(5 * time.Minute), 164 } 165 166 // DefaultTritonSDConfig is the default Triton SD configuration. 167 DefaultTritonSDConfig = TritonSDConfig{ 168 Port: 9163, 169 RefreshInterval: model.Duration(60 * time.Second), 170 Version: 1, 171 } 172 173 // DefaultRemoteWriteConfig is the default remote write configuration. 174 DefaultRemoteWriteConfig = RemoteWriteConfig{ 175 RemoteTimeout: model.Duration(30 * time.Second), 176 QueueConfig: DefaultQueueConfig, 177 } 178 179 // DefaultQueueConfig is the default remote queue configuration. 180 DefaultQueueConfig = QueueConfig{ 181 // With a maximum of 1000 shards, assuming an average of 100ms remote write 182 // time and 100 samples per batch, we will be able to push 1M samples/s. 183 MaxShards: 1000, 184 MaxSamplesPerSend: 100, 185 186 // By default, buffer 1000 batches, which at 100ms per batch is 1:40mins. At 187 // 1000 shards, this will buffer 100M samples total. 188 Capacity: 100 * 1000, 189 BatchSendDeadline: 5 * time.Second, 190 191 // Max number of times to retry a batch on recoverable errors. 192 MaxRetries: 10, 193 MinBackoff: 30 * time.Millisecond, 194 MaxBackoff: 100 * time.Millisecond, 195 } 196 197 // DefaultRemoteReadConfig is the default remote read configuration. 198 DefaultRemoteReadConfig = RemoteReadConfig{ 199 RemoteTimeout: model.Duration(1 * time.Minute), 200 } 201) 202 203// URL is a custom URL type that allows validation at configuration load time. 204type URL struct { 205 *url.URL 206} 207 208// UnmarshalYAML implements the yaml.Unmarshaler interface for URLs. 209func (u *URL) UnmarshalYAML(unmarshal func(interface{}) error) error { 210 var s string 211 if err := unmarshal(&s); err != nil { 212 return err 213 } 214 215 urlp, err := url.Parse(s) 216 if err != nil { 217 return err 218 } 219 u.URL = urlp 220 return nil 221} 222 223// MarshalYAML implements the yaml.Marshaler interface for URLs. 224func (u URL) MarshalYAML() (interface{}, error) { 225 if u.URL != nil { 226 return u.String(), nil 227 } 228 return nil, nil 229} 230 231// Config is the top-level configuration for Prometheus's config files. 232type Config struct { 233 GlobalConfig GlobalConfig `yaml:"global"` 234 AlertingConfig AlertingConfig `yaml:"alerting,omitempty"` 235 RuleFiles []string `yaml:"rule_files,omitempty"` 236 ScrapeConfigs []*ScrapeConfig `yaml:"scrape_configs,omitempty"` 237 238 RemoteWriteConfigs []*RemoteWriteConfig `yaml:"remote_write,omitempty"` 239 RemoteReadConfigs []*RemoteReadConfig `yaml:"remote_read,omitempty"` 240 241 // Catches all undefined fields and must be empty after parsing. 242 XXX map[string]interface{} `yaml:",inline"` 243 244 // original is the input from which the config was parsed. 245 original string 246} 247 248// Secret special type for storing secrets. 249type Secret string 250 251// UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets. 252func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error { 253 type plain Secret 254 return unmarshal((*plain)(s)) 255} 256 257// MarshalYAML implements the yaml.Marshaler interface for Secrets. 258func (s Secret) MarshalYAML() (interface{}, error) { 259 if s != "" { 260 return "<secret>", nil 261 } 262 return nil, nil 263} 264 265// resolveFilepaths joins all relative paths in a configuration 266// with a given base directory. 267func resolveFilepaths(baseDir string, cfg *Config) { 268 join := func(fp string) string { 269 if len(fp) > 0 && !filepath.IsAbs(fp) { 270 fp = filepath.Join(baseDir, fp) 271 } 272 return fp 273 } 274 275 for i, rf := range cfg.RuleFiles { 276 cfg.RuleFiles[i] = join(rf) 277 } 278 279 clientPaths := func(scfg *HTTPClientConfig) { 280 scfg.BearerTokenFile = join(scfg.BearerTokenFile) 281 scfg.TLSConfig.CAFile = join(scfg.TLSConfig.CAFile) 282 scfg.TLSConfig.CertFile = join(scfg.TLSConfig.CertFile) 283 scfg.TLSConfig.KeyFile = join(scfg.TLSConfig.KeyFile) 284 } 285 sdPaths := func(cfg *ServiceDiscoveryConfig) { 286 for _, kcfg := range cfg.KubernetesSDConfigs { 287 kcfg.BearerTokenFile = join(kcfg.BearerTokenFile) 288 kcfg.TLSConfig.CAFile = join(kcfg.TLSConfig.CAFile) 289 kcfg.TLSConfig.CertFile = join(kcfg.TLSConfig.CertFile) 290 kcfg.TLSConfig.KeyFile = join(kcfg.TLSConfig.KeyFile) 291 } 292 for _, mcfg := range cfg.MarathonSDConfigs { 293 mcfg.BearerTokenFile = join(mcfg.BearerTokenFile) 294 mcfg.TLSConfig.CAFile = join(mcfg.TLSConfig.CAFile) 295 mcfg.TLSConfig.CertFile = join(mcfg.TLSConfig.CertFile) 296 mcfg.TLSConfig.KeyFile = join(mcfg.TLSConfig.KeyFile) 297 } 298 for _, consulcfg := range cfg.ConsulSDConfigs { 299 consulcfg.TLSConfig.CAFile = join(consulcfg.TLSConfig.CAFile) 300 consulcfg.TLSConfig.CertFile = join(consulcfg.TLSConfig.CertFile) 301 consulcfg.TLSConfig.KeyFile = join(consulcfg.TLSConfig.KeyFile) 302 } 303 } 304 305 for _, cfg := range cfg.ScrapeConfigs { 306 clientPaths(&cfg.HTTPClientConfig) 307 sdPaths(&cfg.ServiceDiscoveryConfig) 308 } 309 for _, cfg := range cfg.AlertingConfig.AlertmanagerConfigs { 310 clientPaths(&cfg.HTTPClientConfig) 311 sdPaths(&cfg.ServiceDiscoveryConfig) 312 } 313} 314 315func checkOverflow(m map[string]interface{}, ctx string) error { 316 if len(m) > 0 { 317 var keys []string 318 for k := range m { 319 keys = append(keys, k) 320 } 321 return fmt.Errorf("unknown fields in %s: %s", ctx, strings.Join(keys, ", ")) 322 } 323 return nil 324} 325 326func (c Config) String() string { 327 b, err := yaml.Marshal(c) 328 if err != nil { 329 return fmt.Sprintf("<error creating config string: %s>", err) 330 } 331 return string(b) 332} 333 334// UnmarshalYAML implements the yaml.Unmarshaler interface. 335func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { 336 *c = DefaultConfig 337 // We want to set c to the defaults and then overwrite it with the input. 338 // To make unmarshal fill the plain data struct rather than calling UnmarshalYAML 339 // again, we have to hide it using a type indirection. 340 type plain Config 341 if err := unmarshal((*plain)(c)); err != nil { 342 return err 343 } 344 if err := checkOverflow(c.XXX, "config"); err != nil { 345 return err 346 } 347 // If a global block was open but empty the default global config is overwritten. 348 // We have to restore it here. 349 if c.GlobalConfig.isZero() { 350 c.GlobalConfig = DefaultGlobalConfig 351 } 352 353 for _, rf := range c.RuleFiles { 354 if !patRulePath.MatchString(rf) { 355 return fmt.Errorf("invalid rule file path %q", rf) 356 } 357 } 358 // Do global overrides and validate unique names. 359 jobNames := map[string]struct{}{} 360 for _, scfg := range c.ScrapeConfigs { 361 // First set the correct scrape interval, then check that the timeout 362 // (inferred or explicit) is not greater than that. 363 if scfg.ScrapeInterval == 0 { 364 scfg.ScrapeInterval = c.GlobalConfig.ScrapeInterval 365 } 366 if scfg.ScrapeTimeout > scfg.ScrapeInterval { 367 return fmt.Errorf("scrape timeout greater than scrape interval for scrape config with job name %q", scfg.JobName) 368 } 369 if scfg.ScrapeTimeout == 0 { 370 if c.GlobalConfig.ScrapeTimeout > scfg.ScrapeInterval { 371 scfg.ScrapeTimeout = scfg.ScrapeInterval 372 } else { 373 scfg.ScrapeTimeout = c.GlobalConfig.ScrapeTimeout 374 } 375 } 376 377 if _, ok := jobNames[scfg.JobName]; ok { 378 return fmt.Errorf("found multiple scrape configs with job name %q", scfg.JobName) 379 } 380 jobNames[scfg.JobName] = struct{}{} 381 } 382 return nil 383} 384 385// GlobalConfig configures values that are used across other configuration 386// objects. 387type GlobalConfig struct { 388 // How frequently to scrape targets by default. 389 ScrapeInterval model.Duration `yaml:"scrape_interval,omitempty"` 390 // The default timeout when scraping targets. 391 ScrapeTimeout model.Duration `yaml:"scrape_timeout,omitempty"` 392 // How frequently to evaluate rules by default. 393 EvaluationInterval model.Duration `yaml:"evaluation_interval,omitempty"` 394 // The labels to add to any timeseries that this Prometheus instance scrapes. 395 ExternalLabels model.LabelSet `yaml:"external_labels,omitempty"` 396 397 // Catches all undefined fields and must be empty after parsing. 398 XXX map[string]interface{} `yaml:",inline"` 399} 400 401// UnmarshalYAML implements the yaml.Unmarshaler interface. 402func (c *GlobalConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 403 // Create a clean global config as the previous one was already populated 404 // by the default due to the YAML parser behavior for empty blocks. 405 gc := &GlobalConfig{} 406 type plain GlobalConfig 407 if err := unmarshal((*plain)(gc)); err != nil { 408 return err 409 } 410 if err := checkOverflow(gc.XXX, "global config"); err != nil { 411 return err 412 } 413 // First set the correct scrape interval, then check that the timeout 414 // (inferred or explicit) is not greater than that. 415 if gc.ScrapeInterval == 0 { 416 gc.ScrapeInterval = DefaultGlobalConfig.ScrapeInterval 417 } 418 if gc.ScrapeTimeout > gc.ScrapeInterval { 419 return fmt.Errorf("global scrape timeout greater than scrape interval") 420 } 421 if gc.ScrapeTimeout == 0 { 422 if DefaultGlobalConfig.ScrapeTimeout > gc.ScrapeInterval { 423 gc.ScrapeTimeout = gc.ScrapeInterval 424 } else { 425 gc.ScrapeTimeout = DefaultGlobalConfig.ScrapeTimeout 426 } 427 } 428 if gc.EvaluationInterval == 0 { 429 gc.EvaluationInterval = DefaultGlobalConfig.EvaluationInterval 430 } 431 *c = *gc 432 return nil 433} 434 435// isZero returns true iff the global config is the zero value. 436func (c *GlobalConfig) isZero() bool { 437 return c.ExternalLabels == nil && 438 c.ScrapeInterval == 0 && 439 c.ScrapeTimeout == 0 && 440 c.EvaluationInterval == 0 441} 442 443// TLSConfig configures the options for TLS connections. 444type TLSConfig struct { 445 // The CA cert to use for the targets. 446 CAFile string `yaml:"ca_file,omitempty"` 447 // The client cert file for the targets. 448 CertFile string `yaml:"cert_file,omitempty"` 449 // The client key file for the targets. 450 KeyFile string `yaml:"key_file,omitempty"` 451 // Used to verify the hostname for the targets. 452 ServerName string `yaml:"server_name,omitempty"` 453 // Disable target certificate validation. 454 InsecureSkipVerify bool `yaml:"insecure_skip_verify"` 455 456 // Catches all undefined fields and must be empty after parsing. 457 XXX map[string]interface{} `yaml:",inline"` 458} 459 460// UnmarshalYAML implements the yaml.Unmarshaler interface. 461func (c *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 462 type plain TLSConfig 463 if err := unmarshal((*plain)(c)); err != nil { 464 return err 465 } 466 return checkOverflow(c.XXX, "TLS config") 467} 468 469// ServiceDiscoveryConfig configures lists of different service discovery mechanisms. 470type ServiceDiscoveryConfig struct { 471 // List of labeled target groups for this job. 472 StaticConfigs []*TargetGroup `yaml:"static_configs,omitempty"` 473 // List of DNS service discovery configurations. 474 DNSSDConfigs []*DNSSDConfig `yaml:"dns_sd_configs,omitempty"` 475 // List of file service discovery configurations. 476 FileSDConfigs []*FileSDConfig `yaml:"file_sd_configs,omitempty"` 477 // List of Consul service discovery configurations. 478 ConsulSDConfigs []*ConsulSDConfig `yaml:"consul_sd_configs,omitempty"` 479 // List of Serverset service discovery configurations. 480 ServersetSDConfigs []*ServersetSDConfig `yaml:"serverset_sd_configs,omitempty"` 481 // NerveSDConfigs is a list of Nerve service discovery configurations. 482 NerveSDConfigs []*NerveSDConfig `yaml:"nerve_sd_configs,omitempty"` 483 // MarathonSDConfigs is a list of Marathon service discovery configurations. 484 MarathonSDConfigs []*MarathonSDConfig `yaml:"marathon_sd_configs,omitempty"` 485 // List of Kubernetes service discovery configurations. 486 KubernetesSDConfigs []*KubernetesSDConfig `yaml:"kubernetes_sd_configs,omitempty"` 487 // List of GCE service discovery configurations. 488 GCESDConfigs []*GCESDConfig `yaml:"gce_sd_configs,omitempty"` 489 // List of EC2 service discovery configurations. 490 EC2SDConfigs []*EC2SDConfig `yaml:"ec2_sd_configs,omitempty"` 491 // List of OpenStack service discovery configurations. 492 OpenstackSDConfigs []*OpenstackSDConfig `yaml:"openstack_sd_configs,omitempty"` 493 // List of Azure service discovery configurations. 494 AzureSDConfigs []*AzureSDConfig `yaml:"azure_sd_configs,omitempty"` 495 // List of Triton service discovery configurations. 496 TritonSDConfigs []*TritonSDConfig `yaml:"triton_sd_configs,omitempty"` 497 498 // Catches all undefined fields and must be empty after parsing. 499 XXX map[string]interface{} `yaml:",inline"` 500} 501 502// UnmarshalYAML implements the yaml.Unmarshaler interface. 503func (c *ServiceDiscoveryConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 504 type plain ServiceDiscoveryConfig 505 if err := unmarshal((*plain)(c)); err != nil { 506 return err 507 } 508 return checkOverflow(c.XXX, "service discovery config") 509} 510 511// HTTPClientConfig configures an HTTP client. 512type HTTPClientConfig struct { 513 // The HTTP basic authentication credentials for the targets. 514 BasicAuth *BasicAuth `yaml:"basic_auth,omitempty"` 515 // The bearer token for the targets. 516 BearerToken Secret `yaml:"bearer_token,omitempty"` 517 // The bearer token file for the targets. 518 BearerTokenFile string `yaml:"bearer_token_file,omitempty"` 519 // HTTP proxy server to use to connect to the targets. 520 ProxyURL URL `yaml:"proxy_url,omitempty"` 521 // TLSConfig to use to connect to the targets. 522 TLSConfig TLSConfig `yaml:"tls_config,omitempty"` 523 524 // Catches all undefined fields and must be empty after parsing. 525 XXX map[string]interface{} `yaml:",inline"` 526} 527 528func (c *HTTPClientConfig) validate() error { 529 if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 { 530 return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured") 531 } 532 if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) { 533 return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured") 534 } 535 return nil 536} 537 538// ScrapeConfig configures a scraping unit for Prometheus. 539type ScrapeConfig struct { 540 // The job name to which the job label is set by default. 541 JobName string `yaml:"job_name"` 542 // Indicator whether the scraped metrics should remain unmodified. 543 HonorLabels bool `yaml:"honor_labels,omitempty"` 544 // A set of query parameters with which the target is scraped. 545 Params url.Values `yaml:"params,omitempty"` 546 // How frequently to scrape the targets of this scrape config. 547 ScrapeInterval model.Duration `yaml:"scrape_interval,omitempty"` 548 // The timeout for scraping targets of this config. 549 ScrapeTimeout model.Duration `yaml:"scrape_timeout,omitempty"` 550 // The HTTP resource path on which to fetch metrics from targets. 551 MetricsPath string `yaml:"metrics_path,omitempty"` 552 // The URL scheme with which to fetch metrics from targets. 553 Scheme string `yaml:"scheme,omitempty"` 554 // More than this many samples post metric-relabelling will cause the scrape to fail. 555 SampleLimit uint `yaml:"sample_limit,omitempty"` 556 557 // We cannot do proper Go type embedding below as the parser will then parse 558 // values arbitrarily into the overflow maps of further-down types. 559 560 ServiceDiscoveryConfig ServiceDiscoveryConfig `yaml:",inline"` 561 HTTPClientConfig HTTPClientConfig `yaml:",inline"` 562 563 // List of target relabel configurations. 564 RelabelConfigs []*RelabelConfig `yaml:"relabel_configs,omitempty"` 565 // List of metric relabel configurations. 566 MetricRelabelConfigs []*RelabelConfig `yaml:"metric_relabel_configs,omitempty"` 567 568 // Catches all undefined fields and must be empty after parsing. 569 XXX map[string]interface{} `yaml:",inline"` 570} 571 572// UnmarshalYAML implements the yaml.Unmarshaler interface. 573func (c *ScrapeConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 574 *c = DefaultScrapeConfig 575 type plain ScrapeConfig 576 err := unmarshal((*plain)(c)) 577 if err != nil { 578 return err 579 } 580 if err = checkOverflow(c.XXX, "scrape_config"); err != nil { 581 return err 582 } 583 if len(c.JobName) == 0 { 584 return fmt.Errorf("job_name is empty") 585 } 586 587 // The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer. 588 // We cannot make it a pointer as the parser panics for inlined pointer structs. 589 // Thus we just do its validation here. 590 if err = c.HTTPClientConfig.validate(); err != nil { 591 return err 592 } 593 594 // Check for users putting URLs in target groups. 595 if len(c.RelabelConfigs) == 0 { 596 for _, tg := range c.ServiceDiscoveryConfig.StaticConfigs { 597 for _, t := range tg.Targets { 598 if err = CheckTargetAddress(t[model.AddressLabel]); err != nil { 599 return err 600 } 601 } 602 } 603 } 604 return nil 605} 606 607// AlertingConfig configures alerting and alertmanager related configs. 608type AlertingConfig struct { 609 AlertRelabelConfigs []*RelabelConfig `yaml:"alert_relabel_configs,omitempty"` 610 AlertmanagerConfigs []*AlertmanagerConfig `yaml:"alertmanagers,omitempty"` 611 612 // Catches all undefined fields and must be empty after parsing. 613 XXX map[string]interface{} `yaml:",inline"` 614} 615 616// UnmarshalYAML implements the yaml.Unmarshaler interface. 617func (c *AlertingConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 618 // Create a clean global config as the previous one was already populated 619 // by the default due to the YAML parser behavior for empty blocks. 620 *c = AlertingConfig{} 621 type plain AlertingConfig 622 if err := unmarshal((*plain)(c)); err != nil { 623 return err 624 } 625 return checkOverflow(c.XXX, "alerting config") 626} 627 628// AlertmanagerConfig configures how Alertmanagers can be discovered and communicated with. 629type AlertmanagerConfig struct { 630 // We cannot do proper Go type embedding below as the parser will then parse 631 // values arbitrarily into the overflow maps of further-down types. 632 633 ServiceDiscoveryConfig ServiceDiscoveryConfig `yaml:",inline"` 634 HTTPClientConfig HTTPClientConfig `yaml:",inline"` 635 636 // The URL scheme to use when talking to Alertmanagers. 637 Scheme string `yaml:"scheme,omitempty"` 638 // Path prefix to add in front of the push endpoint path. 639 PathPrefix string `yaml:"path_prefix,omitempty"` 640 // The timeout used when sending alerts. 641 Timeout time.Duration `yaml:"timeout,omitempty"` 642 643 // List of Alertmanager relabel configurations. 644 RelabelConfigs []*RelabelConfig `yaml:"relabel_configs,omitempty"` 645 646 // Catches all undefined fields and must be empty after parsing. 647 XXX map[string]interface{} `yaml:",inline"` 648} 649 650// UnmarshalYAML implements the yaml.Unmarshaler interface. 651func (c *AlertmanagerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 652 *c = DefaultAlertmanagerConfig 653 type plain AlertmanagerConfig 654 if err := unmarshal((*plain)(c)); err != nil { 655 return err 656 } 657 if err := checkOverflow(c.XXX, "alertmanager config"); err != nil { 658 return err 659 } 660 661 // The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer. 662 // We cannot make it a pointer as the parser panics for inlined pointer structs. 663 // Thus we just do its validation here. 664 if err := c.HTTPClientConfig.validate(); err != nil { 665 return err 666 } 667 668 // Check for users putting URLs in target groups. 669 if len(c.RelabelConfigs) == 0 { 670 for _, tg := range c.ServiceDiscoveryConfig.StaticConfigs { 671 for _, t := range tg.Targets { 672 if err := CheckTargetAddress(t[model.AddressLabel]); err != nil { 673 return err 674 } 675 } 676 } 677 } 678 return nil 679} 680 681// CheckTargetAddress checks if target address is valid. 682func CheckTargetAddress(address model.LabelValue) error { 683 // For now check for a URL, we may want to expand this later. 684 if strings.Contains(string(address), "/") { 685 return fmt.Errorf("%q is not a valid hostname", address) 686 } 687 return nil 688} 689 690// BasicAuth contains basic HTTP authentication credentials. 691type BasicAuth struct { 692 Username string `yaml:"username"` 693 Password Secret `yaml:"password"` 694 695 // Catches all undefined fields and must be empty after parsing. 696 XXX map[string]interface{} `yaml:",inline"` 697} 698 699// ClientCert contains client cert credentials. 700type ClientCert struct { 701 Cert string `yaml:"cert"` 702 Key Secret `yaml:"key"` 703 704 // Catches all undefined fields and must be empty after parsing. 705 XXX map[string]interface{} `yaml:",inline"` 706} 707 708// UnmarshalYAML implements the yaml.Unmarshaler interface. 709func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error { 710 type plain BasicAuth 711 err := unmarshal((*plain)(a)) 712 if err != nil { 713 return err 714 } 715 return checkOverflow(a.XXX, "basic_auth") 716} 717 718// TargetGroup is a set of targets with a common label set. 719type TargetGroup struct { 720 // Targets is a list of targets identified by a label set. Each target is 721 // uniquely identifiable in the group by its address label. 722 Targets []model.LabelSet 723 // Labels is a set of labels that is common across all targets in the group. 724 Labels model.LabelSet 725 726 // Source is an identifier that describes a group of targets. 727 Source string 728} 729 730func (tg TargetGroup) String() string { 731 return tg.Source 732} 733 734// UnmarshalYAML implements the yaml.Unmarshaler interface. 735func (tg *TargetGroup) UnmarshalYAML(unmarshal func(interface{}) error) error { 736 g := struct { 737 Targets []string `yaml:"targets"` 738 Labels model.LabelSet `yaml:"labels"` 739 XXX map[string]interface{} `yaml:",inline"` 740 }{} 741 if err := unmarshal(&g); err != nil { 742 return err 743 } 744 tg.Targets = make([]model.LabelSet, 0, len(g.Targets)) 745 for _, t := range g.Targets { 746 tg.Targets = append(tg.Targets, model.LabelSet{ 747 model.AddressLabel: model.LabelValue(t), 748 }) 749 } 750 tg.Labels = g.Labels 751 return checkOverflow(g.XXX, "static_config") 752} 753 754// MarshalYAML implements the yaml.Marshaler interface. 755func (tg TargetGroup) MarshalYAML() (interface{}, error) { 756 g := &struct { 757 Targets []string `yaml:"targets"` 758 Labels model.LabelSet `yaml:"labels,omitempty"` 759 }{ 760 Targets: make([]string, 0, len(tg.Targets)), 761 Labels: tg.Labels, 762 } 763 for _, t := range tg.Targets { 764 g.Targets = append(g.Targets, string(t[model.AddressLabel])) 765 } 766 return g, nil 767} 768 769// UnmarshalJSON implements the json.Unmarshaler interface. 770func (tg *TargetGroup) UnmarshalJSON(b []byte) error { 771 g := struct { 772 Targets []string `json:"targets"` 773 Labels model.LabelSet `json:"labels"` 774 }{} 775 if err := json.Unmarshal(b, &g); err != nil { 776 return err 777 } 778 tg.Targets = make([]model.LabelSet, 0, len(g.Targets)) 779 for _, t := range g.Targets { 780 tg.Targets = append(tg.Targets, model.LabelSet{ 781 model.AddressLabel: model.LabelValue(t), 782 }) 783 } 784 tg.Labels = g.Labels 785 return nil 786} 787 788// DNSSDConfig is the configuration for DNS based service discovery. 789type DNSSDConfig struct { 790 Names []string `yaml:"names"` 791 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 792 Type string `yaml:"type"` 793 Port int `yaml:"port"` // Ignored for SRV records 794 // Catches all undefined fields and must be empty after parsing. 795 XXX map[string]interface{} `yaml:",inline"` 796} 797 798// UnmarshalYAML implements the yaml.Unmarshaler interface. 799func (c *DNSSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 800 *c = DefaultDNSSDConfig 801 type plain DNSSDConfig 802 err := unmarshal((*plain)(c)) 803 if err != nil { 804 return err 805 } 806 if err := checkOverflow(c.XXX, "dns_sd_config"); err != nil { 807 return err 808 } 809 if len(c.Names) == 0 { 810 return fmt.Errorf("DNS-SD config must contain at least one SRV record name") 811 } 812 switch strings.ToUpper(c.Type) { 813 case "SRV": 814 case "A", "AAAA": 815 if c.Port == 0 { 816 return fmt.Errorf("a port is required in DNS-SD configs for all record types except SRV") 817 } 818 default: 819 return fmt.Errorf("invalid DNS-SD records type %s", c.Type) 820 } 821 return nil 822} 823 824// FileSDConfig is the configuration for file based discovery. 825type FileSDConfig struct { 826 Files []string `yaml:"files"` 827 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 828 829 // Catches all undefined fields and must be empty after parsing. 830 XXX map[string]interface{} `yaml:",inline"` 831} 832 833// UnmarshalYAML implements the yaml.Unmarshaler interface. 834func (c *FileSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 835 *c = DefaultFileSDConfig 836 type plain FileSDConfig 837 err := unmarshal((*plain)(c)) 838 if err != nil { 839 return err 840 } 841 if err := checkOverflow(c.XXX, "file_sd_config"); err != nil { 842 return err 843 } 844 if len(c.Files) == 0 { 845 return fmt.Errorf("file service discovery config must contain at least one path name") 846 } 847 for _, name := range c.Files { 848 if !patFileSDName.MatchString(name) { 849 return fmt.Errorf("path name %q is not valid for file discovery", name) 850 } 851 } 852 return nil 853} 854 855// ConsulSDConfig is the configuration for Consul service discovery. 856type ConsulSDConfig struct { 857 Server string `yaml:"server"` 858 Token Secret `yaml:"token,omitempty"` 859 Datacenter string `yaml:"datacenter,omitempty"` 860 TagSeparator string `yaml:"tag_separator,omitempty"` 861 Scheme string `yaml:"scheme,omitempty"` 862 Username string `yaml:"username,omitempty"` 863 Password Secret `yaml:"password,omitempty"` 864 // The list of services for which targets are discovered. 865 // Defaults to all services if empty. 866 Services []string `yaml:"services"` 867 868 TLSConfig TLSConfig `yaml:"tls_config,omitempty"` 869 // Catches all undefined fields and must be empty after parsing. 870 XXX map[string]interface{} `yaml:",inline"` 871} 872 873// UnmarshalYAML implements the yaml.Unmarshaler interface. 874func (c *ConsulSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 875 *c = DefaultConsulSDConfig 876 type plain ConsulSDConfig 877 err := unmarshal((*plain)(c)) 878 if err != nil { 879 return err 880 } 881 if err := checkOverflow(c.XXX, "consul_sd_config"); err != nil { 882 return err 883 } 884 if strings.TrimSpace(c.Server) == "" { 885 return fmt.Errorf("Consul SD configuration requires a server address") 886 } 887 return nil 888} 889 890// ServersetSDConfig is the configuration for Twitter serversets in Zookeeper based discovery. 891type ServersetSDConfig struct { 892 Servers []string `yaml:"servers"` 893 Paths []string `yaml:"paths"` 894 Timeout model.Duration `yaml:"timeout,omitempty"` 895 896 // Catches all undefined fields and must be empty after parsing. 897 XXX map[string]interface{} `yaml:",inline"` 898} 899 900// UnmarshalYAML implements the yaml.Unmarshaler interface. 901func (c *ServersetSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 902 *c = DefaultServersetSDConfig 903 type plain ServersetSDConfig 904 err := unmarshal((*plain)(c)) 905 if err != nil { 906 return err 907 } 908 if err := checkOverflow(c.XXX, "serverset_sd_config"); err != nil { 909 return err 910 } 911 if len(c.Servers) == 0 { 912 return fmt.Errorf("serverset SD config must contain at least one Zookeeper server") 913 } 914 if len(c.Paths) == 0 { 915 return fmt.Errorf("serverset SD config must contain at least one path") 916 } 917 for _, path := range c.Paths { 918 if !strings.HasPrefix(path, "/") { 919 return fmt.Errorf("serverset SD config paths must begin with '/': %s", path) 920 } 921 } 922 return nil 923} 924 925// NerveSDConfig is the configuration for AirBnB's Nerve in Zookeeper based discovery. 926type NerveSDConfig struct { 927 Servers []string `yaml:"servers"` 928 Paths []string `yaml:"paths"` 929 Timeout model.Duration `yaml:"timeout,omitempty"` 930 931 // Catches all undefined fields and must be empty after parsing. 932 XXX map[string]interface{} `yaml:",inline"` 933} 934 935// UnmarshalYAML implements the yaml.Unmarshaler interface. 936func (c *NerveSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 937 *c = DefaultNerveSDConfig 938 type plain NerveSDConfig 939 err := unmarshal((*plain)(c)) 940 if err != nil { 941 return err 942 } 943 if err := checkOverflow(c.XXX, "nerve_sd_config"); err != nil { 944 return err 945 } 946 if len(c.Servers) == 0 { 947 return fmt.Errorf("nerve SD config must contain at least one Zookeeper server") 948 } 949 if len(c.Paths) == 0 { 950 return fmt.Errorf("nerve SD config must contain at least one path") 951 } 952 for _, path := range c.Paths { 953 if !strings.HasPrefix(path, "/") { 954 return fmt.Errorf("nerve SD config paths must begin with '/': %s", path) 955 } 956 } 957 return nil 958} 959 960// MarathonSDConfig is the configuration for services running on Marathon. 961type MarathonSDConfig struct { 962 Servers []string `yaml:"servers,omitempty"` 963 Timeout model.Duration `yaml:"timeout,omitempty"` 964 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 965 TLSConfig TLSConfig `yaml:"tls_config,omitempty"` 966 BearerToken Secret `yaml:"bearer_token,omitempty"` 967 BearerTokenFile string `yaml:"bearer_token_file,omitempty"` 968 969 // Catches all undefined fields and must be empty after parsing. 970 XXX map[string]interface{} `yaml:",inline"` 971} 972 973// UnmarshalYAML implements the yaml.Unmarshaler interface. 974func (c *MarathonSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 975 *c = DefaultMarathonSDConfig 976 type plain MarathonSDConfig 977 err := unmarshal((*plain)(c)) 978 if err != nil { 979 return err 980 } 981 if err := checkOverflow(c.XXX, "marathon_sd_config"); err != nil { 982 return err 983 } 984 if len(c.Servers) == 0 { 985 return fmt.Errorf("Marathon SD config must contain at least one Marathon server") 986 } 987 if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 { 988 return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured") 989 } 990 991 return nil 992} 993 994// KubernetesRole is role of the service in Kubernetes. 995type KubernetesRole string 996 997// The valid options for KubernetesRole. 998const ( 999 KubernetesRoleNode KubernetesRole = "node" 1000 KubernetesRolePod KubernetesRole = "pod" 1001 KubernetesRoleService KubernetesRole = "service" 1002 KubernetesRoleEndpoint KubernetesRole = "endpoints" 1003 KubernetesRoleIngress KubernetesRole = "ingress" 1004) 1005 1006// UnmarshalYAML implements the yaml.Unmarshaler interface. 1007func (c *KubernetesRole) UnmarshalYAML(unmarshal func(interface{}) error) error { 1008 if err := unmarshal((*string)(c)); err != nil { 1009 return err 1010 } 1011 switch *c { 1012 case KubernetesRoleNode, KubernetesRolePod, KubernetesRoleService, KubernetesRoleEndpoint, KubernetesRoleIngress: 1013 return nil 1014 default: 1015 return fmt.Errorf("Unknown Kubernetes SD role %q", *c) 1016 } 1017} 1018 1019// KubernetesSDConfig is the configuration for Kubernetes service discovery. 1020type KubernetesSDConfig struct { 1021 APIServer URL `yaml:"api_server"` 1022 Role KubernetesRole `yaml:"role"` 1023 BasicAuth *BasicAuth `yaml:"basic_auth,omitempty"` 1024 BearerToken Secret `yaml:"bearer_token,omitempty"` 1025 BearerTokenFile string `yaml:"bearer_token_file,omitempty"` 1026 TLSConfig TLSConfig `yaml:"tls_config,omitempty"` 1027 NamespaceDiscovery KubernetesNamespaceDiscovery `yaml:"namespaces"` 1028 1029 // Catches all undefined fields and must be empty after parsing. 1030 XXX map[string]interface{} `yaml:",inline"` 1031} 1032 1033// UnmarshalYAML implements the yaml.Unmarshaler interface. 1034func (c *KubernetesSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1035 *c = KubernetesSDConfig{} 1036 type plain KubernetesSDConfig 1037 err := unmarshal((*plain)(c)) 1038 if err != nil { 1039 return err 1040 } 1041 if err := checkOverflow(c.XXX, "kubernetes_sd_config"); err != nil { 1042 return err 1043 } 1044 if c.Role == "" { 1045 return fmt.Errorf("role missing (one of: pod, service, endpoints, node)") 1046 } 1047 if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 { 1048 return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured") 1049 } 1050 if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) { 1051 return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured") 1052 } 1053 if c.APIServer.URL == nil && 1054 (c.BasicAuth != nil || c.BearerToken != "" || c.BearerTokenFile != "" || 1055 c.TLSConfig.CAFile != "" || c.TLSConfig.CertFile != "" || c.TLSConfig.KeyFile != "") { 1056 return fmt.Errorf("to use custom authentication please provide the 'api_server' URL explicitly") 1057 } 1058 return nil 1059} 1060 1061// KubernetesNamespaceDiscovery is the configuration for discovering 1062// Kubernetes namespaces. 1063type KubernetesNamespaceDiscovery struct { 1064 Names []string `yaml:"names"` 1065 // Catches all undefined fields and must be empty after parsing. 1066 XXX map[string]interface{} `yaml:",inline"` 1067} 1068 1069// UnmarshalYAML implements the yaml.Unmarshaler interface. 1070func (c *KubernetesNamespaceDiscovery) UnmarshalYAML(unmarshal func(interface{}) error) error { 1071 *c = KubernetesNamespaceDiscovery{} 1072 type plain KubernetesNamespaceDiscovery 1073 err := unmarshal((*plain)(c)) 1074 if err != nil { 1075 return err 1076 } 1077 return checkOverflow(c.XXX, "namespaces") 1078} 1079 1080// GCESDConfig is the configuration for GCE based service discovery. 1081type GCESDConfig struct { 1082 // Project: The Google Cloud Project ID 1083 Project string `yaml:"project"` 1084 1085 // Zone: The zone of the scrape targets. 1086 // If you need to configure multiple zones use multiple gce_sd_configs 1087 Zone string `yaml:"zone"` 1088 1089 // Filter: Can be used optionally to filter the instance list by other criteria. 1090 // Syntax of this filter string is described here in the filter query parameter section: 1091 // https://cloud.google.com/compute/docs/reference/latest/instances/list 1092 Filter string `yaml:"filter,omitempty"` 1093 1094 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 1095 Port int `yaml:"port"` 1096 TagSeparator string `yaml:"tag_separator,omitempty"` 1097 1098 // Catches all undefined fields and must be empty after parsing. 1099 XXX map[string]interface{} `yaml:",inline"` 1100} 1101 1102// UnmarshalYAML implements the yaml.Unmarshaler interface. 1103func (c *GCESDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1104 *c = DefaultGCESDConfig 1105 type plain GCESDConfig 1106 err := unmarshal((*plain)(c)) 1107 if err != nil { 1108 return err 1109 } 1110 if err := checkOverflow(c.XXX, "gce_sd_config"); err != nil { 1111 return err 1112 } 1113 if c.Project == "" { 1114 return fmt.Errorf("GCE SD configuration requires a project") 1115 } 1116 if c.Zone == "" { 1117 return fmt.Errorf("GCE SD configuration requires a zone") 1118 } 1119 return nil 1120} 1121 1122// EC2SDConfig is the configuration for EC2 based service discovery. 1123type EC2SDConfig struct { 1124 Region string `yaml:"region"` 1125 AccessKey string `yaml:"access_key,omitempty"` 1126 SecretKey Secret `yaml:"secret_key,omitempty"` 1127 Profile string `yaml:"profile,omitempty"` 1128 RoleARN string `yaml:"role_arn,omitempty"` 1129 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 1130 Port int `yaml:"port"` 1131 1132 // Catches all undefined fields and must be empty after parsing. 1133 XXX map[string]interface{} `yaml:",inline"` 1134} 1135 1136// UnmarshalYAML implements the yaml.Unmarshaler interface. 1137func (c *EC2SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1138 *c = DefaultEC2SDConfig 1139 type plain EC2SDConfig 1140 err := unmarshal((*plain)(c)) 1141 if err != nil { 1142 return err 1143 } 1144 if err := checkOverflow(c.XXX, "ec2_sd_config"); err != nil { 1145 return err 1146 } 1147 if c.Region == "" { 1148 sess, err := session.NewSession() 1149 if err != nil { 1150 return err 1151 } 1152 metadata := ec2metadata.New(sess) 1153 region, err := metadata.Region() 1154 if err != nil { 1155 return fmt.Errorf("EC2 SD configuration requires a region") 1156 } 1157 c.Region = region 1158 } 1159 return nil 1160} 1161 1162// OpenstackSDConfig is the configuration for OpenStack based service discovery. 1163type OpenstackSDConfig struct { 1164 IdentityEndpoint string `yaml:"identity_endpoint"` 1165 Username string `yaml:"username"` 1166 UserID string `yaml:"userid"` 1167 Password Secret `yaml:"password"` 1168 ProjectName string `yaml:"project_name"` 1169 ProjectID string `yaml:"project_id"` 1170 DomainName string `yaml:"domain_name"` 1171 DomainID string `yaml:"domain_id"` 1172 Role OpenStackRole `yaml:"role"` 1173 Region string `yaml:"region"` 1174 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 1175 Port int `yaml:"port"` 1176 1177 // Catches all undefined fields and must be empty after parsing. 1178 XXX map[string]interface{} `yaml:",inline"` 1179} 1180 1181// OpenStackRole is role of the target in OpenStack. 1182type OpenStackRole string 1183 1184// The valid options for OpenStackRole. 1185const ( 1186 // OpenStack document reference 1187 // https://docs.openstack.org/nova/pike/admin/arch.html#hypervisors 1188 OpenStackRoleHypervisor OpenStackRole = "hypervisor" 1189 // OpenStack document reference 1190 // https://docs.openstack.org/horizon/pike/user/launch-instances.html 1191 OpenStackRoleInstance OpenStackRole = "instance" 1192) 1193 1194// UnmarshalYAML implements the yaml.Unmarshaler interface. 1195func (c *OpenStackRole) UnmarshalYAML(unmarshal func(interface{}) error) error { 1196 if err := unmarshal((*string)(c)); err != nil { 1197 return err 1198 } 1199 switch *c { 1200 case OpenStackRoleHypervisor, OpenStackRoleInstance: 1201 return nil 1202 default: 1203 return fmt.Errorf("Unknown OpenStack SD role %q", *c) 1204 } 1205} 1206 1207// UnmarshalYAML implements the yaml.Unmarshaler interface. 1208func (c *OpenstackSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1209 *c = DefaultOpenstackSDConfig 1210 type plain OpenstackSDConfig 1211 err := unmarshal((*plain)(c)) 1212 if err != nil { 1213 return err 1214 } 1215 if c.Role == "" { 1216 return fmt.Errorf("role missing (one of: instance, hypervisor)") 1217 } 1218 return checkOverflow(c.XXX, "openstack_sd_config") 1219} 1220 1221// AzureSDConfig is the configuration for Azure based service discovery. 1222type AzureSDConfig struct { 1223 Port int `yaml:"port"` 1224 SubscriptionID string `yaml:"subscription_id"` 1225 TenantID string `yaml:"tenant_id,omitempty"` 1226 ClientID string `yaml:"client_id,omitempty"` 1227 ClientSecret Secret `yaml:"client_secret,omitempty"` 1228 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 1229 1230 // Catches all undefined fields and must be empty after parsing. 1231 XXX map[string]interface{} `yaml:",inline"` 1232} 1233 1234// UnmarshalYAML implements the yaml.Unmarshaler interface. 1235func (c *AzureSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1236 *c = DefaultAzureSDConfig 1237 type plain AzureSDConfig 1238 err := unmarshal((*plain)(c)) 1239 if err != nil { 1240 return err 1241 } 1242 1243 return checkOverflow(c.XXX, "azure_sd_config") 1244} 1245 1246// TritonSDConfig is the configuration for Triton based service discovery. 1247type TritonSDConfig struct { 1248 Account string `yaml:"account"` 1249 DNSSuffix string `yaml:"dns_suffix"` 1250 Endpoint string `yaml:"endpoint"` 1251 Port int `yaml:"port"` 1252 RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` 1253 TLSConfig TLSConfig `yaml:"tls_config,omitempty"` 1254 Version int `yaml:"version"` 1255 // Catches all undefined fields and must be empty after parsing. 1256 XXX map[string]interface{} `yaml:",inline"` 1257} 1258 1259// UnmarshalYAML implements the yaml.Unmarshaler interface. 1260func (c *TritonSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1261 *c = DefaultTritonSDConfig 1262 type plain TritonSDConfig 1263 err := unmarshal((*plain)(c)) 1264 if err != nil { 1265 return err 1266 } 1267 if c.Account == "" { 1268 return fmt.Errorf("Triton SD configuration requires an account") 1269 } 1270 if c.DNSSuffix == "" { 1271 return fmt.Errorf("Triton SD configuration requires a dns_suffix") 1272 } 1273 if c.Endpoint == "" { 1274 return fmt.Errorf("Triton SD configuration requires an endpoint") 1275 } 1276 if c.RefreshInterval <= 0 { 1277 return fmt.Errorf("Triton SD configuration requires RefreshInterval to be a positive integer") 1278 } 1279 return checkOverflow(c.XXX, "triton_sd_config") 1280} 1281 1282// RelabelAction is the action to be performed on relabeling. 1283type RelabelAction string 1284 1285const ( 1286 // RelabelReplace performs a regex replacement. 1287 RelabelReplace RelabelAction = "replace" 1288 // RelabelKeep drops targets for which the input does not match the regex. 1289 RelabelKeep RelabelAction = "keep" 1290 // RelabelDrop drops targets for which the input does match the regex. 1291 RelabelDrop RelabelAction = "drop" 1292 // RelabelHashMod sets a label to the modulus of a hash of labels. 1293 RelabelHashMod RelabelAction = "hashmod" 1294 // RelabelLabelMap copies labels to other labelnames based on a regex. 1295 RelabelLabelMap RelabelAction = "labelmap" 1296 // RelabelLabelDrop drops any label matching the regex. 1297 RelabelLabelDrop RelabelAction = "labeldrop" 1298 // RelabelLabelKeep drops any label not matching the regex. 1299 RelabelLabelKeep RelabelAction = "labelkeep" 1300) 1301 1302// UnmarshalYAML implements the yaml.Unmarshaler interface. 1303func (a *RelabelAction) UnmarshalYAML(unmarshal func(interface{}) error) error { 1304 var s string 1305 if err := unmarshal(&s); err != nil { 1306 return err 1307 } 1308 switch act := RelabelAction(strings.ToLower(s)); act { 1309 case RelabelReplace, RelabelKeep, RelabelDrop, RelabelHashMod, RelabelLabelMap, RelabelLabelDrop, RelabelLabelKeep: 1310 *a = act 1311 return nil 1312 } 1313 return fmt.Errorf("unknown relabel action %q", s) 1314} 1315 1316// RelabelConfig is the configuration for relabeling of target label sets. 1317type RelabelConfig struct { 1318 // A list of labels from which values are taken and concatenated 1319 // with the configured separator in order. 1320 SourceLabels model.LabelNames `yaml:"source_labels,flow,omitempty"` 1321 // Separator is the string between concatenated values from the source labels. 1322 Separator string `yaml:"separator,omitempty"` 1323 // Regex against which the concatenation is matched. 1324 Regex Regexp `yaml:"regex,omitempty"` 1325 // Modulus to take of the hash of concatenated values from the source labels. 1326 Modulus uint64 `yaml:"modulus,omitempty"` 1327 // TargetLabel is the label to which the resulting string is written in a replacement. 1328 // Regexp interpolation is allowed for the replace action. 1329 TargetLabel string `yaml:"target_label,omitempty"` 1330 // Replacement is the regex replacement pattern to be used. 1331 Replacement string `yaml:"replacement,omitempty"` 1332 // Action is the action to be performed for the relabeling. 1333 Action RelabelAction `yaml:"action,omitempty"` 1334 1335 // Catches all undefined fields and must be empty after parsing. 1336 XXX map[string]interface{} `yaml:",inline"` 1337} 1338 1339// UnmarshalYAML implements the yaml.Unmarshaler interface. 1340func (c *RelabelConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1341 *c = DefaultRelabelConfig 1342 type plain RelabelConfig 1343 if err := unmarshal((*plain)(c)); err != nil { 1344 return err 1345 } 1346 if err := checkOverflow(c.XXX, "relabel_config"); err != nil { 1347 return err 1348 } 1349 if c.Regex.Regexp == nil { 1350 c.Regex = MustNewRegexp("") 1351 } 1352 if c.Modulus == 0 && c.Action == RelabelHashMod { 1353 return fmt.Errorf("relabel configuration for hashmod requires non-zero modulus") 1354 } 1355 if (c.Action == RelabelReplace || c.Action == RelabelHashMod) && c.TargetLabel == "" { 1356 return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action) 1357 } 1358 if c.Action == RelabelReplace && !relabelTarget.MatchString(c.TargetLabel) { 1359 return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) 1360 } 1361 if c.Action == RelabelHashMod && !model.LabelName(c.TargetLabel).IsValid() { 1362 return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) 1363 } 1364 1365 if c.Action == RelabelLabelDrop || c.Action == RelabelLabelKeep { 1366 if c.SourceLabels != nil || 1367 c.TargetLabel != DefaultRelabelConfig.TargetLabel || 1368 c.Modulus != DefaultRelabelConfig.Modulus || 1369 c.Separator != DefaultRelabelConfig.Separator || 1370 c.Replacement != DefaultRelabelConfig.Replacement { 1371 return fmt.Errorf("%s action requires only 'regex', and no other fields", c.Action) 1372 } 1373 } 1374 1375 return nil 1376} 1377 1378// Regexp encapsulates a regexp.Regexp and makes it YAML marshallable. 1379type Regexp struct { 1380 *regexp.Regexp 1381 original string 1382} 1383 1384// NewRegexp creates a new anchored Regexp and returns an error if the 1385// passed-in regular expression does not compile. 1386func NewRegexp(s string) (Regexp, error) { 1387 regex, err := regexp.Compile("^(?:" + s + ")$") 1388 return Regexp{ 1389 Regexp: regex, 1390 original: s, 1391 }, err 1392} 1393 1394// MustNewRegexp works like NewRegexp, but panics if the regular expression does not compile. 1395func MustNewRegexp(s string) Regexp { 1396 re, err := NewRegexp(s) 1397 if err != nil { 1398 panic(err) 1399 } 1400 return re 1401} 1402 1403// UnmarshalYAML implements the yaml.Unmarshaler interface. 1404func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error { 1405 var s string 1406 if err := unmarshal(&s); err != nil { 1407 return err 1408 } 1409 r, err := NewRegexp(s) 1410 if err != nil { 1411 return err 1412 } 1413 *re = r 1414 return nil 1415} 1416 1417// MarshalYAML implements the yaml.Marshaler interface. 1418func (re Regexp) MarshalYAML() (interface{}, error) { 1419 if re.original != "" { 1420 return re.original, nil 1421 } 1422 return nil, nil 1423} 1424 1425// RemoteWriteConfig is the configuration for writing to remote storage. 1426type RemoteWriteConfig struct { 1427 URL *URL `yaml:"url"` 1428 RemoteTimeout model.Duration `yaml:"remote_timeout,omitempty"` 1429 WriteRelabelConfigs []*RelabelConfig `yaml:"write_relabel_configs,omitempty"` 1430 1431 // We cannot do proper Go type embedding below as the parser will then parse 1432 // values arbitrarily into the overflow maps of further-down types. 1433 HTTPClientConfig HTTPClientConfig `yaml:",inline"` 1434 QueueConfig QueueConfig `yaml:"queue_config,omitempty"` 1435 1436 // Catches all undefined fields and must be empty after parsing. 1437 XXX map[string]interface{} `yaml:",inline"` 1438} 1439 1440// UnmarshalYAML implements the yaml.Unmarshaler interface. 1441func (c *RemoteWriteConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1442 *c = DefaultRemoteWriteConfig 1443 type plain RemoteWriteConfig 1444 if err := unmarshal((*plain)(c)); err != nil { 1445 return err 1446 } 1447 if c.URL == nil { 1448 return fmt.Errorf("url for remote_write is empty") 1449 } 1450 1451 // The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer. 1452 // We cannot make it a pointer as the parser panics for inlined pointer structs. 1453 // Thus we just do its validation here. 1454 if err := c.HTTPClientConfig.validate(); err != nil { 1455 return err 1456 } 1457 1458 return checkOverflow(c.XXX, "remote_write") 1459} 1460 1461// QueueConfig is the configuration for the queue used to write to remote 1462// storage. 1463type QueueConfig struct { 1464 // Number of samples to buffer per shard before we start dropping them. 1465 Capacity int `yaml:"capacity,omitempty"` 1466 1467 // Max number of shards, i.e. amount of concurrency. 1468 MaxShards int `yaml:"max_shards,omitempty"` 1469 1470 // Maximum number of samples per send. 1471 MaxSamplesPerSend int `yaml:"max_samples_per_send,omitempty"` 1472 1473 // Maximum time sample will wait in buffer. 1474 BatchSendDeadline time.Duration `yaml:"batch_send_deadline,omitempty"` 1475 1476 // Max number of times to retry a batch on recoverable errors. 1477 MaxRetries int `yaml:"max_retries,omitempty"` 1478 1479 // On recoverable errors, backoff exponentially. 1480 MinBackoff time.Duration `yaml:"min_backoff,omitempty"` 1481 MaxBackoff time.Duration `yaml:"max_backoff,omitempty"` 1482} 1483 1484// RemoteReadConfig is the configuration for reading from remote storage. 1485type RemoteReadConfig struct { 1486 URL *URL `yaml:"url"` 1487 RemoteTimeout model.Duration `yaml:"remote_timeout,omitempty"` 1488 1489 // We cannot do proper Go type embedding below as the parser will then parse 1490 // values arbitrarily into the overflow maps of further-down types. 1491 HTTPClientConfig HTTPClientConfig `yaml:",inline"` 1492 1493 // Catches all undefined fields and must be empty after parsing. 1494 XXX map[string]interface{} `yaml:",inline"` 1495} 1496 1497// UnmarshalYAML implements the yaml.Unmarshaler interface. 1498func (c *RemoteReadConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { 1499 *c = DefaultRemoteReadConfig 1500 type plain RemoteReadConfig 1501 if err := unmarshal((*plain)(c)); err != nil { 1502 return err 1503 } 1504 if c.URL == nil { 1505 return fmt.Errorf("url for remote_read is empty") 1506 } 1507 1508 // The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer. 1509 // We cannot make it a pointer as the parser panics for inlined pointer structs. 1510 // Thus we just do its validation here. 1511 if err := c.HTTPClientConfig.validate(); err != nil { 1512 return err 1513 } 1514 1515 return checkOverflow(c.XXX, "remote_read") 1516} 1517