/
profile_resolver.go
127 lines (110 loc) · 4.88 KB
/
profile_resolver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// 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 profile
import (
"fmt"
"strings"
"github.com/DataDog/datadog-agent/pkg/util/log"
"github.com/mohae/deepcopy"
"github.com/DataDog/datadog-agent/pkg/networkdevice/profile/profiledefinition"
"github.com/DataDog/datadog-agent/pkg/networkdevice/utils"
"github.com/DataDog/datadog-agent/pkg/collector/corechecks/snmp/internal/configvalidation"
)
func resolveProfiles(userProfiles, defaultProfiles ProfileConfigMap) (ProfileConfigMap, error) {
rawProfiles := mergeProfiles(defaultProfiles, userProfiles)
userExpandedProfiles, err := loadResolveProfiles(rawProfiles, defaultProfiles)
if err != nil {
return nil, fmt.Errorf("failed to load profiles: %w", err)
}
return userExpandedProfiles, nil
}
func loadResolveProfiles(pConfig ProfileConfigMap, defaultProfiles ProfileConfigMap) (ProfileConfigMap, error) {
profiles := make(ProfileConfigMap, len(pConfig))
for name := range pConfig {
// No need to resolve abstract profile
if strings.HasPrefix(name, "_") {
continue
}
newProfileConfig := deepcopy.Copy(pConfig[name]).(ProfileConfig)
err := recursivelyExpandBaseProfiles(name, &newProfileConfig.Definition, newProfileConfig.Definition.Extends, []string{}, pConfig, defaultProfiles)
if err != nil {
log.Warnf("failed to expand profile %q: %v", name, err)
continue
}
profiledefinition.NormalizeMetrics(newProfileConfig.Definition.Metrics)
errors := configvalidation.ValidateEnrichMetadata(newProfileConfig.Definition.Metadata)
errors = append(errors, configvalidation.ValidateEnrichMetrics(newProfileConfig.Definition.Metrics)...)
errors = append(errors, configvalidation.ValidateEnrichMetricTags(newProfileConfig.Definition.MetricTags)...)
if len(errors) > 0 {
log.Warnf("validation errors in profile %q: %s", name, strings.Join(errors, "\n"))
continue
}
profiles[name] = newProfileConfig
}
return profiles, nil
}
func recursivelyExpandBaseProfiles(parentExtend string, definition *profiledefinition.ProfileDefinition, extends []string, extendsHistory []string, profiles ProfileConfigMap, defaultProfiles ProfileConfigMap) error {
for _, extendEntry := range extends {
extendEntry = strings.TrimSuffix(extendEntry, ".yaml")
var baseDefinition *profiledefinition.ProfileDefinition
// User profile can extend default profile by extending the default profile.
// If the extend entry has the same name as the profile name, we assume the extend entry is referring to a default profile.
if extendEntry == parentExtend {
profile, ok := defaultProfiles[extendEntry]
if !ok {
return fmt.Errorf("extend does not exist: `%s`", extendEntry)
}
baseDefinition = &profile.Definition
} else {
profile, ok := profiles[extendEntry]
if !ok {
profile, ok = defaultProfiles[extendEntry]
if !ok {
return fmt.Errorf("extend does not exist: `%s`", extendEntry)
}
}
baseDefinition = &profile.Definition
}
for _, extend := range extendsHistory {
if extend == extendEntry {
return fmt.Errorf("cyclic profile extend detected, `%s` has already been extended, extendsHistory=`%v`", extendEntry, extendsHistory)
}
}
mergeProfileDefinition(definition, baseDefinition)
newExtendsHistory := append(utils.CopyStrings(extendsHistory), extendEntry)
err := recursivelyExpandBaseProfiles(extendEntry, definition, baseDefinition.Extends, newExtendsHistory, profiles, defaultProfiles)
if err != nil {
return err
}
}
return nil
}
func mergeProfileDefinition(targetDefinition *profiledefinition.ProfileDefinition, baseDefinition *profiledefinition.ProfileDefinition) {
targetDefinition.Metrics = append(targetDefinition.Metrics, baseDefinition.Metrics...)
targetDefinition.MetricTags = append(targetDefinition.MetricTags, baseDefinition.MetricTags...)
targetDefinition.StaticTags = append(targetDefinition.StaticTags, baseDefinition.StaticTags...)
if targetDefinition.Metadata == nil {
targetDefinition.Metadata = make(profiledefinition.MetadataConfig)
}
for baseResName, baseResource := range baseDefinition.Metadata {
if _, ok := targetDefinition.Metadata[baseResName]; !ok {
targetDefinition.Metadata[baseResName] = profiledefinition.NewMetadataResourceConfig()
}
if resource, ok := targetDefinition.Metadata[baseResName]; ok {
for _, tagConfig := range baseResource.IDTags {
resource.IDTags = append(targetDefinition.Metadata[baseResName].IDTags, tagConfig)
}
if resource.Fields == nil {
resource.Fields = make(map[string]profiledefinition.MetadataField, len(baseResource.Fields))
}
for field, symbol := range baseResource.Fields {
if _, ok := resource.Fields[field]; !ok {
resource.Fields[field] = symbol
}
}
targetDefinition.Metadata[baseResName] = resource
}
}
}