mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-14 20:56:42 +00:00
apis/nfd: move annotation and label consts from nfd-master
Move consts related to NFD annotations and labels from nfd-master to the api. Makes them more logically accessible for clients.
This commit is contained in:
parent
906aad6717
commit
c1e6b41e56
4 changed files with 137 additions and 119 deletions
46
pkg/apis/nfd/v1alpha1/annotations_labels.go
Normal file
46
pkg/apis/nfd/v1alpha1/annotations_labels.go
Normal file
|
@ -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"
|
||||
)
|
|
@ -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": {}}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue