github.com/go-follow/prometheus@v2.5.0+incompatible/discovery/consul/consul_test.go (about)

     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 consul
    15  
    16  import (
    17  	"context"
    18  	"testing"
    19  	"time"
    20  
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"net/url"
    24  
    25  	"github.com/go-kit/kit/log"
    26  	"github.com/prometheus/common/model"
    27  	"github.com/prometheus/prometheus/discovery/targetgroup"
    28  	"github.com/prometheus/prometheus/util/testutil"
    29  )
    30  
    31  func TestConfiguredService(t *testing.T) {
    32  	conf := &SDConfig{
    33  		Services: []string{"configuredServiceName"}}
    34  	consulDiscovery, err := NewDiscovery(conf, nil)
    35  
    36  	if err != nil {
    37  		t.Errorf("Unexpected error when initialising discovery %v", err)
    38  	}
    39  	if !consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
    40  		t.Errorf("Expected service %s to be watched", "configuredServiceName")
    41  	}
    42  	if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
    43  		t.Errorf("Expected service %s to not be watched", "nonConfiguredServiceName")
    44  	}
    45  }
    46  
    47  func TestConfiguredServiceWithTag(t *testing.T) {
    48  	conf := &SDConfig{
    49  		Services:   []string{"configuredServiceName"},
    50  		ServiceTag: "http",
    51  	}
    52  	consulDiscovery, err := NewDiscovery(conf, nil)
    53  
    54  	if err != nil {
    55  		t.Errorf("Unexpected error when initialising discovery %v", err)
    56  	}
    57  	if consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
    58  		t.Errorf("Expected service %s to not be watched without tag", "configuredServiceName")
    59  	}
    60  	if !consulDiscovery.shouldWatch("configuredServiceName", []string{"http"}) {
    61  		t.Errorf("Expected service %s to be watched with tag %s", "configuredServiceName", "http")
    62  	}
    63  	if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
    64  		t.Errorf("Expected service %s to not be watched without tag", "nonConfiguredServiceName")
    65  	}
    66  	if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{"http"}) {
    67  		t.Errorf("Expected service %s to not be watched with tag %s", "nonConfiguredServiceName", "http")
    68  	}
    69  }
    70  
    71  func TestNonConfiguredService(t *testing.T) {
    72  	conf := &SDConfig{}
    73  	consulDiscovery, err := NewDiscovery(conf, nil)
    74  
    75  	if err != nil {
    76  		t.Errorf("Unexpected error when initialising discovery %v", err)
    77  	}
    78  	if !consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
    79  		t.Errorf("Expected service %s to be watched", "nonConfiguredServiceName")
    80  	}
    81  }
    82  
    83  const (
    84  	AgentAnswer       = `{"Config": {"Datacenter": "test-dc"}}`
    85  	ServiceTestAnswer = `[{
    86  "ID": "b78c2e48-5ef3-1814-31b8-0d880f50471e",
    87  "Node": "node1",
    88  "Address": "1.1.1.1",
    89  "Datacenter": "test-dc",
    90  "NodeMeta": {"rack_name": "2304"},
    91  "ServiceID": "test",
    92  "ServiceName": "test",
    93  "ServiceMeta": {"version":"1.0.0","environment":"stagging"},
    94  "ServiceTags": ["tag1"],
    95  "ServicePort": 3341,
    96  "CreateIndex": 1,
    97  "ModifyIndex": 1
    98  }]`
    99  	ServicesTestAnswer = `{"test": ["tag1"], "other": ["tag2"]}`
   100  )
   101  
   102  func newServer(t *testing.T) (*httptest.Server, *SDConfig) {
   103  	// github.com/hashicorp/consul/testutil/ would be nice but it needs a local consul binary.
   104  	stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   105  		response := ""
   106  		switch r.URL.String() {
   107  		case "/v1/agent/self":
   108  			response = AgentAnswer
   109  		case "/v1/catalog/service/test?node-meta=rack_name%3A2304&stale=&tag=tag1&wait=30000ms":
   110  			response = ServiceTestAnswer
   111  		case "/v1/catalog/service/test?wait=30000ms":
   112  			response = ServiceTestAnswer
   113  		case "/v1/catalog/service/other?wait=30000ms":
   114  			response = `[]`
   115  		case "/v1/catalog/services?node-meta=rack_name%3A2304&stale=&wait=30000ms":
   116  			response = ServicesTestAnswer
   117  		case "/v1/catalog/services?wait=30000ms":
   118  			response = ServicesTestAnswer
   119  		case "/v1/catalog/services?index=1&node-meta=rack_name%3A2304&stale=&wait=30000ms":
   120  			time.Sleep(5 * time.Second)
   121  			response = ServicesTestAnswer
   122  		case "/v1/catalog/services?index=1&wait=30000ms":
   123  			time.Sleep(5 * time.Second)
   124  			response = ServicesTestAnswer
   125  		default:
   126  			t.Errorf("Unhandeld consul call: %s", r.URL)
   127  		}
   128  		w.Header().Add("X-Consul-Index", "1")
   129  		w.Write([]byte(response))
   130  	}))
   131  	stuburl, err := url.Parse(stub.URL)
   132  	testutil.Ok(t, err)
   133  
   134  	config := &SDConfig{
   135  		Server:          stuburl.Host,
   136  		Token:           "fake-token",
   137  		RefreshInterval: model.Duration(1 * time.Second),
   138  	}
   139  	return stub, config
   140  }
   141  
   142  func newDiscovery(t *testing.T, config *SDConfig) *Discovery {
   143  	logger := log.NewNopLogger()
   144  	d, err := NewDiscovery(config, logger)
   145  	testutil.Ok(t, err)
   146  	return d
   147  }
   148  
   149  func checkOneTarget(t *testing.T, tg []*targetgroup.Group) {
   150  	testutil.Equals(t, 1, len(tg))
   151  	target := tg[0]
   152  	testutil.Equals(t, "test-dc", string(target.Labels["__meta_consul_dc"]))
   153  	testutil.Equals(t, target.Source, string(target.Labels["__meta_consul_service"]))
   154  	if target.Source == "test" {
   155  		// test service should have one node.
   156  		testutil.Assert(t, len(target.Targets) > 0, "Test service should have one node")
   157  	}
   158  }
   159  
   160  // Watch all the services in the catalog.
   161  func TestAllServices(t *testing.T) {
   162  	stub, config := newServer(t)
   163  	defer stub.Close()
   164  
   165  	d := newDiscovery(t, config)
   166  
   167  	ctx, cancel := context.WithCancel(context.Background())
   168  	ch := make(chan []*targetgroup.Group)
   169  	go d.Run(ctx, ch)
   170  	checkOneTarget(t, <-ch)
   171  	checkOneTarget(t, <-ch)
   172  	cancel()
   173  }
   174  
   175  // Watch only the test service.
   176  func TestOneService(t *testing.T) {
   177  	stub, config := newServer(t)
   178  	defer stub.Close()
   179  
   180  	config.Services = []string{"test"}
   181  	d := newDiscovery(t, config)
   182  
   183  	ctx, cancel := context.WithCancel(context.Background())
   184  	ch := make(chan []*targetgroup.Group)
   185  	go d.Run(ctx, ch)
   186  	checkOneTarget(t, <-ch)
   187  	cancel()
   188  }
   189  
   190  // Watch the test service with a specific tag and node-meta.
   191  func TestAllOptions(t *testing.T) {
   192  	stub, config := newServer(t)
   193  	defer stub.Close()
   194  
   195  	config.Services = []string{"test"}
   196  	config.NodeMeta = map[string]string{"rack_name": "2304"}
   197  	config.ServiceTag = "tag1"
   198  	config.AllowStale = true
   199  	config.Token = "fake-token"
   200  
   201  	d := newDiscovery(t, config)
   202  
   203  	ctx, cancel := context.WithCancel(context.Background())
   204  	ch := make(chan []*targetgroup.Group)
   205  	go d.Run(ctx, ch)
   206  	checkOneTarget(t, <-ch)
   207  	cancel()
   208  }