2016-04-13 14:08:22 +00:00
|
|
|
// Copyright 2016 The Prometheus Authors
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2016-11-21 14:51:36 +00:00
|
|
|
package file
|
2015-05-13 10:03:31 +00:00
|
|
|
|
|
|
|
import (
|
2017-10-25 04:21:42 +00:00
|
|
|
"context"
|
2015-05-13 10:03:31 +00:00
|
|
|
"io"
|
|
|
|
"os"
|
2017-07-09 04:34:50 +00:00
|
|
|
"path/filepath"
|
2015-05-13 10:03:31 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2016-01-29 14:23:11 +00:00
|
|
|
"github.com/prometheus/common/model"
|
|
|
|
|
Refactor SD configuration to remove `config` dependency (#3629)
* refactor: move targetGroup struct and CheckOverflow() to their own package
* refactor: move auth and security related structs to a utility package, fix import error in utility package
* refactor: Azure SD, remove SD struct from config
* refactor: DNS SD, remove SD struct from config into dns package
* refactor: ec2 SD, move SD struct from config into the ec2 package
* refactor: file SD, move SD struct from config to file discovery package
* refactor: gce, move SD struct from config to gce discovery package
* refactor: move HTTPClientConfig and URL into util/config, fix import error in httputil
* refactor: consul, move SD struct from config into consul discovery package
* refactor: marathon, move SD struct from config into marathon discovery package
* refactor: triton, move SD struct from config to triton discovery package, fix test
* refactor: zookeeper, move SD structs from config to zookeeper discovery package
* refactor: openstack, remove SD struct from config, move into openstack discovery package
* refactor: kubernetes, move SD struct from config into kubernetes discovery package
* refactor: notifier, use targetgroup package instead of config
* refactor: tests for file, marathon, triton SD - use targetgroup package instead of config.TargetGroup
* refactor: retrieval, use targetgroup package instead of config.TargetGroup
* refactor: storage, use config util package
* refactor: discovery manager, use targetgroup package instead of config.TargetGroup
* refactor: use HTTPClient and TLS config from configUtil instead of config
* refactor: tests, use targetgroup package instead of config.TargetGroup
* refactor: fix tagetgroup.Group pointers that were removed by mistake
* refactor: openstack, kubernetes: drop prefixes
* refactor: remove import aliases forced due to vscode bug
* refactor: move main SD struct out of config into discovery/config
* refactor: rename configUtil to config_util
* refactor: rename yamlUtil to yaml_config
* refactor: kubernetes, remove prefixes
* refactor: move the TargetGroup package to discovery/
* refactor: fix order of imports
2017-12-29 20:01:34 +00:00
|
|
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
2015-05-13 10:03:31 +00:00
|
|
|
)
|
|
|
|
|
2017-11-11 16:20:39 +00:00
|
|
|
const testDir = "fixtures"
|
|
|
|
|
2015-05-13 10:03:31 +00:00
|
|
|
func TestFileSD(t *testing.T) {
|
2017-11-11 16:20:39 +00:00
|
|
|
defer os.Remove(filepath.Join(testDir, "_test_valid.yml"))
|
|
|
|
defer os.Remove(filepath.Join(testDir, "_test_valid.json"))
|
|
|
|
defer os.Remove(filepath.Join(testDir, "_test_invalid_nil.json"))
|
|
|
|
defer os.Remove(filepath.Join(testDir, "_test_invalid_nil.yml"))
|
2017-08-15 03:10:19 +00:00
|
|
|
testFileSD(t, "valid", ".yml", true)
|
|
|
|
testFileSD(t, "valid", ".json", true)
|
|
|
|
testFileSD(t, "invalid_nil", ".json", false)
|
|
|
|
testFileSD(t, "invalid_nil", ".yml", false)
|
2015-05-13 10:03:31 +00:00
|
|
|
}
|
|
|
|
|
2017-08-15 03:10:19 +00:00
|
|
|
func testFileSD(t *testing.T, prefix, ext string, expect bool) {
|
2015-05-13 10:03:31 +00:00
|
|
|
// As interval refreshing is more of a fallback, we only want to test
|
|
|
|
// whether file watches work as expected.
|
Refactor SD configuration to remove `config` dependency (#3629)
* refactor: move targetGroup struct and CheckOverflow() to their own package
* refactor: move auth and security related structs to a utility package, fix import error in utility package
* refactor: Azure SD, remove SD struct from config
* refactor: DNS SD, remove SD struct from config into dns package
* refactor: ec2 SD, move SD struct from config into the ec2 package
* refactor: file SD, move SD struct from config to file discovery package
* refactor: gce, move SD struct from config to gce discovery package
* refactor: move HTTPClientConfig and URL into util/config, fix import error in httputil
* refactor: consul, move SD struct from config into consul discovery package
* refactor: marathon, move SD struct from config into marathon discovery package
* refactor: triton, move SD struct from config to triton discovery package, fix test
* refactor: zookeeper, move SD structs from config to zookeeper discovery package
* refactor: openstack, remove SD struct from config, move into openstack discovery package
* refactor: kubernetes, move SD struct from config into kubernetes discovery package
* refactor: notifier, use targetgroup package instead of config
* refactor: tests for file, marathon, triton SD - use targetgroup package instead of config.TargetGroup
* refactor: retrieval, use targetgroup package instead of config.TargetGroup
* refactor: storage, use config util package
* refactor: discovery manager, use targetgroup package instead of config.TargetGroup
* refactor: use HTTPClient and TLS config from configUtil instead of config
* refactor: tests, use targetgroup package instead of config.TargetGroup
* refactor: fix tagetgroup.Group pointers that were removed by mistake
* refactor: openstack, kubernetes: drop prefixes
* refactor: remove import aliases forced due to vscode bug
* refactor: move main SD struct out of config into discovery/config
* refactor: rename configUtil to config_util
* refactor: rename yamlUtil to yaml_config
* refactor: kubernetes, remove prefixes
* refactor: move the TargetGroup package to discovery/
* refactor: fix order of imports
2017-12-29 20:01:34 +00:00
|
|
|
var conf SDConfig
|
2017-11-11 16:20:39 +00:00
|
|
|
conf.Files = []string{filepath.Join(testDir, "_*"+ext)}
|
2016-01-29 14:23:11 +00:00
|
|
|
conf.RefreshInterval = model.Duration(1 * time.Hour)
|
2015-05-15 12:54:29 +00:00
|
|
|
|
2015-08-10 14:44:32 +00:00
|
|
|
var (
|
2017-08-11 18:45:52 +00:00
|
|
|
fsd = NewDiscovery(&conf, nil)
|
Refactor SD configuration to remove `config` dependency (#3629)
* refactor: move targetGroup struct and CheckOverflow() to their own package
* refactor: move auth and security related structs to a utility package, fix import error in utility package
* refactor: Azure SD, remove SD struct from config
* refactor: DNS SD, remove SD struct from config into dns package
* refactor: ec2 SD, move SD struct from config into the ec2 package
* refactor: file SD, move SD struct from config to file discovery package
* refactor: gce, move SD struct from config to gce discovery package
* refactor: move HTTPClientConfig and URL into util/config, fix import error in httputil
* refactor: consul, move SD struct from config into consul discovery package
* refactor: marathon, move SD struct from config into marathon discovery package
* refactor: triton, move SD struct from config to triton discovery package, fix test
* refactor: zookeeper, move SD structs from config to zookeeper discovery package
* refactor: openstack, remove SD struct from config, move into openstack discovery package
* refactor: kubernetes, move SD struct from config into kubernetes discovery package
* refactor: notifier, use targetgroup package instead of config
* refactor: tests for file, marathon, triton SD - use targetgroup package instead of config.TargetGroup
* refactor: retrieval, use targetgroup package instead of config.TargetGroup
* refactor: storage, use config util package
* refactor: discovery manager, use targetgroup package instead of config.TargetGroup
* refactor: use HTTPClient and TLS config from configUtil instead of config
* refactor: tests, use targetgroup package instead of config.TargetGroup
* refactor: fix tagetgroup.Group pointers that were removed by mistake
* refactor: openstack, kubernetes: drop prefixes
* refactor: remove import aliases forced due to vscode bug
* refactor: move main SD struct out of config into discovery/config
* refactor: rename configUtil to config_util
* refactor: rename yamlUtil to yaml_config
* refactor: kubernetes, remove prefixes
* refactor: move the TargetGroup package to discovery/
* refactor: fix order of imports
2017-12-29 20:01:34 +00:00
|
|
|
ch = make(chan []*targetgroup.Group)
|
2016-02-18 16:26:27 +00:00
|
|
|
ctx, cancel = context.WithCancel(context.Background())
|
2015-08-10 14:44:32 +00:00
|
|
|
)
|
2016-02-18 16:26:27 +00:00
|
|
|
go fsd.Run(ctx, ch)
|
2015-05-13 10:03:31 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(25 * time.Millisecond):
|
|
|
|
// Expected.
|
2016-02-18 16:26:27 +00:00
|
|
|
case tgs := <-ch:
|
|
|
|
t.Fatalf("Unexpected target groups in file discovery: %s", tgs)
|
2015-05-13 10:03:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 16:20:39 +00:00
|
|
|
// To avoid empty group struct sent from the discovery caused by invalid fsnotify updates,
|
|
|
|
// drain the channel until we are ready with the test files.
|
2017-11-13 11:38:46 +00:00
|
|
|
fileReady := make(chan struct{})
|
|
|
|
drainReady := make(chan struct{})
|
2017-11-11 16:20:39 +00:00
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ch:
|
2017-11-13 11:38:46 +00:00
|
|
|
case <-fileReady:
|
|
|
|
close(drainReady)
|
2017-11-11 16:20:39 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
newf, err := os.Create(filepath.Join(testDir, "_test_"+prefix+ext))
|
2015-05-13 10:03:31 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-12-02 13:52:43 +00:00
|
|
|
defer newf.Close()
|
2015-05-13 10:03:31 +00:00
|
|
|
|
2017-11-11 16:20:39 +00:00
|
|
|
f, err := os.Open(filepath.Join(testDir, prefix+ext))
|
2015-05-13 10:03:31 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
_, err = io.Copy(newf, f)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-11-11 16:20:39 +00:00
|
|
|
|
2017-12-01 17:32:27 +00:00
|
|
|
// Test file is ready so stop draining the discovery channel.
|
|
|
|
// It contains two target groups.
|
2017-11-13 11:38:46 +00:00
|
|
|
close(fileReady)
|
|
|
|
<-drainReady
|
2017-12-01 17:32:27 +00:00
|
|
|
newf.WriteString(" ") // One last meaningless write to trigger fsnotify and a new loop of the discovery service.
|
2015-05-13 10:03:31 +00:00
|
|
|
|
2016-03-07 14:39:18 +00:00
|
|
|
timeout := time.After(15 * time.Second)
|
|
|
|
retry:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-timeout:
|
2017-08-15 03:10:19 +00:00
|
|
|
if expect {
|
|
|
|
t.Fatalf("Expected new target group but got none")
|
|
|
|
} else {
|
2017-12-01 17:32:27 +00:00
|
|
|
// Invalid type fsd should always break down.
|
2017-08-15 03:10:19 +00:00
|
|
|
break retry
|
|
|
|
}
|
2016-03-07 14:39:18 +00:00
|
|
|
case tgs := <-ch:
|
2017-08-15 03:10:19 +00:00
|
|
|
if !expect {
|
|
|
|
t.Fatalf("Unexpected target groups %s, we expected a failure here.", tgs)
|
|
|
|
}
|
|
|
|
|
2016-03-07 14:39:18 +00:00
|
|
|
if len(tgs) != 2 {
|
|
|
|
continue retry // Potentially a partial write, just retry.
|
|
|
|
}
|
|
|
|
tg := tgs[0]
|
2016-02-18 16:26:27 +00:00
|
|
|
|
2016-03-07 14:39:18 +00:00
|
|
|
if _, ok := tg.Labels["foo"]; !ok {
|
|
|
|
t.Fatalf("Label not parsed")
|
|
|
|
}
|
2017-11-11 16:20:39 +00:00
|
|
|
if tg.String() != filepath.Join(testDir, "_test_"+prefix+ext+":0") {
|
2016-03-07 14:39:18 +00:00
|
|
|
t.Fatalf("Unexpected target group %s", tg)
|
|
|
|
}
|
2016-02-18 16:26:27 +00:00
|
|
|
|
2016-03-07 14:39:18 +00:00
|
|
|
tg = tgs[1]
|
2017-11-11 16:20:39 +00:00
|
|
|
if tg.String() != filepath.Join(testDir, "_test_"+prefix+ext+":1") {
|
2016-03-07 14:39:18 +00:00
|
|
|
t.Fatalf("Unexpected target groups %s", tg)
|
|
|
|
}
|
|
|
|
break retry
|
2015-05-13 10:03:31 +00:00
|
|
|
}
|
|
|
|
}
|
2016-02-18 16:26:27 +00:00
|
|
|
|
2015-05-13 10:03:31 +00:00
|
|
|
// Based on unknown circumstances, sometimes fsnotify will trigger more events in
|
|
|
|
// some runs (which might be empty, chains of different operations etc.).
|
|
|
|
// We have to drain those (as the target manager would) to avoid deadlocking and must
|
|
|
|
// not try to make sense of it all...
|
2015-08-26 00:58:59 +00:00
|
|
|
drained := make(chan struct{})
|
2015-05-13 10:03:31 +00:00
|
|
|
go func() {
|
2016-11-18 09:55:29 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case tgs := <-ch:
|
|
|
|
// Below we will change the file to a bad syntax. Previously extracted target
|
|
|
|
// groups must not be deleted via sending an empty target group.
|
|
|
|
if len(tgs[0].Targets) == 0 {
|
|
|
|
t.Errorf("Unexpected empty target groups received: %s", tgs)
|
|
|
|
}
|
|
|
|
case <-time.After(500 * time.Millisecond):
|
2017-11-11 16:20:39 +00:00
|
|
|
close(drained)
|
|
|
|
return
|
2015-05-13 10:03:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2017-11-11 16:20:39 +00:00
|
|
|
newf, err = os.Create(filepath.Join(testDir, "_test.new"))
|
2015-05-13 10:03:31 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-05-23 19:20:39 +00:00
|
|
|
defer os.Remove(newf.Name())
|
|
|
|
|
2015-05-13 10:03:31 +00:00
|
|
|
if _, err := newf.Write([]byte("]gibberish\n][")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
newf.Close()
|
2015-05-23 19:20:39 +00:00
|
|
|
|
2017-11-11 16:20:39 +00:00
|
|
|
os.Rename(newf.Name(), filepath.Join(testDir, "_test_"+prefix+ext))
|
2015-05-23 19:20:39 +00:00
|
|
|
|
2016-02-18 16:26:27 +00:00
|
|
|
cancel()
|
2015-08-26 00:58:59 +00:00
|
|
|
<-drained
|
2015-05-13 10:03:31 +00:00
|
|
|
}
|