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