Skip to content

Commit 8b91d39

Browse files
discovery: send empty group on empty SD config (prometheus#4819)
* discovery: send empty group on blank SD config Signed-off-by: Simon Pasquier <[email protected]> * Update comments Signed-off-by: Simon Pasquier <[email protected]> * Add another comment Signed-off-by: Simon Pasquier <[email protected]>
1 parent 7b88360 commit 8b91d39

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

discovery/manager.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,13 @@ func (m *Manager) allGroups() map[string][]*targetgroup.Group {
314314
}
315315

316316
func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setName string) {
317+
var added bool
317318
add := func(cfg interface{}, newDiscoverer func() (Discoverer, error)) {
318319
t := reflect.TypeOf(cfg).String()
319320
for _, p := range m.providers {
320321
if reflect.DeepEqual(cfg, p.config) {
321322
p.subs = append(p.subs, setName)
323+
added = true
322324
return
323325
}
324326
}
@@ -337,6 +339,7 @@ func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setNam
337339
subs: []string{setName},
338340
}
339341
m.providers = append(m.providers, &provider)
342+
added = true
340343
}
341344

342345
for _, c := range cfg.DNSSDConfigs {
@@ -401,7 +404,17 @@ func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setNam
401404
}
402405
if len(cfg.StaticConfigs) > 0 {
403406
add(setName, func() (Discoverer, error) {
404-
return &StaticProvider{cfg.StaticConfigs}, nil
407+
return &StaticProvider{TargetGroups: cfg.StaticConfigs}, nil
408+
})
409+
}
410+
if !added {
411+
// Add an empty target group to force the refresh of the corresponding
412+
// scrape pool and to notify the receiver that this target set has no
413+
// current targets.
414+
// It can happen because the combined set of SD configurations is empty
415+
// or because we fail to instantiate all the SD configurations.
416+
add(setName, func() (Discoverer, error) {
417+
return &StaticProvider{TargetGroups: []*targetgroup.Group{&targetgroup.Group{}}}, nil
405418
})
406419
}
407420
}

discovery/manager_test.go

+64-2
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ func assertEqualGroups(t *testing.T, got, expected []*targetgroup.Group, msg fun
719719
}
720720

721721
func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Group, poolKey poolKey, label string, present bool) {
722+
t.Helper()
722723
if _, ok := tSets[poolKey]; !ok {
723724
t.Fatalf("'%s' should be present in Pool keys: %v", poolKey, tSets)
724725
return
@@ -741,7 +742,7 @@ func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Grou
741742
if !present {
742743
msg = "not"
743744
}
744-
t.Fatalf("'%s' should %s be present in Targets labels: %v", label, msg, mergedTargets)
745+
t.Fatalf("%q should %s be present in Targets labels: %q", label, msg, mergedTargets)
745746
}
746747
}
747748

@@ -781,7 +782,7 @@ scrape_configs:
781782
- targets: ["foo:9090"]
782783
`
783784
if err := yaml.UnmarshalStrict([]byte(sTwo), cfg); err != nil {
784-
t.Fatalf("Unable to load YAML config sOne: %s", err)
785+
t.Fatalf("Unable to load YAML config sTwo: %s", err)
785786
}
786787
c = make(map[string]sd_config.ServiceDiscoveryConfig)
787788
for _, v := range cfg.ScrapeConfigs {
@@ -794,6 +795,67 @@ scrape_configs:
794795
verifyPresence(t, discoveryManager.targets, poolKey{setName: "prometheus", provider: "string/0"}, "{__address__=\"bar:9090\"}", false)
795796
}
796797

798+
// TestTargetSetRecreatesEmptyStaticConfigs ensures that reloading a config file after
799+
// removing all targets from the static_configs sends an update with empty targetGroups.
800+
// This is required to signal the receiver that this target set has no current targets.
801+
func TestTargetSetRecreatesEmptyStaticConfigs(t *testing.T) {
802+
cfg := &config.Config{}
803+
804+
sOne := `
805+
scrape_configs:
806+
- job_name: 'prometheus'
807+
static_configs:
808+
- targets: ["foo:9090"]
809+
`
810+
if err := yaml.UnmarshalStrict([]byte(sOne), cfg); err != nil {
811+
t.Fatalf("Unable to load YAML config sOne: %s", err)
812+
}
813+
ctx, cancel := context.WithCancel(context.Background())
814+
defer cancel()
815+
discoveryManager := NewManager(ctx, log.NewNopLogger())
816+
discoveryManager.updatert = 100 * time.Millisecond
817+
go discoveryManager.Run()
818+
819+
c := make(map[string]sd_config.ServiceDiscoveryConfig)
820+
for _, v := range cfg.ScrapeConfigs {
821+
c[v.JobName] = v.ServiceDiscoveryConfig
822+
}
823+
discoveryManager.ApplyConfig(c)
824+
825+
<-discoveryManager.SyncCh()
826+
verifyPresence(t, discoveryManager.targets, poolKey{setName: "prometheus", provider: "string/0"}, "{__address__=\"foo:9090\"}", true)
827+
828+
sTwo := `
829+
scrape_configs:
830+
- job_name: 'prometheus'
831+
static_configs:
832+
`
833+
if err := yaml.UnmarshalStrict([]byte(sTwo), cfg); err != nil {
834+
t.Fatalf("Unable to load YAML config sTwo: %s", err)
835+
}
836+
c = make(map[string]sd_config.ServiceDiscoveryConfig)
837+
for _, v := range cfg.ScrapeConfigs {
838+
c[v.JobName] = v.ServiceDiscoveryConfig
839+
}
840+
discoveryManager.ApplyConfig(c)
841+
842+
<-discoveryManager.SyncCh()
843+
844+
pkey := poolKey{setName: "prometheus", provider: "string/0"}
845+
targetGroups, ok := discoveryManager.targets[pkey]
846+
if !ok {
847+
t.Fatalf("'%v' should be present in target groups", pkey)
848+
}
849+
group, ok := targetGroups[""]
850+
if !ok {
851+
t.Fatalf("missing '' key in target groups %v", targetGroups)
852+
}
853+
854+
if len(group.Targets) != 0 {
855+
t.Fatalf("Invalid number of targets: expected 0, got %d", len(group.Targets))
856+
}
857+
}
858+
797859
func TestIdenticalConfigurationsAreCoalesced(t *testing.T) {
798860
tmpFile, err := ioutil.TempFile("", "sd")
799861
if err != nil {

0 commit comments

Comments
 (0)