1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-14 11:57:51 +00:00

Use generics for maps and slices

This commit is contained in:
Markus Lehtonen 2023-12-13 11:38:06 +02:00
parent 6ef153e4c3
commit cb0a46ec0e
10 changed files with 42 additions and 79 deletions

2
go.mod
View file

@ -20,6 +20,7 @@ require (
github.com/smartystreets/goconvey v1.6.4 github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
golang.org/x/net v0.19.0 golang.org/x/net v0.19.0
golang.org/x/time v0.5.0 golang.org/x/time v0.5.0
google.golang.org/grpc v1.59.0 google.golang.org/grpc v1.59.0
@ -163,7 +164,6 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.16.0 // indirect golang.org/x/crypto v0.16.0 // indirect
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/mod v0.14.0 // indirect
golang.org/x/oauth2 v0.14.0 // indirect golang.org/x/oauth2 v0.14.0 // indirect
golang.org/x/sync v0.5.0 // indirect golang.org/x/sync v0.5.0 // indirect

View file

@ -24,6 +24,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"golang.org/x/exp/maps"
"k8s.io/klog/v2" "k8s.io/klog/v2"
) )
@ -259,10 +260,7 @@ func (m *MatchExpression) MatchKeys(name string, keys map[string]Nil) (bool, err
if klogV := klog.V(3); klogV.Enabled() { if klogV := klog.V(3); klogV.Enabled() {
klogV.InfoS("matched keys", "matchResult", matched, "matchKey", name, "matchOp", m.Op) klogV.InfoS("matched keys", "matchResult", matched, "matchKey", name, "matchOp", m.Op)
} else if klogV := klog.V(4); klogV.Enabled() { } else if klogV := klog.V(4); klogV.Enabled() {
k := make([]string, 0, len(keys)) k := maps.Keys(keys)
for n := range keys {
k = append(k, n)
}
sort.Strings(k) sort.Strings(k)
klogV.InfoS("matched keys", "matchResult", matched, "matchKey", name, "matchOp", m.Op, "inputKeys", k) klogV.InfoS("matched keys", "matchResult", matched, "matchKey", name, "matchOp", m.Op, "inputKeys", k)
} }

View file

@ -16,6 +16,8 @@ limitations under the License.
package v1alpha1 package v1alpha1
import "maps"
// NewNodeFeatureSpec creates a new emprty instance of NodeFeatureSpec type, // NewNodeFeatureSpec creates a new emprty instance of NodeFeatureSpec type,
// initializing all fields to proper empty values. // initializing all fields to proper empty values.
func NewNodeFeatureSpec() *NodeFeatureSpec { func NewNodeFeatureSpec() *NodeFeatureSpec {
@ -75,9 +77,7 @@ func (f *Features) InsertAttributeFeatures(domain, feature string, values map[st
return return
} }
for k, v := range values { maps.Copy(f.Attributes[key].Elements, values)
f.Attributes[key].Elements[k] = v
}
} }
// Exists returns a non-empty string if a feature exists. The return value is // Exists returns a non-empty string if a feature exists. The return value is
@ -103,9 +103,7 @@ func (in *NodeFeatureSpec) MergeInto(out *NodeFeatureSpec) {
if out.Labels == nil { if out.Labels == nil {
out.Labels = make(map[string]string, len(in.Labels)) out.Labels = make(map[string]string, len(in.Labels))
} }
for key, val := range in.Labels { maps.Copy(out.Labels, in.Labels)
out.Labels[key] = val
}
} }
} }
@ -151,9 +149,7 @@ func (in *FlagFeatureSet) MergeInto(out *FlagFeatureSet) {
if out.Elements == nil { if out.Elements == nil {
out.Elements = make(map[string]Nil, len(in.Elements)) out.Elements = make(map[string]Nil, len(in.Elements))
} }
for key, val := range in.Elements { maps.Copy(out.Elements, in.Elements)
out.Elements[key] = val
}
} }
} }
@ -163,9 +159,7 @@ func (in *AttributeFeatureSet) MergeInto(out *AttributeFeatureSet) {
if out.Elements == nil { if out.Elements == nil {
out.Elements = make(map[string]string, len(in.Elements)) out.Elements = make(map[string]string, len(in.Elements))
} }
for key, val := range in.Elements { maps.Copy(out.Elements, in.Elements)
out.Elements[key] = val
}
} }
} }

View file

@ -19,6 +19,8 @@ package v1alpha1
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"maps"
"slices"
"strings" "strings"
"text/template" "text/template"
@ -40,7 +42,6 @@ type RuleOutput struct {
// Execute the rule against a set of input features. // Execute the rule against a set of input features.
func (r *Rule) Execute(features *Features) (RuleOutput, error) { func (r *Rule) Execute(features *Features) (RuleOutput, error) {
extendedResources := make(map[string]string)
labels := make(map[string]string) labels := make(map[string]string)
vars := make(map[string]string) vars := make(map[string]string)
@ -92,18 +93,16 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) {
} }
} }
for k, v := range r.ExtendedResources { maps.Copy(labels, r.Labels)
extendedResources[k] = v maps.Copy(vars, r.Vars)
}
for k, v := range r.Labels { ret := RuleOutput{
labels[k] = v Labels: labels,
Vars: vars,
Annotations: maps.Clone(r.Annotations),
ExtendedResources: maps.Clone(r.ExtendedResources),
Taints: slices.Clone(r.Taints),
} }
for k, v := range r.Vars {
vars[k] = v
}
ret := RuleOutput{ExtendedResources: extendedResources, Labels: labels, Vars: vars, Taints: r.Taints, Annotations: r.Annotations}
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret)) klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
return ret, nil return ret, nil
} }

View file

@ -20,6 +20,7 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"maps"
"net" "net"
"os" "os"
"path" "path"
@ -477,11 +478,9 @@ func (m *nfdMaster) prune() error {
if err != nil { if err != nil {
return err return err
} }
for a := range node.Annotations { maps.DeleteFunc(node.Annotations, func(k, v string) bool {
if strings.HasPrefix(a, m.instanceAnnotation(nfdv1alpha1.AnnotationNs)) { return strings.HasPrefix(k, m.instanceAnnotation(nfdv1alpha1.AnnotationNs))
delete(node.Annotations, a) })
}
}
err = m.apihelper.UpdateNode(cli, node) err = m.apihelper.UpdateNode(cli, node)
if err != nil { if err != nil {
return fmt.Errorf("failed to prune annotations from node %q: %v", node.Name, err) return fmt.Errorf("failed to prune annotations from node %q: %v", node.Name, err)
@ -812,18 +811,14 @@ func (m *nfdMaster) refreshNodeFeatures(cli *kubernetes.Clientset, nodeName stri
crLabels, crAnnotations, crExtendedResources, crTaints := m.processNodeFeatureRule(nodeName, features) crLabels, crAnnotations, crExtendedResources, crTaints := m.processNodeFeatureRule(nodeName, features)
// Mix in CR-originated labels // Mix in CR-originated labels
for k, v := range crLabels { maps.Copy(labels, crLabels)
labels[k] = v
}
// Remove labels which are intended to be extended resources via // Remove labels which are intended to be extended resources via
// -resource-labels or their NS is not whitelisted // -resource-labels or their NS is not whitelisted
labels, extendedResources := m.filterFeatureLabels(labels, features) labels, extendedResources := m.filterFeatureLabels(labels, features)
// Mix in CR-originated extended resources with -resource-labels // Mix in CR-originated extended resources with -resource-labels
for k, v := range crExtendedResources { maps.Copy(extendedResources, crExtendedResources)
extendedResources[k] = v
}
extendedResources = m.filterExtendedResources(features, extendedResources) extendedResources = m.filterExtendedResources(features, extendedResources)
// Annotations // Annotations
@ -991,15 +986,9 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha
e = addNsToMapKeys(ruleOut.ExtendedResources, nfdv1alpha1.ExtendedResourceNs) e = addNsToMapKeys(ruleOut.ExtendedResources, nfdv1alpha1.ExtendedResourceNs)
a = addNsToMapKeys(ruleOut.Annotations, nfdv1alpha1.FeatureAnnotationNs) a = addNsToMapKeys(ruleOut.Annotations, nfdv1alpha1.FeatureAnnotationNs)
} }
for k, v := range l { maps.Copy(labels, l)
labels[k] = v maps.Copy(extendedResources, e)
} maps.Copy(annotations, a)
for k, v := range e {
extendedResources[k] = v
}
for k, v := range a {
annotations[k] = v
}
// Feed back rule output to features map for subsequent rules to match // Feed back rule output to features map for subsequent rules to match
features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Labels) features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Labels)
@ -1061,9 +1050,7 @@ func (m *nfdMaster) updateNodeObject(cli *kubernetes.Clientset, nodeName string,
} }
sort.Strings(annotationKeys) sort.Strings(annotationKeys)
annotations[m.instanceAnnotation(nfdv1alpha1.FeatureAnnotationsTrackingAnnotation)] = strings.Join(annotationKeys, ",") annotations[m.instanceAnnotation(nfdv1alpha1.FeatureAnnotationsTrackingAnnotation)] = strings.Join(annotationKeys, ",")
for k, v := range featureAnnotations { maps.Copy(annotations, featureAnnotations)
annotations[k] = v
}
} }
// Create JSON patches for changes in labels and annotations // Create JSON patches for changes in labels and annotations

View file

@ -28,6 +28,7 @@ import (
"strings" "strings"
"time" "time"
"golang.org/x/exp/maps"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
@ -415,10 +416,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
} }
} }
w.featureSources = make([]source.FeatureSource, 0, len(featureSources)) w.featureSources = maps.Values(featureSources)
for _, s := range featureSources {
w.featureSources = append(w.featureSources, s)
}
sort.Slice(w.featureSources, func(i, j int) bool { return w.featureSources[i].Name() < w.featureSources[j].Name() }) sort.Slice(w.featureSources, func(i, j int) bool { return w.featureSources[i].Name() < w.featureSources[j].Name() })
@ -450,10 +448,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
} }
} }
w.labelSources = make([]source.LabelSource, 0, len(labelSources)) w.labelSources = maps.Values(labelSources)
for _, s := range labelSources {
w.labelSources = append(w.labelSources, s)
}
sort.Slice(w.labelSources, func(i, j int) bool { sort.Slice(w.labelSources, func(i, j int) bool {
iP, jP := w.labelSources[i].Priority(), w.labelSources[j].Priority() iP, jP := w.labelSources[i].Priority(), w.labelSources[j].Priority()
@ -560,9 +555,7 @@ func createFeatureLabels(sources []source.LabelSource, labelWhiteList regexp.Reg
continue continue
} }
for name, value := range labelsFromSource { maps.Copy(labels, labelsFromSource)
labels[name] = value
}
} }
if klogV := klog.V(1); klogV.Enabled() { if klogV := klog.V(1); klogV.Enabled() {
klogV.InfoS("feature discovery completed", "labels", utils.DelayedDumper(labels)) klogV.InfoS("feature discovery completed", "labels", utils.DelayedDumper(labels))

View file

@ -24,6 +24,8 @@ import (
"sort" "sort"
"strings" "strings"
"time" "time"
"golang.org/x/exp/maps"
) )
// RegexpVal is a wrapper for regexp command line flags // RegexpVal is a wrapper for regexp command line flags
@ -77,10 +79,7 @@ func (a *StringSetVal) String() string {
if *a == nil { if *a == nil {
return "" return ""
} }
vals := make([]string, 0, len(*a)) vals := maps.Keys(*a)
for val := range *a {
vals = append(vals, val)
}
sort.Strings(vals) sort.Strings(vals)
return strings.Join(vals, ",") return strings.Join(vals, ",")
} }

View file

@ -18,6 +18,7 @@ package utils
import ( import (
"fmt" "fmt"
"maps"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -75,9 +76,7 @@ func GetNumaMemoryResources() (NumaMemoryResources, error) {
return nil, err return nil, err
} }
} }
for n, s := range hugepageBytes { maps.Copy(info, hugepageBytes)
info[n] = s
}
memoryResources[nodeID] = info memoryResources[nodeID] = info
} }

View file

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"golang.org/x/exp/maps"
"k8s.io/klog/v2" "k8s.io/klog/v2"
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
@ -102,11 +103,7 @@ func (s *pciSource) GetLabels() (source.FeatureLabels, error) {
} }
} }
if len(configLabelFields) > 0 { if len(configLabelFields) > 0 {
keys := []string{} klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", maps.Keys(configLabelFields))
for key := range configLabelFields {
keys = append(keys, key)
}
klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", keys)
} }
if len(deviceLabelFields) == 0 { if len(deviceLabelFields) == 0 {
deviceLabelFields = []string{"class", "vendor"} deviceLabelFields = []string{"class", "vendor"}

View file

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"golang.org/x/exp/maps"
"k8s.io/klog/v2" "k8s.io/klog/v2"
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
@ -105,11 +106,7 @@ func (s *usbSource) GetLabels() (source.FeatureLabels, error) {
} }
} }
if len(configLabelFields) > 0 { if len(configLabelFields) > 0 {
keys := []string{} klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", maps.Keys(configLabelFields))
for key := range configLabelFields {
keys = append(keys, key)
}
klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", keys)
} }
if len(deviceLabelFields) == 0 { if len(deviceLabelFields) == 0 {
deviceLabelFields = defaultDeviceLabelFields() deviceLabelFields = defaultDeviceLabelFields()