Skip to content

Commit 1376f1c

Browse files
awpricejotak
andauthored
add support for adding annotations to kubernetes transform (#1115)
* add support for adding annotations to kubernetes transform Signed-off-by: Alex Price <[email protected]> * add support for label and annotation inclusion and exclusion lists Signed-off-by: Alex Price <[email protected]> * add support for label and annotation value max lengths Signed-off-by: Alex Price <[email protected]> * add pod, service, node annotations to object meta in informer Signed-off-by: Alex Price <[email protected]> * Apply suggestion from @jotak --------- Signed-off-by: Alex Price <[email protected]> Co-authored-by: Joel Takvorian <[email protected]>
1 parent dcbacce commit 1376f1c

File tree

5 files changed

+715
-16
lines changed

5 files changed

+715
-16
lines changed

docs/api.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,14 @@ Following is the supported API format for network transformations:
265265
macField: entry MAC input field
266266
output: entry output field
267267
assignee: value needs to assign to output field
268-
labels_prefix: labels prefix to use to copy input lables, if empty labels will not be copied
268+
labels_prefix: labels prefix to use to copy input labels, if empty labels will not be copied
269+
label_inclusions: labels to include, if empty all labels will be included. Only used if labels_prefix is specified
270+
label_exclusions: labels to exclude, if empty no labels will be excluded. Only used if labels_prefix is specified
271+
label_value_max_length: label value max length, if specified, will trim label values to this length
272+
annotations_prefix: annotations prefix to use to copy input annotations, if empty annotations will not be copied
273+
annotation_inclusions: annotations to include, if empty all annotations will be included. Only used if annotations_prefix is specified
274+
annotation_exclusions: annotations to exclude, if empty no annotations will be excluded. Only used if annotations_prefix is specified
275+
annotation_value_max_length: annotation value max length, if specified, will trim annotation values to this length
269276
add_zone: if true the rule will add the zone
270277
add_subnet: Add subnet rule configuration
271278
input: entry input field

pkg/api/transform_network.go

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,26 @@ type K8sReference struct {
9898
}
9999

100100
type K8sRule struct {
101-
IPField string `yaml:"ipField,omitempty" json:"ipField,omitempty" doc:"entry IP input field"`
102-
InterfacesField string `yaml:"interfacesField,omitempty" json:"interfacesField,omitempty" doc:"entry Interfaces input field"`
103-
UDNsField string `yaml:"udnsField,omitempty" json:"udnsField,omitempty" doc:"entry UDNs input field"`
104-
MACField string `yaml:"macField,omitempty" json:"macField,omitempty" doc:"entry MAC input field"`
105-
Output string `yaml:"output,omitempty" json:"output,omitempty" doc:"entry output field"`
106-
Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty" doc:"value needs to assign to output field"`
107-
LabelsPrefix string `yaml:"labels_prefix,omitempty" json:"labels_prefix,omitempty" doc:"labels prefix to use to copy input lables, if empty labels will not be copied"`
108-
AddZone bool `yaml:"add_zone,omitempty" json:"add_zone,omitempty" doc:"if true the rule will add the zone"`
109-
OutputKeys K8SOutputKeys `yaml:"-" json:"-"`
101+
IPField string `yaml:"ipField,omitempty" json:"ipField,omitempty" doc:"entry IP input field"`
102+
InterfacesField string `yaml:"interfacesField,omitempty" json:"interfacesField,omitempty" doc:"entry Interfaces input field"`
103+
UDNsField string `yaml:"udnsField,omitempty" json:"udnsField,omitempty" doc:"entry UDNs input field"`
104+
MACField string `yaml:"macField,omitempty" json:"macField,omitempty" doc:"entry MAC input field"`
105+
Output string `yaml:"output,omitempty" json:"output,omitempty" doc:"entry output field"`
106+
Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty" doc:"value needs to assign to output field"`
107+
LabelsPrefix string `yaml:"labels_prefix,omitempty" json:"labels_prefix,omitempty" doc:"labels prefix to use to copy input labels, if empty labels will not be copied"`
108+
LabelInclusions []string `yaml:"label_inclusions,omitempty" json:"label_inclusions,omitempty" doc:"labels to include, if empty all labels will be included. Only used if labels_prefix is specified"`
109+
LabelExclusions []string `yaml:"label_exclusions,omitempty" json:"label_exclusions,omitempty" doc:"labels to exclude, if empty no labels will be excluded. Only used if labels_prefix is specified"`
110+
LabelValueMaxLength *int `yaml:"label_value_max_length,omitempty" json:"label_value_max_length,omitempty" doc:"label value max length, if specified, will trim label values to this length"`
111+
AnnotationsPrefix string `yaml:"annotations_prefix,omitempty" json:"annotations_prefix,omitempty" doc:"annotations prefix to use to copy input annotations, if empty annotations will not be copied"`
112+
AnnotationInclusions []string `yaml:"annotation_inclusions,omitempty" json:"annotation_inclusions,omitempty" doc:"annotations to include, if empty all annotations will be included. Only used if annotations_prefix is specified"`
113+
AnnotationExclusions []string `yaml:"annotation_exclusions,omitempty" json:"annotation_exclusions,omitempty" doc:"annotations to exclude, if empty no annotations will be excluded. Only used if annotations_prefix is specified"`
114+
AnnotationValueMaxLength *int `yaml:"annotation_value_max_length,omitempty" json:"annotation_value_max_length,omitempty" doc:"annotation value max length, if specified, will trim annotation values to this length"`
115+
AddZone bool `yaml:"add_zone,omitempty" json:"add_zone,omitempty" doc:"if true the rule will add the zone"`
116+
OutputKeys K8SOutputKeys `yaml:"-" json:"-"`
117+
LabelInclusionsMap map[string]struct{} `yaml:"-" json:"-"`
118+
LabelExclusionsMap map[string]struct{} `yaml:"-" json:"-"`
119+
AnnotationInclusionsMap map[string]struct{} `yaml:"-" json:"-"`
120+
AnnotationExclusionsMap map[string]struct{} `yaml:"-" json:"-"`
110121
}
111122

112123
type K8SOutputKeys struct {
@@ -150,6 +161,11 @@ func (r *K8sRule) preprocess() {
150161
Zone: r.Output + "_Zone",
151162
}
152163
}
164+
165+
r.LabelInclusionsMap = buildStringMap(r.LabelInclusions)
166+
r.LabelExclusionsMap = buildStringMap(r.LabelExclusions)
167+
r.AnnotationInclusionsMap = buildStringMap(r.AnnotationInclusions)
168+
r.AnnotationExclusionsMap = buildStringMap(r.AnnotationExclusions)
153169
}
154170

155171
type SecondaryNetwork struct {
@@ -199,3 +215,11 @@ type NetworkTransformSubnetLabel struct {
199215
CIDRs []string `yaml:"cidrs,omitempty" json:"cidrs,omitempty" doc:"list of CIDRs to match a label"`
200216
Name string `yaml:"name,omitempty" json:"name,omitempty" doc:"name of the label"`
201217
}
218+
219+
func buildStringMap(items []string) map[string]struct{} {
220+
m := make(map[string]struct{}, len(items))
221+
for _, item := range items {
222+
m[item] = struct{}{}
223+
}
224+
return m
225+
}

pkg/pipeline/transform/kubernetes/enrich.go

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import (
1515
var ds *datasource.Datasource
1616
var infConfig informers.Config
1717

18+
const (
19+
truncateSuffix = "..."
20+
)
21+
1822
// For testing
1923
func MockInformers() {
2024
infConfig = informers.NewConfig(api.NetworkTransformKubeConfig{})
@@ -54,7 +58,24 @@ func Enrich(outputEntry config.GenericMap, rule *api.K8sRule) {
5458
outputEntry[rule.OutputKeys.NetworkName] = kubeInfo.NetworkName
5559
if rule.LabelsPrefix != "" {
5660
for labelKey, labelValue := range kubeInfo.Labels {
57-
outputEntry[rule.LabelsPrefix+"_"+labelKey] = labelValue
61+
if shouldInclude(labelKey, rule.LabelInclusionsMap, rule.LabelExclusionsMap) {
62+
outputEntry[rule.LabelsPrefix+"_"+labelKey] = truncateWithSuffix(
63+
labelValue,
64+
rule.LabelValueMaxLength,
65+
truncateSuffix,
66+
)
67+
}
68+
}
69+
}
70+
if rule.AnnotationsPrefix != "" {
71+
for annotationKey, annotationValue := range kubeInfo.Annotations {
72+
if shouldInclude(annotationKey, rule.AnnotationInclusionsMap, rule.AnnotationExclusionsMap) {
73+
outputEntry[rule.AnnotationsPrefix+"_"+annotationKey] = truncateWithSuffix(
74+
annotationValue,
75+
rule.AnnotationValueMaxLength,
76+
truncateSuffix,
77+
)
78+
}
5879
}
5980
}
6081
if kubeInfo.HostIP != "" {
@@ -142,3 +163,36 @@ func objectIsApp(namespace, name string, rule *api.K8sInfraRule) bool {
142163
}
143164
return true
144165
}
166+
167+
// shouldInclude determines if an item should be included based on inclusion/exclusion maps.
168+
func shouldInclude(key string, inclusions, exclusions map[string]struct{}) bool {
169+
if _, excluded := exclusions[key]; excluded {
170+
return false
171+
}
172+
if len(inclusions) > 0 {
173+
_, included := inclusions[key]
174+
return included
175+
}
176+
return true
177+
}
178+
179+
// truncateWithSuffix truncates s to max runes, including the suffix.
180+
func truncateWithSuffix(s string, maxRunes *int, suffix string) string {
181+
if maxRunes == nil {
182+
return s
183+
}
184+
m := *maxRunes
185+
if m <= 0 {
186+
return ""
187+
}
188+
r := []rune(s)
189+
sr := []rune(suffix)
190+
if len(r) <= m {
191+
return s
192+
}
193+
if m <= len(sr) {
194+
return string(sr[:m])
195+
}
196+
keep := m - len(sr)
197+
return string(r[:keep]) + suffix
198+
}

0 commit comments

Comments
 (0)