discovery: send empty group on empty SD config (#4819)

* discovery: send empty group on blank SD config

Signed-off-by: Simon Pasquier <spasquie@redhat.com>

* Update comments

Signed-off-by: Simon Pasquier <spasquie@redhat.com>

* Add another comment

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
Simon Pasquier 2018-11-30 17:59:57 +01:00 committed by GitHub
parent 7b88360260
commit 8b91d39c43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 3 deletions

View file

@ -314,11 +314,13 @@ func (m *Manager) allGroups() map[string][]*targetgroup.Group {
} }
func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setName string) { func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setName string) {
var added bool
add := func(cfg interface{}, newDiscoverer func() (Discoverer, error)) { add := func(cfg interface{}, newDiscoverer func() (Discoverer, error)) {
t := reflect.TypeOf(cfg).String() t := reflect.TypeOf(cfg).String()
for _, p := range m.providers { for _, p := range m.providers {
if reflect.DeepEqual(cfg, p.config) { if reflect.DeepEqual(cfg, p.config) {
p.subs = append(p.subs, setName) p.subs = append(p.subs, setName)
added = true
return return
} }
} }
@ -337,6 +339,7 @@ func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setNam
subs: []string{setName}, subs: []string{setName},
} }
m.providers = append(m.providers, &provider) m.providers = append(m.providers, &provider)
added = true
} }
for _, c := range cfg.DNSSDConfigs { for _, c := range cfg.DNSSDConfigs {
@ -401,7 +404,17 @@ func (m *Manager) registerProviders(cfg sd_config.ServiceDiscoveryConfig, setNam
} }
if len(cfg.StaticConfigs) > 0 { if len(cfg.StaticConfigs) > 0 {
add(setName, func() (Discoverer, error) { add(setName, func() (Discoverer, error) {
return &StaticProvider{cfg.StaticConfigs}, nil return &StaticProvider{TargetGroups: cfg.StaticConfigs}, nil
})
}
if !added {
// Add an empty target group to force the refresh of the corresponding
// scrape pool and to notify the receiver that this target set has no
// current targets.
// It can happen because the combined set of SD configurations is empty
// or because we fail to instantiate all the SD configurations.
add(setName, func() (Discoverer, error) {
return &StaticProvider{TargetGroups: []*targetgroup.Group{&targetgroup.Group{}}}, nil
}) })
} }
} }

View file

@ -719,6 +719,7 @@ func assertEqualGroups(t *testing.T, got, expected []*targetgroup.Group, msg fun
} }
func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Group, poolKey poolKey, label string, present bool) { func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Group, poolKey poolKey, label string, present bool) {
t.Helper()
if _, ok := tSets[poolKey]; !ok { if _, ok := tSets[poolKey]; !ok {
t.Fatalf("'%s' should be present in Pool keys: %v", poolKey, tSets) t.Fatalf("'%s' should be present in Pool keys: %v", poolKey, tSets)
return return
@ -741,7 +742,7 @@ func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Grou
if !present { if !present {
msg = "not" msg = "not"
} }
t.Fatalf("'%s' should %s be present in Targets labels: %v", label, msg, mergedTargets) t.Fatalf("%q should %s be present in Targets labels: %q", label, msg, mergedTargets)
} }
} }
@ -781,7 +782,7 @@ scrape_configs:
- targets: ["foo:9090"] - targets: ["foo:9090"]
` `
if err := yaml.UnmarshalStrict([]byte(sTwo), cfg); err != nil { if err := yaml.UnmarshalStrict([]byte(sTwo), cfg); err != nil {
t.Fatalf("Unable to load YAML config sOne: %s", err) t.Fatalf("Unable to load YAML config sTwo: %s", err)
} }
c = make(map[string]sd_config.ServiceDiscoveryConfig) c = make(map[string]sd_config.ServiceDiscoveryConfig)
for _, v := range cfg.ScrapeConfigs { for _, v := range cfg.ScrapeConfigs {
@ -794,6 +795,67 @@ scrape_configs:
verifyPresence(t, discoveryManager.targets, poolKey{setName: "prometheus", provider: "string/0"}, "{__address__=\"bar:9090\"}", false) verifyPresence(t, discoveryManager.targets, poolKey{setName: "prometheus", provider: "string/0"}, "{__address__=\"bar:9090\"}", false)
} }
// TestTargetSetRecreatesEmptyStaticConfigs ensures that reloading a config file after
// removing all targets from the static_configs sends an update with empty targetGroups.
// This is required to signal the receiver that this target set has no current targets.
func TestTargetSetRecreatesEmptyStaticConfigs(t *testing.T) {
cfg := &config.Config{}
sOne := `
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ["foo:9090"]
`
if err := yaml.UnmarshalStrict([]byte(sOne), cfg); err != nil {
t.Fatalf("Unable to load YAML config sOne: %s", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
discoveryManager := NewManager(ctx, log.NewNopLogger())
discoveryManager.updatert = 100 * time.Millisecond
go discoveryManager.Run()
c := make(map[string]sd_config.ServiceDiscoveryConfig)
for _, v := range cfg.ScrapeConfigs {
c[v.JobName] = v.ServiceDiscoveryConfig
}
discoveryManager.ApplyConfig(c)
<-discoveryManager.SyncCh()
verifyPresence(t, discoveryManager.targets, poolKey{setName: "prometheus", provider: "string/0"}, "{__address__=\"foo:9090\"}", true)
sTwo := `
scrape_configs:
- job_name: 'prometheus'
static_configs:
`
if err := yaml.UnmarshalStrict([]byte(sTwo), cfg); err != nil {
t.Fatalf("Unable to load YAML config sTwo: %s", err)
}
c = make(map[string]sd_config.ServiceDiscoveryConfig)
for _, v := range cfg.ScrapeConfigs {
c[v.JobName] = v.ServiceDiscoveryConfig
}
discoveryManager.ApplyConfig(c)
<-discoveryManager.SyncCh()
pkey := poolKey{setName: "prometheus", provider: "string/0"}
targetGroups, ok := discoveryManager.targets[pkey]
if !ok {
t.Fatalf("'%v' should be present in target groups", pkey)
}
group, ok := targetGroups[""]
if !ok {
t.Fatalf("missing '' key in target groups %v", targetGroups)
}
if len(group.Targets) != 0 {
t.Fatalf("Invalid number of targets: expected 0, got %d", len(group.Targets))
}
}
func TestIdenticalConfigurationsAreCoalesced(t *testing.T) { func TestIdenticalConfigurationsAreCoalesced(t *testing.T) {
tmpFile, err := ioutil.TempFile("", "sd") tmpFile, err := ioutil.TempFile("", "sd")
if err != nil { if err != nil {