You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ne...@apache.org on 2017/01/13 23:36:11 UTC

[15/29] incubator-trafficcontrol git commit: Add vendor directory with current dependencies

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_ops.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_ops.go b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_ops.go
new file mode 100644
index 0000000..15d8cc8
--- /dev/null
+++ b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_ops.go
@@ -0,0 +1,306 @@
+/*
+
+   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.
+*/
+
+package client
+
+import (
+	"bytes"
+	"crypto/tls"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/juju/persistent-cookiejar"
+	"golang.org/x/net/publicsuffix"
+)
+
+// Session ...
+type Session struct {
+	UserName  string
+	Password  string
+	URL       string
+	UserAgent *http.Client
+	Cache     map[string]CacheEntry
+}
+
+// HTTPError is returned on Update Session failure.
+type HTTPError struct {
+	HTTPStatusCode int
+	HTTPStatus     string
+	URL            string
+}
+
+// Error implements the error interface for our customer error type.
+func (e *HTTPError) Error() string {
+	return fmt.Sprintf("%s[%d] - Error requesting Traffic Ops %s", e.HTTPStatus, e.HTTPStatusCode, e.URL)
+}
+
+// Result {"response":[{"level":"success","text":"Successfully logged in."}],"version":"1.1"}
+type Result struct {
+	Alerts  []Alert
+	Version string `json:"version"`
+}
+
+// Alert ...
+type Alert struct {
+	Level string `json:"level"`
+	Text  string `json:"text"`
+}
+
+// CacheEntry ...
+type CacheEntry struct {
+	Entered int64
+	Bytes   []byte
+}
+
+// Credentials contains Traffic Ops login credentials
+type Credentials struct {
+	Username string `json:"u"`
+	Password string `json:"p"`
+}
+
+// TODO JvD
+const tmPollingInterval = 60
+
+// loginCreds gathers login credentials for Traffic Ops.
+func loginCreds(toUser string, toPasswd string) ([]byte, error) {
+	credentials := Credentials{
+		Username: toUser,
+		Password: toPasswd,
+	}
+
+	js, err := json.Marshal(credentials)
+	if err != nil {
+		err := fmt.Errorf("Error creating login json: %v", err)
+		return nil, err
+	}
+	return js, nil
+}
+
+func ResumeSession(toURL string, insecure bool) (*Session, error) {
+	options := cookiejar.Options{
+		PublicSuffixList: publicsuffix.List,
+	}
+
+	jar, err := cookiejar.New(&options)
+
+	if err != nil {
+		return nil, err
+	}
+
+	to := Session{
+		UserAgent: &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
+			},
+			Jar: jar,
+		},
+		URL:   toURL,
+		Cache: make(map[string]CacheEntry),
+	}
+
+	resp, err := to.request("GET", "/api/1.2/user/current.json", nil)
+
+	if err != nil {
+		return nil, err
+	}
+
+	jar.Save()
+	fmt.Printf("Traffic Ops Session Resumed (%s)\n", resp.Status)
+
+	return &to, nil
+}
+
+// Login to traffic_ops, the response should set the cookie for this session
+// automatically. Start with
+//     to := traffic_ops.Login("user", "passwd", true)
+// subsequent calls like to.GetData("datadeliveryservice") will be authenticated.
+func Login(toURL string, toUser string, toPasswd string, insecure bool) (*Session, error) {
+	credentials, err := loginCreds(toUser, toPasswd)
+	if err != nil {
+		return nil, err
+	}
+
+	options := cookiejar.Options{
+		PublicSuffixList: publicsuffix.List,
+	}
+
+	jar, err := cookiejar.New(&options)
+	if err != nil {
+		return nil, err
+	}
+
+	to := Session{
+		UserAgent: &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
+			},
+			Jar: jar,
+		},
+		URL:      toURL,
+		UserName: toUser,
+		Password: toPasswd,
+		Cache:    make(map[string]CacheEntry),
+	}
+
+	path := "/api/1.2/user/login"
+	resp, err := to.request("POST", path, credentials)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	var result Result
+	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
+		return nil, err
+	}
+
+	success := false
+	for _, alert := range result.Alerts {
+		if alert.Level == "success" && alert.Text == "Successfully logged in." {
+			success = true
+			break
+		}
+	}
+
+	if !success {
+		err := fmt.Errorf("Login failed, result string: %+v", result)
+		return nil, err
+	}
+
+	jar.Save()
+
+	return &to, nil
+}
+
+// request performs the actual HTTP request to Traffic Ops
+func (to *Session) request(method, path string, body []byte) (*http.Response, error) {
+	url := fmt.Sprintf("%s%s", to.URL, path)
+
+	var req *http.Request
+	var err error
+
+	if body != nil && method != "GET" {
+		req, err = http.NewRequest(method, url, bytes.NewBuffer(body))
+		if err != nil {
+			return nil, err
+		}
+		req.Header.Set("Content-Type", "application/json")
+	} else {
+		req, err = http.NewRequest("GET", url, nil)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	resp, err := to.UserAgent.Do(req)
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.StatusCode != http.StatusOK {
+		e := HTTPError{
+			HTTPStatus:     resp.Status,
+			HTTPStatusCode: resp.StatusCode,
+			URL:            url,
+		}
+		return nil, &e
+	}
+
+	return resp, nil
+}
+
+type CacheHitStatus string
+
+const CacheHitStatusHit = CacheHitStatus("hit")
+const CacheHitStatusExpired = CacheHitStatus("expired")
+const CacheHitStatusMiss = CacheHitStatus("miss")
+const CacheHitStatusInvalid = CacheHitStatus("")
+
+func (s CacheHitStatus) String() string {
+	return string(s)
+}
+
+func StringToCacheHitStatus(s string) CacheHitStatus {
+	s = strings.ToLower(s)
+	switch s {
+	case "hit":
+		return CacheHitStatusHit
+	case "expired":
+		return CacheHitStatusExpired
+	case "miss":
+		return CacheHitStatusMiss
+	default:
+		return CacheHitStatusInvalid
+	}
+}
+
+// getBytesWithTTL - get the path, and cache in the session
+// return from cache is found and the ttl isn't expired, otherwise get it and
+// store it in cache
+func (to *Session) getBytesWithTTL(path string, ttl int64) ([]byte, CacheHitStatus, error) {
+	var body []byte
+	var err error
+	var cacheHitStatus CacheHitStatus
+	getFresh := false
+	if cacheEntry, ok := to.Cache[path]; ok {
+		if cacheEntry.Entered > time.Now().Unix()-ttl {
+			cacheHitStatus = CacheHitStatusHit
+			body = cacheEntry.Bytes
+		} else {
+			cacheHitStatus = CacheHitStatusExpired
+			getFresh = true
+		}
+	} else {
+		to.Cache = make(map[string]CacheEntry)
+		cacheHitStatus = CacheHitStatusMiss
+		getFresh = true
+	}
+
+	if getFresh {
+		body, err = to.getBytes(path)
+		if err != nil {
+			return nil, CacheHitStatusInvalid, err
+		}
+
+		newEntry := CacheEntry{
+			Entered: time.Now().Unix(),
+			Bytes:   body,
+		}
+		to.Cache[path] = newEntry
+	}
+
+	return body, cacheHitStatus, nil
+}
+
+// GetBytes - get []bytes array for a certain path on the to session.
+// returns the raw body
+func (to *Session) getBytes(path string) ([]byte, error) {
+	resp, err := to.request("GET", path, nil)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	return body, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_router_config.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_router_config.go b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_router_config.go
new file mode 100644
index 0000000..aecd72d
--- /dev/null
+++ b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/traffic_router_config.go
@@ -0,0 +1,237 @@
+/*
+
+   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.
+*/
+
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+// TRConfigResponse ...
+type TRConfigResponse struct {
+	Version  string              `json:"version"`
+	Response TrafficRouterConfig `json:"response"`
+}
+
+// TrafficRouterConfig is the json unmarshalled without any changes
+// note all structs are local to this file _except_ the TrafficRouterConfig struct.
+type TrafficRouterConfig struct {
+	TrafficServers   []TrafficServer        `json:"trafficServers,omitempty"`
+	TrafficMonitors  []TrafficMonitor       `json:"trafficMonitors,omitempty"`
+	TrafficRouters   []TrafficRouter        `json:"trafficRouters,omitempty"`
+	CacheGroups      []TMCacheGroup         `json:"cacheGroups,omitempty"`
+	DeliveryServices []TRDeliveryService    `json:"deliveryServices,omitempty"`
+	Stats            map[string]interface{} `json:"stats,omitempty"`
+	Config           map[string]interface{} `json:"config,omitempty"`
+}
+
+// TrafficRouterConfigMap ...
+type TrafficRouterConfigMap struct {
+	TrafficServer   map[string]TrafficServer
+	TrafficMonitor  map[string]TrafficMonitor
+	TrafficRouter   map[string]TrafficRouter
+	CacheGroup      map[string]TMCacheGroup
+	DeliveryService map[string]TRDeliveryService
+	Config          map[string]interface{}
+	Stat            map[string]interface{}
+}
+
+// TrafficServer ...
+type TrafficServer struct {
+	Profile          string              `json:"profile"`
+	IP               string              `json:"ip"`
+	Status           string              `json:"status"`
+	CacheGroup       string              `json:"cacheGroup"`
+	IP6              string              `json:"ip6"`
+	Port             int                 `json:"port"`
+	HostName         string              `json:"hostName"`
+	FQDN             string              `json:"fqdn"`
+	InterfaceName    string              `json:"interfaceName"`
+	Type             string              `json:"type"`
+	HashID           string              `json:"hashId"`
+	DeliveryServices []tsdeliveryService `json:"deliveryServices,omitempty"` // the deliveryServices key does not exist on mids
+}
+
+type tsdeliveryService struct {
+	Xmlid  string   `json:"xmlId"`
+	Remaps []string `json:"remaps"`
+}
+
+// TrafficRouter ...
+type TrafficRouter struct {
+	Port     int    `json:"port"`
+	IP6      string `json:"ip6"`
+	IP       string `json:"ip"`
+	FQDN     string `json:"fqdn"`
+	Profile  string `json:"profile"`
+	Location string `json:"location"`
+	Status   string `json:"status"`
+	APIPort  int    `json:"apiPort"`
+}
+
+// TMCacheGroup ...
+// !!! Note the lowercase!!! this is local to this file, there's a CacheGroup definition in cachegroup.go!
+type TMCacheGroup struct {
+	Name        string      `json:"name"`
+	Coordinates Coordinates `json:"coordinates"`
+}
+
+// Coordinates ...
+type Coordinates struct {
+	Latitude  float64 `json:"latitude"`
+	Longitude float64 `json:"longitude"`
+}
+
+// TRDeliveryService ...
+// TODO JvD: move to deliveryservice.go ??
+type TRDeliveryService struct {
+	XMLID             string            `json:"xmlId"`
+	Domains           []string          `json:"domains"`
+	MissLocation      MissLocation      `json:"missCoordinates"`
+	CoverageZoneOnly  bool              `json:"coverageZoneOnly"`
+	MatchSets         []MatchSet        `json:"matchSets"`
+	TTL               int               `json:"ttl"`
+	TTLs              TTLS              `json:"ttls"`
+	BypassDestination BypassDestination `json:"bypassDestination"`
+	StatcDNSEntries   []StaticDNS       `json:"statitDnsEntries"`
+	Soa               SOA               `json:"soa"`
+}
+
+// MissLocation ...
+type MissLocation struct {
+	Latitude  float64 `json:"latitude"`
+	Longitude float64 `json:"longitudef"`
+}
+
+// MatchSet ...
+type MatchSet struct {
+	Protocol  string      `json:"protocol"`
+	MatchList []MatchList `json:"matchList"`
+}
+
+// MatchList ...
+type MatchList struct {
+	Regex     string `json:"regex"`
+	MatchType string `json:"matchType"`
+}
+
+// BypassDestination ...
+type BypassDestination struct {
+	FQDN string `json:"fqdn"`
+	Type string `json:"type"`
+	Port int    `json:"Port"`
+}
+
+// TTLS ...
+type TTLS struct {
+	Arecord    int `json:"A"`
+	SoaRecord  int `json:"SOA"`
+	NsRecord   int `json:"NS"`
+	AaaaRecord int `json:"AAAA"`
+}
+
+// StaticDNS ...
+type StaticDNS struct {
+	Value string `json:"value"`
+	TTL   int    `json:"ttl"`
+	Name  string `json:"name"`
+	Type  string `json:"type"`
+}
+
+// SOA ...
+type SOA struct {
+	Admin   string `json:"admin"`
+	Retry   int    `json:"retry"`
+	Minimum int    `json:"minimum"`
+	Refresh int    `json:"refresh"`
+	Expire  int    `json:"expire"`
+}
+
+// TrafficRouterConfigMap Deprecated: use GetTrafficRouterConfigMap instead.
+func (to *Session) TrafficRouterConfigMap(cdn string) (*TrafficRouterConfigMap, error) {
+	cfg, _, err := to.GetTrafficRouterConfigMap(cdn)
+	return cfg, err
+}
+
+// TrafficRouterConfigMap gets a bunch of maps
+func (to *Session) GetTrafficRouterConfigMap(cdn string) (*TrafficRouterConfigMap, CacheHitStatus, error) {
+	trConfig, cacheHitStatus, err := to.GetTrafficRouterConfig(cdn)
+	if err != nil {
+		return nil, CacheHitStatusInvalid, err
+	}
+
+	trConfigMap := TRTransformToMap(*trConfig)
+	return &trConfigMap, cacheHitStatus, nil
+}
+
+// TrafficRouterConfig Deprecated: use GetTrafficRouterConfig instead.
+func (to *Session) TrafficRouterConfig(cdn string) (*TrafficRouterConfig, error) {
+	cfg, _, err := to.GetTrafficRouterConfig(cdn)
+	return cfg, err
+}
+
+// GetTrafficRouterConfig gets the json arrays
+func (to *Session) GetTrafficRouterConfig(cdn string) (*TrafficRouterConfig, CacheHitStatus, error) {
+	url := fmt.Sprintf("/api/1.2/cdns/%s/configs/routing.json", cdn)
+	body, cacheHitStatus, err := to.getBytesWithTTL(url, tmPollingInterval)
+	if err != nil {
+		return nil, CacheHitStatusInvalid, err
+	}
+
+	var data TRConfigResponse
+	if err := json.Unmarshal(body, &data); err != nil {
+		return nil, CacheHitStatusInvalid, err
+	}
+	return &data.Response, cacheHitStatus, nil
+}
+
+// TRTransformToMap ...
+func TRTransformToMap(trConfig TrafficRouterConfig) TrafficRouterConfigMap {
+	var tr TrafficRouterConfigMap
+	tr.TrafficServer = make(map[string]TrafficServer)
+	tr.TrafficMonitor = make(map[string]TrafficMonitor)
+	tr.TrafficRouter = make(map[string]TrafficRouter)
+	tr.CacheGroup = make(map[string]TMCacheGroup)
+	tr.DeliveryService = make(map[string]TRDeliveryService)
+	tr.Config = make(map[string]interface{})
+	tr.Stat = make(map[string]interface{})
+
+	for _, trServer := range trConfig.TrafficServers {
+		tr.TrafficServer[trServer.HostName] = trServer
+	}
+	for _, trMonitor := range trConfig.TrafficMonitors {
+		tr.TrafficMonitor[trMonitor.HostName] = trMonitor
+	}
+	for _, trServer := range trConfig.TrafficServers {
+		tr.TrafficServer[trServer.HostName] = trServer
+	}
+	for _, trRouter := range trConfig.TrafficRouters {
+		tr.TrafficRouter[trRouter.FQDN] = trRouter
+	}
+	for _, trCacheGroup := range trConfig.CacheGroups {
+		tr.CacheGroup[trCacheGroup.Name] = trCacheGroup
+	}
+	for _, trDeliveryService := range trConfig.DeliveryServices {
+		tr.DeliveryService[trDeliveryService.XMLID] = trDeliveryService
+	}
+	for trSettingKey, trSettingVal := range trConfig.Config {
+		tr.Config[trSettingKey] = trSettingVal
+	}
+	for trStatKey, trStatVal := range trConfig.Stats {
+		tr.Stat[trStatKey] = trStatVal
+	}
+	return tr
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/type.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/type.go b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/type.go
new file mode 100644
index 0000000..f8242f3
--- /dev/null
+++ b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/type.go
@@ -0,0 +1,68 @@
+/*
+
+   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.
+*/
+
+package client
+
+import (
+	"encoding/json"
+	"errors"
+)
+
+// TypeResponse ...
+type TypeResponse struct {
+	Version  string `json:"version"`
+	Response []Type `json:"response"`
+}
+
+// Type contains information about a given Type in Traffic Ops.
+type Type struct {
+	Name        string `json:"name,omitempty"`
+	Description string `json:"description,omitempty"`
+	UseInTable  string `json:"useInTable,omitempt"`
+}
+
+// Types gets an array of Types.
+// optional parameter: userInTable
+func (to *Session) Types(useInTable ...string) ([]Type, error) {
+
+	if len(useInTable) > 1 {
+		return nil, errors.New("Please pass in a single value for the 'useInTable' parameter")
+	}
+
+	url := "/api/1.2/types.json"
+	resp, err := to.request("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	resp.Body.Close()
+
+	var data TypeResponse
+	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
+		return nil, err
+	}
+
+	var types []Type
+	for _, d := range data.Response {
+		if useInTable != nil {
+			if d.UseInTable == useInTable[0] {
+				types = append(types, d)
+			}
+		} else {
+			types = append(types, d)
+		}
+	}
+
+	return types, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/user.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/user.go b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/user.go
new file mode 100644
index 0000000..2819eab
--- /dev/null
+++ b/traffic_stats/vendor/github.com/apache/incubator-trafficcontrol/traffic_ops/client/user.go
@@ -0,0 +1,56 @@
+/*
+
+   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.
+*/
+
+package client
+
+import "encoding/json"
+
+// UserResponse ...
+type UserResponse struct {
+	Version  string `json:"version"`
+	Response []User `json:"response"`
+}
+
+// User contains information about a given user in Traffic Ops.
+type User struct {
+	Username     string `json:"username,omitempty"`
+	PublicSSHKey string `json:"publicSshKey,omitempty"`
+	Role         string `json:"role,omitempty"`
+	RoleName     string `json:"rolename,omitempty"`
+	UID          string `json:"uid,omitempty"`
+	GID          string `json:"gid,omitempty"`
+	Company      string `json:"company,omitempty"`
+	Email        string `json:"email,omitempty"`
+	FullName     string `json:"fullName,omitempty"`
+	NewUser      bool   `json:"newUser,omitempty"`
+	LastUpdated  string `json:"lastUpdated,omitempty"`
+}
+
+// Users gets an array of Users.
+func (to *Session) Users() ([]User, error) {
+	url := "/api/1.2/users.json"
+	resp, err := to.request("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	resp.Body.Close()
+
+	var data UserResponse
+	if err := json.NewDecoder(resp.Body).Decode(&data.Response); err != nil {
+		return nil, err
+	}
+
+	return data.Response, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/cihub/seelog
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog b/traffic_stats/vendor/github.com/cihub/seelog
new file mode 160000
index 0000000..175e6e3
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog
@@ -0,0 +1 @@
+Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client.go b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client.go
new file mode 100644
index 0000000..4d0ce60
--- /dev/null
+++ b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client.go
@@ -0,0 +1,526 @@
+// Package client (v2) is the current official Go client for InfluxDB.
+package client // import "github.com/influxdata/influxdb/client/v2"
+
+import (
+	"bytes"
+	"crypto/tls"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+
+	"github.com/influxdata/influxdb/models"
+)
+
+// HTTPConfig is the config data needed to create an HTTP Client.
+type HTTPConfig struct {
+	// Addr should be of the form "http://host:port"
+	// or "http://[ipv6-host%zone]:port".
+	Addr string
+
+	// Username is the influxdb username, optional.
+	Username string
+
+	// Password is the influxdb password, optional.
+	Password string
+
+	// UserAgent is the http User Agent, defaults to "InfluxDBClient".
+	UserAgent string
+
+	// Timeout for influxdb writes, defaults to no timeout.
+	Timeout time.Duration
+
+	// InsecureSkipVerify gets passed to the http client, if true, it will
+	// skip https certificate verification. Defaults to false.
+	InsecureSkipVerify bool
+
+	// TLSConfig allows the user to set their own TLS config for the HTTP
+	// Client. If set, this option overrides InsecureSkipVerify.
+	TLSConfig *tls.Config
+}
+
+// BatchPointsConfig is the config data needed to create an instance of the BatchPoints struct.
+type BatchPointsConfig struct {
+	// Precision is the write precision of the points, defaults to "ns".
+	Precision string
+
+	// Database is the database to write points to.
+	Database string
+
+	// RetentionPolicy is the retention policy of the points.
+	RetentionPolicy string
+
+	// Write consistency is the number of servers required to confirm write.
+	WriteConsistency string
+}
+
+// Client is a client interface for writing & querying the database.
+type Client interface {
+	// Ping checks that status of cluster, and will always return 0 time and no
+	// error for UDP clients.
+	Ping(timeout time.Duration) (time.Duration, string, error)
+
+	// Write takes a BatchPoints object and writes all Points to InfluxDB.
+	Write(bp BatchPoints) error
+
+	// Query makes an InfluxDB Query on the database. This will fail if using
+	// the UDP client.
+	Query(q Query) (*Response, error)
+
+	// Close releases any resources a Client may be using.
+	Close() error
+}
+
+// NewHTTPClient returns a new Client from the provided config.
+// Client is safe for concurrent use by multiple goroutines.
+func NewHTTPClient(conf HTTPConfig) (Client, error) {
+	if conf.UserAgent == "" {
+		conf.UserAgent = "InfluxDBClient"
+	}
+
+	u, err := url.Parse(conf.Addr)
+	if err != nil {
+		return nil, err
+	} else if u.Scheme != "http" && u.Scheme != "https" {
+		m := fmt.Sprintf("Unsupported protocol scheme: %s, your address"+
+			" must start with http:// or https://", u.Scheme)
+		return nil, errors.New(m)
+	}
+
+	tr := &http.Transport{
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: conf.InsecureSkipVerify,
+		},
+	}
+	if conf.TLSConfig != nil {
+		tr.TLSClientConfig = conf.TLSConfig
+	}
+	return &client{
+		url:       *u,
+		username:  conf.Username,
+		password:  conf.Password,
+		useragent: conf.UserAgent,
+		httpClient: &http.Client{
+			Timeout:   conf.Timeout,
+			Transport: tr,
+		},
+		transport: tr,
+	}, nil
+}
+
+// Ping will check to see if the server is up with an optional timeout on waiting for leader.
+// Ping returns how long the request took, the version of the server it connected to, and an error if one occurred.
+func (c *client) Ping(timeout time.Duration) (time.Duration, string, error) {
+	now := time.Now()
+	u := c.url
+	u.Path = "ping"
+
+	req, err := http.NewRequest("GET", u.String(), nil)
+	if err != nil {
+		return 0, "", err
+	}
+
+	req.Header.Set("User-Agent", c.useragent)
+
+	if c.username != "" {
+		req.SetBasicAuth(c.username, c.password)
+	}
+
+	if timeout > 0 {
+		params := req.URL.Query()
+		params.Set("wait_for_leader", fmt.Sprintf("%.0fs", timeout.Seconds()))
+		req.URL.RawQuery = params.Encode()
+	}
+
+	resp, err := c.httpClient.Do(req)
+	if err != nil {
+		return 0, "", err
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return 0, "", err
+	}
+
+	if resp.StatusCode != http.StatusNoContent {
+		var err = fmt.Errorf(string(body))
+		return 0, "", err
+	}
+
+	version := resp.Header.Get("X-Influxdb-Version")
+	return time.Since(now), version, nil
+}
+
+// Close releases the client's resources.
+func (c *client) Close() error {
+	c.transport.CloseIdleConnections()
+	return nil
+}
+
+// client is safe for concurrent use as the fields are all read-only
+// once the client is instantiated.
+type client struct {
+	// N.B - if url.UserInfo is accessed in future modifications to the
+	// methods on client, you will need to syncronise access to url.
+	url        url.URL
+	username   string
+	password   string
+	useragent  string
+	httpClient *http.Client
+	transport  *http.Transport
+}
+
+// BatchPoints is an interface into a batched grouping of points to write into
+// InfluxDB together. BatchPoints is NOT thread-safe, you must create a separate
+// batch for each goroutine.
+type BatchPoints interface {
+	// AddPoint adds the given point to the Batch of points.
+	AddPoint(p *Point)
+	// AddPoints adds the given points to the Batch of points.
+	AddPoints(ps []*Point)
+	// Points lists the points in the Batch.
+	Points() []*Point
+
+	// Precision returns the currently set precision of this Batch.
+	Precision() string
+	// SetPrecision sets the precision of this batch.
+	SetPrecision(s string) error
+
+	// Database returns the currently set database of this Batch.
+	Database() string
+	// SetDatabase sets the database of this Batch.
+	SetDatabase(s string)
+
+	// WriteConsistency returns the currently set write consistency of this Batch.
+	WriteConsistency() string
+	// SetWriteConsistency sets the write consistency of this Batch.
+	SetWriteConsistency(s string)
+
+	// RetentionPolicy returns the currently set retention policy of this Batch.
+	RetentionPolicy() string
+	// SetRetentionPolicy sets the retention policy of this Batch.
+	SetRetentionPolicy(s string)
+}
+
+// NewBatchPoints returns a BatchPoints interface based on the given config.
+func NewBatchPoints(conf BatchPointsConfig) (BatchPoints, error) {
+	if conf.Precision == "" {
+		conf.Precision = "ns"
+	}
+	if _, err := time.ParseDuration("1" + conf.Precision); err != nil {
+		return nil, err
+	}
+	bp := &batchpoints{
+		database:         conf.Database,
+		precision:        conf.Precision,
+		retentionPolicy:  conf.RetentionPolicy,
+		writeConsistency: conf.WriteConsistency,
+	}
+	return bp, nil
+}
+
+type batchpoints struct {
+	points           []*Point
+	database         string
+	precision        string
+	retentionPolicy  string
+	writeConsistency string
+}
+
+func (bp *batchpoints) AddPoint(p *Point) {
+	bp.points = append(bp.points, p)
+}
+
+func (bp *batchpoints) AddPoints(ps []*Point) {
+	bp.points = append(bp.points, ps...)
+}
+
+func (bp *batchpoints) Points() []*Point {
+	return bp.points
+}
+
+func (bp *batchpoints) Precision() string {
+	return bp.precision
+}
+
+func (bp *batchpoints) Database() string {
+	return bp.database
+}
+
+func (bp *batchpoints) WriteConsistency() string {
+	return bp.writeConsistency
+}
+
+func (bp *batchpoints) RetentionPolicy() string {
+	return bp.retentionPolicy
+}
+
+func (bp *batchpoints) SetPrecision(p string) error {
+	if _, err := time.ParseDuration("1" + p); err != nil {
+		return err
+	}
+	bp.precision = p
+	return nil
+}
+
+func (bp *batchpoints) SetDatabase(db string) {
+	bp.database = db
+}
+
+func (bp *batchpoints) SetWriteConsistency(wc string) {
+	bp.writeConsistency = wc
+}
+
+func (bp *batchpoints) SetRetentionPolicy(rp string) {
+	bp.retentionPolicy = rp
+}
+
+// Point represents a single data point.
+type Point struct {
+	pt models.Point
+}
+
+// NewPoint returns a point with the given timestamp. If a timestamp is not
+// given, then data is sent to the database without a timestamp, in which case
+// the server will assign local time upon reception. NOTE: it is recommended to
+// send data with a timestamp.
+func NewPoint(
+	name string,
+	tags map[string]string,
+	fields map[string]interface{},
+	t ...time.Time,
+) (*Point, error) {
+	var T time.Time
+	if len(t) > 0 {
+		T = t[0]
+	}
+
+	pt, err := models.NewPoint(name, models.NewTags(tags), fields, T)
+	if err != nil {
+		return nil, err
+	}
+	return &Point{
+		pt: pt,
+	}, nil
+}
+
+// String returns a line-protocol string of the Point.
+func (p *Point) String() string {
+	return p.pt.String()
+}
+
+// PrecisionString returns a line-protocol string of the Point,
+// with the timestamp formatted for the given precision.
+func (p *Point) PrecisionString(precison string) string {
+	return p.pt.PrecisionString(precison)
+}
+
+// Name returns the measurement name of the point.
+func (p *Point) Name() string {
+	return p.pt.Name()
+}
+
+// Tags returns the tags associated with the point.
+func (p *Point) Tags() map[string]string {
+	return p.pt.Tags().Map()
+}
+
+// Time return the timestamp for the point.
+func (p *Point) Time() time.Time {
+	return p.pt.Time()
+}
+
+// UnixNano returns timestamp of the point in nanoseconds since Unix epoch.
+func (p *Point) UnixNano() int64 {
+	return p.pt.UnixNano()
+}
+
+// Fields returns the fields for the point.
+func (p *Point) Fields() (map[string]interface{}, error) {
+	return p.pt.Fields()
+}
+
+// NewPointFrom returns a point from the provided models.Point.
+func NewPointFrom(pt models.Point) *Point {
+	return &Point{pt: pt}
+}
+
+func (c *client) Write(bp BatchPoints) error {
+	var b bytes.Buffer
+
+	for _, p := range bp.Points() {
+		if _, err := b.WriteString(p.pt.PrecisionString(bp.Precision())); err != nil {
+			return err
+		}
+
+		if err := b.WriteByte('\n'); err != nil {
+			return err
+		}
+	}
+
+	u := c.url
+	u.Path = "write"
+	req, err := http.NewRequest("POST", u.String(), &b)
+	if err != nil {
+		return err
+	}
+	req.Header.Set("Content-Type", "")
+	req.Header.Set("User-Agent", c.useragent)
+	if c.username != "" {
+		req.SetBasicAuth(c.username, c.password)
+	}
+
+	params := req.URL.Query()
+	params.Set("db", bp.Database())
+	params.Set("rp", bp.RetentionPolicy())
+	params.Set("precision", bp.Precision())
+	params.Set("consistency", bp.WriteConsistency())
+	req.URL.RawQuery = params.Encode()
+
+	resp, err := c.httpClient.Do(req)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+
+	if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK {
+		var err = fmt.Errorf(string(body))
+		return err
+	}
+
+	return nil
+}
+
+// Query defines a query to send to the server.
+type Query struct {
+	Command    string
+	Database   string
+	Precision  string
+	Parameters map[string]interface{}
+}
+
+// NewQuery returns a query object.
+// The database and precision arguments can be empty strings if they are not needed for the query.
+func NewQuery(command, database, precision string) Query {
+	return Query{
+		Command:    command,
+		Database:   database,
+		Precision:  precision,
+		Parameters: make(map[string]interface{}),
+	}
+}
+
+// NewQueryWithParameters returns a query object.
+// The database and precision arguments can be empty strings if they are not needed for the query.
+// parameters is a map of the parameter names used in the command to their values.
+func NewQueryWithParameters(command, database, precision string, parameters map[string]interface{}) Query {
+	return Query{
+		Command:    command,
+		Database:   database,
+		Precision:  precision,
+		Parameters: parameters,
+	}
+}
+
+// Response represents a list of statement results.
+type Response struct {
+	Results []Result
+	Err     string `json:"error,omitempty"`
+}
+
+// Error returns the first error from any statement.
+// It returns nil if no errors occurred on any statements.
+func (r *Response) Error() error {
+	if r.Err != "" {
+		return fmt.Errorf(r.Err)
+	}
+	for _, result := range r.Results {
+		if result.Err != "" {
+			return fmt.Errorf(result.Err)
+		}
+	}
+	return nil
+}
+
+// Message represents a user message.
+type Message struct {
+	Level string
+	Text  string
+}
+
+// Result represents a resultset returned from a single statement.
+type Result struct {
+	Series   []models.Row
+	Messages []*Message
+	Err      string `json:"error,omitempty"`
+}
+
+// Query sends a command to the server and returns the Response.
+func (c *client) Query(q Query) (*Response, error) {
+	u := c.url
+	u.Path = "query"
+
+	jsonParameters, err := json.Marshal(q.Parameters)
+
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest("POST", u.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+
+	req.Header.Set("Content-Type", "")
+	req.Header.Set("User-Agent", c.useragent)
+
+	if c.username != "" {
+		req.SetBasicAuth(c.username, c.password)
+	}
+
+	params := req.URL.Query()
+	params.Set("q", q.Command)
+	params.Set("db", q.Database)
+	params.Set("params", string(jsonParameters))
+
+	if q.Precision != "" {
+		params.Set("epoch", q.Precision)
+	}
+	req.URL.RawQuery = params.Encode()
+
+	resp, err := c.httpClient.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	var response Response
+	dec := json.NewDecoder(resp.Body)
+	dec.UseNumber()
+	decErr := dec.Decode(&response)
+
+	// ignore this error if we got an invalid status code
+	if decErr != nil && decErr.Error() == "EOF" && resp.StatusCode != http.StatusOK {
+		decErr = nil
+	}
+	// If we got a valid decode error, send that back
+	if decErr != nil {
+		return nil, fmt.Errorf("unable to decode json: received status code %d err: %s", resp.StatusCode, decErr)
+	}
+	// If we don't have an error in our json response, and didn't get statusOK
+	// then send back an error
+	if resp.StatusCode != http.StatusOK && response.Error() == nil {
+		return &response, fmt.Errorf("received status code %d from server",
+			resp.StatusCode)
+	}
+	return &response, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client_test.go b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client_test.go
new file mode 100644
index 0000000..d27c162
--- /dev/null
+++ b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/client_test.go
@@ -0,0 +1,525 @@
+package client
+
+import (
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"reflect"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestUDPClient_Query(t *testing.T) {
+	config := UDPConfig{Addr: "localhost:8089"}
+	c, err := NewUDPClient(config)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+	defer c.Close()
+	query := Query{}
+	_, err = c.Query(query)
+	if err == nil {
+		t.Error("Querying UDP client should fail")
+	}
+}
+
+func TestUDPClient_Ping(t *testing.T) {
+	config := UDPConfig{Addr: "localhost:8089"}
+	c, err := NewUDPClient(config)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+	defer c.Close()
+
+	rtt, version, err := c.Ping(0)
+	if rtt != 0 || version != "" || err != nil {
+		t.Errorf("unexpected error.  expected (%v, '%v', %v), actual (%v, '%v', %v)", 0, "", nil, rtt, version, err)
+	}
+}
+
+func TestUDPClient_Write(t *testing.T) {
+	config := UDPConfig{Addr: "localhost:8089"}
+	c, err := NewUDPClient(config)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+	defer c.Close()
+
+	bp, err := NewBatchPoints(BatchPointsConfig{})
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+
+	fields := make(map[string]interface{})
+	fields["value"] = 1.0
+	pt, _ := NewPoint("cpu", make(map[string]string), fields)
+	bp.AddPoint(pt)
+
+	err = c.Write(bp)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+}
+
+func TestUDPClient_BadAddr(t *testing.T) {
+	config := UDPConfig{Addr: "foobar@wahoo"}
+	c, err := NewUDPClient(config)
+	if err == nil {
+		defer c.Close()
+		t.Error("Expected resolve error")
+	}
+}
+
+func TestUDPClient_Batches(t *testing.T) {
+	var logger writeLogger
+	var cl udpclient
+
+	cl.conn = &logger
+	cl.payloadSize = 20 // should allow for two points per batch
+
+	// expected point should look like this: "cpu a=1i"
+	fields := map[string]interface{}{"a": 1}
+
+	p, _ := NewPoint("cpu", nil, fields, time.Time{})
+
+	bp, _ := NewBatchPoints(BatchPointsConfig{})
+
+	for i := 0; i < 9; i++ {
+		bp.AddPoint(p)
+	}
+
+	if err := cl.Write(bp); err != nil {
+		t.Fatalf("Unexpected error during Write: %v", err)
+	}
+
+	if len(logger.writes) != 5 {
+		t.Errorf("Mismatched write count: got %v, exp %v", len(logger.writes), 5)
+	}
+}
+
+func TestUDPClient_Split(t *testing.T) {
+	var logger writeLogger
+	var cl udpclient
+
+	cl.conn = &logger
+	cl.payloadSize = 1 // force one field per point
+
+	fields := map[string]interface{}{"a": 1, "b": 2, "c": 3, "d": 4}
+
+	p, _ := NewPoint("cpu", nil, fields, time.Unix(1, 0))
+
+	bp, _ := NewBatchPoints(BatchPointsConfig{})
+
+	bp.AddPoint(p)
+
+	if err := cl.Write(bp); err != nil {
+		t.Fatalf("Unexpected error during Write: %v", err)
+	}
+
+	if len(logger.writes) != len(fields) {
+		t.Errorf("Mismatched write count: got %v, exp %v", len(logger.writes), len(fields))
+	}
+}
+
+type writeLogger struct {
+	writes [][]byte
+}
+
+func (w *writeLogger) Write(b []byte) (int, error) {
+	w.writes = append(w.writes, append([]byte(nil), b...))
+	return len(b), nil
+}
+
+func (w *writeLogger) Close() error { return nil }
+
+func TestClient_Query(t *testing.T) {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var data Response
+		w.WriteHeader(http.StatusOK)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	query := Query{}
+	_, err := c.Query(query)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+}
+
+func TestClient_BoundParameters(t *testing.T) {
+	var parameterString string
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var data Response
+		r.ParseForm()
+		parameterString = r.FormValue("params")
+		w.WriteHeader(http.StatusOK)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	expectedParameters := map[string]interface{}{
+		"testStringParameter": "testStringValue",
+		"testNumberParameter": 12.3,
+	}
+
+	query := Query{
+		Parameters: expectedParameters,
+	}
+
+	_, err := c.Query(query)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+
+	var actualParameters map[string]interface{}
+
+	err = json.Unmarshal([]byte(parameterString), &actualParameters)
+	if err != nil {
+		t.Errorf("unexpected error. expected %v, actual %v", nil, err)
+	}
+
+	if !reflect.DeepEqual(expectedParameters, actualParameters) {
+		t.Errorf("unexpected parameters. expected %v, actual %v", expectedParameters, actualParameters)
+	}
+}
+
+func TestClient_BasicAuth(t *testing.T) {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		u, p, ok := r.BasicAuth()
+
+		if !ok {
+			t.Errorf("basic auth error")
+		}
+		if u != "username" {
+			t.Errorf("unexpected username, expected %q, actual %q", "username", u)
+		}
+		if p != "password" {
+			t.Errorf("unexpected password, expected %q, actual %q", "password", p)
+		}
+		var data Response
+		w.WriteHeader(http.StatusOK)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL, Username: "username", Password: "password"}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	query := Query{}
+	_, err := c.Query(query)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+}
+
+func TestClient_Ping(t *testing.T) {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var data Response
+		w.WriteHeader(http.StatusNoContent)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	_, _, err := c.Ping(0)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+}
+
+func TestClient_Concurrent_Use(t *testing.T) {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(`{}`))
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	var wg sync.WaitGroup
+	wg.Add(3)
+	n := 1000
+
+	go func() {
+		defer wg.Done()
+		bp, err := NewBatchPoints(BatchPointsConfig{})
+		if err != nil {
+			t.Errorf("got error %v", err)
+		}
+
+		for i := 0; i < n; i++ {
+			if err = c.Write(bp); err != nil {
+				t.Fatalf("got error %v", err)
+			}
+		}
+	}()
+
+	go func() {
+		defer wg.Done()
+		var q Query
+		for i := 0; i < n; i++ {
+			if _, err := c.Query(q); err != nil {
+				t.Fatalf("got error %v", err)
+			}
+		}
+	}()
+
+	go func() {
+		defer wg.Done()
+		for i := 0; i < n; i++ {
+			c.Ping(time.Second)
+		}
+	}()
+	wg.Wait()
+}
+
+func TestClient_Write(t *testing.T) {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var data Response
+		w.WriteHeader(http.StatusNoContent)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	config := HTTPConfig{Addr: ts.URL}
+	c, _ := NewHTTPClient(config)
+	defer c.Close()
+
+	bp, err := NewBatchPoints(BatchPointsConfig{})
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+	err = c.Write(bp)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+}
+
+func TestClient_UserAgent(t *testing.T) {
+	receivedUserAgent := ""
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		receivedUserAgent = r.UserAgent()
+
+		var data Response
+		w.WriteHeader(http.StatusOK)
+		_ = json.NewEncoder(w).Encode(data)
+	}))
+	defer ts.Close()
+
+	_, err := http.Get(ts.URL)
+	if err != nil {
+		t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+	}
+
+	tests := []struct {
+		name      string
+		userAgent string
+		expected  string
+	}{
+		{
+			name:      "Empty user agent",
+			userAgent: "",
+			expected:  "InfluxDBClient",
+		},
+		{
+			name:      "Custom user agent",
+			userAgent: "Test Influx Client",
+			expected:  "Test Influx Client",
+		},
+	}
+
+	for _, test := range tests {
+
+		config := HTTPConfig{Addr: ts.URL, UserAgent: test.userAgent}
+		c, _ := NewHTTPClient(config)
+		defer c.Close()
+
+		receivedUserAgent = ""
+		query := Query{}
+		_, err = c.Query(query)
+		if err != nil {
+			t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+		}
+		if !strings.HasPrefix(receivedUserAgent, test.expected) {
+			t.Errorf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
+		}
+
+		receivedUserAgent = ""
+		bp, _ := NewBatchPoints(BatchPointsConfig{})
+		err = c.Write(bp)
+		if err != nil {
+			t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+		}
+		if !strings.HasPrefix(receivedUserAgent, test.expected) {
+			t.Errorf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
+		}
+
+		receivedUserAgent = ""
+		_, err := c.Query(query)
+		if err != nil {
+			t.Errorf("unexpected error.  expected %v, actual %v", nil, err)
+		}
+		if receivedUserAgent != test.expected {
+			t.Errorf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
+		}
+	}
+}
+
+func TestClient_PointString(t *testing.T) {
+	const shortForm = "2006-Jan-02"
+	time1, _ := time.Parse(shortForm, "2013-Feb-03")
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields, time1)
+
+	s := "cpu_usage,cpu=cpu-total idle=10.1,system=50.9,user=39 1359849600000000000"
+	if p.String() != s {
+		t.Errorf("Point String Error, got %s, expected %s", p.String(), s)
+	}
+
+	s = "cpu_usage,cpu=cpu-total idle=10.1,system=50.9,user=39 1359849600000"
+	if p.PrecisionString("ms") != s {
+		t.Errorf("Point String Error, got %s, expected %s",
+			p.PrecisionString("ms"), s)
+	}
+}
+
+func TestClient_PointWithoutTimeString(t *testing.T) {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields)
+
+	s := "cpu_usage,cpu=cpu-total idle=10.1,system=50.9,user=39"
+	if p.String() != s {
+		t.Errorf("Point String Error, got %s, expected %s", p.String(), s)
+	}
+
+	if p.PrecisionString("ms") != s {
+		t.Errorf("Point String Error, got %s, expected %s",
+			p.PrecisionString("ms"), s)
+	}
+}
+
+func TestClient_PointName(t *testing.T) {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields)
+
+	exp := "cpu_usage"
+	if p.Name() != exp {
+		t.Errorf("Error, got %s, expected %s",
+			p.Name(), exp)
+	}
+}
+
+func TestClient_PointTags(t *testing.T) {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields)
+
+	if !reflect.DeepEqual(tags, p.Tags()) {
+		t.Errorf("Error, got %v, expected %v",
+			p.Tags(), tags)
+	}
+}
+
+func TestClient_PointUnixNano(t *testing.T) {
+	const shortForm = "2006-Jan-02"
+	time1, _ := time.Parse(shortForm, "2013-Feb-03")
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields, time1)
+
+	exp := int64(1359849600000000000)
+	if p.UnixNano() != exp {
+		t.Errorf("Error, got %d, expected %d",
+			p.UnixNano(), exp)
+	}
+}
+
+func TestClient_PointFields(t *testing.T) {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{"idle": 10.1, "system": 50.9, "user": 39.0}
+	p, _ := NewPoint("cpu_usage", tags, fields)
+
+	pfields, err := p.Fields()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(fields, pfields) {
+		t.Errorf("Error, got %v, expected %v",
+			pfields, fields)
+	}
+}
+
+func TestBatchPoints_PrecisionError(t *testing.T) {
+	_, err := NewBatchPoints(BatchPointsConfig{Precision: "foobar"})
+	if err == nil {
+		t.Errorf("Precision: foobar should have errored")
+	}
+
+	bp, _ := NewBatchPoints(BatchPointsConfig{Precision: "ns"})
+	err = bp.SetPrecision("foobar")
+	if err == nil {
+		t.Errorf("Precision: foobar should have errored")
+	}
+}
+
+func TestBatchPoints_SettersGetters(t *testing.T) {
+	bp, _ := NewBatchPoints(BatchPointsConfig{
+		Precision:        "ns",
+		Database:         "db",
+		RetentionPolicy:  "rp",
+		WriteConsistency: "wc",
+	})
+	if bp.Precision() != "ns" {
+		t.Errorf("Expected: %s, got %s", bp.Precision(), "ns")
+	}
+	if bp.Database() != "db" {
+		t.Errorf("Expected: %s, got %s", bp.Database(), "db")
+	}
+	if bp.RetentionPolicy() != "rp" {
+		t.Errorf("Expected: %s, got %s", bp.RetentionPolicy(), "rp")
+	}
+	if bp.WriteConsistency() != "wc" {
+		t.Errorf("Expected: %s, got %s", bp.WriteConsistency(), "wc")
+	}
+
+	bp.SetDatabase("db2")
+	bp.SetRetentionPolicy("rp2")
+	bp.SetWriteConsistency("wc2")
+	err := bp.SetPrecision("s")
+	if err != nil {
+		t.Errorf("Did not expect error: %s", err.Error())
+	}
+
+	if bp.Precision() != "s" {
+		t.Errorf("Expected: %s, got %s", bp.Precision(), "s")
+	}
+	if bp.Database() != "db2" {
+		t.Errorf("Expected: %s, got %s", bp.Database(), "db2")
+	}
+	if bp.RetentionPolicy() != "rp2" {
+		t.Errorf("Expected: %s, got %s", bp.RetentionPolicy(), "rp2")
+	}
+	if bp.WriteConsistency() != "wc2" {
+		t.Errorf("Expected: %s, got %s", bp.WriteConsistency(), "wc2")
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/example_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/example_test.go b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/example_test.go
new file mode 100644
index 0000000..68bb24b
--- /dev/null
+++ b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/example_test.go
@@ -0,0 +1,265 @@
+package client_test
+
+import (
+	"fmt"
+	"math/rand"
+	"os"
+	"time"
+
+	"github.com/influxdata/influxdb/client/v2"
+)
+
+// Create a new client
+func ExampleClient() {
+	// NOTE: this assumes you've setup a user and have setup shell env variables,
+	// namely INFLUX_USER/INFLUX_PWD. If not just omit Username/Password below.
+	_, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr:     "http://localhost:8086",
+		Username: os.Getenv("INFLUX_USER"),
+		Password: os.Getenv("INFLUX_PWD"),
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+}
+
+// Write a point using the UDP client
+func ExampleClient_uDP() {
+	// Make client
+	config := client.UDPConfig{Addr: "localhost:8089"}
+	c, err := client.NewUDPClient(config)
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+	defer c.Close()
+
+	// Create a new point batch
+	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
+		Precision: "s",
+	})
+
+	// Create a point and add to batch
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+	bp.AddPoint(pt)
+
+	// Write the batch
+	c.Write(bp)
+}
+
+// Ping the cluster using the HTTP client
+func ExampleClient_Ping() {
+	// Make client
+	c, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr: "http://localhost:8086",
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+	defer c.Close()
+
+	_, _, err = c.Ping(0)
+	if err != nil {
+		fmt.Println("Error pinging InfluxDB Cluster: ", err.Error())
+	}
+}
+
+// Write a point using the HTTP client
+func ExampleClient_write() {
+	// Make client
+	c, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr: "http://localhost:8086",
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+	defer c.Close()
+
+	// Create a new point batch
+	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
+		Database:  "BumbleBeeTuna",
+		Precision: "s",
+	})
+
+	// Create a point and add to batch
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+	bp.AddPoint(pt)
+
+	// Write the batch
+	c.Write(bp)
+}
+
+// Create a batch and add a point
+func ExampleBatchPoints() {
+	// Create a new point batch
+	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
+		Database:  "BumbleBeeTuna",
+		Precision: "s",
+	})
+
+	// Create a point and add to batch
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+	bp.AddPoint(pt)
+}
+
+// Using the BatchPoints setter functions
+func ExampleBatchPoints_setters() {
+	// Create a new point batch
+	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{})
+	bp.SetDatabase("BumbleBeeTuna")
+	bp.SetPrecision("ms")
+
+	// Create a point and add to batch
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+	bp.AddPoint(pt)
+}
+
+// Create a new point with a timestamp
+func ExamplePoint() {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
+	if err == nil {
+		fmt.Println("We created a point: ", pt.String())
+	}
+}
+
+// Create a new point without a timestamp
+func ExamplePoint_withoutTime() {
+	tags := map[string]string{"cpu": "cpu-total"}
+	fields := map[string]interface{}{
+		"idle":   10.1,
+		"system": 53.3,
+		"user":   46.6,
+	}
+	pt, err := client.NewPoint("cpu_usage", tags, fields)
+	if err == nil {
+		fmt.Println("We created a point w/o time: ", pt.String())
+	}
+}
+
+// Write 1000 points
+func ExampleClient_write1000() {
+	sampleSize := 1000
+
+	// Make client
+	c, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr: "http://localhost:8086",
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+	defer c.Close()
+
+	rand.Seed(42)
+
+	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
+		Database:  "systemstats",
+		Precision: "us",
+	})
+
+	for i := 0; i < sampleSize; i++ {
+		regions := []string{"us-west1", "us-west2", "us-west3", "us-east1"}
+		tags := map[string]string{
+			"cpu":    "cpu-total",
+			"host":   fmt.Sprintf("host%d", rand.Intn(1000)),
+			"region": regions[rand.Intn(len(regions))],
+		}
+
+		idle := rand.Float64() * 100.0
+		fields := map[string]interface{}{
+			"idle": idle,
+			"busy": 100.0 - idle,
+		}
+
+		pt, err := client.NewPoint(
+			"cpu_usage",
+			tags,
+			fields,
+			time.Now(),
+		)
+		if err != nil {
+			println("Error:", err.Error())
+			continue
+		}
+		bp.AddPoint(pt)
+	}
+
+	err = c.Write(bp)
+	if err != nil {
+		fmt.Println("Error: ", err.Error())
+	}
+}
+
+// Make a Query
+func ExampleClient_query() {
+	// Make client
+	c, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr: "http://localhost:8086",
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+	defer c.Close()
+
+	q := client.NewQuery("SELECT count(value) FROM shapes", "square_holes", "ns")
+	if response, err := c.Query(q); err == nil && response.Error() == nil {
+		fmt.Println(response.Results)
+	}
+}
+
+// Create a Database with a query
+func ExampleClient_createDatabase() {
+	// Make client
+	c, err := client.NewHTTPClient(client.HTTPConfig{
+		Addr: "http://localhost:8086",
+	})
+	if err != nil {
+		fmt.Println("Error creating InfluxDB Client: ", err.Error())
+	}
+	defer c.Close()
+
+	q := client.NewQuery("CREATE DATABASE telegraf", "", "")
+	if response, err := c.Query(q); err == nil && response.Error() == nil {
+		fmt.Println(response.Results)
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4563a049/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/udp.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/udp.go b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/udp.go
new file mode 100644
index 0000000..779a28b
--- /dev/null
+++ b/traffic_stats/vendor/github.com/influxdata/influxdb/client/v2/udp.go
@@ -0,0 +1,112 @@
+package client
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"time"
+)
+
+const (
+	// UDPPayloadSize is a reasonable default payload size for UDP packets that
+	// could be travelling over the internet.
+	UDPPayloadSize = 512
+)
+
+// UDPConfig is the config data needed to create a UDP Client.
+type UDPConfig struct {
+	// Addr should be of the form "host:port"
+	// or "[ipv6-host%zone]:port".
+	Addr string
+
+	// PayloadSize is the maximum size of a UDP client message, optional
+	// Tune this based on your network. Defaults to UDPPayloadSize.
+	PayloadSize int
+}
+
+// NewUDPClient returns a client interface for writing to an InfluxDB UDP
+// service from the given config.
+func NewUDPClient(conf UDPConfig) (Client, error) {
+	var udpAddr *net.UDPAddr
+	udpAddr, err := net.ResolveUDPAddr("udp", conf.Addr)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := net.DialUDP("udp", nil, udpAddr)
+	if err != nil {
+		return nil, err
+	}
+
+	payloadSize := conf.PayloadSize
+	if payloadSize == 0 {
+		payloadSize = UDPPayloadSize
+	}
+
+	return &udpclient{
+		conn:        conn,
+		payloadSize: payloadSize,
+	}, nil
+}
+
+// Close releases the udpclient's resources.
+func (uc *udpclient) Close() error {
+	return uc.conn.Close()
+}
+
+type udpclient struct {
+	conn        io.WriteCloser
+	payloadSize int
+}
+
+func (uc *udpclient) Write(bp BatchPoints) error {
+	var b = make([]byte, 0, uc.payloadSize) // initial buffer size, it will grow as needed
+	var d, _ = time.ParseDuration("1" + bp.Precision())
+
+	var delayedError error
+
+	var checkBuffer = func(n int) {
+		if len(b) > 0 && len(b)+n > uc.payloadSize {
+			if _, err := uc.conn.Write(b); err != nil {
+				delayedError = err
+			}
+			b = b[:0]
+		}
+	}
+
+	for _, p := range bp.Points() {
+		p.pt.Round(d)
+		pointSize := p.pt.StringSize() + 1 // include newline in size
+		//point := p.pt.RoundedString(d) + "\n"
+
+		checkBuffer(pointSize)
+
+		if p.Time().IsZero() || pointSize <= uc.payloadSize {
+			b = p.pt.AppendString(b)
+			b = append(b, '\n')
+			continue
+		}
+
+		points := p.pt.Split(uc.payloadSize - 1) // account for newline character
+		for _, sp := range points {
+			checkBuffer(sp.StringSize() + 1)
+			b = sp.AppendString(b)
+			b = append(b, '\n')
+		}
+	}
+
+	if len(b) > 0 {
+		if _, err := uc.conn.Write(b); err != nil {
+			return err
+		}
+	}
+	return delayedError
+}
+
+func (uc *udpclient) Query(q Query) (*Response, error) {
+	return nil, fmt.Errorf("Querying via UDP is not supported")
+}
+
+func (uc *udpclient) Ping(timeout time.Duration) (time.Duration, string, error) {
+	return 0, "", nil
+}