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 }