From 0aa11fa5fee2b4c76029fc6db67a3de49c35e499 Mon Sep 17 00:00:00 2001 From: "agent-platform-auto-pr[bot]" <153269286+agent-platform-auto-pr[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 15:20:18 +0100 Subject: [PATCH 1/3] [Backport 7.63.x] [CWS] add missing exit progs entry for stat (#33353) Co-authored-by: Sylvain Afchain --- pkg/security/ebpf/probes/raw_sys_exit.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/security/ebpf/probes/raw_sys_exit.go b/pkg/security/ebpf/probes/raw_sys_exit.go index 14e489cb47a580..c31717ae003b88 100644 --- a/pkg/security/ebpf/probes/raw_sys_exit.go +++ b/pkg/security/ebpf/probes/raw_sys_exit.go @@ -198,5 +198,12 @@ func getSysExitTailCallRoutes() []manager.TailCallRoute { EBPFFuncName: "tracepoint_handle_sys_chdir_exit", }, }, + { + ProgArrayName: "sys_exit_progs", + Key: uint32(model.StatEventType), + ProbeIdentificationPair: manager.ProbeIdentificationPair{ + EBPFFuncName: "tracepoint_handle_sys_newfstatat_exit", + }, + }, } } From a52854e2f39d0c1be3c813023d78a545c7bb72dd Mon Sep 17 00:00:00 2001 From: "agent-platform-auto-pr[bot]" <153269286+agent-platform-auto-pr[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:25:54 -0500 Subject: [PATCH 2/3] [Backport 7.63.x] exclude `.git` from copyright linter (#33361) Co-authored-by: Paul Cacheux --- tasks/libs/types/copyright.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/libs/types/copyright.py b/tasks/libs/types/copyright.py index 3d19e49ba4603d..9212fbfbbe0715 100755 --- a/tasks/libs/types/copyright.py +++ b/tasks/libs/types/copyright.py @@ -24,6 +24,8 @@ # These path patterns are excluded from checks PATH_EXCLUSION_REGEX = [ + # Git internal folder + '/.git/', # These are auto-generated files but without headers to indicate it '/vendor/', '/pkg/clusteragent/autoscaling/custommetrics/api/generated/', From c9be94b01fc6c4cdc8fd5d572df061f9d404002f Mon Sep 17 00:00:00 2001 From: Daniel Lepage Date: Fri, 24 Jan 2025 11:10:58 -0500 Subject: [PATCH 3/3] Revert "[NDM] Cache in Devicecheck (#32373)" This reverts commit ec49b990ab57302d898fa7e366a2aad6da95a630. --- .../snmp/internal/checkconfig/buildprofile.go | 74 --- .../internal/checkconfig/buildprofile_test.go | 226 -------- .../snmp/internal/checkconfig/config.go | 165 +++++- .../snmp/internal/checkconfig/config_oid.go | 50 ++ .../internal/checkconfig/config_oid_test.go | 40 ++ .../snmp/internal/checkconfig/config_test.go | 541 +++++++++++++----- .../snmp/internal/devicecheck/devicecheck.go | 120 +--- .../internal/devicecheck/devicecheck_test.go | 28 +- .../snmp/internal/discovery/discovery_test.go | 7 - .../corechecks/snmp/internal/fetch/fetch.go | 13 +- .../snmp/internal/fetch/fetch_test.go | 54 +- .../internal/report/report_device_metadata.go | 34 +- .../report/report_device_metadata_test.go | 180 +++--- 13 files changed, 843 insertions(+), 689 deletions(-) delete mode 100644 pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile.go delete mode 100644 pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile_test.go create mode 100644 pkg/collector/corechecks/snmp/internal/checkconfig/config_oid.go create mode 100644 pkg/collector/corechecks/snmp/internal/checkconfig/config_oid_test.go diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile.go b/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile.go deleted file mode 100644 index a448c51381a6ae..00000000000000 --- a/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile.go +++ /dev/null @@ -1,74 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package checkconfig - -import ( - "fmt" - "github.com/DataDog/datadog-agent/pkg/networkdevice/profile/profiledefinition" - "github.com/DataDog/datadog-agent/pkg/util/log" - "slices" -) - -// BuildProfile builds the fetchable profile for this config. -// -// If ProfileName == ProfileNameInline, then the result just contains the inline -// metrics and tags from the initconfig. This is also true if ProfileName == -// ProfileNameAuto and sysObjectID == "" (this is useful when you want basic -// metadata for a device that you can't yet get the sysObjectID from). -// -// Otherwise, the result will be a copy of the profile from ProfileProvider that -// matches this config, either by sysObjectID if ProfileName == ProfileNameAuto -// or by ProfileName directly otherwise. -// -// The error will be non-nil if ProfileProvider doesn't know ProfileName, or if -// ProfileName is ProfileNameAuto and ProfileProvider finds no match for -// sysObjectID. In this case the returned profile will still be non-nil, and -// will be the same as what you'd get for an inline profile. -func (c *CheckConfig) BuildProfile(sysObjectID string) (profiledefinition.ProfileDefinition, error) { - var rootProfile *profiledefinition.ProfileDefinition - var profileErr error - - switch c.ProfileName { - case ProfileNameInline: // inline profile -> no parent - rootProfile = nil - case ProfileNameAuto: // determine based on sysObjectID - // empty sysObjectID happens when we need the profile but couldn't connect to the device. - if sysObjectID != "" { - if profileConfig, err := c.ProfileProvider.GetProfileForSysObjectID(sysObjectID); err != nil { - profileErr = fmt.Errorf("failed to get profile for sysObjectID %q: %v", sysObjectID, err) - } else { - rootProfile = &profileConfig.Definition - log.Debugf("detected profile %q for sysobjectid %q", rootProfile.Name, sysObjectID) - } - } - default: - if profile := c.ProfileProvider.GetProfile(c.ProfileName); profile == nil { - profileErr = fmt.Errorf("unknown profile %q", c.ProfileName) - } else { - rootProfile = &profile.Definition - } - } - - profile := *profiledefinition.NewProfileDefinition() - profile.Metrics = slices.Clone(c.RequestedMetrics) - profile.MetricTags = slices.Clone(c.RequestedMetricTags) - if rootProfile != nil { - profile.Name = rootProfile.Name - profile.Version = rootProfile.Version - profile.StaticTags = append(profile.StaticTags, "snmp_profile:"+rootProfile.Name) - vendor := rootProfile.GetVendor() - if vendor != "" { - profile.StaticTags = append(profile.StaticTags, "device_vendor:"+vendor) - } - profile.StaticTags = append(profile.StaticTags, rootProfile.StaticTags...) - profile.Metadata = rootProfile.Metadata - profile.Metrics = append(profile.Metrics, rootProfile.Metrics...) - profile.MetricTags = append(profile.MetricTags, rootProfile.MetricTags...) - } - profile.Metadata = updateMetadataDefinitionWithDefaults(profile.Metadata, c.CollectTopology) - - return profile, profileErr -} diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile_test.go b/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile_test.go deleted file mode 100644 index 5c1992f848e810..00000000000000 --- a/pkg/collector/corechecks/snmp/internal/checkconfig/buildprofile_test.go +++ /dev/null @@ -1,226 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2024-present Datadog, Inc. - -package checkconfig - -import ( - "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/profile" - "github.com/DataDog/datadog-agent/pkg/networkdevice/profile/profiledefinition" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "testing" -) - -func TestBuildProfile(t *testing.T) { - metrics := []profiledefinition.MetricsConfig{ - {Symbol: profiledefinition.SymbolConfig{OID: "1.2.3.4.5", Name: "someMetric"}}, - { - Symbols: []profiledefinition.SymbolConfig{ - { - OID: "1.2.3.4.6", - Name: "abc", - }, - }, - MetricTags: profiledefinition.MetricTagConfigList{ - profiledefinition.MetricTagConfig{ - Symbol: profiledefinition.SymbolConfigCompat{ - OID: "1.2.3.4.7", - }, - }, - }, - }, - } - profile1 := profiledefinition.ProfileDefinition{ - Name: "profile1", - Version: 12, - Metrics: metrics, - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - Metadata: profiledefinition.MetadataConfig{ - "device": { - Fields: map[string]profiledefinition.MetadataField{ - "vendor": { - Value: "a-vendor", - }, - "description": { - Symbol: profiledefinition.SymbolConfig{ - OID: "1.3.6.1.2.1.1.99.3.0", - Name: "sysDescr", - }, - }, - "name": { - Symbols: []profiledefinition.SymbolConfig{ - { - OID: "1.3.6.1.2.1.1.99.1.0", - Name: "symbol1", - }, - { - OID: "1.3.6.1.2.1.1.99.2.0", - Name: "symbol2", - }, - }, - }, - }, - }, - "interface": { - Fields: map[string]profiledefinition.MetadataField{ - "oper_status": { - Symbol: profiledefinition.SymbolConfig{ - OID: "1.3.6.1.2.1.2.2.1.99", - Name: "someIfSymbol", - }, - }, - }, - IDTags: profiledefinition.MetricTagConfigList{ - { - Tag: "interface", - Symbol: profiledefinition.SymbolConfigCompat{ - OID: "1.3.6.1.2.1.31.1.1.1.1", - Name: "ifName", - }, - }, - }, - }, - }, - SysObjectIDs: profiledefinition.StringArray{"1.1.1.*"}, - } - - mergedMetadata := make(profiledefinition.MetadataConfig) - mergeMetadata(mergedMetadata, profile1.Metadata) - mergedMetadata["ip_addresses"] = LegacyMetadataConfig["ip_addresses"] - - mockProfiles := profile.StaticProvider(profile.ProfileConfigMap{ - "profile1": profile.ProfileConfig{ - Definition: profile1, - }, - }) - - type testCase struct { - name string - config *CheckConfig - sysObjectID string - expected profiledefinition.ProfileDefinition - expectedError string - } - for _, tc := range []testCase{ - { - name: "inline", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - RequestedMetrics: metrics, - RequestedMetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - ProfileName: ProfileNameInline, - }, - expected: profiledefinition.ProfileDefinition{ - Metrics: metrics, - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - Metadata: LegacyMetadataConfig, - }, - }, { - name: "static", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - ProfileProvider: mockProfiles, - ProfileName: "profile1", - }, - expected: profiledefinition.ProfileDefinition{ - Name: "profile1", - Version: 12, - Metrics: metrics, - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - StaticTags: []string{"snmp_profile:profile1", "device_vendor:a-vendor"}, - Metadata: mergedMetadata, - }, - }, { - name: "dynamic", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - ProfileProvider: mockProfiles, - ProfileName: ProfileNameAuto, - }, - sysObjectID: "1.1.1.1", - expected: profiledefinition.ProfileDefinition{ - Name: "profile1", - Version: 12, - Metrics: metrics, - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - StaticTags: []string{"snmp_profile:profile1", "device_vendor:a-vendor"}, - Metadata: mergedMetadata, - }, - }, { - name: "static with requested metrics", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - ProfileProvider: mockProfiles, - CollectDeviceMetadata: true, - CollectTopology: false, - ProfileName: "profile1", - RequestedMetrics: []profiledefinition.MetricsConfig{ - {Symbol: profiledefinition.SymbolConfig{OID: "3.1", Name: "global-metric"}}}, - RequestedMetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "global-tag", Symbol: profiledefinition.SymbolConfigCompat{OID: "3.2", Name: "globalSymbol"}}, - }, - }, - expected: profiledefinition.ProfileDefinition{ - Name: "profile1", - Version: 12, - Metrics: append([]profiledefinition.MetricsConfig{ - {Symbol: profiledefinition.SymbolConfig{OID: "3.1", Name: "global-metric"}}}, - metrics...), - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "global-tag", Symbol: profiledefinition.SymbolConfigCompat{OID: "3.2", Name: "globalSymbol"}}, - {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, - }, - Metadata: mergedMetadata, - StaticTags: []string{"snmp_profile:profile1", "device_vendor:a-vendor"}, - }, - }, { - name: "static unknown", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - ProfileProvider: mockProfiles, - ProfileName: "f5", - }, - expectedError: "unknown profile \"f5\"", - }, { - name: "dynamic unknown", - config: &CheckConfig{ - IPAddress: "1.2.3.4", - ProfileProvider: mockProfiles, - ProfileName: ProfileNameAuto, - }, - sysObjectID: "3.3.3.3", - expectedError: "failed to get profile for sysObjectID \"3.3.3.3\": no profiles found for sysObjectID \"3." + - "3.3.3\"", - }, - } { - t.Run(tc.name, func(t *testing.T) { - profile, err := tc.config.BuildProfile(tc.sysObjectID) - if tc.expectedError != "" { - assert.EqualError(t, err, tc.expectedError) - } else { - require.NoError(t, err) - if !assert.Equal(t, tc.expected, profile) { - for k, v := range tc.expected.Metadata["device"].Fields { - t.Log(k, v) - } - t.Log("===") - for k, v := range profile.Metadata["device"].Fields { - t.Log(k, v) - } - } - } - }) - } -} diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/config.go b/pkg/collector/corechecks/snmp/internal/checkconfig/config.go index 8689e3b69ada15..ab5cc66f49f974 100644 --- a/pkg/collector/corechecks/snmp/internal/checkconfig/config.go +++ b/pkg/collector/corechecks/snmp/internal/checkconfig/config.go @@ -8,6 +8,7 @@ package checkconfig import ( "context" + "encoding/json" "fmt" "hash/fnv" "net" @@ -71,11 +72,6 @@ const DefaultPingTimeout = 3 * time.Second // DefaultPingInterval is the default time to wait between sending ping packets const DefaultPingInterval = 10 * time.Millisecond -// config.ProfileName will be set to ProfileNameAuto if the profile is auto-detected, -// and ProfileNameInline if metrics were provided in the initial config (so that no profile is used) -const ProfileNameAuto = "" -const ProfileNameInline = "" - var uptimeMetricConfig = profiledefinition.MetricsConfig{Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}} // DeviceDigest is the digest of a minimal config used for autodiscovery @@ -168,13 +164,20 @@ type CheckConfig struct { PrivProtocol string PrivKey string ContextName string + OidConfig OidConfig // RequestedMetrics are the metrics explicitly requested by config. RequestedMetrics []profiledefinition.MetricsConfig // RequestedMetricTags are the tags explicitly requested by config. - RequestedMetricTags []profiledefinition.MetricTagConfig + RequestedMetricTags []profiledefinition.MetricTagConfig + // Metrics combines RequestedMetrics with profile metrics. + Metrics []profiledefinition.MetricsConfig + Metadata profiledefinition.MetadataConfig + // MetricTags combines RequestedMetricTags with profile metric tags. + MetricTags []profiledefinition.MetricTagConfig OidBatchSize int BulkMaxRepetitions uint32 ProfileProvider profile.Provider + ProfileTags []string ProfileName string ExtraTags []string InstanceTags []string @@ -185,6 +188,7 @@ type CheckConfig struct { DeviceIDTags []string ResolvedSubnetName string Namespace string + AutodetectProfile bool MinCollectionInterval time.Duration Network string @@ -199,6 +203,61 @@ type CheckConfig struct { PingConfig pinger.Config } +// SetProfile refreshes config based on profile +func (c *CheckConfig) SetProfile(profileName string) error { + profileConf := c.ProfileProvider.GetProfile(profileName) + if profileConf == nil { + return fmt.Errorf("unknown profile `%s`", profileName) + } + log.Debugf("Refreshing with profile `%s`", profileName) + c.ProfileName = profileName + + if log.ShouldLog(log.DebugLvl) { + profileDefJSON, _ := json.Marshal(profileConf.Definition) + log.Debugf("Profile content `%s`: %s", profileName, string(profileDefJSON)) + } + c.RebuildMetadataMetricsAndTags() + return nil +} + +// GetProfileDef returns the autodetected profile definition if there is one, +// the active profile if it exists, or nil if neither is true. +func (c *CheckConfig) GetProfileDef() *profiledefinition.ProfileDefinition { + if c.ProfileName != "" { + profile := c.ProfileProvider.GetProfile(c.ProfileName) + if profile != nil { + return &profile.Definition + } + log.Warnf("profile `%s` not found", c.ProfileName) + } + return nil +} + +// RebuildMetadataMetricsAndTags rebuilds c.Metrics, c.Metadata, c.MetricTags, +// and c.OidConfig by merging data from requested metrics/tags and the current +// profile. +func (c *CheckConfig) RebuildMetadataMetricsAndTags() { + c.Metrics = c.RequestedMetrics + c.MetricTags = c.RequestedMetricTags + c.ProfileTags = nil + profileDef := c.GetProfileDef() + if profileDef != nil { + c.ProfileTags = append(c.ProfileTags, "snmp_profile:"+c.ProfileName) + if profileDef.Device.Vendor != "" { + c.ProfileTags = append(c.ProfileTags, "device_vendor:"+profileDef.Device.Vendor) + } + c.ProfileTags = append(c.ProfileTags, profileDef.StaticTags...) + c.Metadata = updateMetadataDefinitionWithDefaults(profileDef.Metadata, c.CollectTopology) + c.Metrics = append(c.Metrics, profileDef.Metrics...) + c.MetricTags = append(c.MetricTags, profileDef.MetricTags...) + } else { + c.Metadata = updateMetadataDefinitionWithDefaults(nil, c.CollectTopology) + } + c.OidConfig.clean() + c.OidConfig.addScalarOids(c.parseScalarOids(c.Metrics, c.MetricTags, c.Metadata)) + c.OidConfig.addColumnOids(c.parseColumnOids(c.Metrics, c.Metadata)) +} + // UpdateDeviceIDAndTags updates DeviceID and DeviceIDTags func (c *CheckConfig) UpdateDeviceIDAndTags() { c.DeviceIDTags = coreutilsort.UniqInPlace(c.getDeviceIDTags()) @@ -251,7 +310,8 @@ func (c *CheckConfig) getDeviceIDTags() []string { // ToString used for logging CheckConfig without sensitive information func (c *CheckConfig) ToString() string { return fmt.Sprintf("CheckConfig: IPAddress=`%s`, Port=`%d`, SnmpVersion=`%s`, Timeout=`%d`, Retries=`%d`, "+ - "User=`%s`, AuthProtocol=`%s`, PrivProtocol=`%s`, ContextName=`%s`, OidBatchSize=`%d`, ProfileName=`%s`", + "User=`%s`, AuthProtocol=`%s`, PrivProtocol=`%s`, ContextName=`%s`, OidConfig=`%#v`, "+ + "OidBatchSize=`%d`, ProfileTags=`%#v`", c.IPAddress, c.Port, c.SnmpVersion, @@ -261,8 +321,9 @@ func (c *CheckConfig) ToString() string { c.AuthProtocol, c.PrivProtocol, c.ContextName, + c.OidConfig, c.OidBatchSize, - c.ProfileName, + c.ProfileTags, ) } @@ -438,13 +499,11 @@ func NewCheckConfig(rawInstance integration.Data, rawInitConfig integration.Data c.ProfileProvider = profiles // profile configs - c.ProfileName = instance.Profile - if c.ProfileName == "" { - if len(instance.Metrics) > 0 { - c.ProfileName = ProfileNameInline - } else { - c.ProfileName = ProfileNameAuto - } + profileName := instance.Profile + if profileName != "" || len(instance.Metrics) > 0 { + c.AutodetectProfile = false + } else { + c.AutodetectProfile = true } c.InstanceTags = instance.Tags @@ -466,6 +525,15 @@ func NewCheckConfig(rawInstance integration.Data, rawInitConfig integration.Data return nil, fmt.Errorf("validation errors: %s", strings.Join(errors, "\n")) } + if profileName != "" { + err = c.SetProfile(profileName) + if err != nil { + return nil, fmt.Errorf("failed to refresh with profile `%s`: %s", profileName, err) + } + } else { + c.RebuildMetadataMetricsAndTags() + } + // Ping configuration if instance.PingConfig.Enabled != nil { c.PingEnabled = bool(*instance.PingConfig.Enabled) @@ -577,14 +645,24 @@ func (c *CheckConfig) Copy() *CheckConfig { newConfig.PrivKey = c.PrivKey newConfig.ContextName = c.ContextName newConfig.ContextName = c.ContextName + newConfig.OidConfig = c.OidConfig newConfig.RequestedMetrics = make([]profiledefinition.MetricsConfig, len(c.RequestedMetrics)) copy(newConfig.RequestedMetrics, c.RequestedMetrics) + newConfig.Metrics = make([]profiledefinition.MetricsConfig, len(c.Metrics)) + copy(newConfig.Metrics, c.Metrics) + + // Metadata: shallow copy is enough since metadata is not modified. + // However, it might be fully replaced, see CheckConfig.SetProfile + newConfig.Metadata = c.Metadata newConfig.RequestedMetricTags = make([]profiledefinition.MetricTagConfig, len(c.RequestedMetricTags)) copy(newConfig.RequestedMetricTags, c.RequestedMetricTags) + newConfig.MetricTags = make([]profiledefinition.MetricTagConfig, len(c.MetricTags)) + copy(newConfig.MetricTags, c.MetricTags) newConfig.OidBatchSize = c.OidBatchSize newConfig.BulkMaxRepetitions = c.BulkMaxRepetitions newConfig.ProfileProvider = c.ProfileProvider + newConfig.ProfileTags = netutils.CopyStrings(c.ProfileTags) newConfig.ProfileName = c.ProfileName newConfig.ExtraTags = netutils.CopyStrings(c.ExtraTags) newConfig.InstanceTags = netutils.CopyStrings(c.InstanceTags) @@ -596,6 +674,7 @@ func (c *CheckConfig) Copy() *CheckConfig { newConfig.DeviceIDTags = netutils.CopyStrings(c.DeviceIDTags) newConfig.ResolvedSubnetName = c.ResolvedSubnetName newConfig.Namespace = c.Namespace + newConfig.AutodetectProfile = c.AutodetectProfile newConfig.MinCollectionInterval = c.MinCollectionInterval newConfig.InterfaceConfigs = c.InterfaceConfigs @@ -621,6 +700,62 @@ func (c *CheckConfig) IsDiscovery() bool { return c.Network != "" } +func (c *CheckConfig) parseScalarOids(metrics []profiledefinition.MetricsConfig, metricTags []profiledefinition.MetricTagConfig, metadataConfigs profiledefinition.MetadataConfig) []string { + var oids []string + for _, metric := range metrics { + oids = append(oids, metric.Symbol.OID) + } + for _, metricTag := range metricTags { + oids = append(oids, metricTag.Symbol.OID) + } + if c.CollectDeviceMetadata { + for resource, metadataConfig := range metadataConfigs { + if !profiledefinition.IsMetadataResourceWithScalarOids(resource) { + continue + } + for _, field := range metadataConfig.Fields { + oids = append(oids, field.Symbol.OID) + for _, symbol := range field.Symbols { + oids = append(oids, symbol.OID) + } + } + // we don't support tags for now for resource (e.g. device) based on scalar OIDs + // profile root level `metric_tags` (tags used for both metadata, metrics, service checks) + // can be used instead + } + } + return oids +} + +func (c *CheckConfig) parseColumnOids(metrics []profiledefinition.MetricsConfig, metadataConfigs profiledefinition.MetadataConfig) []string { + var oids []string + for _, metric := range metrics { + for _, symbol := range metric.Symbols { + oids = append(oids, symbol.OID) + } + for _, metricTag := range metric.MetricTags { + oids = append(oids, metricTag.Symbol.OID) + } + } + if c.CollectDeviceMetadata { + for resource, metadataConfig := range metadataConfigs { + if profiledefinition.IsMetadataResourceWithScalarOids(resource) { + continue + } + for _, field := range metadataConfig.Fields { + oids = append(oids, field.Symbol.OID) + for _, symbol := range field.Symbols { + oids = append(oids, symbol.OID) + } + } + for _, tagConfig := range metadataConfig.IDTags { + oids = append(oids, tagConfig.Symbol.OID) + } + } + } + return oids +} + func getSubnetFromTags(tags []string) (string, error) { for _, tag := range tags { // `autodiscovery_subnet` is set as tags in AD Template diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid.go b/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid.go new file mode 100644 index 00000000000000..d6992a3d87f797 --- /dev/null +++ b/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid.go @@ -0,0 +1,50 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package checkconfig + +import "sort" + +// OidConfig holds configs for OIDs to fetch +type OidConfig struct { + // ScalarOids are all scalar oids to fetch + ScalarOids []string + // ColumnOids are all column oids to fetch + ColumnOids []string +} + +func (oc *OidConfig) addScalarOids(oidsToAdd []string) { + oc.ScalarOids = oc.addOidsIfNotPresent(oc.ScalarOids, oidsToAdd) +} + +func (oc *OidConfig) addColumnOids(oidsToAdd []string) { + oc.ColumnOids = oc.addOidsIfNotPresent(oc.ColumnOids, oidsToAdd) +} + +func (oc *OidConfig) addOidsIfNotPresent(configOids []string, oidsToAdd []string) []string { + for _, oidToAdd := range oidsToAdd { + if oidToAdd == "" { + continue + } + isAlreadyPresent := false + for _, oid := range configOids { + if oid == oidToAdd { + isAlreadyPresent = true + break + } + } + if isAlreadyPresent { + continue + } + configOids = append(configOids, oidToAdd) + } + sort.Strings(configOids) + return configOids +} + +func (oc *OidConfig) clean() { + oc.ScalarOids = nil + oc.ColumnOids = nil +} diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid_test.go b/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid_test.go new file mode 100644 index 00000000000000..6fae3b75ce0242 --- /dev/null +++ b/pkg/collector/corechecks/snmp/internal/checkconfig/config_oid_test.go @@ -0,0 +1,40 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package checkconfig + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_oidConfig_addScalarOids(t *testing.T) { + conf := OidConfig{} + + assert.ElementsMatch(t, []string{}, conf.ScalarOids) + + conf.addScalarOids([]string{"1.1"}) + conf.addScalarOids([]string{"1.1"}) + conf.addScalarOids([]string{"1.2"}) + conf.addScalarOids([]string{"1.3"}) + conf.addScalarOids([]string{"1.0"}) + conf.addScalarOids([]string{""}) + assert.ElementsMatch(t, []string{"1.1", "1.2", "1.3", "1.0"}, conf.ScalarOids) +} + +func Test_oidConfig_addColumnOids(t *testing.T) { + conf := OidConfig{} + + assert.ElementsMatch(t, []string{}, conf.ColumnOids) + + conf.addColumnOids([]string{"1.1"}) + conf.addColumnOids([]string{"1.1"}) + conf.addColumnOids([]string{"1.2"}) + conf.addColumnOids([]string{"1.3"}) + conf.addColumnOids([]string{"1.0"}) + conf.addColumnOids([]string{""}) + assert.ElementsMatch(t, []string{"1.1", "1.2", "1.3", "1.0"}, conf.ColumnOids) +} diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go b/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go index 34653446818ecb..ef9b8628da93a7 100644 --- a/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go +++ b/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go @@ -6,7 +6,6 @@ package checkconfig import ( - "github.com/stretchr/testify/require" "regexp" "testing" "time" @@ -156,112 +155,106 @@ bulk_max_repetitions: 20 assert.Equal(t, "my-privKey", config.PrivKey) assert.Equal(t, "my-contextName", config.ContextName) assert.Equal(t, []string{"device_namespace:default", "snmp_device:1.2.3.4", "device_ip:1.2.3.4", "device_id:default:1.2.3.4"}, config.GetStaticTags()) - assert.True(t, config.ProfileProvider.HasProfile("f5-big-ip")) - assert.Equal(t, "default:1.2.3.4", config.DeviceID) - assert.Equal(t, []string{"device_namespace:default", "snmp_device:1.2.3.4"}, config.DeviceIDTags) - assert.Equal(t, "127.0.0.0/30", config.ResolvedSubnetName) - assert.Equal(t, "f5-big-ip", config.ProfileName) - - t.Run("BuildProfile", func(t *testing.T) { - expectedMetrics := []profiledefinition.MetricsConfig{ - {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.1", Name: "ifNumber"}}, - {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.2", Name: "ifNumber2"}, MetricTags: profiledefinition.MetricTagConfigList{ - {SymbolTag: "mytag1"}, - {SymbolTag: "mytag2"}, - }}, - {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.4.1.318.1.1.1.11.1.1.0", Name: "upsBasicStateOutputState", ScaleFactor: 10}, MetricType: profiledefinition.ProfileMetricTypeFlagStream, Options: profiledefinition.MetricsConfigOption{Placement: 5, MetricSuffix: "ReplaceBattery"}}, - { - Table: profiledefinition.SymbolConfig{ - OID: "1.3.6.1.2.1.2.2", - Name: "ifTable", - }, - Symbols: []profiledefinition.SymbolConfig{ - // ifInErrors defined in instance config with a different set of metric tags from the one defined - // in the imported profile - {OID: "1.3.6.1.2.1.2.2.1.14", Name: "ifInErrors"}, - {OID: "1.3.6.1.2.1.2.2.1.20", Name: "ifOutErrors", ScaleFactor: 3}, - }, - MetricTags: []profiledefinition.MetricTagConfig{ - {Tag: "if_index", Index: 1}, - {Tag: "if_desc", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.2.2.1.2", Name: "ifDescr"}, - IndexTransform: []profiledefinition.MetricIndexTransform{ - { - Start: 1, - End: 3, - }, - { - Start: 4, - End: 6, - }, + expectedMetrics := []profiledefinition.MetricsConfig{ + {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.1", Name: "ifNumber"}}, + {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.2", Name: "ifNumber2"}, MetricTags: profiledefinition.MetricTagConfigList{ + {SymbolTag: "mytag1"}, + {SymbolTag: "mytag2"}, + }}, + {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.4.1.318.1.1.1.11.1.1.0", Name: "upsBasicStateOutputState", ScaleFactor: 10}, MetricType: profiledefinition.ProfileMetricTypeFlagStream, Options: profiledefinition.MetricsConfigOption{Placement: 5, MetricSuffix: "ReplaceBattery"}}, + { + Table: profiledefinition.SymbolConfig{ + OID: "1.3.6.1.2.1.2.2", + Name: "ifTable", + }, + Symbols: []profiledefinition.SymbolConfig{ + // ifInErrors defined in instance config with a different set of metric tags from the one defined + // in the imported profile + {OID: "1.3.6.1.2.1.2.2.1.14", Name: "ifInErrors"}, + {OID: "1.3.6.1.2.1.2.2.1.20", Name: "ifOutErrors", ScaleFactor: 3}, + }, + MetricTags: []profiledefinition.MetricTagConfig{ + {Tag: "if_index", Index: 1}, + {Tag: "if_desc", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.2.2.1.2", Name: "ifDescr"}, + IndexTransform: []profiledefinition.MetricIndexTransform{ + { + Start: 1, + End: 3, }, - }, - {Tag: "ipversion", Index: 1, Mapping: map[string]string{ - "0": "unknown", - "1": "ipv4", - "2": "ipv6", - "3": "ipv4z", - "4": "ipv6z", - "16": "dns", - }}, - {Tag: "if_type", - Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.2.2.1.3", Name: "ifType"}, - Mapping: map[string]string{ - "1": "other", - "2": "regular1822", - "3": "hdh1822", - "4": "ddn-x25", - "29": "ultra", - }}, - { - Symbol: profiledefinition.SymbolConfigCompat{ - Name: "cpiPduName", - OID: "1.2.3.4.8.1.2", + { + Start: 4, + End: 6, }, - Match: "(\\w)(\\w+)", - Pattern: regexp.MustCompile(`(\w)(\w+)`), - Tags: map[string]string{ - "prefix": "\\1", - "suffix": "\\2", - }}, + }, }, + {Tag: "ipversion", Index: 1, Mapping: map[string]string{ + "0": "unknown", + "1": "ipv4", + "2": "ipv6", + "3": "ipv4z", + "4": "ipv6z", + "16": "dns", + }}, + {Tag: "if_type", + Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.2.2.1.3", Name: "ifType"}, + Mapping: map[string]string{ + "1": "other", + "2": "regular1822", + "3": "hdh1822", + "4": "ddn-x25", + "29": "ultra", + }}, + { + Symbol: profiledefinition.SymbolConfigCompat{ + Name: "cpiPduName", + OID: "1.2.3.4.8.1.2", + }, + Match: "(\\w)(\\w+)", + Pattern: regexp.MustCompile(`(\w)(\w+)`), + Tags: map[string]string{ + "prefix": "\\1", + "suffix": "\\2", + }}, }, - {Symbol: profiledefinition.SymbolConfig{OID: "1.2.3.4", Name: "aGlobalMetric"}}, - } - expectedMetrics = append(expectedMetrics, profiledefinition.MetricsConfig{Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}) - expectedMetrics = append(expectedMetrics, profile.FixtureProfileDefinitionMap()["f5-big-ip"].Definition.Metrics...) + }, + {Symbol: profiledefinition.SymbolConfig{OID: "1.2.3.4", Name: "aGlobalMetric"}}, + } + expectedMetrics = append(expectedMetrics, profiledefinition.MetricsConfig{Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}) + expectedMetrics = append(expectedMetrics, profile.FixtureProfileDefinitionMap()["f5-big-ip"].Definition.Metrics...) - expectedMetricTags := []profiledefinition.MetricTagConfig{ - {Tag: "my_symbol", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}}, - {Tag: "my_symbol_mapped", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}, Mapping: map[string]string{"1": "one", "2": "two"}}, - { - Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}, - Match: "(\\w)(\\w+)", - Pattern: regexp.MustCompile(`(\w)(\w+)`), - Tags: map[string]string{ - "prefix": "\\1", - "suffix": "\\2", - }, + expectedMetricTags := []profiledefinition.MetricTagConfig{ + {Tag: "my_symbol", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}}, + {Tag: "my_symbol_mapped", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}, Mapping: map[string]string{"1": "one", "2": "two"}}, + { + Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}, + Match: "(\\w)(\\w+)", + Pattern: regexp.MustCompile(`(\w)(\w+)`), + Tags: map[string]string{ + "prefix": "\\1", + "suffix": "\\2", }, - { - Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}, - Match: "(\\w)(\\w+)", - Pattern: regexp.MustCompile(`(\w)(\w+)`), - Tags: map[string]string{ - "some_tag": "some_tag_value", - "prefix": "\\1", - "suffix": "\\2", - }, + }, + { + Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}, + Match: "(\\w)(\\w+)", + Pattern: regexp.MustCompile(`(\w)(\w+)`), + Tags: map[string]string{ + "some_tag": "some_tag_value", + "prefix": "\\1", + "suffix": "\\2", }, - {Tag: "snmp_host", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}}, - } - - profile, err := config.BuildProfile("") - require.NoError(t, err) + }, + {Tag: "snmp_host", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}}, + } - assert.Equal(t, expectedMetrics, profile.Metrics) - assert.Equal(t, expectedMetricTags, profile.MetricTags) - assert.Equal(t, []string{"snmp_profile:f5-big-ip", "device_vendor:f5", "static_tag:from_profile_root", "static_tag:from_base_profile"}, profile.StaticTags) - }) + assert.Equal(t, expectedMetrics, config.Metrics) + assert.Equal(t, expectedMetricTags, config.MetricTags) + assert.Equal(t, []string{"snmp_profile:f5-big-ip", "device_vendor:f5", "static_tag:from_profile_root", "static_tag:from_base_profile"}, config.ProfileTags) + assert.True(t, config.ProfileProvider.HasProfile("f5-big-ip")) + assert.Equal(t, "default:1.2.3.4", config.DeviceID) + assert.Equal(t, []string{"device_namespace:default", "snmp_device:1.2.3.4"}, config.DeviceIDTags) + assert.Equal(t, "127.0.0.0/30", config.ResolvedSubnetName) + assert.Equal(t, false, config.AutodetectProfile) } func TestDiscoveryConfigurations(t *testing.T) { @@ -317,10 +310,6 @@ profiles: assert.Nil(t, err) assert.Equal(t, []string{"device_namespace:default", "snmp_device:172.26.0.2", "device_ip:172.26.0.2", "device_id:default:172.26.0.2"}, config.GetStaticTags()) - - profile, err := config.BuildProfile("") - require.NoError(t, err) - metrics := []profiledefinition.MetricsConfig{ {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}, {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.7.1.0", Name: "IAmACounter32"}}, @@ -329,8 +318,10 @@ profiles: {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.88.1.1.1.0", Name: "IAmAnInteger"}}, } - assert.Equal(t, metrics, profile.Metrics) - assert.Empty(t, profile.MetricTags) + metricsTags := []profiledefinition.MetricTagConfig(nil) + + assert.Equal(t, metrics, config.Metrics) + assert.Equal(t, metricsTags, config.MetricTags) } func TestInlineProfileConfiguration(t *testing.T) { @@ -366,31 +357,30 @@ profiles: name: myMetric `) config, err := NewCheckConfig(rawInstanceConfig, rawInitConfig) - require.NoError(t, err) + assert.Nil(t, err) assert.Equal(t, []string{"device_namespace:default", "snmp_device:1.2.3.4", "device_ip:1.2.3.4", "device_id:default:1.2.3.4"}, config.GetStaticTags()) + metrics := []profiledefinition.MetricsConfig{ + {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}, + {MIB: "MY-PROFILE-MIB", Symbol: profiledefinition.SymbolConfig{OID: "1.4.5", Name: "myMetric"}, MetricType: profiledefinition.ProfileMetricTypeGauge}, + } + + metricsTags := []profiledefinition.MetricTagConfig{ + {Tag: "snmp_host", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}}, + } + assert.Equal(t, "123", config.CommunityString) + assert.Equal(t, metrics, config.Metrics) + assert.Equal(t, metricsTags, config.MetricTags) assert.True(t, config.ProfileProvider.HasProfile("f5-big-ip")) assert.True(t, config.ProfileProvider.HasProfile("inline-profile")) assert.Equal(t, "default:1.2.3.4", config.DeviceID) assert.Equal(t, []string{"device_namespace:default", "snmp_device:1.2.3.4"}, config.DeviceIDTags) + assert.Equal(t, false, config.AutodetectProfile) assert.Equal(t, 3600, config.DiscoveryInterval) assert.Equal(t, 3, config.DiscoveryAllowedFailures) assert.Equal(t, 5, config.DiscoveryWorkers) assert.Equal(t, 5, config.Workers) - - metrics := []profiledefinition.MetricsConfig{ - {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}, - {MIB: "MY-PROFILE-MIB", Symbol: profiledefinition.SymbolConfig{OID: "1.4.5", Name: "myMetric"}, MetricType: profiledefinition.ProfileMetricTypeGauge}, - } - - metricsTags := []profiledefinition.MetricTagConfig{ - {Tag: "snmp_host", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.5.0", Name: "sysName"}}, - } - profile, err := config.BuildProfile("") - require.NoError(t, err) - assert.Equal(t, metrics, profile.Metrics) - assert.Equal(t, metricsTags, profile.MetricTags) } func TestDefaultConfigurations(t *testing.T) { @@ -411,17 +401,16 @@ community_string: abc assert.Equal(t, uint16(161), config.Port) assert.Equal(t, 2, config.Timeout) assert.Equal(t, 3, config.Retries) + metrics := []profiledefinition.MetricsConfig{{Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}} + + var metricsTags []profiledefinition.MetricTagConfig + assert.Equal(t, metrics, config.Metrics) + assert.Equal(t, metricsTags, config.MetricTags) + // assert.Equal(t, 2, len(config.Profiles)) assert.True(t, config.ProfileProvider.HasProfile("f5-big-ip")) assert.True(t, config.ProfileProvider.HasProfile("another_profile")) assert.Equal(t, profile.FixtureProfileDefinitionMap()["f5-big-ip"].Definition.Metrics, config.ProfileProvider.GetProfile("f5-big-ip").Definition.Metrics) - - profile, err := config.BuildProfile("") - require.NoError(t, err) - - metrics := []profiledefinition.MetricsConfig{{Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}} - assert.Equal(t, metrics, profile.Metrics) - assert.Empty(t, profile.MetricTags) } func TestPortConfiguration(t *testing.T) { @@ -586,17 +575,14 @@ global_metrics: name: aGlobalMetric `) config, err := NewCheckConfig(rawInstanceConfig, rawInitConfig) - require.NoError(t, err) - - profile, err := config.BuildProfile("") - require.NoError(t, err) + assert.Nil(t, err) metrics := []profiledefinition.MetricsConfig{ {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.1", Name: "ifNumber"}}, {Symbol: profiledefinition.SymbolConfig{OID: "1.2.3.4", Name: "aGlobalMetric"}}, {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}, } - assert.Equal(t, metrics, profile.Metrics) + assert.Equal(t, metrics, config.Metrics) } func TestUseGlobalMetricsFalse(t *testing.T) { @@ -620,16 +606,13 @@ global_metrics: name: aGlobalMetric `) config, err := NewCheckConfig(rawInstanceConfig, rawInitConfig) - require.NoError(t, err) - - profile, err := config.BuildProfile("") - require.NoError(t, err) + assert.Nil(t, err) metrics := []profiledefinition.MetricsConfig{ {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.2.1", Name: "aInstanceMetric"}}, {Symbol: profiledefinition.SymbolConfig{OID: "1.3.6.1.2.1.1.3.0", Name: "sysUpTimeInstance"}}, } - assert.Equal(t, metrics, profile.Metrics) + assert.Equal(t, metrics, config.Metrics) } func Test_NewCheckConfig_errors(t *testing.T) { @@ -641,6 +624,23 @@ func Test_NewCheckConfig_errors(t *testing.T) { rawInitConfig []byte expectedErrors []string }{ + { + name: "unknown profile", + // language=yaml + rawInstanceConfig: []byte(` +ip_address: 1.2.3.4 +profile: does-not-exist +`), + // language=yaml + rawInitConfig: []byte(` +profiles: + f5-big-ip: + definition_file: f5-big-ip.yaml +`), + expectedErrors: []string{ + "failed to refresh with profile `does-not-exist`: unknown profile `does-not-exist`", + }, + }, { name: "validation errors", // language=yaml @@ -699,7 +699,6 @@ network_address: 10.0.0.0/xx t.Run(tt.name, func(t *testing.T) { _, err := NewCheckConfig(tt.rawInstanceConfig, tt.rawInitConfig) for _, errStr := range tt.expectedErrors { - require.NotNil(t, err, "expected error %q", errStr) assert.Contains(t, err.Error(), errStr) } }) @@ -807,6 +806,254 @@ func Test_snmpConfig_getDeviceIDTags(t *testing.T) { assert.Equal(t, expectedTags, actualTags) } +func Test_snmpConfig_setProfile(t *testing.T) { + metrics := []profiledefinition.MetricsConfig{ + {Symbol: profiledefinition.SymbolConfig{OID: "1.2.3.4.5", Name: "someMetric"}}, + { + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "1.2.3.4.6", + Name: "abc", + }, + }, + MetricTags: profiledefinition.MetricTagConfigList{ + profiledefinition.MetricTagConfig{ + Symbol: profiledefinition.SymbolConfigCompat{ + OID: "1.2.3.4.7", + }, + }, + }, + }, + } + profile1 := profiledefinition.ProfileDefinition{ + Device: profiledefinition.DeviceMeta{ + Vendor: "a-vendor", + }, + Metrics: metrics, + MetricTags: []profiledefinition.MetricTagConfig{ + {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, + }, + Metadata: profiledefinition.MetadataConfig{ + "device": { + Fields: map[string]profiledefinition.MetadataField{ + "description": { + Symbol: profiledefinition.SymbolConfig{ + OID: "1.3.6.1.2.1.1.99.3.0", + Name: "sysDescr", + }, + }, + "name": { + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "1.3.6.1.2.1.1.99.1.0", + Name: "symbol1", + }, + { + OID: "1.3.6.1.2.1.1.99.2.0", + Name: "symbol2", + }, + }, + }, + }, + }, + "interface": { + Fields: map[string]profiledefinition.MetadataField{ + "oper_status": { + Symbol: profiledefinition.SymbolConfig{ + OID: "1.3.6.1.2.1.2.2.1.99", + Name: "someIfSymbol", + }, + }, + }, + IDTags: profiledefinition.MetricTagConfigList{ + { + Tag: "interface", + Symbol: profiledefinition.SymbolConfigCompat{ + OID: "1.3.6.1.2.1.31.1.1.1.1", + Name: "ifName", + }, + }, + }, + }, + }, + SysObjectIDs: profiledefinition.StringArray{"1.3.6.1.4.1.3375.2.1.3.4.*"}, + } + profile2 := profiledefinition.ProfileDefinition{ + Device: profiledefinition.DeviceMeta{Vendor: "b-vendor"}, + Metrics: []profiledefinition.MetricsConfig{{Symbol: profiledefinition.SymbolConfig{OID: "2.3.4.5.6.1", Name: "b-metric"}}}, + MetricTags: []profiledefinition.MetricTagConfig{ + {Tag: "btag", Symbol: profiledefinition.SymbolConfigCompat{OID: "2.3.4.5.6.2", Name: "b-tag-name"}}, + }, + Metadata: profiledefinition.MetadataConfig{ + "device": { + Fields: map[string]profiledefinition.MetadataField{ + "b-description": { + Symbol: profiledefinition.SymbolConfig{ + OID: "2.3.4.5.6.3", + Name: "sysDescr", + }, + }, + "b-name": { + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "2.3.4.5.6.4", + Name: "b-symbol1", + }, + { + OID: "2.3.4.5.6.5", + Name: "b-symbol2", + }, + }, + }, + }, + }, + "interface": { + Fields: map[string]profiledefinition.MetadataField{ + "oper_status": { + Symbol: profiledefinition.SymbolConfig{ + OID: "2.3.4.5.6.6", + Name: "b-someIfSymbol", + }, + }, + }, + IDTags: profiledefinition.MetricTagConfigList{ + { + Tag: "b-interface", + Symbol: profiledefinition.SymbolConfigCompat{ + OID: "2.3.4.5.6.7", + Name: "b-ifName", + }, + }, + }, + }, + }, + SysObjectIDs: profiledefinition.StringArray{"1.3.6.1.4.1.3375.2.1.3.4.*"}, + } + + mockProfiles := profile.StaticProvider(profile.ProfileConfigMap{ + "profile1": profile.ProfileConfig{ + Definition: profile1, + }, + "profile2": profile.ProfileConfig{ + Definition: profile2, + }, + }) + c := &CheckConfig{ + IPAddress: "1.2.3.4", + ProfileProvider: mockProfiles, + } + err := c.SetProfile("f5") + assert.EqualError(t, err, "unknown profile `f5`") + + err = c.SetProfile("profile1") + assert.NoError(t, err) + + assert.Equal(t, "profile1", c.ProfileName) + assert.Equal(t, &profile1, c.GetProfileDef()) + assert.Equal(t, metrics, c.Metrics) + assert.Equal(t, []profiledefinition.MetricTagConfig{ + {Tag: "location", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.3.6.1.2.1.1.6.0", Name: "sysLocation"}}, + }, c.MetricTags) + assert.Equal(t, OidConfig{ + ScalarOids: []string{"1.2.3.4.5", "1.3.6.1.2.1.1.6.0"}, + ColumnOids: []string{"1.2.3.4.6", "1.2.3.4.7"}, + }, c.OidConfig) + assert.Equal(t, []string{"snmp_profile:profile1", "device_vendor:a-vendor"}, c.ProfileTags) + + c = &CheckConfig{ + IPAddress: "1.2.3.4", + ProfileProvider: mockProfiles, + CollectDeviceMetadata: true, + CollectTopology: false, + } + err = c.SetProfile("profile1") + assert.NoError(t, err) + assert.Equal(t, OidConfig{ + ScalarOids: []string{ + "1.2.3.4.5", + "1.3.6.1.2.1.1.6.0", + "1.3.6.1.2.1.1.99.1.0", + "1.3.6.1.2.1.1.99.2.0", + "1.3.6.1.2.1.1.99.3.0", + }, + ColumnOids: []string{ + "1.2.3.4.6", + "1.2.3.4.7", + "1.3.6.1.2.1.2.2.1.99", + "1.3.6.1.2.1.31.1.1.1.1", + "1.3.6.1.2.1.4.20.1.2", + "1.3.6.1.2.1.4.20.1.3", + }, + }, c.OidConfig) + + // With metadata disabled + c.CollectDeviceMetadata = false + err = c.SetProfile("profile1") + assert.NoError(t, err) + assert.Equal(t, OidConfig{ + ScalarOids: []string{ + "1.2.3.4.5", + "1.3.6.1.2.1.1.6.0", + }, + ColumnOids: []string{ + "1.2.3.4.6", + "1.2.3.4.7", + }, + }, c.OidConfig) + + c = &CheckConfig{ + IPAddress: "1.2.3.4", + ProfileProvider: mockProfiles, + CollectDeviceMetadata: true, + CollectTopology: false, + } + c.RequestedMetrics = append(c.RequestedMetrics, + profiledefinition.MetricsConfig{Symbol: profiledefinition.SymbolConfig{OID: "3.1", Name: "global-metric"}}) + c.RequestedMetricTags = append(c.RequestedMetricTags, + profiledefinition.MetricTagConfig{Tag: "global-tag", Symbol: profiledefinition.SymbolConfigCompat{OID: "3.2", Name: "globalSymbol"}}) + err = c.SetProfile("profile1") + assert.NoError(t, err) + assert.Equal(t, OidConfig{ + ScalarOids: []string{ + "1.2.3.4.5", + "1.3.6.1.2.1.1.6.0", + "1.3.6.1.2.1.1.99.1.0", + "1.3.6.1.2.1.1.99.2.0", + "1.3.6.1.2.1.1.99.3.0", + "3.1", + "3.2", + }, + ColumnOids: []string{ + "1.2.3.4.6", + "1.2.3.4.7", + "1.3.6.1.2.1.2.2.1.99", + "1.3.6.1.2.1.31.1.1.1.1", + "1.3.6.1.2.1.4.20.1.2", + "1.3.6.1.2.1.4.20.1.3", + }, + }, c.OidConfig) + err = c.SetProfile("profile2") + assert.NoError(t, err) + assert.Equal(t, OidConfig{ + ScalarOids: []string{ + "2.3.4.5.6.1", + "2.3.4.5.6.2", + "2.3.4.5.6.3", + "2.3.4.5.6.4", + "2.3.4.5.6.5", + "3.1", + "3.2", + }, + ColumnOids: []string{ + "1.3.6.1.2.1.4.20.1.2", + "1.3.6.1.2.1.4.20.1.3", + "2.3.4.5.6.6", + "2.3.4.5.6.7", + }, + }, c.OidConfig) + +} + func Test_getSubnetFromTags(t *testing.T) { subnet, err := getSubnetFromTags([]string{"aa", "bb"}) assert.Equal(t, "", subnet) @@ -1666,6 +1913,10 @@ func TestCheckConfig_Copy(t *testing.T) { PrivProtocol: "des", PrivKey: "123", ContextName: "", + OidConfig: OidConfig{ + ScalarOids: []string{"1.2.3"}, + ColumnOids: []string{"1.2.3", "2.3.4"}, + }, RequestedMetrics: []profiledefinition.MetricsConfig{ { Symbol: profiledefinition.SymbolConfig{ @@ -1677,6 +1928,17 @@ func TestCheckConfig_Copy(t *testing.T) { RequestedMetricTags: []profiledefinition.MetricTagConfig{ {Tag: "my_symbol", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}}, }, + Metrics: []profiledefinition.MetricsConfig{ + { + Symbol: profiledefinition.SymbolConfig{ + OID: "1.2", + Name: "abc", + }, + }, + }, + MetricTags: []profiledefinition.MetricTagConfig{ + {Tag: "my_symbol", Symbol: profiledefinition.SymbolConfigCompat{OID: "1.2.3", Name: "mySymbol"}}, + }, OidBatchSize: 10, BulkMaxRepetitions: 10, ProfileProvider: profile.StaticProvider(profile.ProfileConfigMap{"f5-big-ip": profile.ProfileConfig{ @@ -1684,6 +1946,7 @@ func TestCheckConfig_Copy(t *testing.T) { Device: profiledefinition.DeviceMeta{Vendor: "f5"}, }, }}), + ProfileTags: []string{"profile_tag:atag"}, ProfileName: "f5", ExtraTags: []string{"ExtraTags:tag"}, InstanceTags: []string{"InstanceTags:tag"}, @@ -1693,6 +1956,7 @@ func TestCheckConfig_Copy(t *testing.T) { DeviceID: "123", DeviceIDTags: []string{"DeviceIDTags:tag"}, ResolvedSubnetName: "1.2.3.4/28", + AutodetectProfile: true, MinCollectionInterval: 120, } configCopy := config.Copy() @@ -1701,6 +1965,9 @@ func TestCheckConfig_Copy(t *testing.T) { assert.NotSame(t, &config.RequestedMetrics, &configCopy.RequestedMetrics) assert.NotSame(t, &config.RequestedMetricTags, &configCopy.RequestedMetricTags) + assert.NotSame(t, &config.Metrics, &configCopy.Metrics) + assert.NotSame(t, &config.MetricTags, &configCopy.MetricTags) + assert.NotSame(t, &config.ProfileTags, &configCopy.ProfileTags) assert.NotSame(t, &config.ExtraTags, &configCopy.ExtraTags) assert.NotSame(t, &config.InstanceTags, &configCopy.InstanceTags) assert.NotSame(t, &config.DeviceIDTags, &configCopy.DeviceIDTags) diff --git a/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck.go b/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck.go index 12df975fa88120..d23d5642a24702 100644 --- a/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck.go +++ b/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck.go @@ -10,7 +10,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/DataDog/datadog-agent/pkg/networkdevice/profile/profiledefinition" "reflect" "runtime" "strings" @@ -56,60 +55,6 @@ const ( checkDurationThreshold = 30 // Thirty seconds ) -type profileCache struct { - sysObjectID string - timestamp time.Time - profile *profiledefinition.ProfileDefinition - err error - scalarOIDs []string - columnOIDs []string -} - -// GetProfile returns the cached profile, or an empty profile if the cache is empty. -// Use this when you need to make sure you have *some* profile. -func (pc *profileCache) GetProfile() profiledefinition.ProfileDefinition { - if pc.profile == nil { - return profiledefinition.ProfileDefinition{ - Metadata: make(profiledefinition.MetadataConfig), - } - } - return *pc.profile -} - -func (pc *profileCache) Update(sysObjectID string, now time.Time, config *checkconfig.CheckConfig) (profiledefinition.ProfileDefinition, error) { - if pc.IsOutdated(sysObjectID, config.ProfileName, config.ProfileProvider.LastUpdated()) { - // we cache the value even if there's an error, because an error indicates that - // the ProfileProvider couldn't find a match for either config.ProfileName or - // the given sysObjectID, and we're going to have the same error if we call this - // again without either the sysObjectID or the ProfileProvider changing. - pc.sysObjectID = sysObjectID - pc.timestamp = now - profile, err := config.BuildProfile(sysObjectID) - pc.profile = &profile - pc.err = err - pc.scalarOIDs, pc.columnOIDs = pc.profile.SplitOIDs(config.CollectDeviceMetadata) - } - return pc.GetProfile(), pc.err -} - -func (pc *profileCache) IsOutdated(sysObjectID string, profileName string, lastUpdate time.Time) bool { - if pc.profile == nil { - return true - } - if profileName == checkconfig.ProfileNameInline { - // inline profiles never change, so if we have a profile it's up-to-date. - return false - } - if profileName == checkconfig.ProfileNameAuto && pc.sysObjectID != sysObjectID { - // If we're auto-detecting profiles and the sysObjectID has changed, we're out of date. - return true - } - // If we get here then either we're auto-detecting but the sysobjectid hasn't - // changed, or we have a static name; either way we're out of date if and only - // if the profile provider has updated. - return pc.timestamp.Before(lastUpdate) -} - // DeviceCheck hold info necessary to collect info for a single device type DeviceCheck struct { config *checkconfig.CheckConfig @@ -123,7 +68,6 @@ type DeviceCheck struct { interfaceBandwidthState report.InterfaceBandwidthState cacheKey string agentConfig config.Component - profileCache profileCache } const cacheKeyPrefix = "snmp-tags" @@ -156,10 +100,6 @@ func NewDeviceCheck(config *checkconfig.CheckConfig, ipAddress string, sessionFa } d.readTagsFromCache() - if _, err := d.profileCache.Update("", time.Now(), d.config); err != nil { - // This could happen e.g. if the config references a profile that hasn't been loaded yet. - _ = log.Warnf("failed to refresh profile cache: %s", err) - } return &d, nil } @@ -223,7 +163,7 @@ func (d *DeviceCheck) Run(collectionTime time.Time) error { var deviceStatus metadata.DeviceStatus var pingStatus metadata.DeviceStatus - deviceReachable, profile, dynamicTags, values, checkErr := d.getValuesAndTags() + deviceReachable, dynamicTags, values, checkErr := d.getValuesAndTags() tags := utils.CopyStrings(staticTags) if checkErr != nil { @@ -243,7 +183,7 @@ func (d *DeviceCheck) Run(collectionTime time.Time) error { d.sender.Gauge(deviceReachableMetric, utils.BoolToFloat64(deviceReachable), metricTags) d.sender.Gauge(deviceUnreachableMetric, utils.BoolToFloat64(!deviceReachable), metricTags) if values != nil { - d.sender.ReportMetrics(profile.Metrics, values, metricTags, d.config.DeviceID) + d.sender.ReportMetrics(d.config.Metrics, values, metricTags, d.config.DeviceID) } // Get a system appropriate ping check @@ -292,8 +232,7 @@ func (d *DeviceCheck) Run(collectionTime time.Time) error { deviceDiagnosis := d.diagnoses.Report() - d.sender.ReportNetworkDeviceMetadata(d.config, profile, values, deviceMetadataTags, collectionTime, - deviceStatus, pingStatus, deviceDiagnosis) + d.sender.ReportNetworkDeviceMetadata(d.config, values, deviceMetadataTags, collectionTime, deviceStatus, pingStatus, deviceDiagnosis) } d.submitTelemetryMetrics(startTime, metricTags) @@ -321,11 +260,7 @@ func (d *DeviceCheck) buildExternalTags() []string { return agentTags } -// getValuesAndTags build (or fetches from cache) a profile describing all the -// metrics, tags, etc. to be fetched for this device, fetches the resulting -// values, and returns (reachable, profile, tags, values, error). In the event -// of an error, the returned profile will be the last cached profile. -func (d *DeviceCheck) getValuesAndTags() (bool, profiledefinition.ProfileDefinition, []string, *valuestore.ResultValueStore, error) { +func (d *DeviceCheck) getValuesAndTags() (bool, []string, *valuestore.ResultValueStore, error) { var deviceReachable bool var checkErrors []string var tags []string @@ -334,8 +269,7 @@ func (d *DeviceCheck) getValuesAndTags() (bool, profiledefinition.ProfileDefinit connErr := d.session.Connect() if connErr != nil { d.diagnoses.Add("error", "SNMP_FAILED_TO_OPEN_CONNECTION", "Agent failed to open connection.") - // cannot connect -> use cached profile - return false, d.profileCache.GetProfile(), tags, nil, fmt.Errorf("snmp connection error: %s", connErr) + return false, tags, nil, fmt.Errorf("snmp connection error: %s", connErr) } defer func() { err := d.session.Close() @@ -358,16 +292,15 @@ func (d *DeviceCheck) getValuesAndTags() (bool, profiledefinition.ProfileDefinit } } - profile, err := d.detectMetricsToMonitor(d.session) + err = d.detectMetricsToMonitor(d.session) if err != nil { d.diagnoses.Add("error", "SNMP_FAILED_TO_DETECT_PROFILE", "Agent failed to detect a profile for this network device.") checkErrors = append(checkErrors, fmt.Sprintf("failed to autodetect profile: %s", err)) } - tags = append(tags, profile.StaticTags...) + tags = append(tags, d.config.ProfileTags...) - valuesStore, err := fetch.Fetch(d.session, d.profileCache.scalarOIDs, d.profileCache.columnOIDs, d.config.OidBatchSize, - d.config.BulkMaxRepetitions) + valuesStore, err := fetch.Fetch(d.session, d.config) if log.ShouldLog(log.DebugLvl) { log.Debugf("fetched values: %v", valuestore.ResultValueStoreAsString(valuesStore)) } @@ -375,38 +308,37 @@ func (d *DeviceCheck) getValuesAndTags() (bool, profiledefinition.ProfileDefinit if err != nil { checkErrors = append(checkErrors, fmt.Sprintf("failed to fetch values: %s", err)) } else { - tags = append(tags, d.sender.GetCheckInstanceMetricTags(profile.MetricTags, valuesStore)...) + tags = append(tags, d.sender.GetCheckInstanceMetricTags(d.config.MetricTags, valuesStore)...) } var joinedError error if len(checkErrors) > 0 { joinedError = errors.New(strings.Join(checkErrors, "; ")) } - return deviceReachable, profile, tags, valuesStore, joinedError + return deviceReachable, tags, valuesStore, joinedError } -func (d *DeviceCheck) getSysObjectID(sess session.Session) (string, error) { - if d.config.ProfileName == checkconfig.ProfileNameAuto { +func (d *DeviceCheck) detectMetricsToMonitor(sess session.Session) error { + if d.config.AutodetectProfile { // detect using sysObjectID sysObjectID, err := session.FetchSysObjectID(sess) if err != nil { - return "", fmt.Errorf("failed to fetch sysobjectid: %w", err) + return fmt.Errorf("failed to fetch sysobjectid: %s", err) + } + profile, err := d.config.ProfileProvider.GetProfileNameForSysObjectID(sysObjectID) + if err != nil { + return fmt.Errorf("failed to get profile sys object id for `%s`: %s", sysObjectID, err) + } + if profile != d.config.ProfileName { + log.Debugf("detected profile change: %s -> %s", d.config.ProfileName, profile) + err = d.config.SetProfile(profile) + if err != nil { + // Should not happen since the profile is one of those we matched in GetProfileNameForSysObjectID + return fmt.Errorf("failed to refresh with profile `%s` detected using sysObjectID `%s`: %s", profile, sysObjectID, err) + } } - return sysObjectID, nil - } - return "", nil -} - -func (d *DeviceCheck) detectMetricsToMonitor(sess session.Session) (profiledefinition.ProfileDefinition, error) { - sysObjectID, err := d.getSysObjectID(sess) - if err != nil { - return d.profileCache.GetProfile(), err - } - profile, err := d.profileCache.Update(sysObjectID, time.Now(), d.config) - if err != nil { - return profile, fmt.Errorf("failed to refresh profile cache: %w", err) } - return profile, nil + return nil } func (d *DeviceCheck) submitTelemetryMetrics(startTime time.Time, tags []string) { diff --git a/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck_test.go b/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck_test.go index 27fe5f81951e04..1e7ad7fc7a0011 100644 --- a/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck_test.go +++ b/pkg/collector/corechecks/snmp/internal/devicecheck/devicecheck_test.go @@ -70,7 +70,7 @@ profiles: deviceCk.SetSender(report.NewMetricSender(sender, "", nil, report.MakeInterfaceBandwidthState())) - sess. + (sess. SetStr("1.3.6.1.2.1.1.1.0", "my_desc"). SetObj("1.3.6.1.2.1.1.2.0", "1.3.6.1.4.1.3375.2.1.3.4.1"). SetTime("1.3.6.1.2.1.1.3.0", 20). @@ -96,7 +96,7 @@ profiles: // f5-specific sysStatMemoryTotal SetInt("1.3.6.1.4.1.3375.2.1.1.2.1.44.0", 30). // Fake metric specific to another_profile - SetInt("1.3.6.1.2.1.1.999.0", 100) + SetInt("1.3.6.1.2.1.1.999.0", 100)) err = deviceCk.Run(time.Now()) assert.Nil(t, err) @@ -133,8 +133,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.sysStatMemoryTotal", []string{"unknown_symbol:100"}) // f5 has 5 metrics, 2 tags - assert.Len(t, deviceCk.profileCache.profile.Metrics, 5) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 5) + assert.Len(t, deviceCk.config.MetricTags, 2) sender.ResetCalls() @@ -164,8 +164,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.anotherMetric", []string{"some_tag:some_tag_value"}) // Check that we replaced the metrics, instead of just adding to them - assert.Len(t, deviceCk.profileCache.profile.Metrics, 2) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 2) + assert.Len(t, deviceCk.config.MetricTags, 2) } func TestProfileDetectionPreservesGlobals(t *testing.T) { @@ -779,8 +779,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.sysStatMemoryTotal", []string{"unknown_symbol:100"}) // f5 has 5 metrics, 2 tags - assert.Len(t, deviceCk.profileCache.profile.Metrics, 5) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 5) + assert.Len(t, deviceCk.config.MetricTags, 2) sender.ResetCalls() @@ -810,8 +810,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.anotherMetric", []string{"some_tag:some_tag_value"}) // Check that we replaced the metrics, instead of just adding to them - assert.Len(t, deviceCk.profileCache.profile.Metrics, 2) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 2) + assert.Len(t, deviceCk.config.MetricTags, 2) // Assert Ping Metrics sender.AssertMetric(t, "Gauge", pingReachableMetric, float64(1), "", snmpTags) @@ -926,8 +926,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.sysStatMemoryTotal", []string{"unknown_symbol:100"}) // f5 has 5 metrics, 2 tags - assert.Len(t, deviceCk.profileCache.profile.Metrics, 5) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 5) + assert.Len(t, deviceCk.config.MetricTags, 2) sender.ResetCalls() @@ -957,8 +957,8 @@ profiles: sender.AssertMetricNotTaggedWith(t, "Gauge", "snmp.anotherMetric", []string{"some_tag:some_tag_value"}) // Check that we replaced the metrics, instead of just adding to them - assert.Len(t, deviceCk.profileCache.profile.Metrics, 2) - assert.Len(t, deviceCk.profileCache.profile.MetricTags, 2) + assert.Len(t, deviceCk.config.Metrics, 2) + assert.Len(t, deviceCk.config.MetricTags, 2) // Assert Ping reachability metrics are sent sender.AssertMetric(t, "Gauge", pingReachableMetric, float64(0), "", snmpTags) diff --git a/pkg/collector/corechecks/snmp/internal/discovery/discovery_test.go b/pkg/collector/corechecks/snmp/internal/discovery/discovery_test.go index c4aa83a01a663a..4ca8ccc302bf28 100644 --- a/pkg/collector/corechecks/snmp/internal/discovery/discovery_test.go +++ b/pkg/collector/corechecks/snmp/internal/discovery/discovery_test.go @@ -7,7 +7,6 @@ package discovery import ( "fmt" - "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/profile" "net" "testing" "time" @@ -58,7 +57,6 @@ func TestDiscovery(t *testing.T) { DiscoveryInterval: 3600, DiscoveryWorkers: 1, IgnoredIPAddresses: map[string]bool{"192.168.0.5": true}, - ProfileProvider: profile.StaticProvider(nil), } discovery := NewDiscovery(checkConfig, sessionFactory, config) discovery.Start() @@ -109,7 +107,6 @@ func TestDiscoveryCache(t *testing.T) { CommunityString: "public", DiscoveryInterval: 3600, DiscoveryWorkers: 1, - ProfileProvider: profile.StaticProvider(nil), } discovery := NewDiscovery(checkConfig, sessionFactory, config) discovery.Start() @@ -142,7 +139,6 @@ func TestDiscoveryCache(t *testing.T) { CommunityString: "public", DiscoveryInterval: 3600, DiscoveryWorkers: 0, // no workers, the devices will be loaded from cache - ProfileProvider: profile.StaticProvider(nil), } discovery2 := NewDiscovery(checkConfig, sessionFactory, config) discovery2.Start() @@ -185,7 +181,6 @@ func TestDiscoveryTicker(t *testing.T) { CommunityString: "public", DiscoveryInterval: 1, DiscoveryWorkers: 1, - ProfileProvider: profile.StaticProvider(nil), } discovery := NewDiscovery(checkConfig, sessionFactory, config) discovery.Start() @@ -205,7 +200,6 @@ func TestDiscovery_checkDevice(t *testing.T) { CommunityString: "public", DiscoveryInterval: 1, DiscoveryWorkers: 1, - ProfileProvider: profile.StaticProvider(nil), } ipAddr, ipNet, err := net.ParseCIDR(checkConfig.Network) assert.Nil(t, err) @@ -325,7 +319,6 @@ func TestDiscovery_createDevice(t *testing.T) { DiscoveryWorkers: 1, DiscoveryAllowedFailures: 3, Namespace: "default", - ProfileProvider: profile.StaticProvider(nil), } discovery := NewDiscovery(checkConfig, session.NewMockSession, config) ipAddr, ipNet, err := net.ParseCIDR(checkConfig.Network) diff --git a/pkg/collector/corechecks/snmp/internal/fetch/fetch.go b/pkg/collector/corechecks/snmp/internal/fetch/fetch.go index b55d5cbf602d53..54987adef0ed25 100644 --- a/pkg/collector/corechecks/snmp/internal/fetch/fetch.go +++ b/pkg/collector/corechecks/snmp/internal/fetch/fetch.go @@ -12,6 +12,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/checkconfig" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/session" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/valuestore" ) @@ -35,21 +36,19 @@ func (c columnFetchStrategy) String() string { } // Fetch oid values from device -func Fetch(sess session.Session, scalarOIDs, columnOIDs []string, batchSize int, - bulkMaxRepetitions uint32) (*valuestore.ResultValueStore, error) { +// TODO: pass only specific configs instead of the whole CheckConfig +func Fetch(sess session.Session, config *checkconfig.CheckConfig) (*valuestore.ResultValueStore, error) { // fetch scalar values - scalarResults, err := fetchScalarOidsWithBatching(sess, scalarOIDs, batchSize) + scalarResults, err := fetchScalarOidsWithBatching(sess, config.OidConfig.ScalarOids, config.OidBatchSize) if err != nil { return nil, fmt.Errorf("failed to fetch scalar oids with batching: %v", err) } - columnResults, err := fetchColumnOidsWithBatching(sess, columnOIDs, batchSize, - bulkMaxRepetitions, useGetBulk) + columnResults, err := fetchColumnOidsWithBatching(sess, config.OidConfig.ColumnOids, config.OidBatchSize, config.BulkMaxRepetitions, useGetBulk) if err != nil { log.Debugf("failed to fetch oids with GetBulk batching: %v", err) - columnResults, err = fetchColumnOidsWithBatching(sess, columnOIDs, batchSize, bulkMaxRepetitions, - useGetNext) + columnResults, err = fetchColumnOidsWithBatching(sess, config.OidConfig.ColumnOids, config.OidBatchSize, config.BulkMaxRepetitions, useGetNext) if err != nil { return nil, fmt.Errorf("failed to fetch oids with GetNext batching: %v", err) } diff --git a/pkg/collector/corechecks/snmp/internal/fetch/fetch_test.go b/pkg/collector/corechecks/snmp/internal/fetch/fetch_test.go index e219144b768b8e..63c2c4ce937f37 100644 --- a/pkg/collector/corechecks/snmp/internal/fetch/fetch_test.go +++ b/pkg/collector/corechecks/snmp/internal/fetch/fetch_test.go @@ -370,9 +370,14 @@ func Test_fetchColumnOidsBatch_usingGetBulkAndGetNextFallback(t *testing.T) { sess.On("GetNext", []string{"1.1.3"}).Return(&secondBatchPacket1, nil) sess.On("GetNext", []string{"1.1.3.1"}).Return(&secondBatchPacket2, nil) - columnOIDs := []string{"1.1.1", "1.1.2", "1.1.3"} - - columnValues, err := Fetch(sess, nil, columnOIDs, 2, checkconfig.DefaultBulkMaxRepetitions) + config := &checkconfig.CheckConfig{ + BulkMaxRepetitions: checkconfig.DefaultBulkMaxRepetitions, + OidBatchSize: 2, + OidConfig: checkconfig.OidConfig{ + ColumnOids: []string{"1.1.1", "1.1.2", "1.1.3"}, + }, + } + columnValues, err := Fetch(sess, config) assert.Nil(t, err) expectedColumnValues := &valuestore.ResultValueStore{ @@ -714,32 +719,41 @@ func Test_fetchScalarOids_v1NoSuchName_errorIndexTooLow(t *testing.T) { func Test_fetchValues_errors(t *testing.T) { tests := []struct { name string - maxReps uint32 - batchSize int - ScalarOIDs []string - ColumnOIDs []string + config checkconfig.CheckConfig bulkPacket gosnmp.SnmpPacket expectedError error }{ { - name: "invalid batch size", - maxReps: checkconfig.DefaultBulkMaxRepetitions, - ScalarOIDs: []string{"1.1", "1.2"}, + name: "invalid batch size", + config: checkconfig.CheckConfig{ + BulkMaxRepetitions: checkconfig.DefaultBulkMaxRepetitions, + OidConfig: checkconfig.OidConfig{ + ScalarOids: []string{"1.1", "1.2"}, + }, + }, expectedError: fmt.Errorf("failed to fetch scalar oids with batching: failed to create oid batches: batch size must be positive. invalid size: 0"), }, { - name: "get fetch error", - maxReps: checkconfig.DefaultBulkMaxRepetitions, - batchSize: 10, - ScalarOIDs: []string{"1.1", "2.2"}, + name: "get fetch error", + config: checkconfig.CheckConfig{ + BulkMaxRepetitions: checkconfig.DefaultBulkMaxRepetitions, + OidBatchSize: 10, + OidConfig: checkconfig.OidConfig{ + ScalarOids: []string{"1.1", "2.2"}, + }, + }, expectedError: fmt.Errorf("failed to fetch scalar oids with batching: failed to fetch scalar oids: fetch scalar: error getting oids `[1.1 2.2]`: get error"), }, { - name: "bulk fetch error", - maxReps: checkconfig.DefaultBulkMaxRepetitions, - batchSize: 10, - ScalarOIDs: []string{}, - ColumnOIDs: []string{"1.1", "2.2"}, + name: "bulk fetch error", + config: checkconfig.CheckConfig{ + BulkMaxRepetitions: checkconfig.DefaultBulkMaxRepetitions, + OidBatchSize: 10, + OidConfig: checkconfig.OidConfig{ + ScalarOids: []string{}, + ColumnOids: []string{"1.1", "2.2"}, + }, + }, expectedError: fmt.Errorf("failed to fetch oids with GetNext batching: failed to fetch column oids: fetch column: failed getting oids `[1.1 2.2]` using GetNext: getnext error"), }, } @@ -750,7 +764,7 @@ func Test_fetchValues_errors(t *testing.T) { sess.On("GetBulk", []string{"1.1", "2.2"}, checkconfig.DefaultBulkMaxRepetitions).Return(&gosnmp.SnmpPacket{}, fmt.Errorf("bulk error")) sess.On("GetNext", []string{"1.1", "2.2"}).Return(&gosnmp.SnmpPacket{}, fmt.Errorf("getnext error")) - _, err := Fetch(sess, tt.ScalarOIDs, tt.ColumnOIDs, tt.batchSize, tt.maxReps) + _, err := Fetch(sess, &tt.config) assert.Equal(t, tt.expectedError, err) }) diff --git a/pkg/collector/corechecks/snmp/internal/report/report_device_metadata.go b/pkg/collector/corechecks/snmp/internal/report/report_device_metadata.go index c8ef1316aaa0a6..9bc800985b18b6 100644 --- a/pkg/collector/corechecks/snmp/internal/report/report_device_metadata.go +++ b/pkg/collector/corechecks/snmp/internal/report/report_device_metadata.go @@ -51,13 +51,13 @@ var supportedDeviceTypes = map[string]bool{ } // ReportNetworkDeviceMetadata reports device metadata -func (ms *MetricSender) ReportNetworkDeviceMetadata(config *checkconfig.CheckConfig, profile profiledefinition.ProfileDefinition, store *valuestore.ResultValueStore, origTags []string, collectTime time.Time, deviceStatus devicemetadata.DeviceStatus, pingStatus devicemetadata.DeviceStatus, diagnoses []devicemetadata.DiagnosisMetadata) { +func (ms *MetricSender) ReportNetworkDeviceMetadata(config *checkconfig.CheckConfig, store *valuestore.ResultValueStore, origTags []string, collectTime time.Time, deviceStatus devicemetadata.DeviceStatus, pingStatus devicemetadata.DeviceStatus, diagnoses []devicemetadata.DiagnosisMetadata) { tags := utils.CopyStrings(origTags) tags = sortutil.UniqInPlace(tags) - metadataStore := buildMetadataStore(profile.Metadata, store) + metadataStore := buildMetadataStore(config.Metadata, store) - devices := []devicemetadata.DeviceMetadata{buildNetworkDeviceMetadata(config.DeviceID, config.DeviceIDTags, config, profile, metadataStore, tags, deviceStatus, pingStatus)} + devices := []devicemetadata.DeviceMetadata{buildNetworkDeviceMetadata(config.DeviceID, config.DeviceIDTags, config, metadataStore, tags, deviceStatus, pingStatus)} interfaces := buildNetworkInterfacesMetadata(config.DeviceID, metadataStore) ipAddresses := buildNetworkIPAddressesMetadata(config.DeviceID, metadataStore) @@ -191,9 +191,8 @@ func buildMetadataStore(metadataConfigs profiledefinition.MetadataConfig, values return metadataStore } -func buildNetworkDeviceMetadata(deviceID string, idTags []string, config *checkconfig.CheckConfig, profile profiledefinition.ProfileDefinition, store *metadata.Store, tags []string, deviceStatus devicemetadata.DeviceStatus, pingStatus devicemetadata.DeviceStatus) devicemetadata.DeviceMetadata { - var vendor, sysName, sysDescr, sysObjectID, location, serialNumber, version, productName, model, osName, osVersion, osHostname, deviceType, profileName string - var profileVersion uint64 +func buildNetworkDeviceMetadata(deviceID string, idTags []string, config *checkconfig.CheckConfig, store *metadata.Store, tags []string, deviceStatus devicemetadata.DeviceStatus, pingStatus devicemetadata.DeviceStatus) devicemetadata.DeviceMetadata { + var vendor, sysName, sysDescr, sysObjectID, location, serialNumber, version, productName, model, osName, osVersion, osHostname, deviceType string if store != nil { sysName = store.GetScalarAsString("device.name") sysDescr = store.GetScalarAsString("device.description") @@ -210,12 +209,10 @@ func buildNetworkDeviceMetadata(deviceID string, idTags []string, config *checkc deviceType = getDeviceType(store) } - profileName = profile.Name - profileVersion = profile.Version - // TODO(ndm-core) I don't think this can ever happen. - // If the profile provides a static vendor then it should have been populated in the store no matter what. - if vendor == "" { - vendor = profile.GetVendor() + // fallback to Device.Vendor for backward compatibility + profileDef := config.GetProfileDef() + if profileDef != nil && vendor == "" { + vendor = profileDef.Device.Vendor } return devicemetadata.DeviceMetadata{ @@ -226,8 +223,8 @@ func buildNetworkDeviceMetadata(deviceID string, idTags []string, config *checkc IPAddress: config.IPAddress, SysObjectID: sysObjectID, Location: location, - Profile: profileName, - ProfileVersion: profileVersion, + Profile: config.ProfileName, + ProfileVersion: getProfileVersion(config), Vendor: vendor, Tags: tags, Subnet: config.ResolvedSubnetName, @@ -245,6 +242,15 @@ func buildNetworkDeviceMetadata(deviceID string, idTags []string, config *checkc } } +func getProfileVersion(config *checkconfig.CheckConfig) uint64 { + var profileVersion uint64 + profileDef := config.GetProfileDef() + if profileDef != nil { + profileVersion = profileDef.Version + } + return profileVersion +} + func getDeviceType(store *metadata.Store) string { deviceType := strings.ToLower(store.GetScalarAsString("device.type")) if deviceType == "" { diff --git a/pkg/collector/corechecks/snmp/internal/report/report_device_metadata_test.go b/pkg/collector/corechecks/snmp/internal/report/report_device_metadata_test.go index 642cace14d0dd0..22d58e9530216f 100644 --- a/pkg/collector/corechecks/snmp/internal/report/report_device_metadata_test.go +++ b/pkg/collector/corechecks/snmp/internal/report/report_device_metadata_test.go @@ -9,8 +9,6 @@ import ( "bufio" "bytes" "encoding/json" - "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/profile" - "github.com/stretchr/testify/require" "testing" "time" @@ -25,6 +23,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/snmp/snmpintegration" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/checkconfig" + "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/profile" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/valuestore" ) @@ -68,74 +67,72 @@ func Test_metricSender_reportNetworkDeviceMetadata_withoutInterfaces(t *testing. Definition: profiledefinition.ProfileDefinition{ Name: "my-profile", Version: 10, - Metadata: profiledefinition.MetadataConfig{ - "device": { - Fields: map[string]profiledefinition.MetadataField{ - "name": { - // Should use value from Symbol `1.3.6.1.2.1.1.5.0` - Symbol: profiledefinition.SymbolConfig{ - OID: "1.3.6.1.2.1.1.5.0", - Name: "sysName", - }, - Symbols: []profiledefinition.SymbolConfig{ - { - OID: "1.2.99", - Name: "doesNotExist", - }, - }, - }, - "description": { - // Should use value from first element in Symbols `1.3.6.1.2.1.1.1.0` - Symbol: profiledefinition.SymbolConfig{ - OID: "1.9999", - Name: "doesNotExist", - }, - Symbols: []profiledefinition.SymbolConfig{ - { - OID: "1.3.6.1.2.1.1.1.0", - Name: "sysDescr", - }, - }, - }, - "location": { - // Should use value from first element in Symbols `1.3.6.1.2.1.1.1.0` - Symbol: profiledefinition.SymbolConfig{ - OID: "1.9999", - Name: "doesNotExist", - }, - Symbols: []profiledefinition.SymbolConfig{ - { - OID: "1.888", - Name: "doesNotExist2", - }, - { - OID: "1.3.6.1.2.1.1.6.0", - Name: "sysLocation", - }, - { - OID: "1.7777", - Name: "doesNotExist2", - }, - }, - }, - "type": { - Value: "router", - }, + }, + }, + }), + Metadata: profiledefinition.MetadataConfig{ + "device": { + Fields: map[string]profiledefinition.MetadataField{ + "name": { + // Should use value from Symbol `1.3.6.1.2.1.1.5.0` + Symbol: profiledefinition.SymbolConfig{ + OID: "1.3.6.1.2.1.1.5.0", + Name: "sysName", + }, + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "1.2.99", + Name: "doesNotExist", }, }, }, + "description": { + // Should use value from first element in Symbols `1.3.6.1.2.1.1.1.0` + Symbol: profiledefinition.SymbolConfig{ + OID: "1.9999", + Name: "doesNotExist", + }, + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "1.3.6.1.2.1.1.1.0", + Name: "sysDescr", + }, + }, + }, + "location": { + // Should use value from first element in Symbols `1.3.6.1.2.1.1.1.0` + Symbol: profiledefinition.SymbolConfig{ + OID: "1.9999", + Name: "doesNotExist", + }, + Symbols: []profiledefinition.SymbolConfig{ + { + OID: "1.888", + Name: "doesNotExist2", + }, + { + OID: "1.3.6.1.2.1.1.6.0", + Name: "sysLocation", + }, + { + OID: "1.7777", + Name: "doesNotExist2", + }, + }, + }, + "type": { + Value: "router", + }, }, }, - }), + }, } layout := "2006-01-02 15:04:05" str := "2014-11-12 11:45:26" collectTime, err := time.Parse(layout, str) - require.NoError(t, err) - profile, err := config.BuildProfile("") - require.NoError(t, err) + assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, storeWithoutIfName, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusReachable, nil) + ms.ReportNetworkDeviceMetadata(config, storeWithoutIfName, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusReachable, nil) // language=json event := []byte(` @@ -210,17 +207,14 @@ profiles: `) config, err := checkconfig.NewCheckConfig(rawInstanceConfig, rawInitConfig) - require.Nil(t, err) + assert.Nil(t, err) layout := "2006-01-02 15:04:05" str := "2014-11-12 11:45:26" collectTime, err := time.Parse(layout, str) - require.NoError(t, err) - profile, err := config.BuildProfile("") - require.NoError(t, err) + assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, storeWithoutIfName, []string{"tag1", "tag2"}, collectTime, - metadata.DeviceStatusReachable, metadata.DeviceStatusReachable, nil) + ms.ReportNetworkDeviceMetadata(config, storeWithoutIfName, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusReachable, nil) // language=json event := []byte(` @@ -302,8 +296,6 @@ func Test_metricSender_reportNetworkDeviceMetadata_withDeviceInterfacesAndDiagno DeviceIDTags: []string{"device_name:127.0.0.1"}, ResolvedSubnetName: "127.0.0.0/29", Namespace: "my-ns", - } - profile := profiledefinition.ProfileDefinition{ Metadata: profiledefinition.MetadataConfig{ "device": { Fields: map[string]profiledefinition.MetadataField{ @@ -362,7 +354,7 @@ func Test_metricSender_reportNetworkDeviceMetadata_withDeviceInterfacesAndDiagno str := "2014-11-12 11:45:26" collectTime, err := time.Parse(layout, str) assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, storeWithIfName, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, diagnosis) + ms.ReportNetworkDeviceMetadata(config, storeWithIfName, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, diagnosis) ifTags1 := []string{"tag1", "tag2", "status:down", "interface:21", "interface_alias:ifAlias1", "interface_index:1", "oper_status:up", "admin_status:down"} ifTags2 := []string{"tag1", "tag2", "status:off", "interface:22", "interface_index:2", "oper_status:down", "admin_status:down", "muted", "someKey:someValue"} @@ -455,8 +447,6 @@ func Test_metricSender_reportNetworkDeviceMetadata_fallbackOnFieldValue(t *testi DeviceIDTags: []string{"device_name:127.0.0.1"}, ResolvedSubnetName: "127.0.0.0/29", Namespace: "my-ns", - } - profile := profiledefinition.ProfileDefinition{ Metadata: profiledefinition.MetadataConfig{ "device": { Fields: map[string]profiledefinition.MetadataField{ @@ -479,7 +469,7 @@ func Test_metricSender_reportNetworkDeviceMetadata_fallbackOnFieldValue(t *testi collectTime, err := time.Parse(layout, str) assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) + ms.ReportNetworkDeviceMetadata(config, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) // language=json event := []byte(` @@ -532,8 +522,6 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_Nil(t *testing DeviceIDTags: []string{"device_name:127.0.0.1"}, ResolvedSubnetName: "127.0.0.0/29", Namespace: "my-ns", - } - profile := profiledefinition.ProfileDefinition{ Metadata: profiledefinition.MetadataConfig{ "device": { Fields: map[string]profiledefinition.MetadataField{ @@ -553,7 +541,7 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_Nil(t *testing collectTime, err := time.Parse(layout, str) assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, 0, nil) + ms.ReportNetworkDeviceMetadata(config, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, 0, nil) // language=json event := []byte(` @@ -605,8 +593,6 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_True(t *testin DeviceIDTags: []string{"device_name:127.0.0.1"}, ResolvedSubnetName: "127.0.0.0/29", Namespace: "my-ns", - } - profile := profiledefinition.ProfileDefinition{ Metadata: profiledefinition.MetadataConfig{ "device": { Fields: map[string]profiledefinition.MetadataField{ @@ -626,7 +612,7 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_True(t *testin collectTime, err := time.Parse(layout, str) assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) + ms.ReportNetworkDeviceMetadata(config, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) // language=json event := []byte(` @@ -679,8 +665,6 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_False(t *testi DeviceIDTags: []string{"device_name:127.0.0.1"}, ResolvedSubnetName: "127.0.0.0/29", Namespace: "my-ns", - } - profile := profiledefinition.ProfileDefinition{ Metadata: profiledefinition.MetadataConfig{ "device": { Fields: map[string]profiledefinition.MetadataField{ @@ -700,7 +684,7 @@ func Test_metricSender_reportNetworkDeviceMetadata_pingCanConnect_False(t *testi collectTime, err := time.Parse(layout, str) assert.NoError(t, err) - ms.ReportNetworkDeviceMetadata(config, profile, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) + ms.ReportNetworkDeviceMetadata(config, emptyMetadataStore, []string{"tag1", "tag2"}, collectTime, metadata.DeviceStatusReachable, metadata.DeviceStatusUnreachable, nil) // language=json event := []byte(` @@ -980,3 +964,37 @@ func Test_buildInterfaceIndexByIDType(t *testing.T) { } assert.Equal(t, expectedInterfaceIndexByIDType, interfaceIndexByIDType) } + +func Test_getProfileVersion(t *testing.T) { + tests := []struct { + name string + config checkconfig.CheckConfig + expectedProfileVersion uint64 + }{ + { + name: "profile definition is present", + config: checkconfig.CheckConfig{ + ProfileName: "my-profile", + ProfileProvider: profile.StaticProvider(profile.ProfileConfigMap{ + "my-profile": profile.ProfileConfig{ + Definition: profiledefinition.ProfileDefinition{ + Name: "my-profile", + Version: 42, + }, + }, + }), + }, + expectedProfileVersion: 42, + }, + { + name: "profile definition not present", + config: checkconfig.CheckConfig{}, + expectedProfileVersion: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expectedProfileVersion, getProfileVersion(&tt.config)) + }) + } +}