Repository: kentik/ktranslate (go)

Issue:
FR: Ability to embed static values directly in the profile
Looking for a syntax that would allow users to define attributes and values inside the SNMP and trap profiles, independent of device tagging.  For example to help with directing all BGP related traps they could add an attribute that they would key into to direct the event to the team who handles routing, or if a vmware trap comes in they would be able to route it to the virtualization team.

This would primarily be used with cases where customers are using their own modified profiles.

Thinking in the trap profile adding something like

```
traps:
  - trap_oid: 1.3.6.1.4.1.6876.4.3
    trap_name: vmwVCNotifications
    drop_undefined: true
    events:
      - name: vmwVpxdOldStatus
        OID: 1.3.6.1.4.1.6876.4.3.304.0
        tag: old_status
      - name: vmwVpxdNewStatus
        OID: 1.3.6.1.4.1.6876.4.3.305.0
        tag: new_status
      - name: vmwVpxdObjValue
        OID: 1.3.6.1.4.1.6876.4.3.306.0
        tag: object_value
      - name: vmwVpxdTargetObj
        OID: 1.3.6.1.4.1.6876.4.3.307.0
        tag: object_name
      - name: vmwVpxdTargetObjType
        OID: 1.3.6.1.4.1.6876.4.3.308.0
        enum:
          unknown: 1
          host: 2
          vm: 3
          other: 4
        tag: object_type
    attributes:
      responsible_team: vmware
```


Pull request description:
Allow static attributes on traps
Allows adding a value like 

```
    attributes:
      responsible_team: vmware
      cHsrpGrpTable: 777
```

To trap definitions. Then these fields are added to traps caught. If there's a conflict between a variable var name and a constant one, the variable wins. 

Closes #564



Patch:
diff --git a/pkg/inputs/snmp/mibs/load.go b/pkg/inputs/snmp/mibs/load.go
index 93cab0c..08da010 100644
--- a/pkg/inputs/snmp/mibs/load.go
+++ b/pkg/inputs/snmp/mibs/load.go
@@ -95,7 +95,7 @@ func (db *MibDB) GetTrap(oid string) *Trap {
 
 func (db *MibDB) GetForKey(oid string) (*kt.Mib, map[string]string, error) {
 	if res, ok := db.trapMibs[oid]; ok {
-		return res, nil, nil
+		return res, res.XAttr, nil
 	}
 
 	// Now walk resursivly up the tree, seeing what profiles are found via a wildcard or variables.
@@ -115,6 +115,12 @@ func (db *MibDB) GetForKey(oid string) (*kt.Mib, map[string]string, error) {
 					attrs[name] = strings.Join(pts[posits[0]:posits[0]+posits[1]], ".")
 				}
 			}
+			// Also fill in any const attrs here if they are not already set.
+			for k, v := range t.XAttr {
+				if _, ok := attrs[k]; !ok {
+					attrs[k] = v
+				}
+			}
 			return t, attrs, nil
 		}
 	}
diff --git a/pkg/inputs/snmp/mibs/trap.go b/pkg/inputs/snmp/mibs/trap.go
index 9639af8..b9ca786 100644
--- a/pkg/inputs/snmp/mibs/trap.go
+++ b/pkg/inputs/snmp/mibs/trap.go
@@ -12,10 +12,11 @@ import (
 )
 
 type Trap struct {
-	Oid           string `yaml:"trap_oid"`
-	Name          string `yaml:"trap_name"`
-	DropUndefined bool   `yaml:"drop_undefined"`
-	Events        []OID  `yaml:"events"`
+	Oid           string            `yaml:"trap_oid"`
+	Name          string            `yaml:"trap_name"`
+	DropUndefined bool              `yaml:"drop_undefined"`
+	Events        []OID             `yaml:"events"`
+	Attributes    map[string]string `yaml:"attributes"`
 }
 
 type TrapBase struct {
@@ -93,6 +94,7 @@ func (mdb *MibDB) parseTrapsFromYml(fname string, file os.DirEntry, extends map[
 				Extra:      trap.Name,
 				Mib:        trap.Oid,
 				VarSet:     kvs,
+				XAttr:      trap.Attributes,
 			}
 			if len(mib.Enum) > 0 {
 				mib.EnumRev = make(map[int64]string)
diff --git a/pkg/kt/snmp.go b/pkg/kt/snmp.go
index 99c1f8d..245a582 100644
--- a/pkg/kt/snmp.go
+++ b/pkg/kt/snmp.go
@@ -386,6 +386,7 @@ type Mib struct {
 	Condition    *MibCondition
 	Script       Enricher
 	VarSet       map[string][]int
+	XAttr        map[string]string
 }
 
 type Enricher interface {


Test patch:
diff --git a/pkg/inputs/snmp/mibs/trap_test.go b/pkg/inputs/snmp/mibs/trap_test.go
index 0b92ee3..d97ee0d 100644
--- a/pkg/inputs/snmp/mibs/trap_test.go
+++ b/pkg/inputs/snmp/mibs/trap_test.go
@@ -44,6 +44,9 @@ traps:
         OID: 1.3.6.1.4.1.9.9.666.1.3.4.5.{cHsrpGrpTable:2}.{ifIndex:1}
       - name: chsrpTrapVarYandex
         OID: 1.3.6.1.4.1.9.9.1811.1.3.4.5.{ifIndex:1}.{cHsrpGrpTable:2}
+    attributes:
+      responsible_team: vmware
+      cHsrpGrpTable: 777
 `)
 	// Save test data to local.
 	file, err := ioutil.TempFile("", "")
@@ -62,34 +65,39 @@ traps:
 	tr, attr, err := mdb.GetForKey(".1.3.6.1.4.1.34510.2.1.1.3.2.1.1")
 	assert.NoError(t, err)
 	assert.Equal(t, "vdcAlarmId", tr.Name)
-	assert.Equal(t, 0, len(attr))
+	assert.Equal(t, 2, len(attr))
 
 	tr, attr, err = mdb.GetForKey(".1.3.6.1.4.1.34510.22.1.2.3.4.5.6")
 	assert.NoError(t, err)
 	assert.Equal(t, "vdcMonAttribWild", tr.Name)
-	assert.Equal(t, 0, len(attr))
+	assert.Equal(t, 2, len(attr))
 
 	tr, attr, err = mdb.GetForKey(".1.3.6.1.4.1.9.9.187.1.2.1.1.7.2.2.2.3")
 	assert.NoError(t, err)
 	assert.Equal(t, "cbgpPeerLastErrorTxt", tr.Name)
 	assert.Equal(t, "2.2.2.3", attr["bgpPeerRemoteAddr"])
 	assert.Equal(t, "", attr["ifIndex"]) // Since this is after a wildcard, assume nothing because there are no valid tokens to consume.
+	assert.Equal(t, "vmware", attr["responsible_team"])
+	assert.Equal(t, "777", attr["cHsrpGrpTable"])
 
 	tr, attr, err = mdb.GetForKey(".1.3.6.1.4.1.9.9.187.1.3.4.5.999.666")
 	assert.NoError(t, err)
 	assert.Equal(t, "chsrpTrapVarBing", tr.Name)
 	assert.Equal(t, "999", attr["ifIndex"])
 	assert.Equal(t, "666", attr["cHsrpGrpTable"])
+	assert.Equal(t, "vmware", attr["responsible_team"])
 
 	tr, attr, err = mdb.GetForKey(".1.3.6.1.4.1.9.9.666.1.3.4.5.66.99.333")
 	assert.NoError(t, err)
 	assert.Equal(t, "chsrpTwoOne", tr.Name)
 	assert.Equal(t, "333", attr["ifIndex"])
 	assert.Equal(t, "66.99", attr["cHsrpGrpTable"])
+	assert.Equal(t, "vmware", attr["responsible_team"])
 
 	tr, attr, err = mdb.GetForKey(".1.3.6.1.4.1.9.9.1811.1.3.4.5.66.99.333")
 	assert.NoError(t, err)
 	assert.Equal(t, "chsrpTrapVarYandex", tr.Name)
 	assert.Equal(t, "66", attr["ifIndex"])
 	assert.Equal(t, "99.333", attr["cHsrpGrpTable"])
+	assert.Equal(t, "vmware", attr["responsible_team"])
 }