diff --git a/pkg/apis/nfd/v1alpha1/annotations_labels.go b/pkg/apis/nfd/v1alpha1/annotations_labels.go new file mode 100644 index 000000000..0dc82a6a9 --- /dev/null +++ b/pkg/apis/nfd/v1alpha1/annotations_labels.go @@ -0,0 +1,46 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +const ( + // FeatureLabelNs is the (default) namespace for feature labels. + FeatureLabelNs = "feature.node.kubernetes.io" + + // FeatureLabelSubNsSuffix is the suffix for allowed feature label sub-namespaces. + FeatureLabelSubNsSuffix = "." + FeatureLabelNs + + // ProfileLabelNs is the namespace for profile labels. + ProfileLabelNs = "profile.node.kubernetes.io" + + // ProfileLabelSubNsSuffix is the suffix for allowed profile label sub-namespaces. + ProfileLabelSubNsSuffix = "." + ProfileLabelNs + + // AnnotationNs namespace for all NFD-related annotations. + AnnotationNs = "nfd.node.kubernetes.io" + + // ExtendedResourceAnnotation is the annotation that holds all extended resources managed by NFD. + ExtendedResourceAnnotation = AnnotationNs + "/extended-resources" + + // FeatureLabelsAnnotation is the annotation that holds all feature labels managed by NFD. + FeatureLabelsAnnotation = AnnotationNs + "/feature-labels" + + // MasterVersionAnnotation is the annotation that holds the version of nfd-master running on the node + MasterVersionAnnotation = AnnotationNs + "/master.version" + + // WorkerVersionAnnotation is the annotation that holds the version of nfd-worker running on the node + WorkerVersionAnnotation = AnnotationNs + "/worker.version" +) diff --git a/pkg/nfd-master/nfd-master-internal_test.go b/pkg/nfd-master/nfd-master-internal_test.go index 3d36ad805..dbdb98360 100644 --- a/pkg/nfd-master/nfd-master-internal_test.go +++ b/pkg/nfd-master/nfd-master-internal_test.go @@ -17,7 +17,6 @@ limitations under the License. package nfdmaster import ( - "path" "regexp" "sort" "strings" @@ -33,6 +32,7 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sclient "k8s.io/client-go/kubernetes" "sigs.k8s.io/node-feature-discovery/pkg/apihelper" + nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" "sigs.k8s.io/node-feature-discovery/pkg/labeler" "sigs.k8s.io/node-feature-discovery/pkg/utils" "sigs.k8s.io/node-feature-discovery/pkg/version" @@ -54,32 +54,31 @@ func newMockNode() *api.Node { func newMockMaster(apihelper apihelper.APIHelpers) *nfdMaster { return &nfdMaster{ - nodeName: mockNodeName, - annotationNs: AnnotationNsBase, - args: Args{LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")}}, - apihelper: apihelper, + nodeName: mockNodeName, + args: Args{LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")}}, + apihelper: apihelper, } } func TestUpdateNodeFeatures(t *testing.T) { Convey("When I update the node using fake client", t, func() { fakeFeatureLabels := map[string]string{ - FeatureLabelNs + "/source-feature.1": "1", - FeatureLabelNs + "/source-feature.2": "2", - FeatureLabelNs + "/source-feature.3": "val3", - ProfileLabelNs + "/profile-a": "val4"} + nfdv1alpha1.FeatureLabelNs + "/source-feature.1": "1", + nfdv1alpha1.FeatureLabelNs + "/source-feature.2": "2", + nfdv1alpha1.FeatureLabelNs + "/source-feature.3": "val3", + nfdv1alpha1.ProfileLabelNs + "/profile-a": "val4"} fakeAnnotations := map[string]string{"my-annotation": "my-val"} - fakeExtResources := ExtendedResources{FeatureLabelNs + "/source-feature.1": "1", FeatureLabelNs + "/source-feature.2": "2"} + fakeExtResources := ExtendedResources{nfdv1alpha1.FeatureLabelNs + "/source-feature.1": "1", nfdv1alpha1.FeatureLabelNs + "/source-feature.2": "2"} fakeFeatureLabelNames := make([]string, 0, len(fakeFeatureLabels)) for k := range fakeFeatureLabels { - fakeFeatureLabelNames = append(fakeFeatureLabelNames, strings.TrimPrefix(k, FeatureLabelNs+"/")) + fakeFeatureLabelNames = append(fakeFeatureLabelNames, strings.TrimPrefix(k, nfdv1alpha1.FeatureLabelNs+"/")) } sort.Strings(fakeFeatureLabelNames) fakeExtResourceNames := make([]string, 0, len(fakeExtResources)) for k := range fakeExtResources { - fakeExtResourceNames = append(fakeExtResourceNames, strings.TrimPrefix(k, FeatureLabelNs+"/")) + fakeExtResourceNames = append(fakeExtResourceNames, strings.TrimPrefix(k, nfdv1alpha1.FeatureLabelNs+"/")) } sort.Strings(fakeExtResourceNames) @@ -88,15 +87,15 @@ func TestUpdateNodeFeatures(t *testing.T) { mockClient := &k8sclient.Clientset{} // Mock node with old features mockNode := newMockNode() - mockNode.Labels[FeatureLabelNs+"/old-feature"] = "old-value" - mockNode.Annotations[AnnotationNsBase+"/feature-labels"] = "old-feature" + mockNode.Labels[nfdv1alpha1.FeatureLabelNs+"/old-feature"] = "old-value" + mockNode.Annotations[nfdv1alpha1.AnnotationNs+"/feature-labels"] = "old-feature" Convey("When I successfully update the node with feature labels", func() { // Create a list of expected node metadata patches metadataPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("replace", "/metadata/annotations", AnnotationNsBase+"/feature-labels", strings.Join(fakeFeatureLabelNames, ",")), - apihelper.NewJsonPatch("add", "/metadata/annotations", AnnotationNsBase+"/extended-resources", strings.Join(fakeExtResourceNames, ",")), - apihelper.NewJsonPatch("remove", "/metadata/labels", FeatureLabelNs+"/old-feature", ""), + apihelper.NewJsonPatch("replace", "/metadata/annotations", nfdv1alpha1.AnnotationNs+"/feature-labels", strings.Join(fakeFeatureLabelNames, ",")), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.AnnotationNs+"/extended-resources", strings.Join(fakeExtResourceNames, ",")), + apihelper.NewJsonPatch("remove", "/metadata/labels", nfdv1alpha1.FeatureLabelNs+"/old-feature", ""), } for k, v := range fakeFeatureLabels { metadataPatches = append(metadataPatches, apihelper.NewJsonPatch("add", "/metadata/labels", k, v)) @@ -176,7 +175,7 @@ func TestUpdateMasterNode(t *testing.T) { mockNode := newMockNode() Convey("When update operation succeeds", func() { expectedPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/metadata/annotations", AnnotationNsBase+"/master.version", version.Get())} + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.AnnotationNs+"/master.version", version.Get())} mockHelper.On("GetClient").Return(mockClient, nil) mockHelper.On("GetNode", mockClient, mockNodeName).Return(mockNode, nil) mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil) @@ -239,8 +238,8 @@ func TestAddingExtResources(t *testing.T) { Convey("When the resource already exists", func() { mockNode := newMockNode() - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) - mockResourceLabels := ExtendedResources{FeatureLabelNs + "/feature-1": "1"} + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) + mockResourceLabels := ExtendedResources{nfdv1alpha1.FeatureLabelNs + "/feature-1": "1"} patches := mockMaster.createExtendedResourcePatches(mockNode, mockResourceLabels) So(len(patches), ShouldEqual, 0) }) @@ -264,28 +263,28 @@ func TestRemovingExtResources(t *testing.T) { mockMaster := newMockMaster(nil) Convey("When none are removed", func() { mockNode := newMockNode() - mockResourceLabels := ExtendedResources{FeatureLabelNs + "/feature-1": "1", FeatureLabelNs + "/feature-2": "2"} - mockNode.Annotations[AnnotationNsBase+"/extended-resources"] = "feature-1,feature-2" - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) + mockResourceLabels := ExtendedResources{nfdv1alpha1.FeatureLabelNs + "/feature-1": "1", nfdv1alpha1.FeatureLabelNs + "/feature-2": "2"} + mockNode.Annotations[nfdv1alpha1.AnnotationNs+"/extended-resources"] = "feature-1,feature-2" + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) patches := mockMaster.createExtendedResourcePatches(mockNode, mockResourceLabels) So(len(patches), ShouldEqual, 0) }) Convey("When the related label is gone", func() { mockNode := newMockNode() - mockResourceLabels := ExtendedResources{FeatureLabelNs + "/feature-4": "", FeatureLabelNs + "/feature-2": "2"} - mockNode.Annotations[AnnotationNsBase+"/extended-resources"] = "feature-4,feature-2" - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-4")] = *resource.NewQuantity(4, resource.BinarySI) - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) + mockResourceLabels := ExtendedResources{nfdv1alpha1.FeatureLabelNs + "/feature-4": "", nfdv1alpha1.FeatureLabelNs + "/feature-2": "2"} + mockNode.Annotations[nfdv1alpha1.AnnotationNs+"/extended-resources"] = "feature-4,feature-2" + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-4")] = *resource.NewQuantity(4, resource.BinarySI) + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) patches := mockMaster.createExtendedResourcePatches(mockNode, mockResourceLabels) So(len(patches), ShouldBeGreaterThan, 0) }) Convey("When the extended resource is no longer wanted", func() { mockNode := newMockNode() - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) - mockNode.Status.Capacity[api.ResourceName(FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) - mockResourceLabels := ExtendedResources{FeatureLabelNs + "/feature-2": "2"} - mockNode.Annotations[AnnotationNsBase+"/extended-resources"] = "feature-1,feature-2" + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-1")] = *resource.NewQuantity(1, resource.BinarySI) + mockNode.Status.Capacity[api.ResourceName(nfdv1alpha1.FeatureLabelNs+"/feature-2")] = *resource.NewQuantity(2, resource.BinarySI) + mockResourceLabels := ExtendedResources{nfdv1alpha1.FeatureLabelNs + "/feature-2": "2"} + mockNode.Annotations[nfdv1alpha1.AnnotationNs+"/extended-resources"] = "feature-1,feature-2" patches := mockMaster.createExtendedResourcePatches(mockNode, mockResourceLabels) So(len(patches), ShouldBeGreaterThan, 0) }) @@ -313,17 +312,14 @@ func TestSetLabels(t *testing.T) { expectedStatusPatches := []apihelper.JsonPatch{} - wvAnnotation := path.Join(AnnotationNsBase, workerVersionAnnotation) - flAnnotation := path.Join(AnnotationNsBase, featureLabelAnnotation) - erAnnotation := path.Join(AnnotationNsBase, extendedResourceAnnotation) Convey("When node update succeeds", func() { expectedPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/metadata/annotations", wvAnnotation, workerVer), - apihelper.NewJsonPatch("add", "/metadata/annotations", flAnnotation, strings.Join(mockLabelNames, ",")), - apihelper.NewJsonPatch("add", "/metadata/annotations", erAnnotation, ""), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.WorkerVersionAnnotation, workerVer), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.FeatureLabelsAnnotation, strings.Join(mockLabelNames, ",")), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.ExtendedResourceAnnotation, ""), } for k, v := range mockLabels { - expectedPatches = append(expectedPatches, apihelper.NewJsonPatch("add", "/metadata/labels", FeatureLabelNs+"/"+k, v)) + expectedPatches = append(expectedPatches, apihelper.NewJsonPatch("add", "/metadata/labels", nfdv1alpha1.FeatureLabelNs+"/"+k, v)) } mockHelper.On("GetClient").Return(mockClient, nil) @@ -338,10 +334,10 @@ func TestSetLabels(t *testing.T) { Convey("When -label-whitelist is specified", func() { expectedPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/metadata/annotations", wvAnnotation, workerVer), - apihelper.NewJsonPatch("add", "/metadata/annotations", flAnnotation, "feature-2"), - apihelper.NewJsonPatch("add", "/metadata/annotations", erAnnotation, ""), - apihelper.NewJsonPatch("add", "/metadata/labels", FeatureLabelNs+"/feature-2", mockLabels["feature-2"]), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.WorkerVersionAnnotation, workerVer), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.FeatureLabelsAnnotation, "feature-2"), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.ExtendedResourceAnnotation, ""), + apihelper.NewJsonPatch("add", "/metadata/labels", nfdv1alpha1.FeatureLabelNs+"/feature-2", mockLabels["feature-2"]), } mockMaster.args.LabelWhiteList.Regexp = *regexp.MustCompile("^f.*2$") @@ -358,27 +354,27 @@ func TestSetLabels(t *testing.T) { Convey("When -extra-label-ns and -instance are specified", func() { // In the gRPC request the label names may omit the default ns instance := "foo" - vendorFeatureLabel := "vendor." + FeatureLabelNs + "/feature-4" - vendorProfileLabel := "vendor." + ProfileLabelNs + "/feature-5" + vendorFeatureLabel := "vendor." + nfdv1alpha1.FeatureLabelNs + "/feature-4" + vendorProfileLabel := "vendor." + nfdv1alpha1.ProfileLabelNs + "/feature-5" mockLabels := map[string]string{"feature-1": "val-1", "valid.ns/feature-2": "val-2", "invalid.ns/feature-3": "val-3", vendorFeatureLabel: " val-4", vendorProfileLabel: " val-5"} expectedPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/metadata/annotations", instance+"."+wvAnnotation, workerVer), + apihelper.NewJsonPatch("add", "/metadata/annotations", instance+"."+nfdv1alpha1.WorkerVersionAnnotation, workerVer), apihelper.NewJsonPatch("add", "/metadata/annotations", - instance+"."+flAnnotation, + instance+"."+nfdv1alpha1.FeatureLabelsAnnotation, "feature-1,valid.ns/feature-2,"+vendorFeatureLabel+","+vendorProfileLabel), - apihelper.NewJsonPatch("add", "/metadata/annotations", instance+"."+erAnnotation, ""), - apihelper.NewJsonPatch("add", "/metadata/labels", FeatureLabelNs+"/feature-1", mockLabels["feature-1"]), + apihelper.NewJsonPatch("add", "/metadata/annotations", instance+"."+nfdv1alpha1.ExtendedResourceAnnotation, ""), + apihelper.NewJsonPatch("add", "/metadata/labels", nfdv1alpha1.FeatureLabelNs+"/feature-1", mockLabels["feature-1"]), apihelper.NewJsonPatch("add", "/metadata/labels", "valid.ns/feature-2", mockLabels["valid.ns/feature-2"]), apihelper.NewJsonPatch("add", "/metadata/labels", vendorFeatureLabel, mockLabels[vendorFeatureLabel]), apihelper.NewJsonPatch("add", "/metadata/labels", vendorProfileLabel, mockLabels[vendorProfileLabel]), } mockMaster.args.ExtraLabelNs = map[string]struct{}{"valid.ns": {}} - mockMaster.annotationNs = instance + "." + AnnotationNsBase + mockMaster.args.Instance = instance mockHelper.On("GetClient").Return(mockClient, nil) mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil) mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil) @@ -388,19 +384,19 @@ func TestSetLabels(t *testing.T) { Convey("Error is nil", func() { So(err, ShouldBeNil) }) - mockMaster.annotationNs = AnnotationNsBase + mockMaster.args.Instance = "" }) Convey("When -resource-labels is specified", func() { expectedPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/metadata/annotations", wvAnnotation, workerVer), - apihelper.NewJsonPatch("add", "/metadata/annotations", flAnnotation, "feature-2"), - apihelper.NewJsonPatch("add", "/metadata/annotations", erAnnotation, "feature-1,feature-3"), - apihelper.NewJsonPatch("add", "/metadata/labels", FeatureLabelNs+"/feature-2", mockLabels["feature-2"]), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.WorkerVersionAnnotation, workerVer), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.FeatureLabelsAnnotation, "feature-2"), + apihelper.NewJsonPatch("add", "/metadata/annotations", nfdv1alpha1.ExtendedResourceAnnotation, "feature-1,feature-3"), + apihelper.NewJsonPatch("add", "/metadata/labels", nfdv1alpha1.FeatureLabelNs+"/feature-2", mockLabels["feature-2"]), } expectedStatusPatches := []apihelper.JsonPatch{ - apihelper.NewJsonPatch("add", "/status/capacity", FeatureLabelNs+"/feature-1", mockLabels["feature-1"]), - apihelper.NewJsonPatch("add", "/status/capacity", FeatureLabelNs+"/feature-3", mockLabels["feature-3"]), + apihelper.NewJsonPatch("add", "/status/capacity", nfdv1alpha1.FeatureLabelNs+"/feature-1", mockLabels["feature-1"]), + apihelper.NewJsonPatch("add", "/status/capacity", nfdv1alpha1.FeatureLabelNs+"/feature-3", mockLabels["feature-3"]), } mockMaster.args.ResourceLabels = map[string]struct{}{"feature-3": {}, "feature-1": {}} diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index 8913e83a1..b10e08946 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -52,29 +52,6 @@ import ( "sigs.k8s.io/node-feature-discovery/pkg/version" ) -const ( - // FeatureLabelNs is the namespace for feature labels - FeatureLabelNs = "feature.node.kubernetes.io" - - // FeatureLabelSubNsSuffix is the suffix for allowed feature label sub-namespaces - FeatureLabelSubNsSuffix = "." + FeatureLabelNs - - // ProfileLabelNs is the namespace for profile labels - ProfileLabelNs = "profile.node.kubernetes.io" - - // ProfileLabelSubNsSuffix is the suffix for allowed profile label sub-namespaces - ProfileLabelSubNsSuffix = "." + ProfileLabelNs - - // AnnotationNsBase namespace for all NFD-related annotations - AnnotationNsBase = "nfd.node.kubernetes.io" - - // NFD Annotations - extendedResourceAnnotation = "extended-resources" - featureLabelAnnotation = "feature-labels" - masterVersionAnnotation = "master.version" - workerVersionAnnotation = "worker.version" -) - // Labels are a Kubernetes representation of discovered features. type Labels map[string]string @@ -110,14 +87,13 @@ type NfdMaster interface { type nfdMaster struct { *nfdController - args Args - nodeName string - annotationNs string - server *grpc.Server - stop chan struct{} - ready chan bool - apihelper apihelper.APIHelpers - kubeconfig *restclient.Config + args Args + nodeName string + server *grpc.Server + stop chan struct{} + ready chan bool + apihelper apihelper.APIHelpers + kubeconfig *restclient.Config } // NewNfdMaster creates a new NfdMaster server instance. @@ -128,15 +104,12 @@ func NewNfdMaster(args *Args) (NfdMaster, error) { stop: make(chan struct{}, 1), } - if args.Instance == "" { - nfd.annotationNs = AnnotationNsBase - } else { + if args.Instance != "" { if ok, _ := regexp.MatchString(`^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$`, args.Instance); !ok { return nfd, fmt.Errorf("invalid -instance %q: instance name "+ "must start and end with an alphanumeric character and may only contain "+ "alphanumerics, `-`, `_` or `.`", args.Instance) } - nfd.annotationNs = args.Instance + "." + AnnotationNsBase } // Check TLS related args @@ -311,7 +284,7 @@ func (m *nfdMaster) prune() error { return err } for a := range node.Annotations { - if strings.HasPrefix(a, m.annotationNs) { + if strings.HasPrefix(a, m.instanceAnnotation(nfdv1alpha1.AnnotationNs)) { delete(node.Annotations, a) } } @@ -337,7 +310,7 @@ func (m *nfdMaster) updateMasterNode() error { // Advertise NFD version as an annotation p := createPatches(nil, node.Annotations, - Annotations{m.annotationName(masterVersionAnnotation): version.Get()}, + Annotations{m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation): version.Get()}, "/metadata/annotations") err = m.apihelper.PatchNode(cli, node.Name, p) if err != nil { @@ -356,13 +329,13 @@ func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelW for label, value := range labels { // Add possibly missing default ns - label := addNs(label, FeatureLabelNs) + label := addNs(label, nfdv1alpha1.FeatureLabelNs) ns, name := splitNs(label) // Check label namespace, filter out if ns is not whitelisted - if ns != FeatureLabelNs && ns != ProfileLabelNs && - !strings.HasSuffix(ns, FeatureLabelSubNsSuffix) && !strings.HasSuffix(ns, ProfileLabelSubNsSuffix) { + if ns != nfdv1alpha1.FeatureLabelNs && ns != nfdv1alpha1.ProfileLabelNs && + !strings.HasSuffix(ns, nfdv1alpha1.FeatureLabelSubNsSuffix) && !strings.HasSuffix(ns, nfdv1alpha1.ProfileLabelSubNsSuffix) { if _, ok := extraLabelNs[ns]; !ok { klog.Errorf("Namespace %q is not allowed. Ignoring label %q\n", ns, label) continue @@ -381,7 +354,7 @@ func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelW extendedResources := ExtendedResources{} for extendedResourceName := range extendedResourceNames { // Add possibly missing default ns - extendedResourceName = addNs(extendedResourceName, FeatureLabelNs) + extendedResourceName = addNs(extendedResourceName, nfdv1alpha1.FeatureLabelNs) if value, ok := outLabels[extendedResourceName]; ok { if _, err := strconv.Atoi(value); err != nil { klog.Errorf("bad label value (%s: %s) encountered for extended resource: %s", extendedResourceName, value, err.Error()) @@ -437,7 +410,7 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se if !m.args.NoPublish { // Advertise NFD worker version as an annotation - annotations := Annotations{m.annotationName(workerVersionAnnotation): r.NfdVersion} + annotations := Annotations{m.instanceAnnotation(nfdv1alpha1.WorkerVersionAnnotation): r.NfdVersion} err := m.updateNodeFeatures(r.NodeName, labels, annotations, extendedResources) if err != nil { @@ -561,22 +534,22 @@ func (m *nfdMaster) updateNodeFeatures(nodeName string, labels Labels, annotatio labelKeys := make([]string, 0, len(labels)) for key := range labels { // Drop the ns part for labels in the default ns - labelKeys = append(labelKeys, strings.TrimPrefix(key, FeatureLabelNs+"/")) + labelKeys = append(labelKeys, strings.TrimPrefix(key, nfdv1alpha1.FeatureLabelNs+"/")) } sort.Strings(labelKeys) - annotations[m.annotationName(featureLabelAnnotation)] = strings.Join(labelKeys, ",") + annotations[m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation)] = strings.Join(labelKeys, ",") // Store names of extended resources in an annotation extendedResourceKeys := make([]string, 0, len(extendedResources)) for key := range extendedResources { // Drop the ns part if in the default ns - extendedResourceKeys = append(extendedResourceKeys, strings.TrimPrefix(key, FeatureLabelNs+"/")) + extendedResourceKeys = append(extendedResourceKeys, strings.TrimPrefix(key, nfdv1alpha1.FeatureLabelNs+"/")) } sort.Strings(extendedResourceKeys) - annotations[m.annotationName(extendedResourceAnnotation)] = strings.Join(extendedResourceKeys, ",") + annotations[m.instanceAnnotation(nfdv1alpha1.ExtendedResourceAnnotation)] = strings.Join(extendedResourceKeys, ",") // Create JSON patches for changes in labels and annotations - oldLabels := stringToNsNames(node.Annotations[m.annotationName(featureLabelAnnotation)], FeatureLabelNs) + oldLabels := stringToNsNames(node.Annotations[m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation)], nfdv1alpha1.FeatureLabelNs) patches := createPatches(oldLabels, node.Labels, labels, "/metadata/labels") patches = append(patches, createPatches(nil, node.Annotations, annotations, "/metadata/annotations")...) @@ -602,10 +575,6 @@ func (m *nfdMaster) updateNodeFeatures(nodeName string, labels Labels, annotatio return err } -func (m *nfdMaster) annotationName(name string) string { - return path.Join(m.annotationNs, name) -} - func (m *nfdMaster) getKubeconfig() (*restclient.Config, error) { var err error if m.kubeconfig == nil { @@ -647,7 +616,7 @@ func (m *nfdMaster) createExtendedResourcePatches(n *api.Node, extendedResources patches := []apihelper.JsonPatch{} // Form a list of namespaced resource names managed by us - oldResources := stringToNsNames(n.Annotations[m.annotationName(extendedResourceAnnotation)], FeatureLabelNs) + oldResources := stringToNsNames(n.Annotations[m.instanceAnnotation(nfdv1alpha1.ExtendedResourceAnnotation)], nfdv1alpha1.FeatureLabelNs) // figure out which resources to remove for _, resource := range oldResources { @@ -762,3 +731,10 @@ func (m *nfdMaster) updateCR(hostname string, tmpolicy []string, topoUpdaterZone utils.KlogDump(2, "CR instance updated resTopo:", " ", nrtUpdated) return nil } + +func (m *nfdMaster) instanceAnnotation(name string) string { + if m.args.Instance == "" { + return name + } + return m.args.Instance + "." + name +} diff --git a/test/e2e/node_feature_discovery.go b/test/e2e/node_feature_discovery.go index 744ec3ba1..41cbc59eb 100644 --- a/test/e2e/node_feature_discovery.go +++ b/test/e2e/node_feature_discovery.go @@ -36,7 +36,7 @@ import ( e2enetwork "k8s.io/kubernetes/test/e2e/framework/network" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" - master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master" + nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" "sigs.k8s.io/node-feature-discovery/source/custom" testutils "sigs.k8s.io/node-feature-discovery/test/e2e/utils" ) @@ -62,7 +62,7 @@ func cleanupNode(cs clientset.Interface) { update := false // Remove labels for key := range node.Labels { - if strings.HasPrefix(key, master.FeatureLabelNs) { + if strings.HasPrefix(key, nfdv1alpha1.FeatureLabelNs) { delete(node.Labels, key) update = true } @@ -70,7 +70,7 @@ func cleanupNode(cs clientset.Interface) { // Remove annotations for key := range node.Annotations { - if strings.HasPrefix(key, master.AnnotationNsBase) { + if strings.HasPrefix(key, nfdv1alpha1.AnnotationNs) { delete(node.Annotations, key) update = true } @@ -126,7 +126,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() { // Node running nfd-master should have master version annotation masterPodNode, err := f.ClientSet.CoreV1().Nodes().Get(context.TODO(), masterPod.Spec.NodeName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - Expect(masterPodNode.Annotations).To(HaveKey(master.AnnotationNsBase + "/master.version")) + Expect(masterPodNode.Annotations).To(HaveKey(nfdv1alpha1.AnnotationNs + "/master.version")) By("Waiting for the nfd-master service to be up") Expect(e2enetwork.WaitForService(f.ClientSet, f.Namespace.Name, nfdSvc.ObjectMeta.Name, true, time.Second, 10*time.Second)).NotTo(HaveOccurred()) @@ -145,9 +145,9 @@ var _ = SIGDescribe("Node Feature Discovery", func() { It("it should decorate the node with the fake feature labels", func() { fakeFeatureLabels := map[string]string{ - master.FeatureLabelNs + "/fake-fakefeature1": "true", - master.FeatureLabelNs + "/fake-fakefeature2": "true", - master.FeatureLabelNs + "/fake-fakefeature3": "true", + nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature1": "true", + nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature2": "true", + nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature3": "true", } // Launch nfd-worker @@ -171,7 +171,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() { // Check that there are no unexpected NFD labels for k := range node.Labels { - if strings.HasPrefix(k, master.FeatureLabelNs) { + if strings.HasPrefix(k, nfdv1alpha1.FeatureLabelNs) { Expect(fakeFeatureLabels).Should(HaveKey(k)) } } @@ -226,7 +226,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() { Expect(node.Labels).To(HaveKey(k)) } for k := range node.Labels { - if strings.HasPrefix(k, master.FeatureLabelNs) { + if strings.HasPrefix(k, nfdv1alpha1.FeatureLabelNs) { if _, ok := nodeConf.ExpectedLabelValues[k]; ok { continue } @@ -247,7 +247,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() { Expect(node.Annotations).To(HaveKey(k)) } for k := range node.Annotations { - if strings.HasPrefix(k, master.AnnotationNsBase) { + if strings.HasPrefix(k, nfdv1alpha1.AnnotationNs) { if _, ok := nodeConf.ExpectedAnnotationValues[k]; ok { continue }