Update dependencies

- uses newer version of go-ethereum required for go1.11
This commit is contained in:
Rob Mulholand
2018-09-13 16:14:35 -05:00
parent 939ead0c82
commit 560305f601
2356 changed files with 331656 additions and 128304 deletions
+20
View File
@@ -0,0 +1,20 @@
// Copyright (c) 2018 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
package influxlib
//Connection type.
const (
HTTP = "HTTP"
UDP = "UDP"
)
//InfluxConfig is a configuration struct for influxlib.
type InfluxConfig struct {
Hostname string
Port uint16
Protocol string
Database string
RetentionPolicy string
}
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) 2018 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
/*
Package: influxlib
Title: Influx DB Library
Authors: ssdaily, manojm321, senkrish, kthommandra
Email: influxdb-dev@arista.com
Description: The main purpose of influxlib is to provide users with a simple
and easy interface through which to connect to influxdb. It removed a lot of
the need to run the same setup and tear down code to connect the the service.
Example Code:
connection, err := influxlib.Connect(&influxlib.InfluxConfig {
Hostname: conf.Host,
Port: conf.Port,
Protocol: influxlib.UDP,
Database, conf.AlertDB,
})
tags := map[string]string {
"tag1": someStruct.Tag["host"],
"tag2": someStruct.Tag["tag2"],
}
fields := map[string]interface{} {
"field1": someStruct.Somefield,
"field2": someStruct.Somefield2,
}
connection.WritePoint("measurement", tags, fields)
*/
package influxlib
+173
View File
@@ -0,0 +1,173 @@
// Copyright (c) 2018 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
package influxlib
import (
"errors"
"fmt"
"time"
influxdb "github.com/influxdata/influxdb/client/v2"
)
// Row is defined as a map where the key (string) is the name of the
// column (field name) and the value is left as an interface to
// accept any value.
type Row map[string]interface{}
// InfluxDBConnection is an object that the wrapper uses.
// Holds a client of the type v2.Client and the configuration
type InfluxDBConnection struct {
Client influxdb.Client
Config *InfluxConfig
}
// Point represents a datapoint to be written.
// Measurement:
// The measurement to write to
// Tags:
// A dictionary of tags in the form string=string
// Fields:
// A dictionary of fields(keys) with their associated values
type Point struct {
Measurement string
Tags map[string]string
Fields map[string]interface{}
Timestamp time.Time
}
// Connect takes an InfluxConfig and establishes a connection
// to InfluxDB. It returns an InfluxDBConnection structure.
// InfluxConfig may be nil for a default connection.
func Connect(config *InfluxConfig) (*InfluxDBConnection, error) {
var con influxdb.Client
var err error
switch config.Protocol {
case HTTP:
addr := fmt.Sprintf("http://%s:%v", config.Hostname, config.Port)
con, err = influxdb.NewHTTPClient(influxdb.HTTPConfig{
Addr: addr,
Timeout: 1 * time.Second,
})
case UDP:
addr := fmt.Sprintf("%s:%v", config.Hostname, config.Port)
con, err = influxdb.NewUDPClient(influxdb.UDPConfig{
Addr: addr,
})
default:
return nil, errors.New("Invalid Protocol")
}
if err != nil {
return nil, err
}
return &InfluxDBConnection{Client: con, Config: config}, nil
}
// RecordBatchPoints takes in a slice of influxlib.Point and writes them to the
// database.
func (conn *InfluxDBConnection) RecordBatchPoints(points []Point) error {
var err error
bp, err := influxdb.NewBatchPoints(influxdb.BatchPointsConfig{
Database: conn.Config.Database,
Precision: "ns",
RetentionPolicy: conn.Config.RetentionPolicy,
})
if err != nil {
return err
}
var influxPoints []*influxdb.Point
for _, p := range points {
if p.Timestamp.IsZero() {
p.Timestamp = time.Now()
}
point, err := influxdb.NewPoint(p.Measurement, p.Tags, p.Fields,
p.Timestamp)
if err != nil {
return err
}
influxPoints = append(influxPoints, point)
}
bp.AddPoints(influxPoints)
if err = conn.Client.Write(bp); err != nil {
return err
}
return nil
}
// WritePoint stores a datapoint to the database.
// Measurement:
// The measurement to write to
// Tags:
// A dictionary of tags in the form string=string
// Fields:
// A dictionary of fields(keys) with their associated values
func (conn *InfluxDBConnection) WritePoint(measurement string,
tags map[string]string, fields map[string]interface{}) error {
return conn.RecordPoint(Point{
Measurement: measurement,
Tags: tags,
Fields: fields,
Timestamp: time.Now(),
})
}
// RecordPoint implements the same as WritePoint but used a point struct
// as the argument instead.
func (conn *InfluxDBConnection) RecordPoint(p Point) error {
return conn.RecordBatchPoints([]Point{p})
}
// Query sends a query to the influxCli and returns a slice of
// rows. Rows are of type map[string]interface{}
func (conn *InfluxDBConnection) Query(query string) ([]Row, error) {
q := influxdb.NewQuery(query, conn.Config.Database, "ns")
var rows []Row
var index = 0
response, err := conn.Client.Query(q)
if err != nil {
return nil, err
}
if response.Error() != nil {
return nil, response.Error()
}
// The intent here is to combine the separate client v2
// series into a single array. As a result queries that
// utilize "group by" will be combined into a single
// array. And the tag value will be added to the query.
// Similar to what you would expect from a SQL query
for _, result := range response.Results {
for _, series := range result.Series {
columnNames := series.Columns
for _, row := range series.Values {
rows = append(rows, make(Row))
for columnIdx, value := range row {
rows[index][columnNames[columnIdx]] = value
}
for tagKey, tagValue := range series.Tags {
rows[index][tagKey] = tagValue
}
index++
}
}
}
return rows, nil
}
// Close closes the connection opened by Connect()
func (conn *InfluxDBConnection) Close() {
conn.Client.Close()
}
+157
View File
@@ -0,0 +1,157 @@
// Copyright (c) 2018 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
package influxlib
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func testFields(line string, fields map[string]interface{},
t *testing.T) {
for k, v := range fields {
formatString := "%s=%v"
if _, ok := v.(string); ok {
formatString = "%s=%q"
}
assert.Contains(t, line, fmt.Sprintf(formatString, k, v),
fmt.Sprintf(formatString+" expected in %s", k, v, line))
}
}
func testTags(line string, tags map[string]string,
t *testing.T) {
for k, v := range tags {
assert.Contains(t, line, fmt.Sprintf("%s=%s", k, v),
fmt.Sprintf("%s=%s expected in %s", k, v, line))
}
}
func TestBasicWrite(t *testing.T) {
testConn, _ := NewMockConnection()
measurement := "TestData"
tags := map[string]string{
"tag1": "Happy",
"tag2": "Valentines",
"tag3": "Day",
}
fields := map[string]interface{}{
"Data1": 1234,
"Data2": "apples",
"Data3": 5.34,
}
err := testConn.WritePoint(measurement, tags, fields)
assert.NoError(t, err)
line, err := GetTestBuffer(testConn)
assert.NoError(t, err)
assert.Contains(t, line, measurement,
fmt.Sprintf("%s does not appear in %s", measurement, line))
testTags(line, tags, t)
testFields(line, fields, t)
}
func TestConnectionToHostFailure(t *testing.T) {
assert := assert.New(t)
var err error
config := &InfluxConfig{
Port: 8086,
Protocol: HTTP,
Database: "test",
}
config.Hostname = "this is fake.com"
_, err = Connect(config)
assert.Error(err)
config.Hostname = "\\-Fake.Url.Com"
_, err = Connect(config)
assert.Error(err)
}
func TestWriteFailure(t *testing.T) {
con, _ := NewMockConnection()
measurement := "TestData"
tags := map[string]string{
"tag1": "hi",
}
data := map[string]interface{}{
"Data1": "cats",
}
err := con.WritePoint(measurement, tags, data)
assert.NoError(t, err)
fc, _ := con.Client.(*fakeClient)
fc.failAll = true
err = con.WritePoint(measurement, tags, data)
assert.Error(t, err)
}
func TestQuery(t *testing.T) {
query := "SELECT * FROM 'system' LIMIT 50;"
con, _ := NewMockConnection()
_, err := con.Query(query)
assert.NoError(t, err)
}
func TestAddAndWriteBatchPoints(t *testing.T) {
testConn, _ := NewMockConnection()
measurement := "TestData"
points := []Point{
Point{
Measurement: measurement,
Tags: map[string]string{
"tag1": "Happy",
"tag2": "Valentines",
"tag3": "Day",
},
Fields: map[string]interface{}{
"Data1": 1234,
"Data2": "apples",
"Data3": 5.34,
},
Timestamp: time.Now(),
},
Point{
Measurement: measurement,
Tags: map[string]string{
"tag1": "Happy",
"tag2": "New",
"tag3": "Year",
},
Fields: map[string]interface{}{
"Data1": 5678,
"Data2": "bananas",
"Data3": 3.14,
},
Timestamp: time.Now(),
},
}
err := testConn.RecordBatchPoints(points)
assert.NoError(t, err)
line, err := GetTestBuffer(testConn)
assert.NoError(t, err)
assert.Contains(t, line, measurement,
fmt.Sprintf("%s does not appear in %s", measurement, line))
for _, p := range points {
testTags(line, p.Tags, t)
testFields(line, p.Fields, t)
}
}
+79
View File
@@ -0,0 +1,79 @@
// Copyright (c) 2018 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
package influxlib
import (
"bytes"
"errors"
"fmt"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// This will serve as a fake client object to test off of.
// The idea is to provide a way to test the Influx Wrapper
// without having it connected to the database.
type fakeClient struct {
writer bytes.Buffer
failAll bool
}
func (w *fakeClient) Ping(timeout time.Duration) (time.Duration,
string, error) {
return 0, "", nil
}
func (w *fakeClient) Query(q influx.Query) (*influx.Response, error) {
if w.failAll {
return nil, errors.New("quering points failed")
}
return &influx.Response{Results: nil, Err: ""}, nil
}
func (w *fakeClient) Close() error {
return nil
}
func (w *fakeClient) Write(bp influx.BatchPoints) error {
if w.failAll {
return errors.New("writing point failed")
}
w.writer.Reset()
for _, p := range bp.Points() {
fmt.Fprintf(&w.writer, p.String()+"\n")
}
return nil
}
func (w *fakeClient) qString() string {
return w.writer.String()
}
/***************************************************/
// NewMockConnection returns an influxDBConnection with
// a "fake" client for offline testing.
func NewMockConnection() (*InfluxDBConnection, error) {
client := new(fakeClient)
config := &InfluxConfig{
Hostname: "localhost",
Port: 8086,
Protocol: HTTP,
Database: "Test",
}
return &InfluxDBConnection{client, config}, nil
}
// GetTestBuffer returns the string that would normally
// be written to influx DB
func GetTestBuffer(con *InfluxDBConnection) (string, error) {
fc, ok := con.Client.(*fakeClient)
if !ok {
return "", errors.New("Expected a fake client but recieved a real one")
}
return fc.qString(), nil
}