Skip to content

Commit

Permalink
fix(inputs.gnmi): Allow optional origin for update path (#13304)
Browse files Browse the repository at this point in the history
  • Loading branch information
srebhan authored May 23, 2023
1 parent 66f4b5b commit fb3cd61
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 32 deletions.
27 changes: 9 additions & 18 deletions plugins/inputs/gnmi/gnmi.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,34 +346,25 @@ func (s *Subscription) buildFullPath(c *GNMI) error {
}

func (s *Subscription) buildAlias(aliases map[string]string) error {
var err error
var gnmiLongPath, gnmiShortPath *gnmiLib.Path

// Build the subscription path without keys
if gnmiLongPath, err = parsePath(s.Origin, s.Path, ""); err != nil {
return err
}
if gnmiShortPath, err = parsePath("", s.Path, ""); err != nil {
gnmiPath, err := parsePath(s.Origin, s.Path, "")
if err != nil {
return err
}

longPath, _, err := handlePath(gnmiLongPath, nil, nil, "")
if err != nil {
return fmt.Errorf("handling long-path failed: %w", err)
}
shortPath, _, err := handlePath(gnmiShortPath, nil, nil, "")
origin, spath, _, err := handlePath(gnmiPath, nil, nil, "")
if err != nil {
return fmt.Errorf("handling short-path failed: %w", err)
return fmt.Errorf("handling path failed: %w", err)
}

// If the user didn't provide a measurement name, use last path element
name := s.Name
if len(name) == 0 {
name = path.Base(shortPath)
if name == "" {
name = path.Base(spath)
}
if len(name) > 0 {
aliases[longPath] = name
aliases[shortPath] = name
if name != "" {
aliases[origin+spath] = name
aliases[spath] = name
}
return nil
}
6 changes: 4 additions & 2 deletions plugins/inputs/gnmi/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ func (h *handler) handleSubscribeResponseUpdate(acc telegraf.Accumulator, respon
}

if response.Update.Prefix != nil {
var origin string
var err error
if prefix, prefixAliasPath, err = handlePath(response.Update.Prefix, prefixTags, h.aliases, ""); err != nil {
if origin, prefix, prefixAliasPath, err = handlePath(response.Update.Prefix, prefixTags, h.aliases, ""); err != nil {
h.log.Errorf("handling path %q failed: %v", response.Update.Prefix, err)
}
prefix = origin + prefix
}

prefixTags["source"], _, _ = net.SplitHostPort(h.address)
Expand Down Expand Up @@ -287,7 +289,7 @@ func (h *handler) handleSubscribeResponseUpdate(acc telegraf.Accumulator, respon

// HandleTelemetryField and add it to a measurement
func (h *handler) handleTelemetryField(update *gnmiLib.Update, tags map[string]string, prefix string) (string, map[string]interface{}) {
gpath, aliasPath, err := handlePath(update.Path, tags, h.aliases, prefix)
_, gpath, aliasPath, err := handlePath(update.Path, tags, h.aliases, prefix)
if err != nil {
h.log.Errorf("handling path %q failed: %v", update.Path, err)
}
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/gnmi/testcases/issue_12931/expected.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
interface,name=ethernet-1/1,source=127.0.0.1 interface=1i,transceiver=2i,ethernet=3i,ethernet/flow_control="false",sflow="disable" 1679648530391910312
94 changes: 94 additions & 0 deletions plugins/inputs/gnmi/testcases/issue_12931/responses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
[
{
"update": {
"timestamp": "1679648530391910312",
"update": [
{
"path": {
"origin": "srl_nokia-interfaces",
"elem": [
{
"name": "interface",
"key":{"name":"ethernet-1/1"}
}
]
},
"val": {
"intVal": "1"
}
},
{
"path": {
"origin": "srl_nokia-interfaces",
"elem": [
{
"name": "interface",
"key":{"name":"ethernet-1/1"}
},
{
"name": "transceiver"
}
]
},
"val": {
"intVal": "2"
}
},
{
"path": {
"origin": "srl_nokia-interfaces",
"elem": [
{
"name": "interface",
"key":{"name":"ethernet-1/1"}
},
{
"name": "ethernet"
}
]
},
"val": {
"intVal": "3"
}
},
{
"path": {
"origin": "srl_nokia-interfaces",
"elem": [
{
"name": "interface",
"key":{"name":"ethernet-1/1"}
},
{
"name": "ethernet"
},
{
"name": "flow-control"
}
]
},
"val": {
"stringVal": "false"
}
},
{
"path": {
"origin": "srl_nokia-interfaces",
"elem": [
{
"name": "interface",
"key":{"name":"ethernet-1/1"}
},
{
"name": "sflow"
}
]
},
"val": {
"stringVal": "disable"
}
}
]
}
}
]
10 changes: 10 additions & 0 deletions plugins/inputs/gnmi/testcases/issue_12931/telegraf.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[[inputs.gnmi]]
addresses = ["dummy"]
name_override = "gnmi"
redial = "10s"

[[inputs.gnmi.subscription]]
name = "interface"
path = "/interface"
subscription_mode = "sample"
sample_interval = "10s"
23 changes: 11 additions & 12 deletions plugins/inputs/gnmi/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
)

// Parse path to path-buffer and tag-field
func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[string]string, prefix string) (pathBuffer string, aliasPath string, err error) {
//
//nolint:revive //function-result-limit conditionally 4 return results allowed
func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[string]string, prefix string) (origin, path, alias string, err error) {
builder := bytes.NewBufferString(prefix)

// Some devices do report the origin in the first path element
Expand All @@ -28,28 +30,25 @@ func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[stri

// Prefix with origin
if len(gnmiPath.Origin) > 0 {
if _, err := builder.WriteString(gnmiPath.Origin); err != nil {
return "", "", err
}
if _, err := builder.WriteRune(':'); err != nil {
return "", "", err
}
origin = gnmiPath.Origin + ":"
}

// Parse generic keys from prefix
for _, elem := range gnmiPath.Elem {
if len(elem.Name) > 0 {
if _, err := builder.WriteRune('/'); err != nil {
return "", "", err
return "", "", "", err
}
if _, err := builder.WriteString(elem.Name); err != nil {
return "", "", err
return "", "", "", err
}
}
name := builder.String()

if _, exists := aliases[name]; exists {
aliasPath = name
if _, exists := aliases[origin+name]; exists {
alias = origin + name
} else if _, exists := aliases[name]; exists {
alias = name
}

if tags != nil {
Expand All @@ -66,7 +65,7 @@ func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[stri
}
}

return builder.String(), aliasPath, nil
return origin, builder.String(), alias, nil
}

// equalPathNoKeys checks if two gNMI paths are equal, without keys
Expand Down

0 comments on commit fb3cd61

Please sign in to comment.