Skip to content

Commit 1366f44

Browse files
authored
More Data added to OHI Inventory (#2007)
* ohi inventory integrationVersion, integrationName, reportingAgent added custom attributes from infra agent config are added with prefix labels/ labels from ohi config file are added with prefix labels/ * Linting and type checks * Linting issue * Added unit tests for the function building inventory * Testing at the Plugin output level as well * license and only using assert * linting issues * Tests fail when label is not found
1 parent 1765d1f commit 1366f44

File tree

7 files changed

+354
-32
lines changed

7 files changed

+354
-32
lines changed

pkg/integrations/legacy/runner.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -707,9 +707,11 @@ func EmitDataSet(
707707
if err != nil {
708708
return fmt.Errorf("couldn't determine a unique entity Key: %s", err.Error())
709709
}
710+
// Custom attributes are from infra agent config
711+
customAttr := ctx.Config().CustomAttributes.DataMap()
710712

711713
if len(dataSet.Inventory) > 0 {
712-
inventoryDataSet := BuildInventoryDataSet(elog, dataSet.Inventory, labels, integrationUser, pluginName, entityKey.String())
714+
inventoryDataSet := BuildInventoryDataSet(elog, dataSet.Inventory, labels, customAttr, integrationUser, pluginName, pluginVersion, agentIdentifier, entityKey.String())
713715
emitter.EmitInventory(inventoryDataSet, entity.NewWithoutID(entityKey))
714716
}
715717

pkg/integrations/legacy/runner_test.go

+85-16
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ func newFakePlugin(ctx customContext, pluginVersion int) externalPlugin {
509509
Context: ctx,
510510
},
511511
pluginInstance: &PluginV1Instance{
512-
Labels: map[string]string{"role": "fileserver", "environment": "development"},
512+
Labels: map[string]string{"role": "fileserver", "environment": "development", "agent_role": "overwrite agent role"},
513513
plugin: &Plugin{
514514
Name: "new-plugin",
515515
ProtocolVersion: pluginVersion,
@@ -573,7 +573,7 @@ func newFakePluginWithEnvVars(pluginVersion int) externalPlugin {
573573
Context: ctx,
574574
},
575575
pluginInstance: &PluginV1Instance{
576-
Labels: map[string]string{"role": "fileserver", "environment": "development"},
576+
Labels: map[string]string{"role": "fileserver", "environment": "development", "agent_role": "overwrite agent role"},
577577
plugin: &Plugin{
578578
Name: "new-plugin",
579579
ProtocolVersion: pluginVersion,
@@ -676,22 +676,36 @@ func (rs *RunnerSuite) TestPluginHandleOutputV1(c *C) {
676676
c.Assert(err, IsNil)
677677

678678
c.Assert(rd, NotNil)
679-
c.Assert(len(rd.Data), Equals, 4)
680-
c.Assert(rd.Data[0].SortKey(), Equals, "first")
681-
682-
invData := rd.Data[3].(protocol.InventoryData)
683-
c.Assert(invData["id"], Equals, "integrationUser")
684-
c.Assert(invData["value"], Equals, "test")
685679

686680
c.Assert(event, NotNil)
687681
c.Assert(event["event_type"], Equals, "LoadBalancerSample")
688682
c.Assert(event["id"], Equals, "first")
689683
c.Assert(event["value"], Equals, "random")
690684
c.Assert(event["integrationUser"], Equals, "test")
691685

692-
for _, labelKey := range labelKeys {
693-
if rd.Data[1].SortKey() != labelKey && rd.Data[2].SortKey() != labelKey {
694-
c.Errorf("There isn't label '%s'' in the inventory", labelKey)
686+
expectedLabelValues := map[string]string{
687+
"first": "fake",
688+
"labels/my_group": "test group",
689+
"labels/role": "fileserver",
690+
"labels/environment": "development",
691+
"labels/agent_role": "overwrite agent role",
692+
"integrationUser": "test",
693+
"integrationName": "test",
694+
"integrationVersion": "1.0.0",
695+
}
696+
697+
c.Assert(len(rd.Data), Equals, 8)
698+
699+
for _, item := range rd.Data {
700+
if invData, ok := item.(protocol.InventoryData); ok {
701+
id, _ := invData["id"].(string)
702+
value, _ := invData["value"].(string)
703+
704+
if expectedValue, exists := expectedLabelValues[id]; exists {
705+
c.Assert(value, Equals, expectedValue)
706+
} else {
707+
c.Fatalf("Expected label: %v not found in Inventory", id)
708+
}
695709
}
696710
}
697711
}
@@ -726,6 +740,7 @@ func (rs *RunnerSuite) TestPluginHandleOutputEventsV1(c *C) {
726740
// labels from pluginInstance
727741
c.Assert(event["label.environment"], Equals, "development")
728742
c.Assert(event["label.role"], Equals, "fileserver")
743+
c.Assert(event["label.agent_role"], Equals, "overwrite agent role")
729744

730745
// labels from databind
731746
c.Assert(event["label.expected"], Equals, "extra label")
@@ -831,7 +846,7 @@ func (rs *RunnerSuite) TestEventsPluginRunV1(c *C) {
831846
c.Assert(err, IsNil)
832847

833848
c.Assert(rd, NotNil)
834-
c.Assert(len(rd.Data), Equals, 3)
849+
c.Assert(len(rd.Data), Equals, 7)
835850
c.Assert(rd.Data[0].SortKey(), Equals, "first")
836851

837852
c.Assert(event, NotNil)
@@ -1030,7 +1045,7 @@ func (rs *RunnerSuite) TestHandleOutputV1(c *C) {
10301045
c.Assert(err, IsNil)
10311046

10321047
// labels are added as inventory
1033-
c.Assert(len(rd.Data)-len(labelKeys), Equals, 3)
1048+
c.Assert(len(rd.Data)-len(labelKeys), Equals, 7)
10341049

10351050
firstData := rd.Data[0]
10361051
inv := firstData.(protocol.InventoryData)
@@ -1545,12 +1560,16 @@ func TestParsePayloadV3(t *testing.T) {
15451560
type fakeEmitter struct {
15461561
lastEventData map[string]interface{}
15471562
lastEntityKey string
1563+
inventory types.PluginInventoryDataset
15481564
}
15491565

15501566
func (f *fakeEmitter) EmitInventoryWithPluginId(data types.PluginInventoryDataset, entityKey string, pluginId ids.PluginID) {
1567+
f.inventory = data
15511568
}
15521569

1553-
func (f *fakeEmitter) EmitInventory(data types.PluginInventoryDataset, entity entity.Entity) {}
1570+
func (f *fakeEmitter) EmitInventory(data types.PluginInventoryDataset, entity entity.Entity) {
1571+
f.inventory = data
1572+
}
15541573

15551574
func (f *fakeEmitter) EmitEvent(eventData map[string]interface{}, entityKey entity.Key) {
15561575
f.lastEventData = eventData
@@ -1586,6 +1605,29 @@ func TestEmitPayloadV2NoDisplayNameNoEntityName(t *testing.T) {
15861605
assert.EqualValues(t, "Motorbike", emitter.lastEventData["entityName"])
15871606
assert.EqualValues(t, "motorbike:street_hawk", emitter.lastEventData["entityKey"])
15881607

1608+
expectedLabelValues := map[string]string{
1609+
"integrationUser": "testuser",
1610+
"integrationName": "test/test",
1611+
"integrationVersion": "x.y.z",
1612+
"reportingAgent": "my-agent-id",
1613+
"motor": "", // we are type converting to string so motor does not have a value
1614+
}
1615+
1616+
assert.EqualValues(t, len(emitter.inventory), 5)
1617+
1618+
for _, item := range emitter.inventory {
1619+
if invData, ok := item.(protocol.InventoryData); ok {
1620+
id, _ := invData["id"].(string)
1621+
value, _ := invData["value"].(string)
1622+
1623+
if expectedValue, exists := expectedLabelValues[id]; exists {
1624+
assert.EqualValues(t, value, expectedValue)
1625+
} else {
1626+
assert.Fail(t, "Expected label not found in Inventory", "Label: %s not found in inventory", id)
1627+
}
1628+
}
1629+
}
1630+
15891631
// Local entity, no displayName, no entityName
15901632
assert.NoError(t, EmitDataSet(ctx, &emitter, "test/test", "x.y.z", "testuser", rd.DataSets[2], extraAnnotations, labels, entityRewrite, version))
15911633
_, ok := emitter.lastEventData["displayName"]
@@ -1594,6 +1636,27 @@ func TestEmitPayloadV2NoDisplayNameNoEntityName(t *testing.T) {
15941636
assert.False(t, ok)
15951637
// but entityKey is the agent key
15961638
assert.EqualValues(t, "my-agent-id", emitter.lastEventData["entityKey"])
1639+
1640+
// Check inventory data
1641+
assert.EqualValues(t, len(emitter.inventory), 5)
1642+
1643+
for _, item := range emitter.inventory {
1644+
if invData, ok := item.(protocol.InventoryData); ok {
1645+
id, _ := invData["id"].(string)
1646+
value, _ := invData["value"].(string)
1647+
1648+
if expectedValue, exists := expectedLabelValues[id]; exists {
1649+
assert.EqualValues(t, value, expectedValue)
1650+
} else {
1651+
assert.Fail(t, "Expected label not found in Inventory", "Label: %s not found in inventory", id)
1652+
}
1653+
}
1654+
}
1655+
}
1656+
1657+
func createMockConfigWithDataMap(attrs map[string]interface{}) *config.Config {
1658+
customAttrs := config.CustomAttributeMap(attrs)
1659+
return &config.Config{CustomAttributes: customAttrs} //nolint:all
15971660
}
15981661

15991662
func TestEmitDataSet_OnAddHostnameDecoratesWithHostname(t *testing.T) {
@@ -1626,6 +1689,7 @@ func TestEmitDataSet_OnAddHostnameDecoratesWithHostname(t *testing.T) {
16261689
ctx.On("EntityKey").Return(agentIdentifier)
16271690
ctx.On("HostnameResolver").Return(newFixedHostnameResolver(hn, "short"))
16281691
ctx.On("IDLookup").Return(newFixedIDLookup())
1692+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
16291693

16301694
em := &fakeEmitter{}
16311695
extraAnnotations := map[string]string{}
@@ -1677,6 +1741,7 @@ func TestEmitDataSet_EntityNameLocalhostIsNotReplacedWithHostnameV2(t *testing.T
16771741
ctx.On("EntityKey").Return(agID)
16781742
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("foo.bar", "short"))
16791743
ctx.On("IDLookup").Return(newFixedIDLookup())
1744+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
16801745

16811746
em := &fakeEmitter{}
16821747
extraAnnotations := map[string]string{}
@@ -1724,6 +1789,7 @@ func TestEmitDataSet_EntityNameLocalhostIsReplacedWithHostnameV3(t *testing.T) {
17241789
ctx.On("EntityKey").Return(agID)
17251790
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("foo.bar", "short"))
17261791
ctx.On("IDLookup").Return(newFixedIDLookup())
1792+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
17271793

17281794
em := &fakeEmitter{}
17291795
extraAnnotations := map[string]string{}
@@ -1772,6 +1838,7 @@ func TestEmitDataSet_MetricHostnameIsReplacedIfLocalhostV3(t *testing.T) {
17721838
ctx.On("EntityKey").Return(agID)
17731839
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("foo.bar", "short"))
17741840
ctx.On("IDLookup").Return(newFixedIDLookup())
1841+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
17751842

17761843
em := &fakeEmitter{}
17771844
extraAnnotations := map[string]string{}
@@ -1821,6 +1888,7 @@ func TestEmitDataSet_ReportingFieldsAreReplacedIfLocalhostV3(t *testing.T) {
18211888
ctx.On("EntityKey").Return(agID)
18221889
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("foo.bar", "short"))
18231890
ctx.On("IDLookup").Return(newFixedIDLookup())
1891+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
18241892

18251893
em := &fakeEmitter{}
18261894
extraAnnotations := map[string]string{}
@@ -1869,6 +1937,7 @@ func TestEmitDataSet_LogsEntityViolationsOncePerEntity(t *testing.T) {
18691937
ctx.On("EntityKey").Return(agID)
18701938
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("foo.bar", "short"))
18711939
ctx.On("IDLookup").Return(newFixedIDLookup())
1940+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
18721941

18731942
em := &fakeEmitter{}
18741943
extraAnnotations := map[string]string{}
@@ -1906,6 +1975,7 @@ func TestEmitDataSet_DoNotOverrideExistingMetrics(t *testing.T) {
19061975
ctx.On("EntityKey").Return("agent-id")
19071976
ctx.On("HostnameResolver").Return(newFixedHostnameResolver("long", "short"))
19081977
ctx.On("IDLookup").Return(newFixedIDLookup())
1978+
ctx.On("Config").Return(createMockConfigWithDataMap(make(map[string]interface{})))
19091979
em := &fakeEmitter{}
19101980
extraAnnotations := map[string]string{
19111981
"cluster_name": "K8sDiscoveredCluster",
@@ -2207,8 +2277,7 @@ func TestLogFields(t *testing.T) {
22072277
"TEMP_DIR": "a/path",
22082278
})
22092279
assert.Equal(t, fields["labels"], map[string]string{
2210-
"role": "fileserver",
2211-
"environment": "development",
2280+
"agent_role": "overwrite agent role", "environment": "development", "role": "fileserver",
22122281
})
22132282

22142283
if runtime.GOOS == "windows" {

pkg/integrations/legacy/utils.go

+37-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package legacy
44

55
import (
66
"fmt"
7+
78
"github.com/newrelic/infrastructure-agent/internal/agent/types"
89

910
event2 "github.com/newrelic/infrastructure-agent/pkg/event"
@@ -12,12 +13,22 @@ import (
1213
"github.com/sirupsen/logrus"
1314
)
1415

16+
const (
17+
integrationUserID = "integrationUser"
18+
integrationNameID = "integrationName"
19+
integrationVersionID = "integrationVersion"
20+
reportingAgentID = "reportingAgent"
21+
)
22+
1523
func BuildInventoryDataSet(
1624
entryLog log.Entry,
1725
inventoryData map[string]protocol.InventoryData,
1826
labels map[string]string,
27+
customAttr map[string]string,
1928
integrationUser string,
2029
pluginName string,
30+
pluginVersion string,
31+
reportingAgent string,
2132
entityKey string) types.PluginInventoryDataset {
2233
var inventoryDataSet types.PluginInventoryDataset
2334

@@ -31,20 +42,39 @@ func BuildInventoryDataSet(
3142
}
3243
}
3344

34-
for key, value := range labels {
45+
addLabeledData := func(id string, value string) {
3546
inventoryDataSet = append(inventoryDataSet, protocol.InventoryData{
36-
"id": fmt.Sprintf("labels/%s", key),
47+
"id": id,
3748
"value": value,
3849
"entityKey": entityKey,
3950
})
4051
}
4152

53+
for key, value := range customAttr {
54+
// Do not set in the case of duplicate key
55+
if _, exists := labels[key]; !exists {
56+
addLabeledData(fmt.Sprintf("labels/%s", key), value)
57+
}
58+
}
59+
60+
for key, value := range labels {
61+
addLabeledData(fmt.Sprintf("labels/%s", key), value)
62+
}
63+
4264
if integrationUser != "" {
43-
inventoryDataSet = append(inventoryDataSet, protocol.InventoryData{
44-
"id": "integrationUser",
45-
"value": integrationUser,
46-
"entityKey": entityKey,
47-
})
65+
addLabeledData(integrationUserID, integrationUser)
66+
}
67+
68+
if pluginName != "" {
69+
addLabeledData(integrationNameID, pluginName)
70+
}
71+
72+
if pluginVersion != "" {
73+
addLabeledData(integrationVersionID, pluginVersion)
74+
}
75+
76+
if reportingAgent != "" {
77+
addLabeledData(reportingAgentID, reportingAgent)
4878
}
4979

5080
return inventoryDataSet

0 commit comments

Comments
 (0)