Rename cisco_telemetry_gnmi input to gnmi (#7695)

This commit is contained in:
Steven Soroka 2020-07-01 02:19:16 -04:00 committed by GitHub
parent 4350dcd61c
commit 12bf382e88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 58 deletions

View File

@ -164,7 +164,6 @@ For documentation on the latest development code see the [documentation index][d
* [ceph](./plugins/inputs/ceph) * [ceph](./plugins/inputs/ceph)
* [cgroup](./plugins/inputs/cgroup) * [cgroup](./plugins/inputs/cgroup)
* [chrony](./plugins/inputs/chrony) * [chrony](./plugins/inputs/chrony)
* [cisco_telemetry_gnmi](./plugins/inputs/cisco_telemetry_gnmi)
* [cisco_telemetry_mdt](./plugins/inputs/cisco_telemetry_mdt) * [cisco_telemetry_mdt](./plugins/inputs/cisco_telemetry_mdt)
* [clickhouse](./plugins/inputs/clickhouse) * [clickhouse](./plugins/inputs/clickhouse)
* [cloud_pubsub](./plugins/inputs/cloud_pubsub) Google Cloud Pub/Sub * [cloud_pubsub](./plugins/inputs/cloud_pubsub) Google Cloud Pub/Sub
@ -197,6 +196,7 @@ For documentation on the latest development code see the [documentation index][d
* [fireboard](/plugins/inputs/fireboard) * [fireboard](/plugins/inputs/fireboard)
* [fluentd](./plugins/inputs/fluentd) * [fluentd](./plugins/inputs/fluentd)
* [github](./plugins/inputs/github) * [github](./plugins/inputs/github)
* [gnmi](./plugins/inputs/gnmi)
* [graylog](./plugins/inputs/graylog) * [graylog](./plugins/inputs/graylog)
* [haproxy](./plugins/inputs/haproxy) * [haproxy](./plugins/inputs/haproxy)
* [hddtemp](./plugins/inputs/hddtemp) * [hddtemp](./plugins/inputs/hddtemp)

View File

@ -510,6 +510,9 @@ func printFilteredInputs(inputFilters []string, commented bool) {
// Print Inputs // Print Inputs
for _, pname := range pnames { for _, pname := range pnames {
if pname == "cisco_telemetry_gnmi" {
continue
}
creator := inputs.Inputs[pname] creator := inputs.Inputs[pname]
input := creator() input := creator()

View File

@ -17,7 +17,6 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/ceph" _ "github.com/influxdata/telegraf/plugins/inputs/ceph"
_ "github.com/influxdata/telegraf/plugins/inputs/cgroup" _ "github.com/influxdata/telegraf/plugins/inputs/cgroup"
_ "github.com/influxdata/telegraf/plugins/inputs/chrony" _ "github.com/influxdata/telegraf/plugins/inputs/chrony"
_ "github.com/influxdata/telegraf/plugins/inputs/cisco_telemetry_gnmi"
_ "github.com/influxdata/telegraf/plugins/inputs/cisco_telemetry_mdt" _ "github.com/influxdata/telegraf/plugins/inputs/cisco_telemetry_mdt"
_ "github.com/influxdata/telegraf/plugins/inputs/clickhouse" _ "github.com/influxdata/telegraf/plugins/inputs/clickhouse"
_ "github.com/influxdata/telegraf/plugins/inputs/cloud_pubsub" _ "github.com/influxdata/telegraf/plugins/inputs/cloud_pubsub"
@ -51,6 +50,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/fireboard" _ "github.com/influxdata/telegraf/plugins/inputs/fireboard"
_ "github.com/influxdata/telegraf/plugins/inputs/fluentd" _ "github.com/influxdata/telegraf/plugins/inputs/fluentd"
_ "github.com/influxdata/telegraf/plugins/inputs/github" _ "github.com/influxdata/telegraf/plugins/inputs/github"
_ "github.com/influxdata/telegraf/plugins/inputs/gnmi"
_ "github.com/influxdata/telegraf/plugins/inputs/graylog" _ "github.com/influxdata/telegraf/plugins/inputs/graylog"
_ "github.com/influxdata/telegraf/plugins/inputs/haproxy" _ "github.com/influxdata/telegraf/plugins/inputs/haproxy"
_ "github.com/influxdata/telegraf/plugins/inputs/hddtemp" _ "github.com/influxdata/telegraf/plugins/inputs/hddtemp"

View File

@ -1,6 +1,6 @@
# Cisco GNMI Telemetry # gNMI (gRPC Network Management Interface)
This plugin consumes telemetry data based on the [gNMI](https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md) Subscribe method. TLS is supported for authentication and encryption. This input plugin is vendor-agnostic and is supported on any platform that supports the gNMI spec. This plugin consumes telemetry data based on the [gNMI](https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md) Subscribe method. TLS is supported for authentication and encryption. This input plugin is vendor-agnostic and is supported on any platform that supports the gNMI spec.
For Cisco devices: For Cisco devices:
It has been optimized to support gNMI telemetry as produced by Cisco IOS XR (64-bit) version 6.5.1, Cisco NX-OS 9.3 and Cisco IOS XE 16.12 and later. It has been optimized to support gNMI telemetry as produced by Cisco IOS XR (64-bit) version 6.5.1, Cisco NX-OS 9.3 and Cisco IOS XE 16.12 and later.
@ -9,15 +9,15 @@ It has been optimized to support gNMI telemetry as produced by Cisco IOS XR (64-
### Configuration ### Configuration
```toml ```toml
[[inputs.cisco_telemetry_gnmi]] [[inputs.gnmi]]
## Address and port of the GNMI GRPC server ## Address and port of the gNMI GRPC server
addresses = ["10.49.234.114:57777"] addresses = ["10.49.234.114:57777"]
## define credentials ## define credentials
username = "cisco" username = "cisco"
password = "cisco" password = "cisco"
## GNMI encoding requested (one of: "proto", "json", "json_ietf") ## gNMI encoding requested (one of: "proto", "json", "json_ietf")
# encoding = "proto" # encoding = "proto"
## redial in case of failures after ## redial in case of failures after
@ -32,17 +32,17 @@ It has been optimized to support gNMI telemetry as produced by Cisco IOS XR (64-
# tls_cert = "/etc/telegraf/cert.pem" # tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem" # tls_key = "/etc/telegraf/key.pem"
## GNMI subscription prefix (optional, can usually be left empty) ## gNMI subscription prefix (optional, can usually be left empty)
## See: https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#222-paths ## See: https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#222-paths
# origin = "" # origin = ""
# prefix = "" # prefix = ""
# target = "" # target = ""
## Define additional aliases to map telemetry encoding paths to simple measurement names ## Define additional aliases to map telemetry encoding paths to simple measurement names
# [inputs.cisco_telemetry_gnmi.aliases] # [inputs.gnmi.aliases]
# ifcounters = "openconfig:/interfaces/interface/state/counters" # ifcounters = "openconfig:/interfaces/interface/state/counters"
[[inputs.cisco_telemetry_gnmi.subscription]] [[inputs.gnmi.subscription]]
## Name of the measurement that will be emitted ## Name of the measurement that will be emitted
name = "ifcounters" name = "ifcounters"

View File

@ -1,4 +1,4 @@
package cisco_telemetry_gnmi package gnmi
import ( import (
"bytes" "bytes"
@ -26,8 +26,8 @@ import (
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
) )
// CiscoTelemetryGNMI plugin instance // gNMI plugin instance
type CiscoTelemetryGNMI struct { type GNMI struct {
Addresses []string `toml:"addresses"` Addresses []string `toml:"addresses"`
Subscriptions []Subscription `toml:"subscription"` Subscriptions []Subscription `toml:"subscription"`
Aliases map[string]string `toml:"aliases"` Aliases map[string]string `toml:"aliases"`
@ -39,7 +39,7 @@ type CiscoTelemetryGNMI struct {
Target string Target string
UpdatesOnly bool `toml:"updates_only"` UpdatesOnly bool `toml:"updates_only"`
// Cisco IOS XR credentials // gNMI target credentials
Username string Username string
Password string Password string
@ -59,7 +59,7 @@ type CiscoTelemetryGNMI struct {
Log telegraf.Logger Log telegraf.Logger
} }
// Subscription for a GNMI client // Subscription for a gNMI client
type Subscription struct { type Subscription struct {
Name string Name string
Origin string Origin string
@ -75,7 +75,7 @@ type Subscription struct {
} }
// Start the http listener service // Start the http listener service
func (c *CiscoTelemetryGNMI) Start(acc telegraf.Accumulator) error { func (c *GNMI) Start(acc telegraf.Accumulator) error {
var err error var err error
var ctx context.Context var ctx context.Context
var tlscfg *tls.Config var tlscfg *tls.Config
@ -151,8 +151,8 @@ func (c *CiscoTelemetryGNMI) Start(acc telegraf.Accumulator) error {
return nil return nil
} }
// Create a new GNMI SubscribeRequest // Create a new gNMI SubscribeRequest
func (c *CiscoTelemetryGNMI) newSubscribeRequest() (*gnmi.SubscribeRequest, error) { func (c *GNMI) newSubscribeRequest() (*gnmi.SubscribeRequest, error) {
// Create subscription objects // Create subscription objects
subscriptions := make([]*gnmi.Subscription, len(c.Subscriptions)) subscriptions := make([]*gnmi.Subscription, len(c.Subscriptions))
for i, subscription := range c.Subscriptions { for i, subscription := range c.Subscriptions {
@ -197,7 +197,7 @@ func (c *CiscoTelemetryGNMI) newSubscribeRequest() (*gnmi.SubscribeRequest, erro
} }
// SubscribeGNMI and extract telemetry data // SubscribeGNMI and extract telemetry data
func (c *CiscoTelemetryGNMI) subscribeGNMI(ctx context.Context, address string, tlscfg *tls.Config, request *gnmi.SubscribeRequest) error { func (c *GNMI) subscribeGNMI(ctx context.Context, address string, tlscfg *tls.Config, request *gnmi.SubscribeRequest) error {
var opt grpc.DialOption var opt grpc.DialOption
if tlscfg != nil { if tlscfg != nil {
opt = grpc.WithTransportCredentials(credentials.NewTLS(tlscfg)) opt = grpc.WithTransportCredentials(credentials.NewTLS(tlscfg))
@ -220,13 +220,13 @@ func (c *CiscoTelemetryGNMI) subscribeGNMI(ctx context.Context, address string,
return fmt.Errorf("failed to send subscription request: %v", err) return fmt.Errorf("failed to send subscription request: %v", err)
} }
c.Log.Debugf("Connection to GNMI device %s established", address) c.Log.Debugf("Connection to gNMI device %s established", address)
defer c.Log.Debugf("Connection to GNMI device %s closed", address) defer c.Log.Debugf("Connection to gNMI device %s closed", address)
for ctx.Err() == nil { for ctx.Err() == nil {
var reply *gnmi.SubscribeResponse var reply *gnmi.SubscribeResponse
if reply, err = subscribeClient.Recv(); err != nil { if reply, err = subscribeClient.Recv(); err != nil {
if err != io.EOF && ctx.Err() == nil { if err != io.EOF && ctx.Err() == nil {
return fmt.Errorf("aborted GNMI subscription: %v", err) return fmt.Errorf("aborted gNMI subscription: %v", err)
} }
break break
} }
@ -236,9 +236,9 @@ func (c *CiscoTelemetryGNMI) subscribeGNMI(ctx context.Context, address string,
return nil return nil
} }
// HandleSubscribeResponse message from GNMI and parse contained telemetry data // HandleSubscribeResponse message from gNMI and parse contained telemetry data
func (c *CiscoTelemetryGNMI) handleSubscribeResponse(address string, reply *gnmi.SubscribeResponse) { func (c *GNMI) handleSubscribeResponse(address string, reply *gnmi.SubscribeResponse) {
// Check if response is a GNMI Update and if we have a prefix to derive the measurement name // Check if response is a gNMI Update and if we have a prefix to derive the measurement name
response, ok := reply.Response.(*gnmi.SubscribeResponse_Update) response, ok := reply.Response.(*gnmi.SubscribeResponse_Update)
if !ok { if !ok {
return return
@ -276,7 +276,7 @@ func (c *CiscoTelemetryGNMI) handleSubscribeResponse(address string, reply *gnmi
if alias, ok := c.aliases[aliasPath]; ok { if alias, ok := c.aliases[aliasPath]; ok {
name = alias name = alias
} else { } else {
c.Log.Debugf("No measurement alias for GNMI path: %s", name) c.Log.Debugf("No measurement alias for gNMI path: %s", name)
} }
} }
@ -313,7 +313,7 @@ func (c *CiscoTelemetryGNMI) handleSubscribeResponse(address string, reply *gnmi
} }
// HandleTelemetryField and add it to a measurement // HandleTelemetryField and add it to a measurement
func (c *CiscoTelemetryGNMI) handleTelemetryField(update *gnmi.Update, tags map[string]string, prefix string) (string, map[string]interface{}) { func (c *GNMI) handleTelemetryField(update *gnmi.Update, tags map[string]string, prefix string) (string, map[string]interface{}) {
path, aliasPath := c.handlePath(update.Path, tags, prefix) path, aliasPath := c.handlePath(update.Path, tags, prefix)
var value interface{} var value interface{}
@ -364,7 +364,7 @@ func (c *CiscoTelemetryGNMI) handleTelemetryField(update *gnmi.Update, tags map[
} }
// Parse path to path-buffer and tag-field // Parse path to path-buffer and tag-field
func (c *CiscoTelemetryGNMI) handlePath(path *gnmi.Path, tags map[string]string, prefix string) (string, string) { func (c *GNMI) handlePath(path *gnmi.Path, tags map[string]string, prefix string) (string, string) {
var aliasPath string var aliasPath string
builder := bytes.NewBufferString(prefix) builder := bytes.NewBufferString(prefix)
@ -404,7 +404,7 @@ func (c *CiscoTelemetryGNMI) handlePath(path *gnmi.Path, tags map[string]string,
return builder.String(), aliasPath return builder.String(), aliasPath
} }
//ParsePath from XPath-like string to GNMI path structure //ParsePath from XPath-like string to gNMI path structure
func parsePath(origin string, path string, target string) (*gnmi.Path, error) { func parsePath(origin string, path string, target string) (*gnmi.Path, error) {
var err error var err error
gnmiPath := gnmi.Path{Origin: origin, Target: target} gnmiPath := gnmi.Path{Origin: origin, Target: target}
@ -458,7 +458,7 @@ func parsePath(origin string, path string, target string) (*gnmi.Path, error) {
} }
if name >= 0 || value >= 0 { if name >= 0 || value >= 0 {
err = fmt.Errorf("Invalid GNMI path: %s", path) err = fmt.Errorf("Invalid gNMI path: %s", path)
} }
if err != nil { if err != nil {
@ -469,20 +469,20 @@ func parsePath(origin string, path string, target string) (*gnmi.Path, error) {
} }
// Stop listener and cleanup // Stop listener and cleanup
func (c *CiscoTelemetryGNMI) Stop() { func (c *GNMI) Stop() {
c.cancel() c.cancel()
c.wg.Wait() c.wg.Wait()
} }
const sampleConfig = ` const sampleConfig = `
## Address and port of the GNMI GRPC server ## Address and port of the gNMI GRPC server
addresses = ["10.49.234.114:57777"] addresses = ["10.49.234.114:57777"]
## define credentials ## define credentials
username = "cisco" username = "cisco"
password = "cisco" password = "cisco"
## GNMI encoding requested (one of: "proto", "json", "json_ietf") ## gNMI encoding requested (one of: "proto", "json", "json_ietf")
# encoding = "proto" # encoding = "proto"
## redial in case of failures after ## redial in case of failures after
@ -497,17 +497,17 @@ const sampleConfig = `
# tls_cert = "/etc/telegraf/cert.pem" # tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem" # tls_key = "/etc/telegraf/key.pem"
## GNMI subscription prefix (optional, can usually be left empty) ## gNMI subscription prefix (optional, can usually be left empty)
## See: https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#222-paths ## See: https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#222-paths
# origin = "" # origin = ""
# prefix = "" # prefix = ""
# target = "" # target = ""
## Define additional aliases to map telemetry encoding paths to simple measurement names ## Define additional aliases to map telemetry encoding paths to simple measurement names
#[inputs.cisco_telemetry_gnmi.aliases] #[inputs.gnmi.aliases]
# ifcounters = "openconfig:/interfaces/interface/state/counters" # ifcounters = "openconfig:/interfaces/interface/state/counters"
[[inputs.cisco_telemetry_gnmi.subscription]] [[inputs.gnmi.subscription]]
## Name of the measurement that will be emitted ## Name of the measurement that will be emitted
name = "ifcounters" name = "ifcounters"
@ -532,25 +532,29 @@ const sampleConfig = `
` `
// SampleConfig of plugin // SampleConfig of plugin
func (c *CiscoTelemetryGNMI) SampleConfig() string { func (c *GNMI) SampleConfig() string {
return sampleConfig return sampleConfig
} }
// Description of plugin // Description of plugin
func (c *CiscoTelemetryGNMI) Description() string { func (c *GNMI) Description() string {
return "Cisco GNMI telemetry input plugin based on GNMI telemetry data produced in IOS XR" return "gNMI telemetry input plugin"
} }
// Gather plugin measurements (unused) // Gather plugin measurements (unused)
func (c *CiscoTelemetryGNMI) Gather(_ telegraf.Accumulator) error { func (c *GNMI) Gather(_ telegraf.Accumulator) error {
return nil return nil
} }
func init() { func New() telegraf.Input {
inputs.Add("cisco_telemetry_gnmi", func() telegraf.Input { return &GNMI{
return &CiscoTelemetryGNMI{ Encoding: "proto",
Encoding: "proto", Redial: internal.Duration{Duration: 10 * time.Second},
Redial: internal.Duration{Duration: 10 * time.Second}, }
} }
})
func init() {
inputs.Add("gnmi", New)
// Backwards compatible alias:
inputs.Add("cisco_telemetry_gnmi", New)
} }

View File

@ -1,4 +1,4 @@
package cisco_telemetry_gnmi package gnmi
import ( import (
"context" "context"
@ -36,7 +36,7 @@ func TestParsePath(t *testing.T) {
parsed, err = parsePath("", "/foo[[", "") parsed, err = parsePath("", "/foo[[", "")
assert.Nil(t, parsed) assert.Nil(t, parsed)
assert.Equal(t, errors.New("Invalid GNMI path: /foo[[/"), err) assert.Equal(t, errors.New("Invalid gNMI path: /foo[[/"), err)
} }
type MockServer struct { type MockServer struct {
@ -73,7 +73,7 @@ func TestWaitError(t *testing.T) {
} }
gnmi.RegisterGNMIServer(grpcServer, gnmiServer) gnmi.RegisterGNMIServer(grpcServer, gnmiServer)
plugin := &CiscoTelemetryGNMI{ plugin := &GNMI{
Log: testutil.Logger{}, Log: testutil.Logger{},
Addresses: []string{listener.Addr().String()}, Addresses: []string{listener.Addr().String()},
Encoding: "proto", Encoding: "proto",
@ -98,7 +98,7 @@ func TestWaitError(t *testing.T) {
wg.Wait() wg.Wait()
require.Contains(t, acc.Errors, require.Contains(t, acc.Errors,
errors.New("aborted GNMI subscription: rpc error: code = Unknown desc = testerror")) errors.New("aborted gNMI subscription: rpc error: code = Unknown desc = testerror"))
} }
func TestUsernamePassword(t *testing.T) { func TestUsernamePassword(t *testing.T) {
@ -129,7 +129,7 @@ func TestUsernamePassword(t *testing.T) {
} }
gnmi.RegisterGNMIServer(grpcServer, gnmiServer) gnmi.RegisterGNMIServer(grpcServer, gnmiServer)
plugin := &CiscoTelemetryGNMI{ plugin := &GNMI{
Log: testutil.Logger{}, Log: testutil.Logger{},
Addresses: []string{listener.Addr().String()}, Addresses: []string{listener.Addr().String()},
Username: "theusername", Username: "theusername",
@ -156,7 +156,7 @@ func TestUsernamePassword(t *testing.T) {
wg.Wait() wg.Wait()
require.Contains(t, acc.Errors, require.Contains(t, acc.Errors,
errors.New("aborted GNMI subscription: rpc error: code = Unknown desc = success")) errors.New("aborted gNMI subscription: rpc error: code = Unknown desc = success"))
} }
func mockGNMINotification() *gnmi.Notification { func mockGNMINotification() *gnmi.Notification {
@ -209,13 +209,13 @@ func mockGNMINotification() *gnmi.Notification {
func TestNotification(t *testing.T) { func TestNotification(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
plugin *CiscoTelemetryGNMI plugin *GNMI
server *MockServer server *MockServer
expected []telegraf.Metric expected []telegraf.Metric
}{ }{
{ {
name: "multiple metrics", name: "multiple metrics",
plugin: &CiscoTelemetryGNMI{ plugin: &GNMI{
Log: testutil.Logger{}, Log: testutil.Logger{},
Encoding: "proto", Encoding: "proto",
Redial: internal.Duration{Duration: 1 * time.Second}, Redial: internal.Duration{Duration: 1 * time.Second},
@ -299,7 +299,7 @@ func TestNotification(t *testing.T) {
}, },
{ {
name: "full path field key", name: "full path field key",
plugin: &CiscoTelemetryGNMI{ plugin: &GNMI{
Log: testutil.Logger{}, Log: testutil.Logger{},
Encoding: "proto", Encoding: "proto",
Redial: internal.Duration{Duration: 1 * time.Second}, Redial: internal.Duration{Duration: 1 * time.Second},
@ -407,7 +407,7 @@ func TestRedial(t *testing.T) {
listener, err := net.Listen("tcp", "127.0.0.1:0") listener, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err) require.NoError(t, err)
plugin := &CiscoTelemetryGNMI{ plugin := &GNMI{
Log: testutil.Logger{}, Log: testutil.Logger{},
Addresses: []string{listener.Addr().String()}, Addresses: []string{listener.Addr().String()},
Encoding: "proto", Encoding: "proto",
@ -441,7 +441,7 @@ func TestRedial(t *testing.T) {
grpcServer.Stop() grpcServer.Stop()
wg.Wait() wg.Wait()
// Restart GNMI server at the same address // Restart gNMI server at the same address
listener, err = net.Listen("tcp", listener.Addr().String()) listener, err = net.Listen("tcp", listener.Addr().String())
require.NoError(t, err) require.NoError(t, err)