github.com/jonaz/heapster@v1.3.0-beta.0.0.20170208112634-cd3c15ca3d29/metrics/sinks/opentsdb/driver_test.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package opentsdb 16 17 import ( 18 "fmt" 19 "net/url" 20 "testing" 21 "time" 22 23 opentsdb "github.com/bluebreezecf/opentsdb-goclient/client" 24 opentsdbcfg "github.com/bluebreezecf/opentsdb-goclient/config" 25 "github.com/stretchr/testify/assert" 26 "k8s.io/heapster/metrics/core" 27 ) 28 29 var ( 30 fakeOpenTSDBHost = "192.168.1.8:823" 31 fakeNodeIp = "192.168.1.23" 32 fakePodName = "redis-test" 33 fakePodUid = "redis-test-uid" 34 fakeLabel = map[string]string{ 35 "name": "redis", 36 "io.kubernetes.pod.name": "default/redis-test", 37 "pod_id": fakePodUid, 38 "pod_namespace": "default", 39 "pod_name": fakePodName, 40 "container_name": "redis", 41 "container_base_image": "kubernetes/redis:v1", 42 "namespace_id": "namespace-test-uid", 43 "host_id": fakeNodeIp, 44 } 45 errorPingFailed = fmt.Errorf("Failed to connect the target opentsdb.") 46 errorPutFailed = fmt.Errorf("The target opentsdb gets error and failed to store the datapoints.") 47 ) 48 49 type fakeOpenTSDBClient struct { 50 successfulPing bool 51 successfulPut bool 52 receivedDataPoints []opentsdb.DataPoint 53 } 54 55 func (client *fakeOpenTSDBClient) Ping() error { 56 if client.successfulPing { 57 return nil 58 } 59 return errorPingFailed 60 } 61 62 func (client *fakeOpenTSDBClient) Put(datapoints []opentsdb.DataPoint, queryParam string) (*opentsdb.PutResponse, error) { 63 if !client.successfulPut { 64 return nil, errorPutFailed 65 } 66 client.receivedDataPoints = append(client.receivedDataPoints, datapoints...) 67 putRes := opentsdb.PutResponse{ 68 StatusCode: 200, 69 Failed: 0, 70 Success: int64(len(datapoints)), 71 } 72 return &putRes, nil 73 } 74 75 type fakeOpenTSDBSink struct { 76 *openTSDBSink 77 fakeClient *fakeOpenTSDBClient 78 } 79 80 func NewFakeOpenTSDBSink(successfulPing, successfulPut bool) fakeOpenTSDBSink { 81 client := &fakeOpenTSDBClient{ 82 successfulPing: successfulPing, 83 successfulPut: successfulPut, 84 } 85 cfg := opentsdbcfg.OpenTSDBConfig{OpentsdbHost: fakeOpenTSDBHost} 86 return fakeOpenTSDBSink{ 87 &openTSDBSink{ 88 client: client, 89 config: cfg, 90 }, 91 client, 92 } 93 } 94 95 func TestStoreTimeseriesEmptyInput(t *testing.T) { 96 fakeSink := NewFakeOpenTSDBSink(true, true) 97 db := core.DataBatch{} 98 fakeSink.ExportData(&db) 99 assert.Equal(t, 0, len(fakeSink.fakeClient.receivedDataPoints)) 100 } 101 102 func TestStoreTimeseriesWithPingFailed(t *testing.T) { 103 fakeSink := NewFakeOpenTSDBSink(false, true) 104 batch := generateFakeBatch() 105 fakeSink.ExportData(batch) 106 assert.Equal(t, 0, len(fakeSink.fakeClient.receivedDataPoints)) 107 } 108 109 func TestStoreTimeseriesWithPutFailed(t *testing.T) { 110 fakeSink := NewFakeOpenTSDBSink(true, false) 111 batch := generateFakeBatch() 112 fakeSink.ExportData(batch) 113 assert.Equal(t, 0, len(fakeSink.fakeClient.receivedDataPoints)) 114 } 115 116 func TestStoreTimeseriesSingleTimeserieInput(t *testing.T) { 117 fakeSink := NewFakeOpenTSDBSink(true, true) 118 batch := core.DataBatch{ 119 Timestamp: time.Now(), 120 MetricSets: map[string]*core.MetricSet{}, 121 } 122 seriesName := "cpu/limit" 123 batch.MetricSets["m1"] = generateMetricSet(seriesName, core.MetricGauge, 1000) 124 batch.MetricSets["m1"].Labels = map[string]string{} 125 fakeSink.ExportData(&batch) 126 assert.Equal(t, 1, len(fakeSink.fakeClient.receivedDataPoints)) 127 assert.Equal(t, "cpu_limit_gauge", fakeSink.fakeClient.receivedDataPoints[0].Metric) 128 //tsdbSink.secureTags() add a default tag key and value pair 129 assert.Equal(t, 1, len(fakeSink.fakeClient.receivedDataPoints[0].Tags)) 130 assert.Equal(t, defaultTagValue, fakeSink.fakeClient.receivedDataPoints[0].Tags[defaultTagName]) 131 } 132 133 func TestStoreTimeseriesMultipleTimeseriesInput(t *testing.T) { 134 fakeSink := NewFakeOpenTSDBSink(true, true) 135 batch := generateFakeBatch() 136 fakeSink.ExportData(batch) 137 assert.Equal(t, len(batch.MetricSets), len(fakeSink.fakeClient.receivedDataPoints)) 138 } 139 func TestName(t *testing.T) { 140 fakeSink := NewFakeOpenTSDBSink(true, true) 141 name := fakeSink.Name() 142 assert.Equal(t, name, opentsdbSinkName) 143 } 144 145 func TestDebugInfo(t *testing.T) { 146 fakeSink := NewFakeOpenTSDBSink(true, true) 147 debugInfo := fakeSink.DebugInfo() 148 assert.Contains(t, debugInfo, "Sink Type: OpenTSDB") 149 assert.Contains(t, debugInfo, "client: Host "+fakeOpenTSDBHost) 150 assert.Contains(t, debugInfo, "Number of write failures:") 151 } 152 153 func TestCreateOpenTSDBSinkWithEmptyInputs(t *testing.T) { 154 sink, err := CreateOpenTSDBSink(&url.URL{}) 155 assert.NoError(t, err) 156 assert.NotNil(t, sink) 157 tsdbSink, ok := sink.(*openTSDBSink) 158 assert.Equal(t, true, ok) 159 assert.Equal(t, defaultOpentsdbHost, tsdbSink.config.OpentsdbHost) 160 } 161 162 func TestCreateOpenTSDBSinkWithNoEmptyInputs(t *testing.T) { 163 fakeOpentsdbHost := "192.168.8.23:4242" 164 sink, err := CreateOpenTSDBSink(&url.URL{Host: fakeOpentsdbHost}) 165 assert.NoError(t, err) 166 assert.NotNil(t, sink) 167 tsdbSink, ok := sink.(*openTSDBSink) 168 assert.Equal(t, true, ok) 169 assert.Equal(t, fakeOpentsdbHost, tsdbSink.config.OpentsdbHost) 170 } 171 172 func generateFakeBatch() *core.DataBatch { 173 batch := core.DataBatch{ 174 Timestamp: time.Now(), 175 MetricSets: map[string]*core.MetricSet{}, 176 } 177 178 batch.MetricSets["m1"] = generateMetricSet("cpu/limit", core.MetricGauge, 1000) 179 batch.MetricSets["m2"] = generateMetricSet("cpu/usage", core.MetricCumulative, 43363664) 180 batch.MetricSets["m3"] = generateMetricSet("filesystem/limit", core.MetricGauge, 42241163264) 181 batch.MetricSets["m4"] = generateMetricSet("filesystem/usage", core.MetricGauge, 32768) 182 batch.MetricSets["m5"] = generateMetricSet("memory/limit", core.MetricGauge, -1) 183 batch.MetricSets["m6"] = generateMetricSet("memory/usage", core.MetricGauge, 487424) 184 batch.MetricSets["m7"] = generateMetricSet("memory/working_set", core.MetricGauge, 491520) 185 batch.MetricSets["m8"] = generateMetricSet("uptime", core.MetricCumulative, 910823) 186 return &batch 187 } 188 189 func generateMetricSet(name string, metricType core.MetricType, value int64) *core.MetricSet { 190 return &core.MetricSet{ 191 Labels: fakeLabel, 192 MetricValues: map[string]core.MetricValue{ 193 name: { 194 MetricType: metricType, 195 ValueType: core.ValueInt64, 196 IntValue: value, 197 }, 198 }, 199 } 200 }