From 272eaf84077d913e519ade011ab014ac8f9322a4 Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Mon, 24 Jul 2017 11:39:40 -0700 Subject: [PATCH] e2e: test /metrics endpoints with health info Signed-off-by: Gyu-Ho Lee --- e2e/cluster_proxy_test.go | 10 +++++++++ e2e/cluster_test.go | 13 ++++++++++- e2e/etcd_process.go | 7 ++++-- e2e/metrics_test.go | 46 +++++++++++++++++++++++++++++++++++++++ e2e/v2_curl_test.go | 5 +++++ 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 e2e/metrics_test.go diff --git a/e2e/cluster_proxy_test.go b/e2e/cluster_proxy_test.go index a2bab6f587e9..608d7ea96deb 100644 --- a/e2e/cluster_proxy_test.go +++ b/e2e/cluster_proxy_test.go @@ -54,6 +54,9 @@ func (p *proxyEtcdProcess) Config() *etcdServerProcessConfig { return p.etcdProc func (p *proxyEtcdProcess) EndpointsV2() []string { return p.proxyV2.endpoints() } func (p *proxyEtcdProcess) EndpointsV3() []string { return p.proxyV3.endpoints() } +func (p *proxyEtcdProcess) EndpointsMetrics() []string { + panic("not implemented; proxy doesn't provide health information") +} func (p *proxyEtcdProcess) Start() error { if err := p.etcdProc.Start(); err != nil { @@ -113,6 +116,7 @@ type proxyProc struct { execPath string args []string ep string + murl string donec chan struct{} proc *expect.ExpectProcess @@ -232,6 +236,11 @@ func newProxyV3Proc(cfg *etcdServerProcessConfig) *proxyV3Proc { // pass-through member RPCs "--advertise-client-url", "", } + murl := "" + if cfg.murl != "" { + murl = proxyListenURL(cfg, 4) + args = append(args, "--metrics-addr", murl) + } tlsArgs := []string{} for i := 0; i < len(cfg.tlsArgs); i++ { switch cfg.tlsArgs[i] { @@ -258,6 +267,7 @@ func newProxyV3Proc(cfg *etcdServerProcessConfig) *proxyV3Proc { execPath: cfg.execPath, args: append(args, tlsArgs...), ep: listenAddr, + murl: murl, donec: make(chan struct{}), }, } diff --git a/e2e/cluster_test.go b/e2e/cluster_test.go index ebd2c265d7e0..991fb13dce95 100644 --- a/e2e/cluster_test.go +++ b/e2e/cluster_test.go @@ -101,6 +101,8 @@ type etcdProcessClusterConfig struct { baseScheme string basePort int + metricsURLScheme string + snapCount int // default is 10000 clientTLS clientConnType @@ -175,7 +177,7 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs() []*etcdServerPro for i := 0; i < cfg.clusterSize; i++ { var curls []string var curl, curltls string - port := cfg.basePort + 4*i + port := cfg.basePort + 5*i curlHost := fmt.Sprintf("localhost:%d", port) switch cfg.clientTLS { @@ -221,6 +223,14 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs() []*etcdServerPro if cfg.noStrictReconfig { args = append(args, "--strict-reconfig-check=false") } + var murl string + if cfg.metricsURLScheme != "" { + murl = (&url.URL{ + Scheme: cfg.metricsURLScheme, + Host: fmt.Sprintf("localhost:%d", port+2), + }).String() + args = append(args, "--listen-metrics-urls", murl) + } args = append(args, cfg.tlsArgs()...) etcdCfgs[i] = &etcdServerProcessConfig{ @@ -232,6 +242,7 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs() []*etcdServerPro name: name, purl: purl, acurl: curl, + murl: murl, initialToken: cfg.initialToken, } } diff --git a/e2e/etcd_process.go b/e2e/etcd_process.go index cfde0255a6e6..3ae710563c43 100644 --- a/e2e/etcd_process.go +++ b/e2e/etcd_process.go @@ -29,6 +29,7 @@ var etcdServerReadyLines = []string{"enabled capabilities for version", "publish type etcdProcess interface { EndpointsV2() []string EndpointsV3() []string + EndpointsMetrics() []string Start() error Restart() error @@ -57,6 +58,7 @@ type etcdServerProcessConfig struct { purl url.URL acurl string + murl string initialToken string initialCluster string @@ -74,8 +76,9 @@ func newEtcdServerProcess(cfg *etcdServerProcessConfig) (*etcdServerProcess, err return &etcdServerProcess{cfg: cfg, donec: make(chan struct{})}, nil } -func (ep *etcdServerProcess) EndpointsV2() []string { return []string{ep.cfg.acurl} } -func (ep *etcdServerProcess) EndpointsV3() []string { return ep.EndpointsV2() } +func (ep *etcdServerProcess) EndpointsV2() []string { return []string{ep.cfg.acurl} } +func (ep *etcdServerProcess) EndpointsV3() []string { return ep.EndpointsV2() } +func (ep *etcdServerProcess) EndpointsMetrics() []string { return []string{ep.cfg.murl} } func (ep *etcdServerProcess) Start() error { if ep.proc != nil { diff --git a/e2e/metrics_test.go b/e2e/metrics_test.go new file mode 100644 index 000000000000..3b770b3db874 --- /dev/null +++ b/e2e/metrics_test.go @@ -0,0 +1,46 @@ +// Copyright 2017 The etcd 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. + +// +build !cluster_proxy + +package e2e + +import ( + "testing" + + "github.com/coreos/etcd/pkg/testutil" +) + +func TestV3MetricsSecure(t *testing.T) { testV3Metrics(t, "https") } +func TestV3MetricsInsecure(t *testing.T) { testV3Metrics(t, "http") } +func testV3Metrics(t *testing.T, metricsScheme string) { + defer testutil.AfterTest(t) + + cfg := configTLS + cfg.metricsURLScheme = metricsScheme + + epc, err := newEtcdProcessCluster(&cfg) + if err != nil { + t.Fatalf("could not start etcd process cluster (%v)", err) + } + defer func() { + if cerr := epc.Close(); err != nil { + t.Fatalf("error closing etcd processes (%v)", cerr) + } + }() + + if err = cURLGet(epc, cURLReq{endpoint: "/metrics", expected: `health true`, metricsURL: true}); err != nil { + t.Fatalf("failed get with curl (%v)", err) + } +} diff --git a/e2e/v2_curl_test.go b/e2e/v2_curl_test.go index 2322a8549f6a..2d044adca868 100644 --- a/e2e/v2_curl_test.go +++ b/e2e/v2_curl_test.go @@ -125,6 +125,8 @@ type cURLReq struct { value string expected string header string + + metricsURL bool } // cURLPrefixArgs builds the beginning of a curl command for a given key @@ -143,6 +145,9 @@ func cURLPrefixArgs(clus *etcdProcessCluster, method string, req cURLReq) []stri } else if clus.cfg.clientTLS == clientTLS { cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath) } + if req.metricsURL { + acurl = clus.procs[rand.Intn(clus.cfg.clusterSize)].EndpointsMetrics()[0] + } ep := acurl + req.endpoint if req.username != "" || req.password != "" {