2019-02-08 19:43:54 +00:00
/ *
2021-02-19 05:38:55 +00:00
Copyright 2019 - 2021 The Kubernetes Authors .
2019-02-08 19:43:54 +00:00
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 nfdmaster
import (
2024-01-22 17:08:04 +00:00
"errors"
2022-11-06 20:25:04 +00:00
"fmt"
2024-01-22 17:08:04 +00:00
"maps"
2023-03-05 21:56:46 +00:00
"os"
"path/filepath"
2019-05-07 09:41:20 +00:00
"sort"
2019-02-08 19:43:54 +00:00
"strings"
"testing"
2023-03-05 21:56:46 +00:00
"time"
2019-02-08 19:43:54 +00:00
. "github.com/smartystreets/goconvey/convey"
"golang.org/x/net/context"
2024-01-22 17:08:04 +00:00
2022-10-14 12:28:52 +00:00
corev1 "k8s.io/api/core/v1"
2020-03-05 14:40:55 +00:00
"k8s.io/apimachinery/pkg/api/resource"
2024-01-22 17:08:04 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
2023-05-13 19:03:53 +00:00
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2024-01-22 17:08:04 +00:00
fakeclient "k8s.io/client-go/kubernetes/fake"
fakecorev1client "k8s.io/client-go/kubernetes/typed/core/v1/fake"
clienttesting "k8s.io/client-go/testing"
2023-05-13 19:03:53 +00:00
"k8s.io/client-go/tools/cache"
2024-01-22 17:08:04 +00:00
2024-02-27 13:42:23 +00:00
fakenfdclient "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/fake"
nfdscheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
nfdinformers "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions"
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
2024-03-14 18:23:07 +00:00
"sigs.k8s.io/node-feature-discovery/pkg/features"
2019-02-08 19:43:54 +00:00
"sigs.k8s.io/node-feature-discovery/pkg/labeler"
2021-02-19 05:38:55 +00:00
"sigs.k8s.io/node-feature-discovery/pkg/utils"
2019-02-08 19:43:54 +00:00
)
const (
2024-01-22 17:08:04 +00:00
testNodeName = "mock-node"
2019-02-08 19:43:54 +00:00
)
2024-01-22 17:08:04 +00:00
func newTestNode ( ) * corev1 . Node {
2022-10-14 12:28:52 +00:00
n := corev1 . Node { }
2024-01-22 17:08:04 +00:00
n . Name = testNodeName
2019-02-12 13:31:59 +00:00
n . Labels = map [ string ] string { }
n . Annotations = map [ string ] string { }
2024-01-22 17:08:04 +00:00
n . Status . Capacity = corev1 . ResourceList { "cpu" : resource . MustParse ( "2" ) }
2019-02-12 13:31:59 +00:00
return & n
}
2024-01-22 17:08:04 +00:00
func newFakeNfdAPIController ( client * fakenfdclient . Clientset ) * nfdController {
2023-05-13 19:03:53 +00:00
c := & nfdController {
2024-04-05 06:18:00 +00:00
stopChan : make ( chan struct { } ) ,
2023-05-13 19:03:53 +00:00
updateAllNodesChan : make ( chan struct { } , 1 ) ,
updateOneNodeChan : make ( chan string ) ,
}
informerFactory := nfdinformers . NewSharedInformerFactory ( client , 1 * time . Hour )
// Add informer for NodeFeature objects
featureInformer := informerFactory . Nfd ( ) . V1alpha1 ( ) . NodeFeatures ( )
if _ , err := featureInformer . Informer ( ) . AddEventHandler ( cache . ResourceEventHandlerFuncs {
AddFunc : func ( obj interface { } ) { } ,
UpdateFunc : func ( oldObj , newObj interface { } ) { } ,
DeleteFunc : func ( obj interface { } ) { } ,
} ) ; err != nil {
return nil
}
c . featureLister = featureInformer . Lister ( )
// Add informer for NodeFeatureRule objects
ruleInformer := informerFactory . Nfd ( ) . V1alpha1 ( ) . NodeFeatureRules ( )
if _ , err := ruleInformer . Informer ( ) . AddEventHandler ( cache . ResourceEventHandlerFuncs {
AddFunc : func ( object interface { } ) { } ,
UpdateFunc : func ( oldObject , newObject interface { } ) { } ,
DeleteFunc : func ( object interface { } ) { } ,
} ) ; err != nil {
return nil
}
c . ruleLister = ruleInformer . Lister ( )
// Start informers
informerFactory . Start ( c . stopChan )
utilruntime . Must ( nfdv1alpha1 . AddToScheme ( nfdscheme . Scheme ) )
return c
}
2024-04-05 10:24:54 +00:00
func withNodeName ( nodeName string ) NfdMasterOption {
return & nfdMasterOpt { f : func ( n * nfdMaster ) { n . nodeName = nodeName } }
}
func withConfig ( config * NFDConfig ) NfdMasterOption {
return & nfdMasterOpt { f : func ( n * nfdMaster ) { n . config = config } }
}
func newFakeMaster ( opts ... NfdMasterOption ) * nfdMaster {
defaultOpts := [ ] NfdMasterOption {
withNodeName ( testNodeName ) ,
withConfig ( & NFDConfig { } ) ,
2024-04-04 14:48:47 +00:00
WithKubernetesClient ( fakeclient . NewSimpleClientset ( ) ) ,
2024-04-05 10:24:54 +00:00
}
m , err := NewNfdMaster ( append ( defaultOpts , opts ... ) ... )
if err != nil {
panic ( err )
2021-02-03 17:15:00 +00:00
}
2024-04-05 10:24:54 +00:00
return m . ( * nfdMaster )
2021-02-03 17:15:00 +00:00
}
2022-10-12 10:45:11 +00:00
func TestUpdateNodeObject ( t * testing . T ) {
2019-02-08 19:43:54 +00:00
Convey ( "When I update the node using fake client" , t , func ( ) {
2024-01-22 17:08:04 +00:00
featureLabels := map [ string ] string {
2022-08-16 18:39:11 +00:00
nfdv1alpha1 . FeatureLabelNs + "/source-feature.1" : "1" ,
nfdv1alpha1 . FeatureLabelNs + "/source-feature.2" : "2" ,
nfdv1alpha1 . FeatureLabelNs + "/source-feature.3" : "val3" ,
2024-01-22 17:08:04 +00:00
nfdv1alpha1 . ProfileLabelNs + "/profile-a" : "val4" ,
2019-02-08 19:43:54 +00:00
}
2024-01-22 17:08:04 +00:00
featureAnnotations := map [ string ] string {
"feature.node.kubernetesl.io/my-annotation" : "my-val" ,
}
featureExtResources := map [ string ] string {
nfdv1alpha1 . FeatureLabelNs + "/source-feature.1" : "1" ,
nfdv1alpha1 . FeatureLabelNs + "/source-feature.2" : "2" ,
2023-10-13 15:36:32 +00:00
}
2024-01-22 17:08:04 +00:00
featureLabelNames := make ( [ ] string , 0 , len ( featureLabels ) )
for k := range featureLabels {
featureLabelNames = append ( featureLabelNames , strings . TrimPrefix ( k , nfdv1alpha1 . FeatureLabelNs + "/" ) )
2020-08-13 14:14:27 +00:00
}
2024-01-22 17:08:04 +00:00
sort . Strings ( featureLabelNames )
2020-08-13 14:14:27 +00:00
2024-01-22 17:08:04 +00:00
featureAnnotationNames := make ( [ ] string , 0 , len ( featureLabels ) )
for k := range featureAnnotations {
featureAnnotationNames = append ( featureAnnotationNames , strings . TrimPrefix ( k , nfdv1alpha1 . FeatureAnnotationNs + "/" ) )
2023-04-06 18:20:24 +00:00
}
2024-01-22 17:08:04 +00:00
sort . Strings ( featureAnnotationNames )
2023-04-06 18:20:24 +00:00
2024-01-22 17:08:04 +00:00
featureExtResourceNames := make ( [ ] string , 0 , len ( featureExtResources ) )
for k := range featureExtResources {
featureExtResourceNames = append ( featureExtResourceNames , strings . TrimPrefix ( k , nfdv1alpha1 . FeatureLabelNs + "/" ) )
}
sort . Strings ( featureExtResourceNames )
2019-02-08 19:43:54 +00:00
2024-01-22 17:08:04 +00:00
// Create a node with some existing features
testNode := newTestNode ( )
testNode . Labels [ nfdv1alpha1 . FeatureLabelNs + "/old-feature" ] = "old-value"
testNode . Annotations [ nfdv1alpha1 . AnnotationNs + "/feature-labels" ] = "old-feature"
2020-08-18 15:05:06 +00:00
2024-01-22 17:08:04 +00:00
// Create fake api client and initialize NfdMaster instance
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2019-02-08 19:43:54 +00:00
2024-01-22 17:08:04 +00:00
Convey ( "When I successfully update the node with feature labels" , func ( ) {
2024-04-03 18:12:04 +00:00
err := fakeMaster . updateNodeObject ( fakeCli , testNode , featureLabels , featureAnnotations , featureExtResources , nil )
2019-02-08 19:43:54 +00:00
Convey ( "Error is nil" , func ( ) {
So ( err , ShouldBeNil )
} )
2024-01-22 17:08:04 +00:00
Convey ( "Node object is updated" , func ( ) {
expectedAnnotations := map [ string ] string {
nfdv1alpha1 . FeatureLabelsAnnotation : strings . Join ( featureLabelNames , "," ) ,
nfdv1alpha1 . FeatureAnnotationsTrackingAnnotation : strings . Join ( featureAnnotationNames , "," ) ,
nfdv1alpha1 . ExtendedResourceAnnotation : strings . Join ( featureExtResourceNames , "," ) ,
}
maps . Copy ( expectedAnnotations , featureAnnotations )
2019-02-08 19:43:54 +00:00
2024-01-22 17:08:04 +00:00
expectedCapacity := testNode . Status . Capacity . DeepCopy ( )
for k , v := range featureExtResources {
2024-04-22 20:27:15 +00:00
expectedCapacity [ corev1 . ResourceName ( k ) ] = resource . MustParse ( v )
2024-01-22 17:08:04 +00:00
}
2019-02-08 19:43:54 +00:00
2024-01-22 17:08:04 +00:00
// Get the node
updatedNode , err := fakeCli . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , testNodeName , metav1 . GetOptions { } )
2019-02-08 19:43:54 +00:00
2024-01-22 17:08:04 +00:00
So ( err , ShouldBeNil )
So ( updatedNode . Labels , ShouldEqual , featureLabels )
So ( updatedNode . Annotations , ShouldEqual , expectedAnnotations )
So ( updatedNode . Status . Capacity , ShouldEqual , expectedCapacity )
2019-02-08 19:43:54 +00:00
} )
} )
2024-01-22 17:08:04 +00:00
Convey ( "When I fail to patch a node" , func ( ) {
fakeCli . CoreV1 ( ) . ( * fakecorev1client . FakeCoreV1 ) . PrependReactor ( "patch" , "nodes" , func ( action clienttesting . Action ) ( handled bool , ret runtime . Object , err error ) {
2024-04-22 20:27:15 +00:00
return true , & corev1 . Node { } , errors . New ( "Fake error when patching node" )
2024-01-22 17:08:04 +00:00
} )
2024-04-03 18:12:04 +00:00
err := fakeMaster . updateNodeObject ( fakeCli , testNode , nil , featureAnnotations , ExtendedResources { "" : "" } , nil )
2019-02-08 19:43:54 +00:00
Convey ( "Error is produced" , func ( ) {
2024-01-22 17:08:04 +00:00
So ( err , ShouldBeError )
2019-02-08 19:43:54 +00:00
} )
} )
} )
}
func TestUpdateMasterNode ( t * testing . T ) {
Convey ( "When updating the nfd-master node" , t , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
testNode . Annotations [ "nfd.node.kubernetes.io/master.version" ] = "foo"
2019-02-08 19:43:54 +00:00
Convey ( "When update operation succeeds" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
err := fakeMaster . updateMasterNode ( )
2019-02-08 19:43:54 +00:00
Convey ( "No error should be returned" , func ( ) {
So ( err , ShouldBeNil )
} )
2024-01-22 17:08:04 +00:00
Convey ( "Master version annotation was removed" , func ( ) {
updatedNode , err := fakeCli . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , testNodeName , metav1 . GetOptions { } )
So ( err , ShouldBeNil )
So ( updatedNode . Annotations , ShouldBeEmpty )
2019-02-08 19:43:54 +00:00
} )
} )
Convey ( "When getting API node object fails" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
fakeMaster . nodeName = "does-not-exist"
err := fakeMaster . updateMasterNode ( )
2019-02-08 19:43:54 +00:00
Convey ( "An error should be returned" , func ( ) {
2024-01-22 17:08:04 +00:00
So ( err , ShouldBeError )
2019-02-08 19:43:54 +00:00
} )
} )
Convey ( "When updating node object fails" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeErr := errors . New ( "Fake error when patching node" )
fakeCli := fakeclient . NewSimpleClientset ( testNode )
fakeCli . CoreV1 ( ) . ( * fakecorev1client . FakeCoreV1 ) . PrependReactor ( "patch" , "nodes" , func ( action clienttesting . Action ) ( handled bool , ret runtime . Object , err error ) {
2024-04-22 20:27:15 +00:00
return true , & corev1 . Node { } , fakeErr
2024-01-22 17:08:04 +00:00
} )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
err := fakeMaster . updateMasterNode ( )
2019-02-08 19:43:54 +00:00
Convey ( "An error should be returned" , func ( ) {
2024-01-22 17:08:04 +00:00
So ( err , ShouldWrap , fakeErr )
2019-02-08 19:43:54 +00:00
} )
} )
} )
}
2020-03-05 14:40:55 +00:00
func TestAddingExtResources ( t * testing . T ) {
Convey ( "When adding extended resources" , t , func ( ) {
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( )
2020-03-05 14:40:55 +00:00
Convey ( "When there are no matching labels" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
resourceLabels := ExtendedResources { }
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-13 14:14:27 +00:00
So ( len ( patches ) , ShouldEqual , 0 )
2020-03-05 14:40:55 +00:00
} )
Convey ( "When there are matching labels" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
resourceLabels := ExtendedResources { "feature-1" : "1" , "feature-2" : "2" }
2024-01-22 13:32:02 +00:00
expectedPatches := [ ] utils . JsonPatch {
utils . NewJsonPatch ( "add" , "/status/capacity" , "feature-1" , "1" ) ,
utils . NewJsonPatch ( "add" , "/status/capacity" , "feature-2" , "2" ) ,
2020-08-18 15:05:06 +00:00
}
2024-01-22 17:08:04 +00:00
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-18 15:05:06 +00:00
So ( sortJsonPatches ( patches ) , ShouldResemble , sortJsonPatches ( expectedPatches ) )
2020-03-05 14:40:55 +00:00
} )
Convey ( "When the resource already exists" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-1" ) ] = * resource . NewQuantity ( 1 , resource . BinarySI )
resourceLabels := ExtendedResources { nfdv1alpha1 . FeatureLabelNs + "/feature-1" : "1" }
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-13 14:14:27 +00:00
So ( len ( patches ) , ShouldEqual , 0 )
2020-03-05 14:40:55 +00:00
} )
Convey ( "When the resource already exists but its capacity has changed" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
testNode . Status . Capacity [ corev1 . ResourceName ( "feature-1" ) ] = * resource . NewQuantity ( 2 , resource . BinarySI )
resourceLabels := ExtendedResources { "feature-1" : "1" }
2024-01-22 13:32:02 +00:00
expectedPatches := [ ] utils . JsonPatch {
utils . NewJsonPatch ( "replace" , "/status/capacity" , "feature-1" , "1" ) ,
utils . NewJsonPatch ( "replace" , "/status/allocatable" , "feature-1" , "1" ) ,
2020-08-18 15:05:06 +00:00
}
2024-01-22 17:08:04 +00:00
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-18 15:05:06 +00:00
So ( sortJsonPatches ( patches ) , ShouldResemble , sortJsonPatches ( expectedPatches ) )
2020-03-05 14:40:55 +00:00
} )
} )
}
func TestRemovingExtResources ( t * testing . T ) {
Convey ( "When removing extended resources" , t , func ( ) {
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( )
2020-03-05 14:40:55 +00:00
Convey ( "When none are removed" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
resourceLabels := ExtendedResources { nfdv1alpha1 . FeatureLabelNs + "/feature-1" : "1" , nfdv1alpha1 . FeatureLabelNs + "/feature-2" : "2" }
testNode . Annotations [ nfdv1alpha1 . AnnotationNs + "/extended-resources" ] = "feature-1,feature-2"
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-1" ) ] = * resource . NewQuantity ( 1 , resource . BinarySI )
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-2" ) ] = * resource . NewQuantity ( 2 , resource . BinarySI )
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-13 14:14:27 +00:00
So ( len ( patches ) , ShouldEqual , 0 )
2020-03-05 14:40:55 +00:00
} )
Convey ( "When the related label is gone" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
resourceLabels := ExtendedResources { nfdv1alpha1 . FeatureLabelNs + "/feature-4" : "" , nfdv1alpha1 . FeatureLabelNs + "/feature-2" : "2" }
testNode . Annotations [ nfdv1alpha1 . AnnotationNs + "/extended-resources" ] = "feature-4,feature-2"
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-4" ) ] = * resource . NewQuantity ( 4 , resource . BinarySI )
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-2" ) ] = * resource . NewQuantity ( 2 , resource . BinarySI )
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-13 14:14:27 +00:00
So ( len ( patches ) , ShouldBeGreaterThan , 0 )
2020-03-05 14:40:55 +00:00
} )
Convey ( "When the extended resource is no longer wanted" , func ( ) {
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-1" ) ] = * resource . NewQuantity ( 1 , resource . BinarySI )
testNode . Status . Capacity [ corev1 . ResourceName ( nfdv1alpha1 . FeatureLabelNs + "/feature-2" ) ] = * resource . NewQuantity ( 2 , resource . BinarySI )
resourceLabels := ExtendedResources { nfdv1alpha1 . FeatureLabelNs + "/feature-2" : "2" }
testNode . Annotations [ nfdv1alpha1 . AnnotationNs + "/extended-resources" ] = "feature-1,feature-2"
patches := fakeMaster . createExtendedResourcePatches ( testNode , resourceLabels )
2020-08-13 14:14:27 +00:00
So ( len ( patches ) , ShouldBeGreaterThan , 0 )
2020-03-05 14:40:55 +00:00
} )
} )
}
2019-02-08 19:43:54 +00:00
func TestSetLabels ( t * testing . T ) {
Convey ( "When servicing SetLabels request" , t , func ( ) {
2024-05-15 09:03:06 +00:00
// Add feature gates as running nfd-master depends on that
err := features . NFDMutableFeatureGate . Add ( features . DefaultNFDFeatureGates )
So ( err , ShouldBeNil )
2024-01-22 17:08:04 +00:00
testNode := newTestNode ( )
// We need to populate the node with some annotations or the patching in the fake client fails
testNode . Labels [ "feature.node.kubernetes.io/foo" ] = "bar"
testNode . Annotations [ nfdv1alpha1 . FeatureLabelsAnnotation ] = "foo"
2019-05-07 09:41:20 +00:00
2024-01-22 17:08:04 +00:00
ctx := context . Background ( )
// In the gRPC request the label names may omit the default ns
featureLabels := map [ string ] string {
"feature.node.kubernetes.io/feature-1" : "1" ,
"example.io/feature-2" : "val-2" ,
"feature.node.kubernetes.io/feature-3" : "3" ,
2019-05-07 09:41:20 +00:00
}
2024-01-22 17:08:04 +00:00
req := & labeler . SetLabelsRequest { NodeName : testNodeName , NfdVersion : "0.1-test" , Labels : featureLabels }
2020-08-18 15:05:06 +00:00
2019-02-08 19:43:54 +00:00
Convey ( "When node update succeeds" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2020-08-13 14:14:27 +00:00
2024-01-22 17:08:04 +00:00
_ , err := fakeMaster . SetLabels ( ctx , req )
2019-02-08 19:43:54 +00:00
Convey ( "No error should be returned" , func ( ) {
So ( err , ShouldBeNil )
} )
2024-01-22 17:08:04 +00:00
Convey ( "Node object should be updated" , func ( ) {
updatedNode , err := fakeCli . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , testNodeName , metav1 . GetOptions { } )
2019-05-07 09:41:20 +00:00
So ( err , ShouldBeNil )
2024-01-22 17:08:04 +00:00
So ( updatedNode . Labels , ShouldEqual , featureLabels )
2019-05-07 09:41:20 +00:00
} )
2019-02-08 19:43:54 +00:00
} )
2024-01-22 17:08:04 +00:00
Convey ( "When -resource-labels is specified" , func ( ) {
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster (
WithKubernetesClient ( fakeCli ) ,
withConfig ( & NFDConfig {
ResourceLabels : map [ string ] struct { } {
"feature.node.kubernetes.io/feature-3" : { } ,
"feature-1" : { } } ,
} ) )
2020-08-13 14:14:27 +00:00
2024-01-22 17:08:04 +00:00
_ , err := fakeMaster . SetLabels ( ctx , req )
2019-04-05 22:31:40 +00:00
Convey ( "Error is nil" , func ( ) {
So ( err , ShouldBeNil )
} )
2020-08-18 15:05:06 +00:00
2024-01-22 17:08:04 +00:00
Convey ( "Node object should be updated" , func ( ) {
updatedNode , err := fakeCli . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , testNodeName , metav1 . GetOptions { } )
2020-08-18 15:05:06 +00:00
So ( err , ShouldBeNil )
2024-01-22 17:08:04 +00:00
So ( updatedNode . Labels , ShouldEqual , map [ string ] string { "example.io/feature-2" : "val-2" } )
2020-08-18 15:05:06 +00:00
} )
2019-04-05 22:31:40 +00:00
} )
2019-02-08 19:43:54 +00:00
Convey ( "When node update fails" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
fakeErr := errors . New ( "Fake error when patching node" )
fakeCli . CoreV1 ( ) . ( * fakecorev1client . FakeCoreV1 ) . PrependReactor ( "patch" , "nodes" , func ( action clienttesting . Action ) ( handled bool , ret runtime . Object , err error ) {
2024-04-22 20:27:15 +00:00
return true , & corev1 . Node { } , fakeErr
2024-01-22 17:08:04 +00:00
} )
_ , err := fakeMaster . SetLabels ( ctx , req )
2019-02-08 19:43:54 +00:00
Convey ( "An error should be returned" , func ( ) {
2024-01-22 17:08:04 +00:00
So ( err , ShouldWrap , fakeErr )
2019-02-08 19:43:54 +00:00
} )
} )
2021-11-25 10:14:19 +00:00
Convey ( "With '-no-publish'" , func ( ) {
2024-01-22 17:08:04 +00:00
fakeCli := fakeclient . NewSimpleClientset ( testNode )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
fakeMaster . config . NoPublish = true
_ , err := fakeMaster . SetLabels ( ctx , req )
2019-02-08 19:43:54 +00:00
Convey ( "Operation should succeed" , func ( ) {
So ( err , ShouldBeNil )
} )
} )
} )
}
2019-02-12 13:31:59 +00:00
2023-05-24 10:56:36 +00:00
func TestFilterLabels ( t * testing . T ) {
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( )
2024-01-22 17:08:04 +00:00
fakeMaster . config . ExtraLabelNs = map [ string ] struct { } { "example.io" : { } }
fakeMaster . deniedNs = deniedNs {
2024-04-22 20:27:15 +00:00
normal : map [ string ] struct { } { "" : { } , "kubernetes.io" : { } , "denied.ns" : { } } ,
wildcard : map [ string ] struct { } { ".kubernetes.io" : { } , ".denied.subns" : { } } ,
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
}
type TC struct {
description string
labelName string
labelValue string
features nfdv1alpha1 . Features
expectErr bool
expectedValue string
}
2023-05-24 10:56:36 +00:00
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
tcs := [ ] TC {
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "Static value" ,
labelName : "example.io/test" ,
labelValue : "test-val" ,
expectedValue : "test-val" ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "Dynamic value" ,
labelName : "example.io/testLabel" ,
labelValue : "@test.feature.LSM" ,
features : nfdv1alpha1 . Features {
Attributes : map [ string ] nfdv1alpha1 . AttributeFeatureSet {
2024-04-22 20:27:15 +00:00
"test.feature" : {
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
Elements : map [ string ] string {
"LSM" : "123" ,
} ,
2023-05-24 10:56:36 +00:00
} ,
} ,
} ,
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
expectedValue : "123" ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "Unprefixed should be denied" ,
labelName : "test-label" ,
labelValue : "test-value" ,
expectErr : true ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "kubernetes.io ns should be denied" ,
labelName : "kubernetes.io/test-label" ,
labelValue : "test-value" ,
expectErr : true ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "*.kubernetes.io ns should be denied" ,
labelName : "sub.ns.kubernetes.io/test-label" ,
labelValue : "test-value" ,
expectErr : true ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "denied.ns ns should be denied" ,
labelName : "denied.ns/test-label" ,
labelValue : "test-value" ,
expectErr : true ,
} ,
2024-04-22 20:27:15 +00:00
{
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
description : "*.denied.subns ns should be denied" ,
labelName : "my.denied.subns/test-label" ,
labelValue : "test-value" ,
expectErr : true ,
} ,
}
2023-05-24 10:56:36 +00:00
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
for _ , tc := range tcs {
t . Run ( tc . description , func ( t * testing . T ) {
2024-01-22 17:08:04 +00:00
labelValue , err := fakeMaster . filterFeatureLabel ( tc . labelName , tc . labelValue , & tc . features )
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
if tc . expectErr {
Convey ( "Label should be filtered out" , t , func ( ) {
So ( err , ShouldBeError )
} )
} else {
Convey ( "Label should not be filtered out" , t , func ( ) {
So ( err , ShouldBeNil )
} )
Convey ( "Label value should be correct" , t , func ( ) {
So ( labelValue , ShouldEqual , tc . expectedValue )
} )
}
2023-05-24 10:56:36 +00:00
} )
Option to stop implicitly adding default prefix to names
Add new autoDefaultNs (default is "true") config option to nfd-master.
Setting the config option to false stops NFD from automatically adding
the "feature.node.kubernetes.io/" prefix to labels, annotations and
extended resources. Taints are not affected as for them no prefix is
automatically added. The user-visible part of enabling the option change
is that NodeFeatureRules, local feature files, hooks and configuration
of the "custom" may need to be altereda (if the auto-prefixing is
relied on).
For now, the config option defaults to "true", meaning no change in
default behavior. However, the intent is to change the default to
"false" in a future release, deprecating the option and eventually
removing it (forcing it to "false").
The goal of stopping doing "auto-prefixing" is to simplify the operation
(of nfd and users). Make the naming more straightforward and easier to
understand and debug (kind of WYSIWYG), eliminating peculiar corner
cases:
1. Make validation simpler and unambiguous
2. Remove "overloading" of names, i.e. the mapping two values to the
same actual name. E.g. previously something like
labels:
feature.node.kubernetes.io/foo: bar
foo: baz
Could actually result in node label:
feature.node.kubernetes.io/foo: baz
3. Make the processing/usagee of the "rule.matched" and "local.labels"
feature in NodeFeatureRules unambiguous and more understadable. E.g.
previously you could have node label
"feature.node.kubernetes.io/local-foo: bar" but in the NodeFeatureRule
you'd need to use the unprefixed name "local-foo" or the fully
prefixed name, depending on what was specified in the feature file (or
hook) on the node(s).
NOTE: setting autoDefaultNs to false is a breaking change for users who
rely on automatic prefixing with the default feature.node.kubernetes.io/
namespace. NodeFeatureRules, feature files, hooks and custom rules
(configuration of the "custom" source of nfd-worker) will need to be
altered. Unprefixed labels, annoations and extended resources will be
denied by nfd-master.
2023-11-08 07:51:19 +00:00
}
2023-05-24 10:56:36 +00:00
}
2020-08-13 14:14:27 +00:00
func TestCreatePatches ( t * testing . T ) {
Convey ( "When creating JSON patches" , t , func ( ) {
existingItems := map [ string ] string { "key-1" : "val-1" , "key-2" : "val-2" , "key-3" : "val-3" }
jsonPath := "/root"
2019-02-12 13:31:59 +00:00
2020-08-13 14:14:27 +00:00
Convey ( "When when there are neither itmes to remoe nor to add or update" , func ( ) {
p := createPatches ( [ ] string { "foo" , "bar" } , existingItems , map [ string ] string { } , jsonPath )
So ( len ( p ) , ShouldEqual , 0 )
} )
2019-02-12 13:31:59 +00:00
2020-08-13 14:14:27 +00:00
Convey ( "When when there are itmes to remoe but none to add or update" , func ( ) {
p := createPatches ( [ ] string { "key-2" , "key-3" , "foo" } , existingItems , map [ string ] string { } , jsonPath )
2024-01-22 13:32:02 +00:00
expected := [ ] utils . JsonPatch {
utils . NewJsonPatch ( "remove" , jsonPath , "key-2" , "" ) ,
utils . NewJsonPatch ( "remove" , jsonPath , "key-3" , "" ) ,
2020-08-13 14:14:27 +00:00
}
So ( sortJsonPatches ( p ) , ShouldResemble , sortJsonPatches ( expected ) )
2019-02-12 13:31:59 +00:00
} )
2020-08-13 14:14:27 +00:00
Convey ( "When when there are no itmes to remove but new items to add" , func ( ) {
newItems := map [ string ] string { "new-key" : "new-val" , "key-1" : "new-1" }
p := createPatches ( [ ] string { "key-1" } , existingItems , newItems , jsonPath )
2024-01-22 13:32:02 +00:00
expected := [ ] utils . JsonPatch {
utils . NewJsonPatch ( "add" , jsonPath , "new-key" , newItems [ "new-key" ] ) ,
utils . NewJsonPatch ( "replace" , jsonPath , "key-1" , newItems [ "key-1" ] ) ,
2020-08-13 14:14:27 +00:00
}
So ( sortJsonPatches ( p ) , ShouldResemble , sortJsonPatches ( expected ) )
} )
Convey ( "When when there are items to remove add and update" , func ( ) {
newItems := map [ string ] string { "new-key" : "new-val" , "key-2" : "new-2" , "key-4" : "val-4" }
p := createPatches ( [ ] string { "key-1" , "key-2" , "key-3" , "foo" } , existingItems , newItems , jsonPath )
2024-01-22 13:32:02 +00:00
expected := [ ] utils . JsonPatch {
utils . NewJsonPatch ( "add" , jsonPath , "new-key" , newItems [ "new-key" ] ) ,
utils . NewJsonPatch ( "add" , jsonPath , "key-4" , newItems [ "key-4" ] ) ,
utils . NewJsonPatch ( "replace" , jsonPath , "key-2" , newItems [ "key-2" ] ) ,
utils . NewJsonPatch ( "remove" , jsonPath , "key-1" , "" ) ,
utils . NewJsonPatch ( "remove" , jsonPath , "key-3" , "" ) ,
2020-08-13 14:14:27 +00:00
}
So ( sortJsonPatches ( p ) , ShouldResemble , sortJsonPatches ( expected ) )
2019-02-12 13:31:59 +00:00
} )
} )
}
func TestRemoveLabelsWithPrefix ( t * testing . T ) {
Convey ( "When removing labels" , t , func ( ) {
2022-10-14 12:28:52 +00:00
n := & corev1 . Node {
2024-01-22 17:08:04 +00:00
ObjectMeta : metav1 . ObjectMeta {
2019-02-12 13:31:59 +00:00
Labels : map [ string ] string {
"single-label" : "123" ,
"multiple_A" : "a" ,
"multiple_B" : "b" ,
} ,
} ,
}
Convey ( "a unique label should be removed" , func ( ) {
2020-08-13 14:14:27 +00:00
p := removeLabelsWithPrefix ( n , "single" )
2024-01-22 13:32:02 +00:00
So ( p , ShouldResemble , [ ] utils . JsonPatch { utils . NewJsonPatch ( "remove" , "/metadata/labels" , "single-label" , "" ) } )
2019-02-12 13:31:59 +00:00
} )
Convey ( "a non-unique search string should remove all matching keys" , func ( ) {
2020-08-13 14:14:27 +00:00
p := removeLabelsWithPrefix ( n , "multiple" )
2024-01-22 13:32:02 +00:00
So ( sortJsonPatches ( p ) , ShouldResemble , sortJsonPatches ( [ ] utils . JsonPatch {
utils . NewJsonPatch ( "remove" , "/metadata/labels" , "multiple_A" , "" ) ,
utils . NewJsonPatch ( "remove" , "/metadata/labels" , "multiple_B" , "" ) ,
2020-08-13 14:14:27 +00:00
} ) )
2019-02-12 13:31:59 +00:00
} )
Convey ( "a search string with no matches should not alter labels" , func ( ) {
removeLabelsWithPrefix ( n , "unique" )
So ( n . Labels , ShouldContainKey , "single-label" )
So ( n . Labels , ShouldContainKey , "multiple_A" )
So ( n . Labels , ShouldContainKey , "multiple_B" )
So ( len ( n . Labels ) , ShouldEqual , 3 )
} )
} )
}
2020-08-13 14:14:27 +00:00
2023-03-05 21:56:46 +00:00
func TestConfigParse ( t * testing . T ) {
Convey ( "When parsing configuration" , t , func ( ) {
2024-04-05 10:24:54 +00:00
master := newFakeMaster ( )
2023-03-05 21:56:46 +00:00
overrides := ` { "noPublish": true, "enableTaints": true, "extraLabelNs": ["added.ns.io","added.kubernetes.io"], "denyLabelNs": ["denied.ns.io","denied.kubernetes.io"], "resourceLabels": ["vendor-1.com/feature-1","vendor-2.io/feature-2"], "labelWhiteList": "foo"} `
Convey ( "and no core cmdline flags have been specified" , func ( ) {
So ( master . configure ( "non-existing-file" , overrides ) , ShouldBeNil )
Convey ( "overrides should be in effect" , func ( ) {
So ( master . config . NoPublish , ShouldResemble , true )
So ( master . config . EnableTaints , ShouldResemble , true )
So ( master . config . ExtraLabelNs , ShouldResemble , utils . StringSetVal { "added.ns.io" : struct { } { } , "added.kubernetes.io" : struct { } { } } )
So ( master . config . DenyLabelNs , ShouldResemble , utils . StringSetVal { "denied.ns.io" : struct { } { } , "denied.kubernetes.io" : struct { } { } } )
So ( master . config . ResourceLabels , ShouldResemble , utils . StringSetVal { "vendor-1.com/feature-1" : struct { } { } , "vendor-2.io/feature-2" : struct { } { } } )
So ( master . config . LabelWhiteList . String ( ) , ShouldEqual , "foo" )
} )
} )
Convey ( "and a non-accessible file, but cmdline flags and some overrides are specified" , func ( ) {
master . args = Args { Overrides : ConfigOverrideArgs {
ExtraLabelNs : & utils . StringSetVal { "override.added.ns.io" : struct { } { } } ,
DenyLabelNs : & utils . StringSetVal { "override.denied.ns.io" : struct { } { } } } }
So ( master . configure ( "non-existing-file" , overrides ) , ShouldBeNil )
Convey ( "cmdline flags should be in effect instead overrides" , func ( ) {
So ( master . config . ExtraLabelNs , ShouldResemble , utils . StringSetVal { "override.added.ns.io" : struct { } { } } )
So ( master . config . DenyLabelNs , ShouldResemble , utils . StringSetVal { "override.denied.ns.io" : struct { } { } } )
} )
Convey ( "overrides should take effect" , func ( ) {
So ( master . config . NoPublish , ShouldBeTrue )
So ( master . config . EnableTaints , ShouldBeTrue )
} )
} )
// Create a temporary config file
f , err := os . CreateTemp ( "" , "nfd-test-" )
defer os . Remove ( f . Name ( ) )
So ( err , ShouldBeNil )
_ , err = f . WriteString ( `
noPublish : true
denyLabelNs : [ "denied.ns.io" , "denied.kubernetes.io" ]
resourceLabels : [ "vendor-1.com/feature-1" , "vendor-2.io/feature-2" ]
enableTaints : false
labelWhiteList : "foo"
2023-05-05 10:01:32 +00:00
leaderElection :
leaseDuration : 20 s
renewDeadline : 4 s
retryPeriod : 30 s
2023-03-05 21:56:46 +00:00
` )
f . Close ( )
So ( err , ShouldBeNil )
Convey ( "and a proper config file is specified" , func ( ) {
master . args = Args { Overrides : ConfigOverrideArgs { ExtraLabelNs : & utils . StringSetVal { "override.added.ns.io" : struct { } { } } } }
So ( master . configure ( f . Name ( ) , "" ) , ShouldBeNil )
Convey ( "specified configuration should take effect" , func ( ) {
// Verify core config
So ( master . config . NoPublish , ShouldBeTrue )
So ( master . config . EnableTaints , ShouldBeFalse )
So ( master . config . ExtraLabelNs , ShouldResemble , utils . StringSetVal { "override.added.ns.io" : struct { } { } } )
So ( master . config . ResourceLabels , ShouldResemble , utils . StringSetVal { "vendor-1.com/feature-1" : struct { } { } , "vendor-2.io/feature-2" : struct { } { } } ) // from cmdline
So ( master . config . DenyLabelNs , ShouldResemble , utils . StringSetVal { "denied.ns.io" : struct { } { } , "denied.kubernetes.io" : struct { } { } } )
So ( master . config . LabelWhiteList . String ( ) , ShouldEqual , "foo" )
2023-05-05 10:01:32 +00:00
So ( master . config . LeaderElection . LeaseDuration . Seconds ( ) , ShouldEqual , float64 ( 20 ) )
So ( master . config . LeaderElection . RenewDeadline . Seconds ( ) , ShouldEqual , float64 ( 4 ) )
So ( master . config . LeaderElection . RetryPeriod . Seconds ( ) , ShouldEqual , float64 ( 30 ) )
2023-03-05 21:56:46 +00:00
} )
} )
Convey ( "and a proper config file and overrides are given" , func ( ) {
master . args = Args { Overrides : ConfigOverrideArgs { DenyLabelNs : & utils . StringSetVal { "denied.ns.io" : struct { } { } } } }
overrides := ` { "extraLabelNs": ["added.ns.io"], "noPublish": true} `
So ( master . configure ( f . Name ( ) , overrides ) , ShouldBeNil )
Convey ( "overrides should take precedence over the config file" , func ( ) {
// Verify core config
So ( master . config . ExtraLabelNs , ShouldResemble , utils . StringSetVal { "added.ns.io" : struct { } { } } ) // from overrides
So ( master . config . DenyLabelNs , ShouldResemble , utils . StringSetVal { "denied.ns.io" : struct { } { } } ) // from cmdline
} )
} )
} )
}
func TestDynamicConfig ( t * testing . T ) {
Convey ( "When running nfd-master" , t , func ( ) {
2024-04-04 14:48:47 +00:00
// Add feature gates as running nfd-master depends on that
err := features . NFDMutableFeatureGate . Add ( features . DefaultNFDFeatureGates )
So ( err , ShouldBeNil )
2023-03-05 21:56:46 +00:00
tmpDir , err := os . MkdirTemp ( "" , "*.nfd-test" )
So ( err , ShouldBeNil )
defer os . RemoveAll ( tmpDir )
// Create (temporary) dir for config
configDir := filepath . Join ( tmpDir , "subdir-1" , "subdir-2" , "master.conf" )
err = os . MkdirAll ( configDir , 0755 )
So ( err , ShouldBeNil )
// Create config file
2024-04-04 14:48:47 +00:00
configFile := filepath . Clean ( filepath . Join ( configDir , "master.conf" ) )
2023-03-05 21:56:46 +00:00
writeConfig := func ( data string ) {
f , err := os . Create ( configFile )
So ( err , ShouldBeNil )
_ , err = f . WriteString ( data )
So ( err , ShouldBeNil )
err = f . Close ( )
So ( err , ShouldBeNil )
}
writeConfig ( `
2024-04-04 14:48:47 +00:00
klog :
v : "4"
2023-03-05 21:56:46 +00:00
extraLabelNs : [ "added.ns.io" ]
` )
2024-04-04 14:48:47 +00:00
master := newFakeMaster (
WithArgs ( & Args { ConfigFile : configFile } ) ,
WithKubernetesClient ( fakeclient . NewSimpleClientset ( newTestNode ( ) ) ) )
2023-03-05 21:56:46 +00:00
Convey ( "config file updates should take effect" , func ( ) {
2024-04-04 14:48:47 +00:00
go func ( ) {
Convey ( "nfd-master should exit gracefully" , t , func ( ) {
err = master . Run ( )
So ( err , ShouldBeNil )
} )
} ( )
2024-04-05 10:24:54 +00:00
defer master . Stop ( )
2023-03-05 21:56:46 +00:00
// Check initial config
time . Sleep ( 10 * time . Second )
So ( func ( ) interface { } { return master . config . ExtraLabelNs } ,
withTimeout , 2 * time . Second , ShouldResemble , utils . StringSetVal { "added.ns.io" : struct { } { } } )
// Update config and verify the effect
writeConfig ( `
extraLabelNs : [ "override.ns.io" ]
2023-04-15 15:11:59 +00:00
resyncPeriod : ' 2 h '
2023-05-13 19:03:53 +00:00
nfdApiParallelism : 300
2023-03-05 21:56:46 +00:00
` )
So ( func ( ) interface { } { return master . config . ExtraLabelNs } ,
withTimeout , 2 * time . Second , ShouldResemble , utils . StringSetVal { "override.ns.io" : struct { } { } } )
2023-04-15 15:11:59 +00:00
So ( func ( ) interface { } { return master . config . ResyncPeriod . Duration } ,
withTimeout , 2 * time . Second , ShouldResemble , time . Duration ( 2 ) * time . Hour )
2023-05-13 19:03:53 +00:00
So ( func ( ) interface { } { return master . config . NfdApiParallelism } ,
withTimeout , 2 * time . Second , ShouldResemble , 300 )
2023-03-05 21:56:46 +00:00
// Removing config file should get back our defaults
err = os . RemoveAll ( tmpDir )
So ( err , ShouldBeNil )
So ( func ( ) interface { } { return master . config . ExtraLabelNs } ,
withTimeout , 2 * time . Second , ShouldResemble , utils . StringSetVal { } )
2023-04-15 15:11:59 +00:00
So ( func ( ) interface { } { return master . config . ResyncPeriod . Duration } ,
withTimeout , 2 * time . Second , ShouldResemble , time . Duration ( 1 ) * time . Hour )
2023-05-13 19:03:53 +00:00
So ( func ( ) interface { } { return master . config . NfdApiParallelism } ,
withTimeout , 2 * time . Second , ShouldResemble , 10 )
2023-03-05 21:56:46 +00:00
// Re-creating config dir and file should change the config
err = os . MkdirAll ( configDir , 0755 )
So ( err , ShouldBeNil )
writeConfig ( `
extraLabelNs : [ "another.override.ns" ]
2023-04-15 15:11:59 +00:00
resyncPeriod : ' 3 m '
2023-05-13 19:03:53 +00:00
nfdApiParallelism : 100
2023-03-05 21:56:46 +00:00
` )
So ( func ( ) interface { } { return master . config . ExtraLabelNs } ,
withTimeout , 2 * time . Second , ShouldResemble , utils . StringSetVal { "another.override.ns" : struct { } { } } )
2023-04-15 15:11:59 +00:00
So ( func ( ) interface { } { return master . config . ResyncPeriod . Duration } ,
withTimeout , 2 * time . Second , ShouldResemble , time . Duration ( 3 ) * time . Minute )
2023-05-13 19:03:53 +00:00
So ( func ( ) interface { } { return master . config . NfdApiParallelism } ,
withTimeout , 2 * time . Second , ShouldResemble , 100 )
2023-03-05 21:56:46 +00:00
} )
} )
}
2024-01-22 17:08:04 +00:00
func newTestNodeList ( ) * corev1 . NodeList {
l := corev1 . NodeList { }
2023-05-13 19:03:53 +00:00
2024-01-22 17:08:04 +00:00
for i := 0 ; i < 1000 ; i ++ {
n := corev1 . Node { }
n . Name = fmt . Sprintf ( "node %v" , i )
n . Labels = map [ string ] string { }
n . Annotations = map [ string ] string { }
n . Status . Capacity = corev1 . ResourceList { }
2023-05-13 19:03:53 +00:00
2024-01-22 17:08:04 +00:00
l . Items = append ( l . Items , n )
2023-05-13 19:03:53 +00:00
}
2024-01-22 17:08:04 +00:00
return & l
}
2023-05-13 19:03:53 +00:00
2024-01-22 17:08:04 +00:00
func BenchmarkNfdAPIUpdateAllNodes ( b * testing . B ) {
fakeCli := fakeclient . NewSimpleClientset ( newTestNodeList ( ) )
2024-04-05 10:24:54 +00:00
fakeMaster := newFakeMaster ( WithKubernetesClient ( fakeCli ) )
2024-01-22 17:08:04 +00:00
fakeMaster . nfdController = newFakeNfdAPIController ( fakenfdclient . NewSimpleClientset ( ) )
2023-05-13 19:03:53 +00:00
2024-04-17 12:33:01 +00:00
updaterPool := newUpdaterPool ( fakeMaster )
fakeMaster . updaterPool = updaterPool
2024-01-22 17:08:04 +00:00
2024-04-17 12:33:01 +00:00
updaterPool . start ( 10 )
2023-05-13 19:03:53 +00:00
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
2024-01-22 17:08:04 +00:00
_ = fakeMaster . nfdAPIUpdateAllNodes ( )
2023-05-13 19:03:53 +00:00
}
fmt . Println ( b . Elapsed ( ) )
}
2023-03-05 21:56:46 +00:00
// withTimeout is a custom assertion for polling a value asynchronously
// actual is a function for getting the actual value
// expected[0] is a time.Duration value specifying the timeout
// expected[1] is the "real" assertion function to be called
// expected[2:] are the arguments for the "real" assertion function
func withTimeout ( actual interface { } , expected ... interface { } ) string {
getter , ok := actual . ( func ( ) interface { } )
if ! ok {
return "not getterFunc"
}
t , ok := expected [ 0 ] . ( time . Duration )
if ! ok {
return "not time.Duration"
}
f , ok := expected [ 1 ] . ( func ( interface { } , ... interface { } ) string )
if ! ok {
return "not an assert func"
}
timeout := time . After ( t )
for {
result := f ( getter ( ) , expected [ 2 : ] ... )
if result == "" {
return ""
}
select {
case <- timeout :
return result
case <- time . After ( 10 * time . Millisecond ) :
}
}
}
2024-01-22 13:32:02 +00:00
func sortJsonPatches ( p [ ] utils . JsonPatch ) [ ] utils . JsonPatch {
2020-08-13 14:14:27 +00:00
sort . Slice ( p , func ( i , j int ) bool { return p [ i ] . Path < p [ j ] . Path } )
return p
}
2022-09-20 16:56:58 +00:00
// Remove any labels having the given prefix
2024-01-22 13:32:02 +00:00
func removeLabelsWithPrefix ( n * corev1 . Node , search string ) [ ] utils . JsonPatch {
var p [ ] utils . JsonPatch
2022-09-20 16:56:58 +00:00
for k := range n . Labels {
if strings . HasPrefix ( k , search ) {
2024-01-22 13:32:02 +00:00
p = append ( p , utils . NewJsonPatch ( "remove" , "/metadata/labels" , k , "" ) )
2022-09-20 16:56:58 +00:00
}
}
return p
}
2023-11-01 14:57:31 +00:00
func TestGetDynamicValue ( t * testing . T ) {
tests := [ ] struct {
name string
value string
features * nfdv1alpha1 . Features
want string
fail bool
} {
{
name : "Valid dynamic value" ,
value : "@test.feature.LSM" ,
features : & nfdv1alpha1 . Features {
Attributes : map [ string ] nfdv1alpha1 . AttributeFeatureSet {
2024-04-22 20:27:15 +00:00
"test.feature" : {
2023-11-01 14:57:31 +00:00
Elements : map [ string ] string {
"LSM" : "123" ,
} ,
} ,
} ,
} ,
want : "123" ,
fail : false ,
} ,
{
name : "Invalid feature name" ,
value : "@invalid" ,
features : & nfdv1alpha1 . Features { } ,
want : "" ,
fail : true ,
} ,
{
name : "Element not found" ,
value : "@test.feature.LSM" ,
features : & nfdv1alpha1 . Features { } ,
want : "" ,
fail : true ,
} ,
{
name : "Invalid dynamic value" ,
value : "@test.feature.LSM" ,
features : & nfdv1alpha1 . Features { } ,
want : "" ,
fail : true ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
got , err := getDynamicValue ( tt . value , tt . features )
if err != nil && ! tt . fail {
t . Errorf ( "getDynamicValue() = %v, want %v" , err , tt . want )
}
if got != tt . want {
t . Errorf ( "getDynamicValue() = %v, want %v" , got , tt . want )
}
} )
}
}