prometheus

Форк
0
/
config_test.go 
2263 строки · 73.2 Кб
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

14
package config
15

16
import (
17
	"crypto/tls"
18
	"encoding/json"
19
	"net/url"
20
	"os"
21
	"path/filepath"
22
	"testing"
23
	"time"
24

25
	"github.com/alecthomas/units"
26
	"github.com/go-kit/log"
27
	"github.com/grafana/regexp"
28
	"github.com/prometheus/common/config"
29
	"github.com/prometheus/common/model"
30
	"github.com/stretchr/testify/require"
31
	"gopkg.in/yaml.v2"
32

33
	"github.com/prometheus/prometheus/discovery"
34
	"github.com/prometheus/prometheus/discovery/aws"
35
	"github.com/prometheus/prometheus/discovery/azure"
36
	"github.com/prometheus/prometheus/discovery/consul"
37
	"github.com/prometheus/prometheus/discovery/digitalocean"
38
	"github.com/prometheus/prometheus/discovery/dns"
39
	"github.com/prometheus/prometheus/discovery/eureka"
40
	"github.com/prometheus/prometheus/discovery/file"
41
	"github.com/prometheus/prometheus/discovery/hetzner"
42
	"github.com/prometheus/prometheus/discovery/http"
43
	"github.com/prometheus/prometheus/discovery/ionos"
44
	"github.com/prometheus/prometheus/discovery/kubernetes"
45
	"github.com/prometheus/prometheus/discovery/linode"
46
	"github.com/prometheus/prometheus/discovery/marathon"
47
	"github.com/prometheus/prometheus/discovery/moby"
48
	"github.com/prometheus/prometheus/discovery/nomad"
49
	"github.com/prometheus/prometheus/discovery/openstack"
50
	"github.com/prometheus/prometheus/discovery/ovhcloud"
51
	"github.com/prometheus/prometheus/discovery/puppetdb"
52
	"github.com/prometheus/prometheus/discovery/scaleway"
53
	"github.com/prometheus/prometheus/discovery/targetgroup"
54
	"github.com/prometheus/prometheus/discovery/triton"
55
	"github.com/prometheus/prometheus/discovery/uyuni"
56
	"github.com/prometheus/prometheus/discovery/vultr"
57
	"github.com/prometheus/prometheus/discovery/xds"
58
	"github.com/prometheus/prometheus/discovery/zookeeper"
59
	"github.com/prometheus/prometheus/model/labels"
60
	"github.com/prometheus/prometheus/model/relabel"
61
	"github.com/prometheus/prometheus/util/testutil"
62
)
63

64
func mustParseURL(u string) *config.URL {
65
	parsed, err := url.Parse(u)
66
	if err != nil {
67
		panic(err)
68
	}
69
	return &config.URL{URL: parsed}
70
}
71

72
const (
73
	globBodySizeLimit         = 15 * units.MiB
74
	globSampleLimit           = 1500
75
	globTargetLimit           = 30
76
	globLabelLimit            = 30
77
	globLabelNameLengthLimit  = 200
78
	globLabelValueLengthLimit = 200
79
)
80

81
var expectedConf = &Config{
82
	GlobalConfig: GlobalConfig{
83
		ScrapeInterval:     model.Duration(15 * time.Second),
84
		ScrapeTimeout:      DefaultGlobalConfig.ScrapeTimeout,
85
		EvaluationInterval: model.Duration(30 * time.Second),
86
		QueryLogFile:       "",
87

88
		ExternalLabels: labels.FromStrings("foo", "bar", "monitor", "codelab"),
89

90
		BodySizeLimit:         globBodySizeLimit,
91
		SampleLimit:           globSampleLimit,
92
		TargetLimit:           globTargetLimit,
93
		LabelLimit:            globLabelLimit,
94
		LabelNameLengthLimit:  globLabelNameLengthLimit,
95
		LabelValueLengthLimit: globLabelValueLengthLimit,
96
		ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
97
	},
98

99
	RuleFiles: []string{
100
		filepath.FromSlash("testdata/first.rules"),
101
		filepath.FromSlash("testdata/my/*.rules"),
102
	},
103

104
	RemoteWriteConfigs: []*RemoteWriteConfig{
105
		{
106
			URL:           mustParseURL("http://remote1/push"),
107
			RemoteTimeout: model.Duration(30 * time.Second),
108
			Name:          "drop_expensive",
109
			WriteRelabelConfigs: []*relabel.Config{
110
				{
111
					SourceLabels: model.LabelNames{"__name__"},
112
					Separator:    ";",
113
					Regex:        relabel.MustNewRegexp("expensive.*"),
114
					Replacement:  "$1",
115
					Action:       relabel.Drop,
116
				},
117
			},
118
			QueueConfig:    DefaultQueueConfig,
119
			MetadataConfig: DefaultMetadataConfig,
120
			HTTPClientConfig: config.HTTPClientConfig{
121
				OAuth2: &config.OAuth2{
122
					ClientID:     "123",
123
					ClientSecret: "456",
124
					TokenURL:     "http://remote1/auth",
125
					TLSConfig: config.TLSConfig{
126
						CertFile: filepath.FromSlash("testdata/valid_cert_file"),
127
						KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
128
					},
129
				},
130
				FollowRedirects: true,
131
				EnableHTTP2:     true,
132
			},
133
		},
134
		{
135
			URL:            mustParseURL("http://remote2/push"),
136
			RemoteTimeout:  model.Duration(30 * time.Second),
137
			QueueConfig:    DefaultQueueConfig,
138
			MetadataConfig: DefaultMetadataConfig,
139
			Name:           "rw_tls",
140
			HTTPClientConfig: config.HTTPClientConfig{
141
				TLSConfig: config.TLSConfig{
142
					CertFile: filepath.FromSlash("testdata/valid_cert_file"),
143
					KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
144
				},
145
				FollowRedirects: true,
146
				EnableHTTP2:     true,
147
			},
148
			Headers: map[string]string{"name": "value"},
149
		},
150
	},
151

152
	RemoteReadConfigs: []*RemoteReadConfig{
153
		{
154
			URL:           mustParseURL("http://remote1/read"),
155
			RemoteTimeout: model.Duration(1 * time.Minute),
156
			ReadRecent:    true,
157
			Name:          "default",
158
			HTTPClientConfig: config.HTTPClientConfig{
159
				FollowRedirects: true,
160
				EnableHTTP2:     false,
161
			},
162
			FilterExternalLabels: true,
163
		},
164
		{
165
			URL:              mustParseURL("http://remote3/read"),
166
			RemoteTimeout:    model.Duration(1 * time.Minute),
167
			ReadRecent:       false,
168
			Name:             "read_special",
169
			RequiredMatchers: model.LabelSet{"job": "special"},
170
			HTTPClientConfig: config.HTTPClientConfig{
171
				TLSConfig: config.TLSConfig{
172
					CertFile: filepath.FromSlash("testdata/valid_cert_file"),
173
					KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
174
				},
175
				FollowRedirects: true,
176
				EnableHTTP2:     true,
177
			},
178
			FilterExternalLabels: true,
179
		},
180
	},
181

182
	ScrapeConfigs: []*ScrapeConfig{
183
		{
184
			JobName: "prometheus",
185

186
			HonorLabels:           true,
187
			HonorTimestamps:       true,
188
			ScrapeInterval:        model.Duration(15 * time.Second),
189
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
190
			EnableCompression:     true,
191
			BodySizeLimit:         globBodySizeLimit,
192
			SampleLimit:           globSampleLimit,
193
			TargetLimit:           globTargetLimit,
194
			LabelLimit:            globLabelLimit,
195
			LabelNameLengthLimit:  globLabelNameLengthLimit,
196
			LabelValueLengthLimit: globLabelValueLengthLimit,
197
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
198

199
			MetricsPath: DefaultScrapeConfig.MetricsPath,
200
			Scheme:      DefaultScrapeConfig.Scheme,
201

202
			HTTPClientConfig: config.HTTPClientConfig{
203
				Authorization: &config.Authorization{
204
					Type:            "Bearer",
205
					CredentialsFile: filepath.FromSlash("testdata/valid_token_file"),
206
				},
207
				FollowRedirects: true,
208
				EnableHTTP2:     true,
209
				TLSConfig: config.TLSConfig{
210
					MinVersion: config.TLSVersion(tls.VersionTLS10),
211
				},
212
			},
213

214
			ServiceDiscoveryConfigs: discovery.Configs{
215
				&file.SDConfig{
216
					Files:           []string{"testdata/foo/*.slow.json", "testdata/foo/*.slow.yml", "testdata/single/file.yml"},
217
					RefreshInterval: model.Duration(10 * time.Minute),
218
				},
219
				&file.SDConfig{
220
					Files:           []string{"testdata/bar/*.yaml"},
221
					RefreshInterval: model.Duration(5 * time.Minute),
222
				},
223
				discovery.StaticConfig{
224
					{
225
						Targets: []model.LabelSet{
226
							{model.AddressLabel: "localhost:9090"},
227
							{model.AddressLabel: "localhost:9191"},
228
						},
229
						Labels: model.LabelSet{
230
							"my":   "label",
231
							"your": "label",
232
						},
233
						Source: "0",
234
					},
235
				},
236
			},
237

238
			RelabelConfigs: []*relabel.Config{
239
				{
240
					SourceLabels: model.LabelNames{"job", "__meta_dns_name"},
241
					TargetLabel:  "job",
242
					Separator:    ";",
243
					Regex:        relabel.MustNewRegexp("(.*)some-[regex]"),
244
					Replacement:  "foo-${1}",
245
					Action:       relabel.Replace,
246
				},
247
				{
248
					SourceLabels: model.LabelNames{"abc"},
249
					TargetLabel:  "cde",
250
					Separator:    ";",
251
					Regex:        relabel.DefaultRelabelConfig.Regex,
252
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
253
					Action:       relabel.Replace,
254
				},
255
				{
256
					TargetLabel: "abc",
257
					Separator:   ";",
258
					Regex:       relabel.DefaultRelabelConfig.Regex,
259
					Replacement: "static",
260
					Action:      relabel.Replace,
261
				},
262
				{
263
					TargetLabel: "abc",
264
					Separator:   ";",
265
					Regex:       relabel.MustNewRegexp(""),
266
					Replacement: "static",
267
					Action:      relabel.Replace,
268
				},
269
				{
270
					SourceLabels: model.LabelNames{"foo"},
271
					TargetLabel:  "abc",
272
					Action:       relabel.KeepEqual,
273
					Regex:        relabel.DefaultRelabelConfig.Regex,
274
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
275
					Separator:    relabel.DefaultRelabelConfig.Separator,
276
				},
277
				{
278
					SourceLabels: model.LabelNames{"foo"},
279
					TargetLabel:  "abc",
280
					Action:       relabel.DropEqual,
281
					Regex:        relabel.DefaultRelabelConfig.Regex,
282
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
283
					Separator:    relabel.DefaultRelabelConfig.Separator,
284
				},
285
			},
286
		},
287
		{
288
			JobName: "service-x",
289

290
			HonorTimestamps:       true,
291
			ScrapeInterval:        model.Duration(50 * time.Second),
292
			ScrapeTimeout:         model.Duration(5 * time.Second),
293
			EnableCompression:     true,
294
			BodySizeLimit:         10 * units.MiB,
295
			SampleLimit:           1000,
296
			TargetLimit:           35,
297
			LabelLimit:            35,
298
			LabelNameLengthLimit:  210,
299
			LabelValueLengthLimit: 210,
300
			ScrapeProtocols:       []ScrapeProtocol{PrometheusText0_0_4},
301

302
			HTTPClientConfig: config.HTTPClientConfig{
303
				BasicAuth: &config.BasicAuth{
304
					Username: "admin_name",
305
					Password: "multiline\nmysecret\ntest",
306
				},
307
				FollowRedirects: true,
308
				EnableHTTP2:     true,
309
			},
310
			MetricsPath: "/my_path",
311
			Scheme:      "https",
312

313
			ServiceDiscoveryConfigs: discovery.Configs{
314
				&dns.SDConfig{
315
					Names: []string{
316
						"first.dns.address.domain.com",
317
						"second.dns.address.domain.com",
318
					},
319
					RefreshInterval: model.Duration(15 * time.Second),
320
					Type:            "SRV",
321
				},
322
				&dns.SDConfig{
323
					Names: []string{
324
						"first.dns.address.domain.com",
325
					},
326
					RefreshInterval: model.Duration(30 * time.Second),
327
					Type:            "SRV",
328
				},
329
			},
330

331
			RelabelConfigs: []*relabel.Config{
332
				{
333
					SourceLabels: model.LabelNames{"job"},
334
					Regex:        relabel.MustNewRegexp("(.*)some-[regex]"),
335
					Separator:    ";",
336
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
337
					Action:       relabel.Drop,
338
				},
339
				{
340
					SourceLabels: model.LabelNames{"__address__"},
341
					TargetLabel:  "__tmp_hash",
342
					Regex:        relabel.DefaultRelabelConfig.Regex,
343
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
344
					Modulus:      8,
345
					Separator:    ";",
346
					Action:       relabel.HashMod,
347
				},
348
				{
349
					SourceLabels: model.LabelNames{"__tmp_hash"},
350
					Regex:        relabel.MustNewRegexp("1"),
351
					Separator:    ";",
352
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
353
					Action:       relabel.Keep,
354
				},
355
				{
356
					Regex:       relabel.MustNewRegexp("1"),
357
					Separator:   ";",
358
					Replacement: relabel.DefaultRelabelConfig.Replacement,
359
					Action:      relabel.LabelMap,
360
				},
361
				{
362
					Regex:       relabel.MustNewRegexp("d"),
363
					Separator:   ";",
364
					Replacement: relabel.DefaultRelabelConfig.Replacement,
365
					Action:      relabel.LabelDrop,
366
				},
367
				{
368
					Regex:       relabel.MustNewRegexp("k"),
369
					Separator:   ";",
370
					Replacement: relabel.DefaultRelabelConfig.Replacement,
371
					Action:      relabel.LabelKeep,
372
				},
373
			},
374
			MetricRelabelConfigs: []*relabel.Config{
375
				{
376
					SourceLabels: model.LabelNames{"__name__"},
377
					Regex:        relabel.MustNewRegexp("expensive_metric.*"),
378
					Separator:    ";",
379
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
380
					Action:       relabel.Drop,
381
				},
382
			},
383
		},
384
		{
385
			JobName: "service-y",
386

387
			HonorTimestamps:       true,
388
			ScrapeInterval:        model.Duration(15 * time.Second),
389
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
390
			EnableCompression:     true,
391
			BodySizeLimit:         globBodySizeLimit,
392
			SampleLimit:           globSampleLimit,
393
			TargetLimit:           globTargetLimit,
394
			LabelLimit:            globLabelLimit,
395
			LabelNameLengthLimit:  globLabelNameLengthLimit,
396
			LabelValueLengthLimit: globLabelValueLengthLimit,
397
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
398

399
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
400
			Scheme:           DefaultScrapeConfig.Scheme,
401
			HTTPClientConfig: config.DefaultHTTPClientConfig,
402

403
			ServiceDiscoveryConfigs: discovery.Configs{
404
				&consul.SDConfig{
405
					Server:          "localhost:1234",
406
					PathPrefix:      "/consul",
407
					Token:           "mysecret",
408
					Services:        []string{"nginx", "cache", "mysql"},
409
					ServiceTags:     []string{"canary", "v1"},
410
					NodeMeta:        map[string]string{"rack": "123"},
411
					TagSeparator:    consul.DefaultSDConfig.TagSeparator,
412
					Scheme:          "https",
413
					RefreshInterval: consul.DefaultSDConfig.RefreshInterval,
414
					AllowStale:      true,
415
					HTTPClientConfig: config.HTTPClientConfig{
416
						TLSConfig: config.TLSConfig{
417
							CertFile:           filepath.FromSlash("testdata/valid_cert_file"),
418
							KeyFile:            filepath.FromSlash("testdata/valid_key_file"),
419
							CAFile:             filepath.FromSlash("testdata/valid_ca_file"),
420
							InsecureSkipVerify: false,
421
						},
422
						FollowRedirects: true,
423
						EnableHTTP2:     true,
424
					},
425
				},
426
			},
427

428
			RelabelConfigs: []*relabel.Config{
429
				{
430
					SourceLabels: model.LabelNames{"__meta_sd_consul_tags"},
431
					Regex:        relabel.MustNewRegexp("label:([^=]+)=([^,]+)"),
432
					Separator:    ",",
433
					TargetLabel:  "${1}",
434
					Replacement:  "${2}",
435
					Action:       relabel.Replace,
436
				},
437
			},
438
		},
439
		{
440
			JobName: "service-z",
441

442
			HonorTimestamps:       true,
443
			ScrapeInterval:        model.Duration(15 * time.Second),
444
			ScrapeTimeout:         model.Duration(10 * time.Second),
445
			EnableCompression:     true,
446
			BodySizeLimit:         globBodySizeLimit,
447
			SampleLimit:           globSampleLimit,
448
			TargetLimit:           globTargetLimit,
449
			LabelLimit:            globLabelLimit,
450
			LabelNameLengthLimit:  globLabelNameLengthLimit,
451
			LabelValueLengthLimit: globLabelValueLengthLimit,
452
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
453

454
			MetricsPath: "/metrics",
455
			Scheme:      "http",
456

457
			HTTPClientConfig: config.HTTPClientConfig{
458
				TLSConfig: config.TLSConfig{
459
					CertFile: filepath.FromSlash("testdata/valid_cert_file"),
460
					KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
461
				},
462

463
				Authorization: &config.Authorization{
464
					Type:        "Bearer",
465
					Credentials: "mysecret",
466
				},
467

468
				FollowRedirects: true,
469
				EnableHTTP2:     true,
470
			},
471
		},
472
		{
473
			JobName: "service-kubernetes",
474

475
			HonorTimestamps:       true,
476
			ScrapeInterval:        model.Duration(15 * time.Second),
477
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
478
			EnableCompression:     true,
479
			BodySizeLimit:         globBodySizeLimit,
480
			SampleLimit:           globSampleLimit,
481
			TargetLimit:           globTargetLimit,
482
			LabelLimit:            globLabelLimit,
483
			LabelNameLengthLimit:  globLabelNameLengthLimit,
484
			LabelValueLengthLimit: globLabelValueLengthLimit,
485
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
486

487
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
488
			Scheme:           DefaultScrapeConfig.Scheme,
489
			HTTPClientConfig: config.DefaultHTTPClientConfig,
490

491
			ServiceDiscoveryConfigs: discovery.Configs{
492
				&kubernetes.SDConfig{
493
					APIServer: kubernetesSDHostURL(),
494
					Role:      kubernetes.RoleEndpoint,
495
					HTTPClientConfig: config.HTTPClientConfig{
496
						BasicAuth: &config.BasicAuth{
497
							Username: "myusername",
498
							Password: "mysecret",
499
						},
500
						TLSConfig: config.TLSConfig{
501
							CertFile: filepath.FromSlash("testdata/valid_cert_file"),
502
							KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
503
						},
504
						FollowRedirects: true,
505
						EnableHTTP2:     true,
506
					},
507
					NamespaceDiscovery: kubernetes.NamespaceDiscovery{},
508
				},
509
			},
510
		},
511
		{
512
			JobName: "service-kubernetes-namespaces",
513

514
			HonorTimestamps:       true,
515
			ScrapeInterval:        model.Duration(15 * time.Second),
516
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
517
			EnableCompression:     true,
518
			BodySizeLimit:         globBodySizeLimit,
519
			SampleLimit:           globSampleLimit,
520
			TargetLimit:           globTargetLimit,
521
			LabelLimit:            globLabelLimit,
522
			LabelNameLengthLimit:  globLabelNameLengthLimit,
523
			LabelValueLengthLimit: globLabelValueLengthLimit,
524
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
525

526
			MetricsPath: DefaultScrapeConfig.MetricsPath,
527
			Scheme:      DefaultScrapeConfig.Scheme,
528
			HTTPClientConfig: config.HTTPClientConfig{
529
				BasicAuth: &config.BasicAuth{
530
					Username:     "myusername",
531
					PasswordFile: filepath.FromSlash("testdata/valid_password_file"),
532
				},
533
				FollowRedirects: true,
534
				EnableHTTP2:     true,
535
			},
536

537
			ServiceDiscoveryConfigs: discovery.Configs{
538
				&kubernetes.SDConfig{
539
					APIServer: kubernetesSDHostURL(),
540
					Role:      kubernetes.RoleEndpoint,
541
					NamespaceDiscovery: kubernetes.NamespaceDiscovery{
542
						Names: []string{
543
							"default",
544
						},
545
					},
546
					HTTPClientConfig: config.DefaultHTTPClientConfig,
547
				},
548
			},
549
		},
550
		{
551
			JobName: "service-kuma",
552

553
			HonorTimestamps:       true,
554
			ScrapeInterval:        model.Duration(15 * time.Second),
555
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
556
			EnableCompression:     true,
557
			BodySizeLimit:         globBodySizeLimit,
558
			SampleLimit:           globSampleLimit,
559
			TargetLimit:           globTargetLimit,
560
			LabelLimit:            globLabelLimit,
561
			LabelNameLengthLimit:  globLabelNameLengthLimit,
562
			LabelValueLengthLimit: globLabelValueLengthLimit,
563
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
564

565
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
566
			Scheme:           DefaultScrapeConfig.Scheme,
567
			HTTPClientConfig: config.DefaultHTTPClientConfig,
568

569
			ServiceDiscoveryConfigs: discovery.Configs{
570
				&xds.KumaSDConfig{
571
					Server:           "http://kuma-control-plane.kuma-system.svc:5676",
572
					ClientID:         "main-prometheus",
573
					HTTPClientConfig: config.DefaultHTTPClientConfig,
574
					RefreshInterval:  model.Duration(15 * time.Second),
575
					FetchTimeout:     model.Duration(2 * time.Minute),
576
				},
577
			},
578
		},
579
		{
580
			JobName: "service-marathon",
581

582
			HonorTimestamps:       true,
583
			ScrapeInterval:        model.Duration(15 * time.Second),
584
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
585
			EnableCompression:     true,
586
			BodySizeLimit:         globBodySizeLimit,
587
			SampleLimit:           globSampleLimit,
588
			TargetLimit:           globTargetLimit,
589
			LabelLimit:            globLabelLimit,
590
			LabelNameLengthLimit:  globLabelNameLengthLimit,
591
			LabelValueLengthLimit: globLabelValueLengthLimit,
592
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
593

594
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
595
			Scheme:           DefaultScrapeConfig.Scheme,
596
			HTTPClientConfig: config.DefaultHTTPClientConfig,
597

598
			ServiceDiscoveryConfigs: discovery.Configs{
599
				&marathon.SDConfig{
600
					Servers: []string{
601
						"https://marathon.example.com:443",
602
					},
603
					RefreshInterval: model.Duration(30 * time.Second),
604
					AuthToken:       "mysecret",
605
					HTTPClientConfig: config.HTTPClientConfig{
606
						TLSConfig: config.TLSConfig{
607
							CertFile: filepath.FromSlash("testdata/valid_cert_file"),
608
							KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
609
						},
610
						FollowRedirects: true,
611
						EnableHTTP2:     true,
612
					},
613
				},
614
			},
615
		},
616
		{
617
			JobName: "service-nomad",
618

619
			HonorTimestamps:       true,
620
			ScrapeInterval:        model.Duration(15 * time.Second),
621
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
622
			EnableCompression:     true,
623
			BodySizeLimit:         globBodySizeLimit,
624
			SampleLimit:           globSampleLimit,
625
			TargetLimit:           globTargetLimit,
626
			LabelLimit:            globLabelLimit,
627
			LabelNameLengthLimit:  globLabelNameLengthLimit,
628
			LabelValueLengthLimit: globLabelValueLengthLimit,
629
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
630

631
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
632
			Scheme:           DefaultScrapeConfig.Scheme,
633
			HTTPClientConfig: config.DefaultHTTPClientConfig,
634

635
			ServiceDiscoveryConfigs: discovery.Configs{
636
				&nomad.SDConfig{
637
					AllowStale:      true,
638
					Namespace:       "default",
639
					RefreshInterval: model.Duration(60 * time.Second),
640
					Region:          "global",
641
					Server:          "http://localhost:4646",
642
					TagSeparator:    ",",
643
					HTTPClientConfig: config.HTTPClientConfig{
644
						FollowRedirects: true,
645
						EnableHTTP2:     true,
646
					},
647
				},
648
			},
649
		},
650
		{
651
			JobName: "service-ec2",
652

653
			HonorTimestamps:       true,
654
			ScrapeInterval:        model.Duration(15 * time.Second),
655
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
656
			EnableCompression:     true,
657
			BodySizeLimit:         globBodySizeLimit,
658
			SampleLimit:           globSampleLimit,
659
			TargetLimit:           globTargetLimit,
660
			LabelLimit:            globLabelLimit,
661
			LabelNameLengthLimit:  globLabelNameLengthLimit,
662
			LabelValueLengthLimit: globLabelValueLengthLimit,
663
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
664

665
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
666
			Scheme:           DefaultScrapeConfig.Scheme,
667
			HTTPClientConfig: config.DefaultHTTPClientConfig,
668

669
			ServiceDiscoveryConfigs: discovery.Configs{
670
				&aws.EC2SDConfig{
671
					Region:          "us-east-1",
672
					AccessKey:       "access",
673
					SecretKey:       "mysecret",
674
					Profile:         "profile",
675
					RefreshInterval: model.Duration(60 * time.Second),
676
					Port:            80,
677
					Filters: []*aws.EC2Filter{
678
						{
679
							Name:   "tag:environment",
680
							Values: []string{"prod"},
681
						},
682
						{
683
							Name:   "tag:service",
684
							Values: []string{"web", "db"},
685
						},
686
					},
687
					HTTPClientConfig: config.DefaultHTTPClientConfig,
688
				},
689
			},
690
		},
691
		{
692
			JobName: "service-lightsail",
693

694
			HonorTimestamps:       true,
695
			ScrapeInterval:        model.Duration(15 * time.Second),
696
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
697
			EnableCompression:     true,
698
			BodySizeLimit:         globBodySizeLimit,
699
			SampleLimit:           globSampleLimit,
700
			TargetLimit:           globTargetLimit,
701
			LabelLimit:            globLabelLimit,
702
			LabelNameLengthLimit:  globLabelNameLengthLimit,
703
			LabelValueLengthLimit: globLabelValueLengthLimit,
704
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
705

706
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
707
			Scheme:           DefaultScrapeConfig.Scheme,
708
			HTTPClientConfig: config.DefaultHTTPClientConfig,
709

710
			ServiceDiscoveryConfigs: discovery.Configs{
711
				&aws.LightsailSDConfig{
712
					Region:           "us-east-1",
713
					AccessKey:        "access",
714
					SecretKey:        "mysecret",
715
					Profile:          "profile",
716
					RefreshInterval:  model.Duration(60 * time.Second),
717
					Port:             80,
718
					HTTPClientConfig: config.DefaultHTTPClientConfig,
719
				},
720
			},
721
		},
722
		{
723
			JobName: "service-azure",
724

725
			HonorTimestamps:       true,
726
			ScrapeInterval:        model.Duration(15 * time.Second),
727
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
728
			EnableCompression:     true,
729
			BodySizeLimit:         globBodySizeLimit,
730
			SampleLimit:           globSampleLimit,
731
			TargetLimit:           globTargetLimit,
732
			LabelLimit:            globLabelLimit,
733
			LabelNameLengthLimit:  globLabelNameLengthLimit,
734
			LabelValueLengthLimit: globLabelValueLengthLimit,
735
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
736

737
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
738
			Scheme:           DefaultScrapeConfig.Scheme,
739
			HTTPClientConfig: config.DefaultHTTPClientConfig,
740

741
			ServiceDiscoveryConfigs: discovery.Configs{
742
				&azure.SDConfig{
743
					Environment:          "AzurePublicCloud",
744
					SubscriptionID:       "11AAAA11-A11A-111A-A111-1111A1111A11",
745
					ResourceGroup:        "my-resource-group",
746
					TenantID:             "BBBB222B-B2B2-2B22-B222-2BB2222BB2B2",
747
					ClientID:             "333333CC-3C33-3333-CCC3-33C3CCCCC33C",
748
					ClientSecret:         "mysecret",
749
					AuthenticationMethod: "OAuth",
750
					RefreshInterval:      model.Duration(5 * time.Minute),
751
					Port:                 9100,
752
					HTTPClientConfig:     config.DefaultHTTPClientConfig,
753
				},
754
			},
755
		},
756
		{
757
			JobName: "service-nerve",
758

759
			HonorTimestamps:       true,
760
			ScrapeInterval:        model.Duration(15 * time.Second),
761
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
762
			EnableCompression:     true,
763
			BodySizeLimit:         globBodySizeLimit,
764
			SampleLimit:           globSampleLimit,
765
			TargetLimit:           globTargetLimit,
766
			LabelLimit:            globLabelLimit,
767
			LabelNameLengthLimit:  globLabelNameLengthLimit,
768
			LabelValueLengthLimit: globLabelValueLengthLimit,
769
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
770

771
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
772
			Scheme:           DefaultScrapeConfig.Scheme,
773
			HTTPClientConfig: config.DefaultHTTPClientConfig,
774

775
			ServiceDiscoveryConfigs: discovery.Configs{
776
				&zookeeper.NerveSDConfig{
777
					Servers: []string{"localhost"},
778
					Paths:   []string{"/monitoring"},
779
					Timeout: model.Duration(10 * time.Second),
780
				},
781
			},
782
		},
783
		{
784
			JobName: "0123service-xxx",
785

786
			HonorTimestamps:       true,
787
			ScrapeInterval:        model.Duration(15 * time.Second),
788
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
789
			EnableCompression:     true,
790
			BodySizeLimit:         globBodySizeLimit,
791
			SampleLimit:           globSampleLimit,
792
			TargetLimit:           globTargetLimit,
793
			LabelLimit:            globLabelLimit,
794
			LabelNameLengthLimit:  globLabelNameLengthLimit,
795
			LabelValueLengthLimit: globLabelValueLengthLimit,
796
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
797

798
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
799
			Scheme:           DefaultScrapeConfig.Scheme,
800
			HTTPClientConfig: config.DefaultHTTPClientConfig,
801

802
			ServiceDiscoveryConfigs: discovery.Configs{
803
				discovery.StaticConfig{
804
					{
805
						Targets: []model.LabelSet{
806
							{model.AddressLabel: "localhost:9090"},
807
						},
808
						Source: "0",
809
					},
810
				},
811
			},
812
		},
813
		{
814
			JobName: "badfederation",
815

816
			HonorTimestamps:       false,
817
			ScrapeInterval:        model.Duration(15 * time.Second),
818
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
819
			EnableCompression:     true,
820
			BodySizeLimit:         globBodySizeLimit,
821
			SampleLimit:           globSampleLimit,
822
			TargetLimit:           globTargetLimit,
823
			LabelLimit:            globLabelLimit,
824
			LabelNameLengthLimit:  globLabelNameLengthLimit,
825
			LabelValueLengthLimit: globLabelValueLengthLimit,
826
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
827

828
			MetricsPath:      "/federate",
829
			Scheme:           DefaultScrapeConfig.Scheme,
830
			HTTPClientConfig: config.DefaultHTTPClientConfig,
831

832
			ServiceDiscoveryConfigs: discovery.Configs{
833
				discovery.StaticConfig{
834
					{
835
						Targets: []model.LabelSet{
836
							{model.AddressLabel: "localhost:9090"},
837
						},
838
						Source: "0",
839
					},
840
				},
841
			},
842
		},
843
		{
844
			JobName: "測試",
845

846
			HonorTimestamps:       true,
847
			ScrapeInterval:        model.Duration(15 * time.Second),
848
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
849
			EnableCompression:     true,
850
			BodySizeLimit:         globBodySizeLimit,
851
			SampleLimit:           globSampleLimit,
852
			TargetLimit:           globTargetLimit,
853
			LabelLimit:            globLabelLimit,
854
			LabelNameLengthLimit:  globLabelNameLengthLimit,
855
			LabelValueLengthLimit: globLabelValueLengthLimit,
856
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
857

858
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
859
			Scheme:           DefaultScrapeConfig.Scheme,
860
			HTTPClientConfig: config.DefaultHTTPClientConfig,
861

862
			ServiceDiscoveryConfigs: discovery.Configs{
863
				discovery.StaticConfig{
864
					{
865
						Targets: []model.LabelSet{
866
							{model.AddressLabel: "localhost:9090"},
867
						},
868
						Source: "0",
869
					},
870
				},
871
			},
872
		},
873
		{
874
			JobName: "httpsd",
875

876
			HonorTimestamps:       true,
877
			ScrapeInterval:        model.Duration(15 * time.Second),
878
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
879
			EnableCompression:     true,
880
			BodySizeLimit:         globBodySizeLimit,
881
			SampleLimit:           globSampleLimit,
882
			TargetLimit:           globTargetLimit,
883
			LabelLimit:            globLabelLimit,
884
			LabelNameLengthLimit:  globLabelNameLengthLimit,
885
			LabelValueLengthLimit: globLabelValueLengthLimit,
886
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
887

888
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
889
			Scheme:           DefaultScrapeConfig.Scheme,
890
			HTTPClientConfig: config.DefaultHTTPClientConfig,
891

892
			ServiceDiscoveryConfigs: discovery.Configs{
893
				&http.SDConfig{
894
					HTTPClientConfig: config.DefaultHTTPClientConfig,
895
					URL:              "http://example.com/prometheus",
896
					RefreshInterval:  model.Duration(60 * time.Second),
897
				},
898
			},
899
		},
900
		{
901
			JobName: "service-triton",
902

903
			HonorTimestamps:       true,
904
			ScrapeInterval:        model.Duration(15 * time.Second),
905
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
906
			EnableCompression:     true,
907
			BodySizeLimit:         globBodySizeLimit,
908
			SampleLimit:           globSampleLimit,
909
			TargetLimit:           globTargetLimit,
910
			LabelLimit:            globLabelLimit,
911
			LabelNameLengthLimit:  globLabelNameLengthLimit,
912
			LabelValueLengthLimit: globLabelValueLengthLimit,
913
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
914

915
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
916
			Scheme:           DefaultScrapeConfig.Scheme,
917
			HTTPClientConfig: config.DefaultHTTPClientConfig,
918

919
			ServiceDiscoveryConfigs: discovery.Configs{
920
				&triton.SDConfig{
921
					Account:         "testAccount",
922
					Role:            "container",
923
					DNSSuffix:       "triton.example.com",
924
					Endpoint:        "triton.example.com",
925
					Port:            9163,
926
					RefreshInterval: model.Duration(60 * time.Second),
927
					Version:         1,
928
					TLSConfig: config.TLSConfig{
929
						CertFile: "testdata/valid_cert_file",
930
						KeyFile:  "testdata/valid_key_file",
931
					},
932
				},
933
			},
934
		},
935
		{
936
			JobName: "digitalocean-droplets",
937

938
			HonorTimestamps:       true,
939
			ScrapeInterval:        model.Duration(15 * time.Second),
940
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
941
			EnableCompression:     true,
942
			BodySizeLimit:         globBodySizeLimit,
943
			SampleLimit:           globSampleLimit,
944
			TargetLimit:           globTargetLimit,
945
			LabelLimit:            globLabelLimit,
946
			LabelNameLengthLimit:  globLabelNameLengthLimit,
947
			LabelValueLengthLimit: globLabelValueLengthLimit,
948
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
949

950
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
951
			Scheme:           DefaultScrapeConfig.Scheme,
952
			HTTPClientConfig: config.DefaultHTTPClientConfig,
953

954
			ServiceDiscoveryConfigs: discovery.Configs{
955
				&digitalocean.SDConfig{
956
					HTTPClientConfig: config.HTTPClientConfig{
957
						Authorization: &config.Authorization{
958
							Type:        "Bearer",
959
							Credentials: "abcdef",
960
						},
961
						FollowRedirects: true,
962
						EnableHTTP2:     true,
963
					},
964
					Port:            80,
965
					RefreshInterval: model.Duration(60 * time.Second),
966
				},
967
			},
968
		},
969
		{
970
			JobName: "docker",
971

972
			HonorTimestamps:       true,
973
			ScrapeInterval:        model.Duration(15 * time.Second),
974
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
975
			EnableCompression:     true,
976
			BodySizeLimit:         globBodySizeLimit,
977
			SampleLimit:           globSampleLimit,
978
			TargetLimit:           globTargetLimit,
979
			LabelLimit:            globLabelLimit,
980
			LabelNameLengthLimit:  globLabelNameLengthLimit,
981
			LabelValueLengthLimit: globLabelValueLengthLimit,
982
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
983

984
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
985
			Scheme:           DefaultScrapeConfig.Scheme,
986
			HTTPClientConfig: config.DefaultHTTPClientConfig,
987

988
			ServiceDiscoveryConfigs: discovery.Configs{
989
				&moby.DockerSDConfig{
990
					Filters:            []moby.Filter{},
991
					Host:               "unix:///var/run/docker.sock",
992
					Port:               80,
993
					HostNetworkingHost: "localhost",
994
					RefreshInterval:    model.Duration(60 * time.Second),
995
					HTTPClientConfig:   config.DefaultHTTPClientConfig,
996
				},
997
			},
998
		},
999
		{
1000
			JobName: "dockerswarm",
1001

1002
			HonorTimestamps:       true,
1003
			ScrapeInterval:        model.Duration(15 * time.Second),
1004
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1005
			EnableCompression:     true,
1006
			BodySizeLimit:         globBodySizeLimit,
1007
			SampleLimit:           globSampleLimit,
1008
			TargetLimit:           globTargetLimit,
1009
			LabelLimit:            globLabelLimit,
1010
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1011
			LabelValueLengthLimit: globLabelValueLengthLimit,
1012
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1013

1014
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1015
			Scheme:           DefaultScrapeConfig.Scheme,
1016
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1017

1018
			ServiceDiscoveryConfigs: discovery.Configs{
1019
				&moby.DockerSwarmSDConfig{
1020
					Filters:          []moby.Filter{},
1021
					Host:             "http://127.0.0.1:2375",
1022
					Role:             "nodes",
1023
					Port:             80,
1024
					RefreshInterval:  model.Duration(60 * time.Second),
1025
					HTTPClientConfig: config.DefaultHTTPClientConfig,
1026
				},
1027
			},
1028
		},
1029
		{
1030
			JobName: "service-openstack",
1031

1032
			HonorTimestamps:       true,
1033
			ScrapeInterval:        model.Duration(15 * time.Second),
1034
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1035
			EnableCompression:     true,
1036
			BodySizeLimit:         globBodySizeLimit,
1037
			SampleLimit:           globSampleLimit,
1038
			TargetLimit:           globTargetLimit,
1039
			LabelLimit:            globLabelLimit,
1040
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1041
			LabelValueLengthLimit: globLabelValueLengthLimit,
1042
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1043

1044
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1045
			Scheme:           DefaultScrapeConfig.Scheme,
1046
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1047

1048
			ServiceDiscoveryConfigs: discovery.Configs{
1049
				&openstack.SDConfig{
1050
					Role:            "instance",
1051
					Region:          "RegionOne",
1052
					Port:            80,
1053
					Availability:    "public",
1054
					RefreshInterval: model.Duration(60 * time.Second),
1055
					TLSConfig: config.TLSConfig{
1056
						CAFile:   "testdata/valid_ca_file",
1057
						CertFile: "testdata/valid_cert_file",
1058
						KeyFile:  "testdata/valid_key_file",
1059
					},
1060
				},
1061
			},
1062
		},
1063
		{
1064
			JobName: "service-puppetdb",
1065

1066
			HonorTimestamps:       true,
1067
			ScrapeInterval:        model.Duration(15 * time.Second),
1068
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1069
			EnableCompression:     true,
1070
			BodySizeLimit:         globBodySizeLimit,
1071
			SampleLimit:           globSampleLimit,
1072
			TargetLimit:           globTargetLimit,
1073
			LabelLimit:            globLabelLimit,
1074
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1075
			LabelValueLengthLimit: globLabelValueLengthLimit,
1076
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1077

1078
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1079
			Scheme:           DefaultScrapeConfig.Scheme,
1080
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1081

1082
			ServiceDiscoveryConfigs: discovery.Configs{
1083
				&puppetdb.SDConfig{
1084
					URL:               "https://puppetserver/",
1085
					Query:             "resources { type = \"Package\" and title = \"httpd\" }",
1086
					IncludeParameters: true,
1087
					Port:              80,
1088
					RefreshInterval:   model.Duration(60 * time.Second),
1089
					HTTPClientConfig: config.HTTPClientConfig{
1090
						FollowRedirects: true,
1091
						EnableHTTP2:     true,
1092
						TLSConfig: config.TLSConfig{
1093
							CAFile:   "testdata/valid_ca_file",
1094
							CertFile: "testdata/valid_cert_file",
1095
							KeyFile:  "testdata/valid_key_file",
1096
						},
1097
					},
1098
				},
1099
			},
1100
		},
1101
		{
1102
			JobName:               "hetzner",
1103
			HonorTimestamps:       true,
1104
			ScrapeInterval:        model.Duration(15 * time.Second),
1105
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1106
			EnableCompression:     true,
1107
			BodySizeLimit:         globBodySizeLimit,
1108
			SampleLimit:           globSampleLimit,
1109
			TargetLimit:           globTargetLimit,
1110
			LabelLimit:            globLabelLimit,
1111
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1112
			LabelValueLengthLimit: globLabelValueLengthLimit,
1113
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1114

1115
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1116
			Scheme:           DefaultScrapeConfig.Scheme,
1117
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1118

1119
			RelabelConfigs: []*relabel.Config{
1120
				{
1121
					Action:       relabel.Uppercase,
1122
					Regex:        relabel.DefaultRelabelConfig.Regex,
1123
					Replacement:  relabel.DefaultRelabelConfig.Replacement,
1124
					Separator:    relabel.DefaultRelabelConfig.Separator,
1125
					SourceLabels: model.LabelNames{"instance"},
1126
					TargetLabel:  "instance",
1127
				},
1128
			},
1129

1130
			ServiceDiscoveryConfigs: discovery.Configs{
1131
				&hetzner.SDConfig{
1132
					HTTPClientConfig: config.HTTPClientConfig{
1133
						Authorization: &config.Authorization{
1134
							Type:        "Bearer",
1135
							Credentials: "abcdef",
1136
						},
1137
						FollowRedirects: true,
1138
						EnableHTTP2:     true,
1139
					},
1140
					Port:            80,
1141
					RefreshInterval: model.Duration(60 * time.Second),
1142
					Role:            "hcloud",
1143
				},
1144
				&hetzner.SDConfig{
1145
					HTTPClientConfig: config.HTTPClientConfig{
1146
						BasicAuth:       &config.BasicAuth{Username: "abcdef", Password: "abcdef"},
1147
						FollowRedirects: true,
1148
						EnableHTTP2:     true,
1149
					},
1150
					Port:            80,
1151
					RefreshInterval: model.Duration(60 * time.Second),
1152
					Role:            "robot",
1153
				},
1154
			},
1155
		},
1156
		{
1157
			JobName: "service-eureka",
1158

1159
			HonorTimestamps:       true,
1160
			ScrapeInterval:        model.Duration(15 * time.Second),
1161
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1162
			EnableCompression:     true,
1163
			BodySizeLimit:         globBodySizeLimit,
1164
			SampleLimit:           globSampleLimit,
1165
			TargetLimit:           globTargetLimit,
1166
			LabelLimit:            globLabelLimit,
1167
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1168
			LabelValueLengthLimit: globLabelValueLengthLimit,
1169
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1170

1171
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1172
			Scheme:           DefaultScrapeConfig.Scheme,
1173
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1174

1175
			ServiceDiscoveryConfigs: discovery.Configs{
1176
				&eureka.SDConfig{
1177
					Server:           "http://eureka.example.com:8761/eureka",
1178
					RefreshInterval:  model.Duration(30 * time.Second),
1179
					HTTPClientConfig: config.DefaultHTTPClientConfig,
1180
				},
1181
			},
1182
		},
1183
		{
1184
			JobName: "ovhcloud",
1185

1186
			HonorTimestamps:       true,
1187
			ScrapeInterval:        model.Duration(15 * time.Second),
1188
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1189
			EnableCompression:     true,
1190
			BodySizeLimit:         globBodySizeLimit,
1191
			SampleLimit:           globSampleLimit,
1192
			TargetLimit:           globTargetLimit,
1193
			LabelLimit:            globLabelLimit,
1194
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1195
			LabelValueLengthLimit: globLabelValueLengthLimit,
1196
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1197

1198
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1199
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1200
			Scheme:           DefaultScrapeConfig.Scheme,
1201

1202
			ServiceDiscoveryConfigs: discovery.Configs{
1203
				&ovhcloud.SDConfig{
1204
					Endpoint:          "ovh-eu",
1205
					ApplicationKey:    "testAppKey",
1206
					ApplicationSecret: "testAppSecret",
1207
					ConsumerKey:       "testConsumerKey",
1208
					RefreshInterval:   model.Duration(60 * time.Second),
1209
					Service:           "vps",
1210
				},
1211
				&ovhcloud.SDConfig{
1212
					Endpoint:          "ovh-eu",
1213
					ApplicationKey:    "testAppKey",
1214
					ApplicationSecret: "testAppSecret",
1215
					ConsumerKey:       "testConsumerKey",
1216
					RefreshInterval:   model.Duration(60 * time.Second),
1217
					Service:           "dedicated_server",
1218
				},
1219
			},
1220
		},
1221
		{
1222
			JobName: "scaleway",
1223

1224
			HonorTimestamps:       true,
1225
			ScrapeInterval:        model.Duration(15 * time.Second),
1226
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1227
			EnableCompression:     true,
1228
			BodySizeLimit:         globBodySizeLimit,
1229
			SampleLimit:           globSampleLimit,
1230
			TargetLimit:           globTargetLimit,
1231
			LabelLimit:            globLabelLimit,
1232
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1233
			LabelValueLengthLimit: globLabelValueLengthLimit,
1234
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1235

1236
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1237
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1238
			Scheme:           DefaultScrapeConfig.Scheme,
1239

1240
			ServiceDiscoveryConfigs: discovery.Configs{
1241
				&scaleway.SDConfig{
1242
					APIURL:           "https://api.scaleway.com",
1243
					AccessKey:        "SCWXXXXXXXXXXXXXXXXX",
1244
					HTTPClientConfig: config.DefaultHTTPClientConfig,
1245
					Port:             80,
1246
					Project:          "11111111-1111-1111-1111-111111111112",
1247
					RefreshInterval:  model.Duration(60 * time.Second),
1248
					Role:             "instance",
1249
					SecretKey:        "11111111-1111-1111-1111-111111111111",
1250
					Zone:             "fr-par-1",
1251
				},
1252
				&scaleway.SDConfig{
1253
					APIURL:           "https://api.scaleway.com",
1254
					AccessKey:        "SCWXXXXXXXXXXXXXXXXX",
1255
					HTTPClientConfig: config.DefaultHTTPClientConfig,
1256
					Port:             80,
1257
					Project:          "11111111-1111-1111-1111-111111111112",
1258
					RefreshInterval:  model.Duration(60 * time.Second),
1259
					Role:             "baremetal",
1260
					SecretKey:        "11111111-1111-1111-1111-111111111111",
1261
					Zone:             "fr-par-1",
1262
				},
1263
			},
1264
		},
1265
		{
1266
			JobName: "linode-instances",
1267

1268
			HonorTimestamps:       true,
1269
			ScrapeInterval:        model.Duration(15 * time.Second),
1270
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1271
			EnableCompression:     true,
1272
			BodySizeLimit:         globBodySizeLimit,
1273
			SampleLimit:           globSampleLimit,
1274
			TargetLimit:           globTargetLimit,
1275
			LabelLimit:            globLabelLimit,
1276
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1277
			LabelValueLengthLimit: globLabelValueLengthLimit,
1278
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1279

1280
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1281
			Scheme:           DefaultScrapeConfig.Scheme,
1282
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1283

1284
			ServiceDiscoveryConfigs: discovery.Configs{
1285
				&linode.SDConfig{
1286
					HTTPClientConfig: config.HTTPClientConfig{
1287
						Authorization: &config.Authorization{
1288
							Type:        "Bearer",
1289
							Credentials: "abcdef",
1290
						},
1291
						FollowRedirects: true,
1292
						EnableHTTP2:     true,
1293
					},
1294
					Port:            80,
1295
					TagSeparator:    linode.DefaultSDConfig.TagSeparator,
1296
					RefreshInterval: model.Duration(60 * time.Second),
1297
				},
1298
			},
1299
		},
1300
		{
1301
			JobName: "uyuni",
1302

1303
			HonorTimestamps:       true,
1304
			ScrapeInterval:        model.Duration(15 * time.Second),
1305
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1306
			EnableCompression:     true,
1307
			BodySizeLimit:         globBodySizeLimit,
1308
			SampleLimit:           globSampleLimit,
1309
			TargetLimit:           globTargetLimit,
1310
			LabelLimit:            globLabelLimit,
1311
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1312
			LabelValueLengthLimit: globLabelValueLengthLimit,
1313
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1314

1315
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1316
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1317
			Scheme:           DefaultScrapeConfig.Scheme,
1318
			ServiceDiscoveryConfigs: discovery.Configs{
1319
				&uyuni.SDConfig{
1320
					Server:           "https://localhost:1234",
1321
					Username:         "gopher",
1322
					Password:         "hole",
1323
					Entitlement:      "monitoring_entitled",
1324
					Separator:        ",",
1325
					RefreshInterval:  model.Duration(60 * time.Second),
1326
					HTTPClientConfig: config.DefaultHTTPClientConfig,
1327
				},
1328
			},
1329
		},
1330
		{
1331
			JobName:               "ionos",
1332
			HonorTimestamps:       true,
1333
			ScrapeInterval:        model.Duration(15 * time.Second),
1334
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1335
			EnableCompression:     true,
1336
			BodySizeLimit:         globBodySizeLimit,
1337
			SampleLimit:           globSampleLimit,
1338
			TargetLimit:           globTargetLimit,
1339
			LabelLimit:            globLabelLimit,
1340
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1341
			LabelValueLengthLimit: globLabelValueLengthLimit,
1342
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1343

1344
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1345
			Scheme:           DefaultScrapeConfig.Scheme,
1346
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1347

1348
			ServiceDiscoveryConfigs: discovery.Configs{
1349
				&ionos.SDConfig{
1350
					DatacenterID: "8feda53f-15f0-447f-badf-ebe32dad2fc0",
1351
					HTTPClientConfig: config.HTTPClientConfig{
1352
						Authorization:   &config.Authorization{Type: "Bearer", Credentials: "abcdef"},
1353
						FollowRedirects: true,
1354
						EnableHTTP2:     true,
1355
					},
1356
					Port:            80,
1357
					RefreshInterval: model.Duration(60 * time.Second),
1358
				},
1359
			},
1360
		},
1361
		{
1362
			JobName: "vultr",
1363

1364
			HonorTimestamps:       true,
1365
			ScrapeInterval:        model.Duration(15 * time.Second),
1366
			ScrapeTimeout:         DefaultGlobalConfig.ScrapeTimeout,
1367
			EnableCompression:     true,
1368
			BodySizeLimit:         globBodySizeLimit,
1369
			SampleLimit:           globSampleLimit,
1370
			TargetLimit:           globTargetLimit,
1371
			LabelLimit:            globLabelLimit,
1372
			LabelNameLengthLimit:  globLabelNameLengthLimit,
1373
			LabelValueLengthLimit: globLabelValueLengthLimit,
1374
			ScrapeProtocols:       DefaultGlobalConfig.ScrapeProtocols,
1375

1376
			MetricsPath:      DefaultScrapeConfig.MetricsPath,
1377
			Scheme:           DefaultScrapeConfig.Scheme,
1378
			HTTPClientConfig: config.DefaultHTTPClientConfig,
1379

1380
			ServiceDiscoveryConfigs: discovery.Configs{
1381
				&vultr.SDConfig{
1382
					HTTPClientConfig: config.HTTPClientConfig{
1383
						Authorization: &config.Authorization{
1384
							Type:        "Bearer",
1385
							Credentials: "abcdef",
1386
						},
1387
						FollowRedirects: true,
1388
						EnableHTTP2:     true,
1389
					},
1390
					Port:            80,
1391
					RefreshInterval: model.Duration(60 * time.Second),
1392
				},
1393
			},
1394
		},
1395
	},
1396
	AlertingConfig: AlertingConfig{
1397
		AlertmanagerConfigs: []*AlertmanagerConfig{
1398
			{
1399
				Scheme:           "https",
1400
				Timeout:          model.Duration(10 * time.Second),
1401
				APIVersion:       AlertmanagerAPIVersionV2,
1402
				HTTPClientConfig: config.DefaultHTTPClientConfig,
1403
				ServiceDiscoveryConfigs: discovery.Configs{
1404
					discovery.StaticConfig{
1405
						{
1406
							Targets: []model.LabelSet{
1407
								{model.AddressLabel: "1.2.3.4:9093"},
1408
								{model.AddressLabel: "1.2.3.5:9093"},
1409
								{model.AddressLabel: "1.2.3.6:9093"},
1410
							},
1411
							Source: "0",
1412
						},
1413
					},
1414
				},
1415
			},
1416
		},
1417
	},
1418
	StorageConfig: StorageConfig{
1419
		TSDBConfig: &TSDBConfig{
1420
			OutOfOrderTimeWindow:     30 * time.Minute.Milliseconds(),
1421
			OutOfOrderTimeWindowFlag: model.Duration(30 * time.Minute),
1422
		},
1423
	},
1424
	TracingConfig: TracingConfig{
1425
		Endpoint:    "localhost:4317",
1426
		ClientType:  TracingClientGRPC,
1427
		Insecure:    false,
1428
		Compression: "gzip",
1429
		Timeout:     model.Duration(5 * time.Second),
1430
		Headers:     map[string]string{"foo": "bar"},
1431
		TLSConfig: config.TLSConfig{
1432
			CertFile:           "testdata/valid_cert_file",
1433
			KeyFile:            "testdata/valid_key_file",
1434
			InsecureSkipVerify: true,
1435
		},
1436
	},
1437
}
1438

1439
func TestYAMLRoundtrip(t *testing.T) {
1440
	want, err := LoadFile("testdata/roundtrip.good.yml", false, false, log.NewNopLogger())
1441
	require.NoError(t, err)
1442

1443
	out, err := yaml.Marshal(want)
1444

1445
	require.NoError(t, err)
1446
	got := &Config{}
1447
	require.NoError(t, yaml.UnmarshalStrict(out, got))
1448

1449
	require.Equal(t, want, got)
1450
}
1451

1452
func TestRemoteWriteRetryOnRateLimit(t *testing.T) {
1453
	want, err := LoadFile("testdata/remote_write_retry_on_rate_limit.good.yml", false, false, log.NewNopLogger())
1454
	require.NoError(t, err)
1455

1456
	out, err := yaml.Marshal(want)
1457

1458
	require.NoError(t, err)
1459
	got := &Config{}
1460
	require.NoError(t, yaml.UnmarshalStrict(out, got))
1461

1462
	require.True(t, got.RemoteWriteConfigs[0].QueueConfig.RetryOnRateLimit)
1463
	require.False(t, got.RemoteWriteConfigs[1].QueueConfig.RetryOnRateLimit)
1464
}
1465

1466
func TestLoadConfig(t *testing.T) {
1467
	// Parse a valid file that sets a global scrape timeout. This tests whether parsing
1468
	// an overwritten default field in the global config permanently changes the default.
1469
	_, err := LoadFile("testdata/global_timeout.good.yml", false, false, log.NewNopLogger())
1470
	require.NoError(t, err)
1471

1472
	c, err := LoadFile("testdata/conf.good.yml", false, false, log.NewNopLogger())
1473
	require.NoError(t, err)
1474
	require.Equal(t, expectedConf, c)
1475
}
1476

1477
func TestScrapeIntervalLarger(t *testing.T) {
1478
	c, err := LoadFile("testdata/scrape_interval_larger.good.yml", false, false, log.NewNopLogger())
1479
	require.NoError(t, err)
1480
	require.Len(t, c.ScrapeConfigs, 1)
1481
	for _, sc := range c.ScrapeConfigs {
1482
		require.GreaterOrEqual(t, sc.ScrapeInterval, sc.ScrapeTimeout)
1483
	}
1484
}
1485

1486
// YAML marshaling must not reveal authentication credentials.
1487
func TestElideSecrets(t *testing.T) {
1488
	c, err := LoadFile("testdata/conf.good.yml", false, false, log.NewNopLogger())
1489
	require.NoError(t, err)
1490

1491
	secretRe := regexp.MustCompile(`\\u003csecret\\u003e|<secret>`)
1492

1493
	config, err := yaml.Marshal(c)
1494
	require.NoError(t, err)
1495
	yamlConfig := string(config)
1496

1497
	matches := secretRe.FindAllStringIndex(yamlConfig, -1)
1498
	require.Len(t, matches, 22, "wrong number of secret matches found")
1499
	require.NotContains(t, yamlConfig, "mysecret",
1500
		"yaml marshal reveals authentication credentials.")
1501
}
1502

1503
func TestLoadConfigRuleFilesAbsolutePath(t *testing.T) {
1504
	// Parse a valid file that sets a rule files with an absolute path
1505
	c, err := LoadFile(ruleFilesConfigFile, false, false, log.NewNopLogger())
1506
	require.NoError(t, err)
1507
	require.Equal(t, ruleFilesExpectedConf, c)
1508
}
1509

1510
func TestKubernetesEmptyAPIServer(t *testing.T) {
1511
	_, err := LoadFile("testdata/kubernetes_empty_apiserver.good.yml", false, false, log.NewNopLogger())
1512
	require.NoError(t, err)
1513
}
1514

1515
func TestKubernetesWithKubeConfig(t *testing.T) {
1516
	_, err := LoadFile("testdata/kubernetes_kubeconfig_without_apiserver.good.yml", false, false, log.NewNopLogger())
1517
	require.NoError(t, err)
1518
}
1519

1520
func TestKubernetesSelectors(t *testing.T) {
1521
	_, err := LoadFile("testdata/kubernetes_selectors_endpoints.good.yml", false, false, log.NewNopLogger())
1522
	require.NoError(t, err)
1523
	_, err = LoadFile("testdata/kubernetes_selectors_node.good.yml", false, false, log.NewNopLogger())
1524
	require.NoError(t, err)
1525
	_, err = LoadFile("testdata/kubernetes_selectors_ingress.good.yml", false, false, log.NewNopLogger())
1526
	require.NoError(t, err)
1527
	_, err = LoadFile("testdata/kubernetes_selectors_pod.good.yml", false, false, log.NewNopLogger())
1528
	require.NoError(t, err)
1529
	_, err = LoadFile("testdata/kubernetes_selectors_service.good.yml", false, false, log.NewNopLogger())
1530
	require.NoError(t, err)
1531
}
1532

1533
var expectedErrors = []struct {
1534
	filename string
1535
	errMsg   string
1536
}{
1537
	{
1538
		filename: "jobname.bad.yml",
1539
		errMsg:   `job_name is empty`,
1540
	},
1541
	{
1542
		filename: "jobname_dup.bad.yml",
1543
		errMsg:   `found multiple scrape configs with job name "prometheus"`,
1544
	},
1545
	{
1546
		filename: "scrape_interval.bad.yml",
1547
		errMsg:   `scrape timeout greater than scrape interval`,
1548
	},
1549
	{
1550
		filename: "labelname.bad.yml",
1551
		errMsg:   `"not$allowed" is not a valid label name`,
1552
	},
1553
	{
1554
		filename: "labelname2.bad.yml",
1555
		errMsg:   `"not:allowed" is not a valid label name`,
1556
	},
1557
	{
1558
		filename: "labelvalue.bad.yml",
1559
		errMsg:   `"\xff" is not a valid label value`,
1560
	},
1561
	{
1562
		filename: "regex.bad.yml",
1563
		errMsg:   "error parsing regexp",
1564
	},
1565
	{
1566
		filename: "modulus_missing.bad.yml",
1567
		errMsg:   "relabel configuration for hashmod requires non-zero modulus",
1568
	},
1569
	{
1570
		filename: "labelkeep.bad.yml",
1571
		errMsg:   "labelkeep action requires only 'regex', and no other fields",
1572
	},
1573
	{
1574
		filename: "labelkeep2.bad.yml",
1575
		errMsg:   "labelkeep action requires only 'regex', and no other fields",
1576
	},
1577
	{
1578
		filename: "labelkeep3.bad.yml",
1579
		errMsg:   "labelkeep action requires only 'regex', and no other fields",
1580
	},
1581
	{
1582
		filename: "labelkeep4.bad.yml",
1583
		errMsg:   "labelkeep action requires only 'regex', and no other fields",
1584
	},
1585
	{
1586
		filename: "labelkeep5.bad.yml",
1587
		errMsg:   "labelkeep action requires only 'regex', and no other fields",
1588
	},
1589
	{
1590
		filename: "labeldrop.bad.yml",
1591
		errMsg:   "labeldrop action requires only 'regex', and no other fields",
1592
	},
1593
	{
1594
		filename: "labeldrop2.bad.yml",
1595
		errMsg:   "labeldrop action requires only 'regex', and no other fields",
1596
	},
1597
	{
1598
		filename: "labeldrop3.bad.yml",
1599
		errMsg:   "labeldrop action requires only 'regex', and no other fields",
1600
	},
1601
	{
1602
		filename: "labeldrop4.bad.yml",
1603
		errMsg:   "labeldrop action requires only 'regex', and no other fields",
1604
	},
1605
	{
1606
		filename: "labeldrop5.bad.yml",
1607
		errMsg:   "labeldrop action requires only 'regex', and no other fields",
1608
	},
1609
	{
1610
		filename: "dropequal.bad.yml",
1611
		errMsg:   "relabel configuration for dropequal action requires 'target_label' value",
1612
	},
1613
	{
1614
		filename: "dropequal1.bad.yml",
1615
		errMsg:   "dropequal action requires only 'source_labels' and `target_label`, and no other fields",
1616
	},
1617
	{
1618
		filename: "keepequal.bad.yml",
1619
		errMsg:   "relabel configuration for keepequal action requires 'target_label' value",
1620
	},
1621
	{
1622
		filename: "keepequal1.bad.yml",
1623
		errMsg:   "keepequal action requires only 'source_labels' and `target_label`, and no other fields",
1624
	},
1625
	{
1626
		filename: "labelmap.bad.yml",
1627
		errMsg:   "\"l-$1\" is invalid 'replacement' for labelmap action",
1628
	},
1629
	{
1630
		filename: "lowercase.bad.yml",
1631
		errMsg:   "relabel configuration for lowercase action requires 'target_label' value",
1632
	},
1633
	{
1634
		filename: "lowercase2.bad.yml",
1635
		errMsg:   "\"42lab\" is invalid 'target_label' for lowercase action",
1636
	},
1637
	{
1638
		filename: "lowercase3.bad.yml",
1639
		errMsg:   "'replacement' can not be set for lowercase action",
1640
	},
1641
	{
1642
		filename: "uppercase.bad.yml",
1643
		errMsg:   "relabel configuration for uppercase action requires 'target_label' value",
1644
	},
1645
	{
1646
		filename: "uppercase2.bad.yml",
1647
		errMsg:   "\"42lab\" is invalid 'target_label' for uppercase action",
1648
	},
1649
	{
1650
		filename: "uppercase3.bad.yml",
1651
		errMsg:   "'replacement' can not be set for uppercase action",
1652
	},
1653
	{
1654
		filename: "rules.bad.yml",
1655
		errMsg:   "invalid rule file path",
1656
	},
1657
	{
1658
		filename: "unknown_attr.bad.yml",
1659
		errMsg:   "field consult_sd_configs not found in type",
1660
	},
1661
	{
1662
		filename: "bearertoken.bad.yml",
1663
		errMsg:   "at most one of bearer_token & bearer_token_file must be configured",
1664
	},
1665
	{
1666
		filename: "bearertoken_basicauth.bad.yml",
1667
		errMsg:   "at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured",
1668
	},
1669
	{
1670
		filename: "kubernetes_http_config_without_api_server.bad.yml",
1671
		errMsg:   "to use custom HTTP client configuration please provide the 'api_server' URL explicitly",
1672
	},
1673
	{
1674
		filename: "kubernetes_kubeconfig_with_own_namespace.bad.yml",
1675
		errMsg:   "cannot use 'kubeconfig_file' and 'namespaces.own_namespace' simultaneously",
1676
	},
1677
	{
1678
		filename: "kubernetes_api_server_with_own_namespace.bad.yml",
1679
		errMsg:   "cannot use 'api_server' and 'namespaces.own_namespace' simultaneously",
1680
	},
1681
	{
1682
		filename: "kubernetes_kubeconfig_with_apiserver.bad.yml",
1683
		errMsg:   "cannot use 'kubeconfig_file' and 'api_server' simultaneously",
1684
	},
1685
	{
1686
		filename: "kubernetes_kubeconfig_with_http_config.bad.yml",
1687
		errMsg:   "cannot use a custom HTTP client configuration together with 'kubeconfig_file'",
1688
	},
1689
	{
1690
		filename: "kubernetes_bearertoken.bad.yml",
1691
		errMsg:   "at most one of bearer_token & bearer_token_file must be configured",
1692
	},
1693
	{
1694
		filename: "kubernetes_role.bad.yml",
1695
		errMsg:   "role",
1696
	},
1697
	{
1698
		filename: "kubernetes_selectors_endpoints.bad.yml",
1699
		errMsg:   "endpoints role supports only pod, service, endpoints selectors",
1700
	},
1701
	{
1702
		filename: "kubernetes_selectors_ingress.bad.yml",
1703
		errMsg:   "ingress role supports only ingress selectors",
1704
	},
1705
	{
1706
		filename: "kubernetes_selectors_node.bad.yml",
1707
		errMsg:   "node role supports only node selectors",
1708
	},
1709
	{
1710
		filename: "kubernetes_selectors_pod.bad.yml",
1711
		errMsg:   "pod role supports only pod selectors",
1712
	},
1713
	{
1714
		filename: "kubernetes_selectors_service.bad.yml",
1715
		errMsg:   "service role supports only service selectors",
1716
	},
1717
	{
1718
		filename: "kubernetes_namespace_discovery.bad.yml",
1719
		errMsg:   "field foo not found in type kubernetes.plain",
1720
	},
1721
	{
1722
		filename: "kubernetes_selectors_duplicated_role.bad.yml",
1723
		errMsg:   "duplicated selector role: pod",
1724
	},
1725
	{
1726
		filename: "kubernetes_selectors_incorrect_selector.bad.yml",
1727
		errMsg:   "invalid selector: 'metadata.status-Running'; can't understand 'metadata.status-Running'",
1728
	},
1729
	{
1730
		filename: "kubernetes_bearertoken_basicauth.bad.yml",
1731
		errMsg:   "at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured",
1732
	},
1733
	{
1734
		filename: "kubernetes_authorization_basicauth.bad.yml",
1735
		errMsg:   "at most one of basic_auth, oauth2 & authorization must be configured",
1736
	},
1737
	{
1738
		filename: "marathon_no_servers.bad.yml",
1739
		errMsg:   "marathon_sd: must contain at least one Marathon server",
1740
	},
1741
	{
1742
		filename: "marathon_authtoken_authtokenfile.bad.yml",
1743
		errMsg:   "marathon_sd: at most one of auth_token & auth_token_file must be configured",
1744
	},
1745
	{
1746
		filename: "marathon_authtoken_basicauth.bad.yml",
1747
		errMsg:   "marathon_sd: at most one of basic_auth, auth_token & auth_token_file must be configured",
1748
	},
1749
	{
1750
		filename: "marathon_authtoken_bearertoken.bad.yml",
1751
		errMsg:   "marathon_sd: at most one of bearer_token, bearer_token_file, auth_token & auth_token_file must be configured",
1752
	},
1753
	{
1754
		filename: "marathon_authtoken_authorization.bad.yml",
1755
		errMsg:   "marathon_sd: at most one of auth_token, auth_token_file & authorization must be configured",
1756
	},
1757
	{
1758
		filename: "openstack_role.bad.yml",
1759
		errMsg:   "unknown OpenStack SD role",
1760
	},
1761
	{
1762
		filename: "openstack_availability.bad.yml",
1763
		errMsg:   "unknown availability invalid, must be one of admin, internal or public",
1764
	},
1765
	{
1766
		filename: "url_in_targetgroup.bad.yml",
1767
		errMsg:   "\"http://bad\" is not a valid hostname",
1768
	},
1769
	{
1770
		filename: "target_label_missing.bad.yml",
1771
		errMsg:   "relabel configuration for replace action requires 'target_label' value",
1772
	},
1773
	{
1774
		filename: "target_label_hashmod_missing.bad.yml",
1775
		errMsg:   "relabel configuration for hashmod action requires 'target_label' value",
1776
	},
1777
	{
1778
		filename: "unknown_global_attr.bad.yml",
1779
		errMsg:   "field nonexistent_field not found in type config.plain",
1780
	},
1781
	{
1782
		filename: "remote_read_url_missing.bad.yml",
1783
		errMsg:   `url for remote_read is empty`,
1784
	},
1785
	{
1786
		filename: "remote_write_header.bad.yml",
1787
		errMsg:   `x-prometheus-remote-write-version is a reserved header. It must not be changed`,
1788
	},
1789
	{
1790
		filename: "remote_read_header.bad.yml",
1791
		errMsg:   `x-prometheus-remote-write-version is a reserved header. It must not be changed`,
1792
	},
1793
	{
1794
		filename: "remote_write_authorization_header.bad.yml",
1795
		errMsg:   `authorization header must be changed via the basic_auth, authorization, oauth2, sigv4, or azuread parameter`,
1796
	},
1797
	{
1798
		filename: "remote_write_url_missing.bad.yml",
1799
		errMsg:   `url for remote_write is empty`,
1800
	},
1801
	{
1802
		filename: "remote_write_dup.bad.yml",
1803
		errMsg:   `found multiple remote write configs with job name "queue1"`,
1804
	},
1805
	{
1806
		filename: "remote_read_dup.bad.yml",
1807
		errMsg:   `found multiple remote read configs with job name "queue1"`,
1808
	},
1809
	{
1810
		filename: "ec2_filters_empty_values.bad.yml",
1811
		errMsg:   `EC2 SD configuration filter values cannot be empty`,
1812
	},
1813
	{
1814
		filename: "ec2_token_file.bad.yml",
1815
		errMsg:   `at most one of bearer_token & bearer_token_file must be configured`,
1816
	},
1817
	{
1818
		filename: "lightsail_token_file.bad.yml",
1819
		errMsg:   `at most one of bearer_token & bearer_token_file must be configured`,
1820
	},
1821
	{
1822
		filename: "section_key_dup.bad.yml",
1823
		errMsg:   "field scrape_configs already set in type config.plain",
1824
	},
1825
	{
1826
		filename: "azure_client_id_missing.bad.yml",
1827
		errMsg:   "azure SD configuration requires a client_id",
1828
	},
1829
	{
1830
		filename: "azure_client_secret_missing.bad.yml",
1831
		errMsg:   "azure SD configuration requires a client_secret",
1832
	},
1833
	{
1834
		filename: "azure_subscription_id_missing.bad.yml",
1835
		errMsg:   "azure SD configuration requires a subscription_id",
1836
	},
1837
	{
1838
		filename: "azure_tenant_id_missing.bad.yml",
1839
		errMsg:   "azure SD configuration requires a tenant_id",
1840
	},
1841
	{
1842
		filename: "azure_authentication_method.bad.yml",
1843
		errMsg:   "unknown authentication_type \"invalid\". Supported types are \"OAuth\", \"ManagedIdentity\" or \"SDK\"",
1844
	},
1845
	{
1846
		filename: "azure_bearertoken_basicauth.bad.yml",
1847
		errMsg:   "at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured",
1848
	},
1849
	{
1850
		filename: "empty_scrape_config.bad.yml",
1851
		errMsg:   "empty or null scrape config section",
1852
	},
1853
	{
1854
		filename: "empty_rw_config.bad.yml",
1855
		errMsg:   "empty or null remote write config section",
1856
	},
1857
	{
1858
		filename: "empty_rr_config.bad.yml",
1859
		errMsg:   "empty or null remote read config section",
1860
	},
1861
	{
1862
		filename: "empty_target_relabel_config.bad.yml",
1863
		errMsg:   "empty or null target relabeling rule",
1864
	},
1865
	{
1866
		filename: "empty_metric_relabel_config.bad.yml",
1867
		errMsg:   "empty or null metric relabeling rule",
1868
	},
1869
	{
1870
		filename: "empty_alert_relabel_config.bad.yml",
1871
		errMsg:   "empty or null alert relabeling rule",
1872
	},
1873
	{
1874
		filename: "empty_alertmanager_relabel_config.bad.yml",
1875
		errMsg:   "empty or null Alertmanager target relabeling rule",
1876
	},
1877
	{
1878
		filename: "empty_rw_relabel_config.bad.yml",
1879
		errMsg:   "empty or null relabeling rule in remote write config",
1880
	},
1881
	{
1882
		filename: "empty_static_config.bad.yml",
1883
		errMsg:   "empty or null section in static_configs",
1884
	},
1885
	{
1886
		filename: "puppetdb_no_query.bad.yml",
1887
		errMsg:   "query missing",
1888
	},
1889
	{
1890
		filename: "puppetdb_no_url.bad.yml",
1891
		errMsg:   "URL is missing",
1892
	},
1893
	{
1894
		filename: "puppetdb_bad_url.bad.yml",
1895
		errMsg:   "host is missing in URL",
1896
	},
1897
	{
1898
		filename: "puppetdb_no_scheme.bad.yml",
1899
		errMsg:   "URL scheme must be 'http' or 'https'",
1900
	},
1901
	{
1902
		filename: "puppetdb_token_file.bad.yml",
1903
		errMsg:   "at most one of bearer_token & bearer_token_file must be configured",
1904
	},
1905
	{
1906
		filename: "hetzner_role.bad.yml",
1907
		errMsg:   "unknown role",
1908
	},
1909
	{
1910
		filename: "eureka_no_server.bad.yml",
1911
		errMsg:   "empty or null eureka server",
1912
	},
1913
	{
1914
		filename: "eureka_invalid_server.bad.yml",
1915
		errMsg:   "invalid eureka server URL",
1916
	},
1917
	{
1918
		filename: "scaleway_role.bad.yml",
1919
		errMsg:   `unknown role "invalid"`,
1920
	},
1921
	{
1922
		filename: "scaleway_no_secret.bad.yml",
1923
		errMsg:   "one of secret_key & secret_key_file must be configured",
1924
	},
1925
	{
1926
		filename: "scaleway_two_secrets.bad.yml",
1927
		errMsg:   "at most one of secret_key & secret_key_file must be configured",
1928
	},
1929
	{
1930
		filename: "scrape_body_size_limit.bad.yml",
1931
		errMsg:   "units: unknown unit  in 100",
1932
	},
1933
	{
1934
		filename: "http_url_no_scheme.bad.yml",
1935
		errMsg:   "URL scheme must be 'http' or 'https'",
1936
	},
1937
	{
1938
		filename: "http_url_no_host.bad.yml",
1939
		errMsg:   "host is missing in URL",
1940
	},
1941
	{
1942
		filename: "http_token_file.bad.yml",
1943
		errMsg:   "at most one of bearer_token & bearer_token_file must be configured",
1944
	},
1945
	{
1946
		filename: "http_url_bad_scheme.bad.yml",
1947
		errMsg:   "URL scheme must be 'http' or 'https'",
1948
	},
1949
	{
1950
		filename: "empty_scrape_config_action.bad.yml",
1951
		errMsg:   "relabel action cannot be empty",
1952
	},
1953
	{
1954
		filename: "tracing_missing_endpoint.bad.yml",
1955
		errMsg:   "tracing endpoint must be set",
1956
	},
1957
	{
1958
		filename: "tracing_invalid_header.bad.yml",
1959
		errMsg:   "x-prometheus-remote-write-version is a reserved header. It must not be changed",
1960
	},
1961
	{
1962
		filename: "tracing_invalid_authorization_header.bad.yml",
1963
		errMsg:   "authorization header configuration is not yet supported",
1964
	},
1965
	{
1966
		filename: "tracing_invalid_compression.bad.yml",
1967
		errMsg:   "invalid compression type foo provided, valid options: gzip",
1968
	},
1969
	{
1970
		filename: "uyuni_no_server.bad.yml",
1971
		errMsg:   "Uyuni SD configuration requires server host",
1972
	},
1973
	{
1974
		filename: "uyuni_token_file.bad.yml",
1975
		errMsg:   "at most one of bearer_token & bearer_token_file must be configured",
1976
	},
1977
	{
1978
		filename: "ionos_datacenter.bad.yml",
1979
		errMsg:   "datacenter id can't be empty",
1980
	},
1981
	{
1982
		filename: "ovhcloud_no_secret.bad.yml",
1983
		errMsg:   "application secret can not be empty",
1984
	},
1985
	{
1986
		filename: "ovhcloud_bad_service.bad.yml",
1987
		errMsg:   "unknown service: fakeservice",
1988
	},
1989
	{
1990
		filename: "scrape_config_files_glob.bad.yml",
1991
		errMsg:   `parsing YAML file testdata/scrape_config_files_glob.bad.yml: invalid scrape config file path "scrape_configs/*/*"`,
1992
	},
1993
	{
1994
		filename: "scrape_config_files_scrape_protocols.bad.yml",
1995
		errMsg:   `parsing YAML file testdata/scrape_config_files_scrape_protocols.bad.yml: scrape_protocols: unknown scrape protocol prometheusproto, supported: [OpenMetricsText0.0.1 OpenMetricsText1.0.0 PrometheusProto PrometheusText0.0.4] for scrape config with job name "node"`,
1996
	},
1997
	{
1998
		filename: "scrape_config_files_scrape_protocols2.bad.yml",
1999
		errMsg:   `parsing YAML file testdata/scrape_config_files_scrape_protocols2.bad.yml: duplicated protocol in scrape_protocols, got [OpenMetricsText1.0.0 PrometheusProto OpenMetricsText1.0.0] for scrape config with job name "node"`,
2000
	},
2001
}
2002

2003
func TestBadConfigs(t *testing.T) {
2004
	for _, ee := range expectedErrors {
2005
		_, err := LoadFile("testdata/"+ee.filename, false, false, log.NewNopLogger())
2006
		require.Error(t, err, "%s", ee.filename)
2007
		require.Contains(t, err.Error(), ee.errMsg,
2008
			"Expected error for %s to contain %q but got: %s", ee.filename, ee.errMsg, err)
2009
	}
2010
}
2011

2012
func TestBadStaticConfigsJSON(t *testing.T) {
2013
	content, err := os.ReadFile("testdata/static_config.bad.json")
2014
	require.NoError(t, err)
2015
	var tg targetgroup.Group
2016
	err = json.Unmarshal(content, &tg)
2017
	require.Error(t, err)
2018
}
2019

2020
func TestBadStaticConfigsYML(t *testing.T) {
2021
	content, err := os.ReadFile("testdata/static_config.bad.yml")
2022
	require.NoError(t, err)
2023
	var tg targetgroup.Group
2024
	err = yaml.UnmarshalStrict(content, &tg)
2025
	require.Error(t, err)
2026
}
2027

2028
func TestEmptyConfig(t *testing.T) {
2029
	c, err := Load("", false, log.NewNopLogger())
2030
	require.NoError(t, err)
2031
	exp := DefaultConfig
2032
	require.Equal(t, exp, *c)
2033
}
2034

2035
func TestExpandExternalLabels(t *testing.T) {
2036
	// Cleanup ant TEST env variable that could exist on the system.
2037
	os.Setenv("TEST", "")
2038

2039
	c, err := LoadFile("testdata/external_labels.good.yml", false, false, log.NewNopLogger())
2040
	require.NoError(t, err)
2041
	testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foo${TEST}bar", "foo", "${TEST}", "qux", "foo$${TEST}", "xyz", "foo$$bar"), c.GlobalConfig.ExternalLabels)
2042

2043
	c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
2044
	require.NoError(t, err)
2045
	testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foobar", "foo", "", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
2046

2047
	os.Setenv("TEST", "TestValue")
2048
	c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
2049
	require.NoError(t, err)
2050
	testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "fooTestValuebar", "foo", "TestValue", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
2051
}
2052

2053
func TestAgentMode(t *testing.T) {
2054
	_, err := LoadFile("testdata/agent_mode.with_alert_manager.yml", true, false, log.NewNopLogger())
2055
	require.ErrorContains(t, err, "field alerting is not allowed in agent mode")
2056

2057
	_, err = LoadFile("testdata/agent_mode.with_alert_relabels.yml", true, false, log.NewNopLogger())
2058
	require.ErrorContains(t, err, "field alerting is not allowed in agent mode")
2059

2060
	_, err = LoadFile("testdata/agent_mode.with_rule_files.yml", true, false, log.NewNopLogger())
2061
	require.ErrorContains(t, err, "field rule_files is not allowed in agent mode")
2062

2063
	_, err = LoadFile("testdata/agent_mode.with_remote_reads.yml", true, false, log.NewNopLogger())
2064
	require.ErrorContains(t, err, "field remote_read is not allowed in agent mode")
2065

2066
	c, err := LoadFile("testdata/agent_mode.without_remote_writes.yml", true, false, log.NewNopLogger())
2067
	require.NoError(t, err)
2068
	require.Empty(t, c.RemoteWriteConfigs)
2069

2070
	c, err = LoadFile("testdata/agent_mode.good.yml", true, false, log.NewNopLogger())
2071
	require.NoError(t, err)
2072
	require.Len(t, c.RemoteWriteConfigs, 1)
2073
	require.Equal(
2074
		t,
2075
		"http://remote1/push",
2076
		c.RemoteWriteConfigs[0].URL.String(),
2077
	)
2078
}
2079

2080
func TestEmptyGlobalBlock(t *testing.T) {
2081
	c, err := Load("global:\n", false, log.NewNopLogger())
2082
	require.NoError(t, err)
2083
	exp := DefaultConfig
2084
	require.Equal(t, exp, *c)
2085
}
2086

2087
func TestGetScrapeConfigs(t *testing.T) {
2088
	sc := func(jobName string, scrapeInterval, scrapeTimeout model.Duration) *ScrapeConfig {
2089
		return &ScrapeConfig{
2090
			JobName:         jobName,
2091
			HonorTimestamps: true,
2092
			ScrapeInterval:  scrapeInterval,
2093
			ScrapeTimeout:   scrapeTimeout,
2094
			ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols,
2095

2096
			MetricsPath:       "/metrics",
2097
			Scheme:            "http",
2098
			EnableCompression: true,
2099
			HTTPClientConfig:  config.DefaultHTTPClientConfig,
2100
			ServiceDiscoveryConfigs: discovery.Configs{
2101
				discovery.StaticConfig{
2102
					{
2103
						Targets: []model.LabelSet{
2104
							{
2105
								model.AddressLabel: "localhost:8080",
2106
							},
2107
						},
2108
						Source: "0",
2109
					},
2110
				},
2111
			},
2112
		}
2113
	}
2114

2115
	testCases := []struct {
2116
		name           string
2117
		configFile     string
2118
		expectedResult []*ScrapeConfig
2119
		expectedError  string
2120
	}{
2121
		{
2122
			name:           "An included config file should be a valid global config.",
2123
			configFile:     "testdata/scrape_config_files.good.yml",
2124
			expectedResult: []*ScrapeConfig{sc("prometheus", model.Duration(60*time.Second), model.Duration(10*time.Second))},
2125
		},
2126
		{
2127
			name:           "An global config that only include a scrape config file.",
2128
			configFile:     "testdata/scrape_config_files_only.good.yml",
2129
			expectedResult: []*ScrapeConfig{sc("prometheus", model.Duration(60*time.Second), model.Duration(10*time.Second))},
2130
		},
2131
		{
2132
			name:       "An global config that combine scrape config files and scrape configs.",
2133
			configFile: "testdata/scrape_config_files_combined.good.yml",
2134
			expectedResult: []*ScrapeConfig{
2135
				sc("node", model.Duration(60*time.Second), model.Duration(10*time.Second)),
2136
				sc("prometheus", model.Duration(60*time.Second), model.Duration(10*time.Second)),
2137
				sc("alertmanager", model.Duration(60*time.Second), model.Duration(10*time.Second)),
2138
			},
2139
		},
2140
		{
2141
			name:       "An global config that includes a scrape config file with globs",
2142
			configFile: "testdata/scrape_config_files_glob.good.yml",
2143
			expectedResult: []*ScrapeConfig{
2144
				{
2145
					JobName: "prometheus",
2146

2147
					HonorTimestamps: true,
2148
					ScrapeInterval:  model.Duration(60 * time.Second),
2149
					ScrapeTimeout:   DefaultGlobalConfig.ScrapeTimeout,
2150
					ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols,
2151

2152
					MetricsPath: DefaultScrapeConfig.MetricsPath,
2153
					Scheme:      DefaultScrapeConfig.Scheme,
2154

2155
					EnableCompression: true,
2156

2157
					HTTPClientConfig: config.HTTPClientConfig{
2158
						TLSConfig: config.TLSConfig{
2159
							CertFile: filepath.FromSlash("testdata/scrape_configs/valid_cert_file"),
2160
							KeyFile:  filepath.FromSlash("testdata/scrape_configs/valid_key_file"),
2161
						},
2162
						FollowRedirects: true,
2163
						EnableHTTP2:     true,
2164
					},
2165

2166
					ServiceDiscoveryConfigs: discovery.Configs{
2167
						discovery.StaticConfig{
2168
							{
2169
								Targets: []model.LabelSet{
2170
									{model.AddressLabel: "localhost:8080"},
2171
								},
2172
								Source: "0",
2173
							},
2174
						},
2175
					},
2176
				},
2177
				{
2178
					JobName: "node",
2179

2180
					HonorTimestamps: true,
2181
					ScrapeInterval:  model.Duration(15 * time.Second),
2182
					ScrapeTimeout:   DefaultGlobalConfig.ScrapeTimeout,
2183
					ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols,
2184

2185
					HTTPClientConfig: config.HTTPClientConfig{
2186
						TLSConfig: config.TLSConfig{
2187
							CertFile: filepath.FromSlash("testdata/valid_cert_file"),
2188
							KeyFile:  filepath.FromSlash("testdata/valid_key_file"),
2189
						},
2190
						FollowRedirects: true,
2191
						EnableHTTP2:     true,
2192
					},
2193

2194
					MetricsPath: DefaultScrapeConfig.MetricsPath,
2195
					Scheme:      DefaultScrapeConfig.Scheme,
2196

2197
					EnableCompression: true,
2198

2199
					ServiceDiscoveryConfigs: discovery.Configs{
2200
						&vultr.SDConfig{
2201
							HTTPClientConfig: config.HTTPClientConfig{
2202
								Authorization: &config.Authorization{
2203
									Type:        "Bearer",
2204
									Credentials: "abcdef",
2205
								},
2206
								FollowRedirects: true,
2207
								EnableHTTP2:     true,
2208
							},
2209
							Port:            80,
2210
							RefreshInterval: model.Duration(60 * time.Second),
2211
						},
2212
					},
2213
				},
2214
			},
2215
		},
2216
		{
2217
			name:          "An global config that includes twice the same scrape configs.",
2218
			configFile:    "testdata/scrape_config_files_double_import.bad.yml",
2219
			expectedError: `found multiple scrape configs with job name "prometheus"`,
2220
		},
2221
		{
2222
			name:          "An global config that includes a scrape config identical to a scrape config in the main file.",
2223
			configFile:    "testdata/scrape_config_files_duplicate.bad.yml",
2224
			expectedError: `found multiple scrape configs with job name "prometheus"`,
2225
		},
2226
		{
2227
			name:          "An global config that includes a scrape config file with errors.",
2228
			configFile:    "testdata/scrape_config_files_global.bad.yml",
2229
			expectedError: `scrape timeout greater than scrape interval for scrape config with job name "prometheus"`,
2230
		},
2231
	}
2232

2233
	for _, tc := range testCases {
2234
		t.Run(tc.name, func(t *testing.T) {
2235
			c, err := LoadFile(tc.configFile, false, false, log.NewNopLogger())
2236
			require.NoError(t, err)
2237

2238
			scfgs, err := c.GetScrapeConfigs()
2239
			if len(tc.expectedError) > 0 {
2240
				require.ErrorContains(t, err, tc.expectedError)
2241
			}
2242
			require.Equal(t, tc.expectedResult, scfgs)
2243
		})
2244
	}
2245
}
2246

2247
func kubernetesSDHostURL() config.URL {
2248
	tURL, _ := url.Parse("https://localhost:1234")
2249
	return config.URL{URL: tURL}
2250
}
2251

2252
func TestScrapeConfigDisableCompression(t *testing.T) {
2253
	want, err := LoadFile("testdata/scrape_config_disable_compression.good.yml", false, false, log.NewNopLogger())
2254
	require.NoError(t, err)
2255

2256
	out, err := yaml.Marshal(want)
2257

2258
	require.NoError(t, err)
2259
	got := &Config{}
2260
	require.NoError(t, yaml.UnmarshalStrict(out, got))
2261

2262
	require.False(t, got.ScrapeConfigs[0].EnableCompression)
2263
}
2264

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.