2017-03-15 01:33:53 -07:00
|
|
|
// Copyright 2015 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.
|
|
|
|
|
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
2018-04-27 05:11:16 -07:00
|
|
|
"context"
|
2017-03-15 01:33:53 -07:00
|
|
|
"testing"
|
2018-04-27 05:11:16 -07:00
|
|
|
"time"
|
2018-03-23 07:48:43 -07:00
|
|
|
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"net/url"
|
|
|
|
|
|
|
|
"github.com/go-kit/kit/log"
|
|
|
|
"github.com/prometheus/common/model"
|
|
|
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
2018-04-27 05:11:16 -07:00
|
|
|
"github.com/prometheus/prometheus/util/testutil"
|
2017-03-15 01:33:53 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestConfiguredService(t *testing.T) {
|
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 12:01:34 -08:00
|
|
|
conf := &SDConfig{
|
2017-03-15 01:33:53 -07:00
|
|
|
Services: []string{"configuredServiceName"}}
|
2017-08-11 11:45:52 -07:00
|
|
|
consulDiscovery, err := NewDiscovery(conf, nil)
|
2017-03-15 01:33:53 -07:00
|
|
|
|
|
|
|
if err != nil {
|
2018-11-27 08:44:29 -08:00
|
|
|
t.Errorf("Unexpected error when initializing discovery %v", err)
|
2017-03-15 01:33:53 -07:00
|
|
|
}
|
2018-03-23 07:48:43 -07:00
|
|
|
if !consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
|
2017-03-15 01:33:53 -07:00
|
|
|
t.Errorf("Expected service %s to be watched", "configuredServiceName")
|
|
|
|
}
|
2018-03-23 07:48:43 -07:00
|
|
|
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
2017-03-15 01:33:53 -07:00
|
|
|
t.Errorf("Expected service %s to not be watched", "nonConfiguredServiceName")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-23 07:48:43 -07:00
|
|
|
func TestConfiguredServiceWithTag(t *testing.T) {
|
|
|
|
conf := &SDConfig{
|
|
|
|
Services: []string{"configuredServiceName"},
|
|
|
|
ServiceTag: "http",
|
|
|
|
}
|
|
|
|
consulDiscovery, err := NewDiscovery(conf, nil)
|
|
|
|
|
|
|
|
if err != nil {
|
2018-11-27 08:44:29 -08:00
|
|
|
t.Errorf("Unexpected error when initializing discovery %v", err)
|
2018-03-23 07:48:43 -07:00
|
|
|
}
|
|
|
|
if consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
|
|
|
|
t.Errorf("Expected service %s to not be watched without tag", "configuredServiceName")
|
|
|
|
}
|
|
|
|
if !consulDiscovery.shouldWatch("configuredServiceName", []string{"http"}) {
|
|
|
|
t.Errorf("Expected service %s to be watched with tag %s", "configuredServiceName", "http")
|
|
|
|
}
|
|
|
|
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
|
|
|
t.Errorf("Expected service %s to not be watched without tag", "nonConfiguredServiceName")
|
|
|
|
}
|
|
|
|
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{"http"}) {
|
|
|
|
t.Errorf("Expected service %s to not be watched with tag %s", "nonConfiguredServiceName", "http")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 01:33:53 -07:00
|
|
|
func TestNonConfiguredService(t *testing.T) {
|
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 12:01:34 -08:00
|
|
|
conf := &SDConfig{}
|
2017-08-11 11:45:52 -07:00
|
|
|
consulDiscovery, err := NewDiscovery(conf, nil)
|
2017-03-15 01:33:53 -07:00
|
|
|
|
|
|
|
if err != nil {
|
2018-11-27 08:44:29 -08:00
|
|
|
t.Errorf("Unexpected error when initializing discovery %v", err)
|
2017-03-15 01:33:53 -07:00
|
|
|
}
|
2018-03-23 07:48:43 -07:00
|
|
|
if !consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
2017-03-15 01:33:53 -07:00
|
|
|
t.Errorf("Expected service %s to be watched", "nonConfiguredServiceName")
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 07:48:43 -07:00
|
|
|
|
|
|
|
const (
|
|
|
|
AgentAnswer = `{"Config": {"Datacenter": "test-dc"}}`
|
|
|
|
ServiceTestAnswer = `[{
|
|
|
|
"ID": "b78c2e48-5ef3-1814-31b8-0d880f50471e",
|
|
|
|
"Node": "node1",
|
|
|
|
"Address": "1.1.1.1",
|
|
|
|
"Datacenter": "test-dc",
|
2018-12-18 02:51:05 -08:00
|
|
|
"TaggedAddresses": {"lan":"192.168.10.10","wan":"10.0.10.10"},
|
2018-03-23 07:48:43 -07:00
|
|
|
"NodeMeta": {"rack_name": "2304"},
|
|
|
|
"ServiceID": "test",
|
|
|
|
"ServiceName": "test",
|
2018-07-17 21:06:56 -07:00
|
|
|
"ServiceMeta": {"version":"1.0.0","environment":"stagging"},
|
2018-03-23 07:48:43 -07:00
|
|
|
"ServiceTags": ["tag1"],
|
|
|
|
"ServicePort": 3341,
|
|
|
|
"CreateIndex": 1,
|
|
|
|
"ModifyIndex": 1
|
|
|
|
}]`
|
|
|
|
ServicesTestAnswer = `{"test": ["tag1"], "other": ["tag2"]}`
|
|
|
|
)
|
|
|
|
|
|
|
|
func newServer(t *testing.T) (*httptest.Server, *SDConfig) {
|
|
|
|
// github.com/hashicorp/consul/testutil/ would be nice but it needs a local consul binary.
|
|
|
|
stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
response := ""
|
|
|
|
switch r.URL.String() {
|
|
|
|
case "/v1/agent/self":
|
|
|
|
response = AgentAnswer
|
|
|
|
case "/v1/catalog/service/test?node-meta=rack_name%3A2304&stale=&tag=tag1&wait=30000ms":
|
|
|
|
response = ServiceTestAnswer
|
|
|
|
case "/v1/catalog/service/test?wait=30000ms":
|
|
|
|
response = ServiceTestAnswer
|
|
|
|
case "/v1/catalog/service/other?wait=30000ms":
|
|
|
|
response = `[]`
|
|
|
|
case "/v1/catalog/services?node-meta=rack_name%3A2304&stale=&wait=30000ms":
|
|
|
|
response = ServicesTestAnswer
|
|
|
|
case "/v1/catalog/services?wait=30000ms":
|
|
|
|
response = ServicesTestAnswer
|
|
|
|
case "/v1/catalog/services?index=1&node-meta=rack_name%3A2304&stale=&wait=30000ms":
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
response = ServicesTestAnswer
|
|
|
|
case "/v1/catalog/services?index=1&wait=30000ms":
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
response = ServicesTestAnswer
|
|
|
|
default:
|
|
|
|
t.Errorf("Unhandeld consul call: %s", r.URL)
|
|
|
|
}
|
|
|
|
w.Header().Add("X-Consul-Index", "1")
|
|
|
|
w.Write([]byte(response))
|
|
|
|
}))
|
2018-04-27 05:11:16 -07:00
|
|
|
stuburl, err := url.Parse(stub.URL)
|
|
|
|
testutil.Ok(t, err)
|
2018-03-23 07:48:43 -07:00
|
|
|
|
|
|
|
config := &SDConfig{
|
2018-04-27 05:11:16 -07:00
|
|
|
Server: stuburl.Host,
|
2018-03-23 07:48:43 -07:00
|
|
|
Token: "fake-token",
|
|
|
|
RefreshInterval: model.Duration(1 * time.Second),
|
|
|
|
}
|
|
|
|
return stub, config
|
|
|
|
}
|
|
|
|
|
|
|
|
func newDiscovery(t *testing.T, config *SDConfig) *Discovery {
|
|
|
|
logger := log.NewNopLogger()
|
|
|
|
d, err := NewDiscovery(config, logger)
|
2018-04-27 05:11:16 -07:00
|
|
|
testutil.Ok(t, err)
|
2018-03-23 07:48:43 -07:00
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkOneTarget(t *testing.T, tg []*targetgroup.Group) {
|
2018-04-27 05:11:16 -07:00
|
|
|
testutil.Equals(t, 1, len(tg))
|
2018-03-23 07:48:43 -07:00
|
|
|
target := tg[0]
|
2018-04-27 05:11:16 -07:00
|
|
|
testutil.Equals(t, "test-dc", string(target.Labels["__meta_consul_dc"]))
|
|
|
|
testutil.Equals(t, target.Source, string(target.Labels["__meta_consul_service"]))
|
2018-03-23 07:48:43 -07:00
|
|
|
if target.Source == "test" {
|
|
|
|
// test service should have one node.
|
2018-04-27 05:11:16 -07:00
|
|
|
testutil.Assert(t, len(target.Targets) > 0, "Test service should have one node")
|
2018-03-23 07:48:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watch all the services in the catalog.
|
|
|
|
func TestAllServices(t *testing.T) {
|
|
|
|
stub, config := newServer(t)
|
|
|
|
defer stub.Close()
|
|
|
|
|
|
|
|
d := newDiscovery(t, config)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
ch := make(chan []*targetgroup.Group)
|
|
|
|
go d.Run(ctx, ch)
|
|
|
|
checkOneTarget(t, <-ch)
|
|
|
|
checkOneTarget(t, <-ch)
|
|
|
|
cancel()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watch only the test service.
|
|
|
|
func TestOneService(t *testing.T) {
|
|
|
|
stub, config := newServer(t)
|
|
|
|
defer stub.Close()
|
|
|
|
|
|
|
|
config.Services = []string{"test"}
|
|
|
|
d := newDiscovery(t, config)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
ch := make(chan []*targetgroup.Group)
|
|
|
|
go d.Run(ctx, ch)
|
|
|
|
checkOneTarget(t, <-ch)
|
|
|
|
cancel()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watch the test service with a specific tag and node-meta.
|
|
|
|
func TestAllOptions(t *testing.T) {
|
|
|
|
stub, config := newServer(t)
|
|
|
|
defer stub.Close()
|
|
|
|
|
|
|
|
config.Services = []string{"test"}
|
|
|
|
config.NodeMeta = map[string]string{"rack_name": "2304"}
|
|
|
|
config.ServiceTag = "tag1"
|
|
|
|
config.AllowStale = true
|
|
|
|
config.Token = "fake-token"
|
|
|
|
|
|
|
|
d := newDiscovery(t, config)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
ch := make(chan []*targetgroup.Group)
|
|
|
|
go d.Run(ctx, ch)
|
|
|
|
checkOneTarget(t, <-ch)
|
|
|
|
cancel()
|
|
|
|
}
|