From 7bad0d583ccdcf01521c97d1a84f520b6684b577 Mon Sep 17 00:00:00 2001 From: AhmedGrati Date: Thu, 15 Feb 2024 15:57:50 +0100 Subject: [PATCH 1/8] feat/nfd-master: support CR restrictions Signed-off-by: AhmedGrati --- go.mod | 2 + pkg/nfd-master/nfd-api-controller.go | 56 +++++- pkg/nfd-master/nfd-api-controller_test.go | 56 ++++++ pkg/nfd-master/nfd-master-internal_test.go | 84 +++++++- pkg/nfd-master/nfd-master.go | 62 +++++- test/e2e/node_feature_discovery_test.go | 221 +++++++++++++++++++++ 6 files changed, 453 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 7c25f60f55..be823b2d3c 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module sigs.k8s.io/node-feature-discovery go 1.22.2 +toolchain go1.22.0 + require ( github.com/fsnotify/fsnotify v1.7.0 github.com/golang/protobuf v1.5.4 diff --git a/pkg/nfd-master/nfd-api-controller.go b/pkg/nfd-master/nfd-api-controller.go index 81b5bd35e1..905a2ed0c6 100644 --- a/pkg/nfd-master/nfd-api-controller.go +++ b/pkg/nfd-master/nfd-api-controller.go @@ -17,6 +17,7 @@ limitations under the License. package nfdmaster import ( + "context" "fmt" "time" @@ -26,7 +27,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" - nfdclientset "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned" nfdscheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme" nfdinformers "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions" nfdinformersv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/nfd/v1alpha1" @@ -65,6 +65,8 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC updateOneNodeChan: make(chan string), updateAllNodeFeatureGroupsChan: make(chan struct{}, 1), updateNodeFeatureGroupChan: make(chan string), + k8sClient: nfdApiControllerOptions.K8sClient, + nodeFeatureNamespaceSelector: nfdApiControllerOptions.NodeFeatureNamespaceSelector, } nfdClient := nfdclientset.NewForConfigOrDie(config) @@ -89,25 +91,28 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC AddFunc: func(obj interface{}) { nfr := obj.(*nfdv1alpha1.NodeFeature) klog.V(2).InfoS("NodeFeature added", "nodefeature", klog.KObj(nfr)) - c.updateOneNode("NodeFeature", nfr) - if !nfdApiControllerOptions.DisableNodeFeatureGroup { - c.updateAllNodeFeatureGroups() + if c.isNamespaceSelected(nfr.Namespace) { + c.updateOneNode("NodeFeature", nfr) + } else { + klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) } }, UpdateFunc: func(oldObj, newObj interface{}) { nfr := newObj.(*nfdv1alpha1.NodeFeature) klog.V(2).InfoS("NodeFeature updated", "nodefeature", klog.KObj(nfr)) - c.updateOneNode("NodeFeature", nfr) - if !nfdApiControllerOptions.DisableNodeFeatureGroup { - c.updateAllNodeFeatureGroups() + if c.isNamespaceSelected(nfr.Namespace) { + c.updateOneNode("NodeFeature", nfr) + } else { + klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) } }, DeleteFunc: func(obj interface{}) { nfr := obj.(*nfdv1alpha1.NodeFeature) klog.V(2).InfoS("NodeFeature deleted", "nodefeature", klog.KObj(nfr)) - c.updateOneNode("NodeFeature", nfr) - if !nfdApiControllerOptions.DisableNodeFeatureGroup { - c.updateAllNodeFeatureGroups() + if c.isNamespaceSelected(nfr.Namespace) { + c.updateOneNode("NodeFeature", nfr) + } else { + klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) } }, }); err != nil { @@ -209,6 +214,37 @@ func (c *nfdController) updateOneNode(typ string, obj metav1.Object) { c.updateOneNodeChan <- nodeName } +func (c *nfdController) isNamespaceSelected(namespace string) bool { + // no namespace restrictions are made here + if c.nodeFeatureNamespaceSelector == nil { + return true + } + + labelMap, err := metav1.LabelSelectorAsSelector(c.nodeFeatureNamespaceSelector) + if err != nil { + klog.ErrorS(err, "failed to convert label selector to map", "selector", c.nodeFeatureNamespaceSelector) + return false + } + + listOptions := metav1.ListOptions{ + LabelSelector: labelMap.String(), + } + + namespaces, err := c.k8sClient.CoreV1().Namespaces().List(context.Background(), listOptions) + if err != nil { + klog.ErrorS(err, "failed to query namespaces", "listOptions", listOptions) + return false + } + + for _, ns := range namespaces.Items { + if ns.Name == namespace { + return true + } + } + + return false +} + func (c *nfdController) updateAllNodes() { select { case c.updateAllNodesChan <- struct{}{}: diff --git a/pkg/nfd-master/nfd-api-controller_test.go b/pkg/nfd-master/nfd-api-controller_test.go index 44153f41a0..21401d96c0 100644 --- a/pkg/nfd-master/nfd-api-controller_test.go +++ b/pkg/nfd-master/nfd-api-controller_test.go @@ -23,6 +23,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" + fakeclient "k8s.io/client-go/kubernetes/fake" + corev1 "k8s.io/api/core/v1" ) func TestGetNodeNameForObj(t *testing.T) { @@ -42,3 +44,57 @@ func TestGetNodeNameForObj(t *testing.T) { assert.Nil(t, err) assert.Equal(t, n, "node-1") } + +func newTestNamespace(name string) *corev1.Namespace{ + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "name": name, + }, + }, + } +} + +func TestIsNamespaceAllowed(t *testing.T) { + fakeCli := fakeclient.NewSimpleClientset(newTestNamespace("fake")) + c := &nfdController{ + k8sClient: fakeCli, + } + + testcases := []struct { + name string + objectNamespace string + nodeFeatureNamespaceSelector *metav1.LabelSelector + expectedResult bool + }{ + { + name: "namespace not allowed", + objectNamespace: "random", + nodeFeatureNamespaceSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "name", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"fake"}, + }, + }, + }, + expectedResult: false, + }, + { + name: "namespace is allowed", + objectNamespace: "fake", + nodeFeatureNamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "fake"}, + }, + expectedResult: false, + }, + } + + for _, tc := range testcases { + c.nodeFeatureNamespaceSelector = tc.nodeFeatureNamespaceSelector + res := c.isNamespaceSelected(tc.name) + assert.Equal(t, res, tc.expectedResult) + } +} diff --git a/pkg/nfd-master/nfd-master-internal_test.go b/pkg/nfd-master/nfd-master-internal_test.go index 498070a86b..e6e73103e8 100644 --- a/pkg/nfd-master/nfd-master-internal_test.go +++ b/pkg/nfd-master/nfd-master-internal_test.go @@ -509,15 +509,16 @@ func TestFilterLabels(t *testing.T) { 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"} + overwriteKeys := true jsonPath := "/root" - 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) + Convey("When there are neither itmes to remoe nor to add or update", func() { + p := createPatches([]string{"foo", "bar"}, existingItems, map[string]string{}, jsonPath, overwriteKeys) So(len(p), ShouldEqual, 0) }) - 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) + Convey("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, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("remove", jsonPath, "key-2", ""), utils.NewJsonPatch("remove", jsonPath, "key-3", ""), @@ -525,9 +526,9 @@ func TestCreatePatches(t *testing.T) { So(sortJsonPatches(p), ShouldResemble, sortJsonPatches(expected)) }) - Convey("When when there are no itmes to remove but new items to add", func() { + Convey("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) + p := createPatches([]string{"key-1"}, existingItems, newItems, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("add", jsonPath, "new-key", newItems["new-key"]), utils.NewJsonPatch("replace", jsonPath, "key-1", newItems["key-1"]), @@ -535,9 +536,9 @@ func TestCreatePatches(t *testing.T) { So(sortJsonPatches(p), ShouldResemble, sortJsonPatches(expected)) }) - Convey("When when there are items to remove add and update", func() { + Convey("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) + p := createPatches([]string{"key-1", "key-2", "key-3", "foo"}, existingItems, newItems, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("add", jsonPath, "new-key", newItems["new-key"]), utils.NewJsonPatch("add", jsonPath, "key-4", newItems["key-4"]), @@ -547,6 +548,16 @@ func TestCreatePatches(t *testing.T) { } So(sortJsonPatches(p), ShouldResemble, sortJsonPatches(expected)) }) + + Convey("When overwrite of keys is denied and there is already an existant key", func() { + overwriteKeys = false + newItems := map[string]string{"key-1": "new-2", "key-4": "val-4"} + p := createPatches([]string{}, existingItems, newItems, jsonPath, overwriteKeys) + expected := []utils.JsonPatch{ + utils.NewJsonPatch("add", jsonPath, "key-4", newItems["key-4"]), + } + So(sortJsonPatches(p), ShouldResemble, sortJsonPatches(expected)) + }) }) } @@ -896,3 +907,60 @@ func TestGetDynamicValue(t *testing.T) { }) } } + +func TestFilterTaints(t *testing.T) { + testcases := []struct { + name string + taints []corev1.Taint + maxTaints int + expectedResult []corev1.Taint + }{ + { + name: "no restriction on the number of taints", + taints: []corev1.Taint{ + { + Key: "feature.node.kubernetes.io/key1", + Value: "dummy", + Effect: corev1.TaintEffectNoSchedule, + }, + }, + maxTaints: 0, + expectedResult: []corev1.Taint{ + { + Key: "feature.node.kubernetes.io/key1", + Value: "dummy", + Effect: corev1.TaintEffectNoSchedule, + }, + }, + }, + { + name: "max of 1 Taint should be generated", + taints: []corev1.Taint{ + { + Key: "feature.node.kubernetes.io/key1", + Value: "dummy", + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "feature.node.kubernetes.io/key2", + Value: "dummy", + Effect: corev1.TaintEffectNoSchedule, + }, + }, + maxTaints: 1, + expectedResult: []corev1.Taint{}, + }, + } + + mockMaster := newFakeMaster(nil) + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + mockMaster.config.Restrictions.MaxTaintsPerCR = tc.maxTaints + res := mockMaster.filterTaints(tc.taints) + Convey("The expected number of taints should be correct", t, func() { + So(len(res), ShouldEqual, len(tc.expectedResult)) + }) + }) + } +} diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index e34bb3e5fb..b95685b3b9 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -75,6 +75,16 @@ type ExtendedResources map[string]string // Annotations are used for NFD-related node metadata type Annotations map[string]string +// Restrictions contains the restrictions on the NF and NFR Crs +type Restrictions struct { + AllowedNamespaces *metav1.LabelSelector + MaxLabelsPerCR int + MaxTaintsPerCR int + MaxExtendedResourcesPerCR int + DenyNodeFeatureLabels bool + OverwriteLabels bool +} + // NFDConfig contains the configuration settings of NfdMaster. type NFDConfig struct { AutoDefaultNs bool @@ -88,6 +98,7 @@ type NFDConfig struct { LeaderElection LeaderElectionConfig NfdApiParallelism int Klog klogutils.KlogConfigOpts + Restrictions Restrictions } // LeaderElectionConfig contains the configuration for leader election @@ -273,6 +284,13 @@ func newDefaultConfig() *NFDConfig { RenewDeadline: utils.DurationVal{Duration: time.Duration(10) * time.Second}, }, Klog: make(map[string]string), + Restrictions: Restrictions{ + MaxLabelsPerCR: 0, + MaxTaintsPerCR: 0, + MaxExtendedResourcesPerCR: 0, + OverwriteLabels: true, + DenyNodeFeatureLabels: false, + }, } } @@ -620,7 +638,7 @@ func (m *nfdMaster) updateMasterNode() error { p := createPatches([]string{m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation)}, node.Annotations, nil, - "/metadata/annotations") + "/metadata/annotations", true) err = patchNode(m.k8sClient, node.Name, p) if err != nil { @@ -661,6 +679,11 @@ func (m *nfdMaster) filterFeatureLabels(labels Labels, features *nfdv1alpha1.Fea } } + if m.config.Restrictions.MaxLabelsPerCR > 0 && len(outLabels) > m.config.Restrictions.MaxLabelsPerCR { + klog.InfoS("number of labels in the request exceeds the restriction maximum labels per CR, skipping") + outLabels = Labels{} + } + return outLabels, extendedResources } @@ -715,7 +738,7 @@ func getDynamicValue(value string, features *nfdv1alpha1.Features) (string, erro return element, nil } -func filterTaints(taints []corev1.Taint) []corev1.Taint { +func (m *nfdMaster) filterTaints(taints []corev1.Taint) []corev1.Taint { outTaints := []corev1.Taint{} for _, taint := range taints { @@ -726,6 +749,12 @@ func filterTaints(taints []corev1.Taint) []corev1.Taint { outTaints = append(outTaints, taint) } } + + if m.config.Restrictions.MaxTaintsPerCR > 0 && len(taints) > m.config.Restrictions.MaxTaintsPerCR { + klog.InfoS("number of taints in the request exceeds the restriction maximum taints per CR, skipping") + outTaints = []corev1.Taint{} + } + return outTaints } @@ -1031,13 +1060,24 @@ func (m *nfdMaster) refreshNodeFeatures(cli k8sclient.Interface, node *corev1.No maps.Copy(extendedResources, crExtendedResources) extendedResources = m.filterExtendedResources(features, extendedResources) + if m.config.Restrictions.MaxExtendedResourcesPerCR > 0 && len(extendedResources) > m.config.Restrictions.MaxExtendedResourcesPerCR { + klog.InfoS("number of extended resources in the request exceeds the restriction maximum extended resources per CR, skipping") + extendedResources = map[string]string{} + } + // Annotations annotations := m.filterFeatureAnnotations(crAnnotations) // Taints var taints []corev1.Taint if m.config.EnableTaints { - taints = filterTaints(crTaints) + taints = m.filterTaints(crTaints) + } + + // If we deny node feature labels, we'll empty the labels variable + if m.config.Restrictions.DenyNodeFeatureLabels { + klog.InfoS("node feature labels are denied, skipping...") + labels = map[string]string{} } if m.config.NoPublish { @@ -1114,7 +1154,7 @@ func setTaints(cli k8sclient.Interface, taints []corev1.Taint, node *corev1.Node newAnnotations[nfdv1alpha1.NodeTaintsAnnotation] = strings.Join(taintStrs, ",") } - patches := createPatches([]string{nfdv1alpha1.NodeTaintsAnnotation}, node.Annotations, newAnnotations, "/metadata/annotations") + patches := createPatches([]string{nfdv1alpha1.NodeTaintsAnnotation}, node.Annotations, newAnnotations, "/metadata/annotations", true) if len(patches) > 0 { if err := patchNode(cli, node.Name, patches); err != nil { return fmt.Errorf("error while patching node object: %w", err) @@ -1254,7 +1294,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, // Create JSON patches for changes in labels and annotations oldLabels := stringToNsNames(node.Annotations[m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation)], nfdv1alpha1.FeatureLabelNs) oldAnnotations := stringToNsNames(node.Annotations[m.instanceAnnotation(nfdv1alpha1.FeatureAnnotationsTrackingAnnotation)], nfdv1alpha1.FeatureAnnotationNs) - patches := createPatches(oldLabels, node.Labels, labels, "/metadata/labels") + patches := createPatches(oldLabels, node.Labels, labels, "/metadata/labels", m.config.Restrictions.OverwriteLabels) oldAnnotations = append(oldAnnotations, []string{ m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation), m.instanceAnnotation(nfdv1alpha1.ExtendedResourceAnnotation), @@ -1262,7 +1302,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, // Clean up deprecated/stale nfd version annotations m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation), m.instanceAnnotation(nfdv1alpha1.WorkerVersionAnnotation)}...) - patches = append(patches, createPatches(oldAnnotations, node.Annotations, annotations, "/metadata/annotations")...) + patches = append(patches, createPatches(oldAnnotations, node.Annotations, annotations, "/metadata/annotations", true)...) // patch node status with extended resource changes statusPatches := m.createExtendedResourcePatches(node, extendedResources) @@ -1294,7 +1334,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, } // createPatches is a generic helper that returns json patch operations to perform -func createPatches(removeKeys []string, oldItems map[string]string, newItems map[string]string, jsonPath string) []utils.JsonPatch { +func createPatches(removeKeys []string, oldItems map[string]string, newItems map[string]string, jsonPath string, overwrite bool) []utils.JsonPatch { patches := []utils.JsonPatch{} // Determine items to remove @@ -1309,7 +1349,7 @@ func createPatches(removeKeys []string, oldItems map[string]string, newItems map // Determine items to add or replace for key, newVal := range newItems { if oldVal, ok := oldItems[key]; ok { - if newVal != oldVal { + if newVal != oldVal && overwrite { patches = append(patches, utils.NewJsonPatch("replace", jsonPath, key, newVal)) } } else { @@ -1511,8 +1551,10 @@ func (m *nfdMaster) startNfdApiController() error { } klog.InfoS("starting the nfd api controller") m.nfdController, err = newNfdController(kubeconfig, nfdApiControllerOptions{ - DisableNodeFeature: !nfdfeatures.NFDFeatureGate.Enabled(nfdfeatures.NodeFeatureAPI), - ResyncPeriod: m.config.ResyncPeriod.Duration, + DisableNodeFeature: !nfdfeatures.NFDFeatureGate.Enabled(nfdfeatures.NodeFeatureAPI), + ResyncPeriod: m.config.ResyncPeriod.Duration, + K8sClient: m.k8sClient, + NodeFeatureNamespaceSelector: m.config.Restrictions.AllowedNamespaces, }) if err != nil { return fmt.Errorf("failed to initialize CRD controller: %w", err) diff --git a/test/e2e/node_feature_discovery_test.go b/test/e2e/node_feature_discovery_test.go index 38e0a49f0d..dd692ce76c 100644 --- a/test/e2e/node_feature_discovery_test.go +++ b/test/e2e/node_feature_discovery_test.go @@ -853,6 +853,227 @@ core: } eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchLabels(expectedLabels, nodes)) }) + + Context("allowed namespaces restriction is respected or not", func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + allowedNamespaces: + matchLabels: + kubernetes.io/metadata.name: "fake" +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("Nothing should be created", func(ctx context.Context) { + // deploy node feature object + if !useNodeFeatureApi { + Skip("NodeFeature API not enabled") + } + + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + // Apply Node Feature object + By("Creating NodeFeature object") + nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) + Expect(err).NotTo(HaveOccurred()) + + By("Verifying node labels from NodeFeature object #1 are not created") + // No labels should be created since the f.Namespace is not in the allowed Namespaces + expectedLabels := map[string]k8sLabels{} + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Deleting NodeFeature object") + err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + }) + + Context("max labels, taints restrictions should be respected", func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +enableTaints: true +restrictions: + maxLabelsPerCR: 1 + maxTaintsPerCR: 1 +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("No labels or taints should be created", func(ctx context.Context) { + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + By("Creating nfd-worker config") + cm := testutils.NewConfigMap("nfd-worker-conf", "nfd-worker.conf", ` +core: + sleepInterval: "1s" + featureSources: ["fake"] + labelSources: [] +`) + cm, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + By("Creating nfd-worker daemonset") + podSpecOpts := createPodSpecOpts( + testpod.SpecWithContainerImage(dockerImage()), + testpod.SpecWithConfigMap(cm.Name, "/etc/kubernetes/node-feature-discovery"), + ) + workerDS := testds.NFDWorker(podSpecOpts...) + workerDS, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ctx, workerDS, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + + By("Waiting for worker daemonset pods to be ready") + Expect(testpod.WaitForReady(ctx, f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 2)).NotTo(HaveOccurred()) + + // Add features from NodeFeatureRule #3 + By("Creating NodeFeatureRules #3") + Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-3.yaml")).NotTo(HaveOccurred()) + + By("Verifying node taints and annotation from NodeFeatureRules #3") + expectedLabels := map[string]k8sLabels{} + + expectedTaints := map[string][]corev1.Taint{} + + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) + + By("Deleting NodeFeatureRule #3") + err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-test-3", metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + By("Verifying taints from NodeFeatureRules #3 were removed") + expectedTaints["*"] = []corev1.Taint{} + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) + }) + }) + + Context("max extended resources restriction should be respected", func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + maxExtendedResourcesPerCR: 1 +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("Nothing should be created", func(ctx context.Context) { + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + By("Creating nfd-worker config") + cm := testutils.NewConfigMap("nfd-worker-conf", "nfd-worker.conf", ` +core: + sleepInterval: "1s" + featureSources: ["fake"] + labelSources: [] +`) + cm, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + By("Creating nfd-worker daemonset") + podSpecOpts := createPodSpecOpts( + testpod.SpecWithContainerImage(dockerImage()), + testpod.SpecWithConfigMap(cm.Name, "/etc/kubernetes/node-feature-discovery"), + ) + workerDS := testds.NFDWorker(podSpecOpts...) + workerDS, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ctx, workerDS, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + + By("Waiting for worker daemonset pods to be ready") + Expect(testpod.WaitForReady(ctx, f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 2)).NotTo(HaveOccurred()) + + expectedAnnotations := map[string]k8sAnnotations{ + "*": {}, + } + expectedCapacity := map[string]corev1.ResourceList{ + "*": {}, + } + + By("Creating NodeFeatureRules #4") + Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-4.yaml")).NotTo(HaveOccurred()) + + By("Verifying node annotations from NodeFeatureRules #4") + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes)) + + By("Verifying node status capacity from NodeFeatureRules #4") + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes)) + + By("Deleting NodeFeatureRules #4") + err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-extened-resource-test", metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + + By("Deleting nfd-worker daemonset") + err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Delete(ctx, workerDS.Name, metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + + if useNodeFeatureApi { + By("Verify that labels from nfd-worker are garbage-collected") + expectedLabels := map[string]k8sLabels{ + "*": {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchLabels(expectedLabels, nodes)) + } + }) + }) + + Context("deny node feature labels restriction should be respected", func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + denyNodeFeatureLabels: true +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("No labels should be created", func(ctx context.Context) { + // deploy node feature object + if !useNodeFeatureApi { + Skip("NodeFeature API not enabled") + } + + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + // Apply Node Feature object + By("Creating NodeFeature object") + nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) + Expect(err).NotTo(HaveOccurred()) + + By("Verifying node labels from NodeFeature object #1 are not created") + + expectedLabels := map[string]k8sLabels{ + "*": {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Deleting NodeFeature object") + err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + }) }) // Test NodeFeatureGroups From 925a071595b16860543575ab606e562a7aa735ee Mon Sep 17 00:00:00 2001 From: AhmedGrati Date: Fri, 16 Feb 2024 11:51:52 +0100 Subject: [PATCH 2/8] docs: add CR restrictions to the master configuration reference Signed-off-by: AhmedGrati --- .../master-configuration-reference.md | 112 ++++++++++++++++++ examples/nodefeature.yaml | 2 +- nfd-master.conf | 35 ++++++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 nfd-master.conf diff --git a/docs/reference/master-configuration-reference.md b/docs/reference/master-configuration-reference.md index 863cb2e135..3f04cbc0fb 100644 --- a/docs/reference/master-configuration-reference.md +++ b/docs/reference/master-configuration-reference.md @@ -338,3 +338,115 @@ Comma-separated list of `pattern=N` settings for file-filtered logging. Default: *empty* Run-time configurable: yes + + +## restrictions + +The following options specify the restrictions that can be applied by nfd-master +on the deployed Custom Resources in the cluster. + +### restrictions.allowedNamespaces + +The `allowedNamespaces` option specifies the NodeFeatures namespaces to watch. +To select the appropriate namespaces to watch, you can use the `metav1.LabelSelector` +as a type for this option. + +Default: all namespaces are allowed to be watched. + +Example: + +```yaml +restrictions: + allowedNamespaces: + matchLabels: + kubernetes.io/metadata.name: "node-feature-discovery" + matchExpressions: + - key: "kubernetes.io/metadata.name" + operator: "In" + values: + - "node-feature-discovery" +``` + +### restrictions.maxLabelsPerCR + +The `maxLabelsPerCR` option specifies the maximum number of labels that can +be generated by a single CustomResource. + +Default: no limit + +Example: + +```yaml +restrictions: + maxLabelsPerCR: 20 +``` + +### restrictions.maxTaintsPerCR + +The `maxTaintsPerCR` option specifies the maximum number of taints that can +be generated by a single CustomResource. + +Default: no limit + +Example: + +```yaml +restrictions: + maxTaintsPerCR: 10 +``` + +### restrictions.maxExtendedResourcesPerCR + +The `maxExtendedResourcesPerCR` option specifies the maximum number of extended +resources that can be generated by a single CustomResource. + +Default: no limit + +Example: + +```yaml +restrictions: + maxExtendedResourcesPerCR: 15 +``` + +### restrictions.maxExtendedResourcesPerCR + +The `maxExtendedResourcesPerCR` option specifies the maximum number of extended +resources that can be generated by a single CustomResource. + +Default: no limit + +Example: + +```yaml +restrictions: + maxExtendedResourcesPerCR: 15 +``` + +### restrictions.overwriteLabels + +The `overwriteLabels` option specifies whether to overwrite existing +labels, if there's an overlap, or not. + +Default: true + +Example: + +```yaml +restrictions: + overwriteLabels: false +``` + +### restrictions.denyNodeFeatureLabels + +The `denyNodeFeatureLabels` option specifies whether to deny labels from NodeFeature +objects or not. + +Default: false + +Example: + +```yaml +restrictions: + denyNodeFeatureLabels: true +``` diff --git a/examples/nodefeature.yaml b/examples/nodefeature.yaml index 7ef4dd56c5..71078c9e25 100644 --- a/examples/nodefeature.yaml +++ b/examples/nodefeature.yaml @@ -4,7 +4,7 @@ apiVersion: nfd.k8s-sigs.io/v1alpha1 kind: NodeFeature metadata: labels: - nfd.node.kubernetes.io/node-name: example-node + nfd.node.kubernetes.io/node-name: nfd-control-plane name: example-node namespace: node-feature-discovery spec: diff --git a/nfd-master.conf b/nfd-master.conf new file mode 100644 index 0000000000..bea5ccb562 --- /dev/null +++ b/nfd-master.conf @@ -0,0 +1,35 @@ +noPublish: false +autoDefaultNs: true +extraLabelNs: ["added.ns.io","added.kubernets.io"] +denyLabelNs: ["denied.ns.io","denied.kubernetes.io"] +resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"] +enableTaints: false +labelWhiteList: "" +resyncPeriod: "2h" +restrictions: + allowedNamespaces: + matchLabels: + kubernetes.io/metadata.name: "node-feature-discovery" + matchExpressions: + - key: "kubernetes.io/metadata.name" + operator: "In" + values: + - "node-feature-discovery" +klog: + addDirHeader: false + alsologtostderr: false + logBacktraceAt: + logtostderr: true + skipHeaders: false + stderrthreshold: 2 + v: 0 + vmodule: + logDir: + logFile: + logFileMaxSize: 1800 + skipLogHeaders: false +leaderElection: + leaseDuration: 15s + renewDeadline: 10s + retryPeriod: 2s +nfdApiParallelism: 10 From 28b40c90b8eb17892bf578c44af3a65167efa7fa Mon Sep 17 00:00:00 2001 From: AhmedGrati Date: Sat, 10 Aug 2024 22:28:52 +0200 Subject: [PATCH 3/8] deploy: add CR restrictions to the helm config Signed-off-by: AhmedGrati Signed-off-by: AhmedThresh Signed-off-by: AhmedGrati Signed-off-by: AhmedThresh Signed-off-by: AhmedGrati Signed-off-by: AhmedThresh --- deployment/base/rbac/master-clusterrole.yaml | 7 + .../master-config/nfd-master.conf.example | 15 + .../templates/clusterrole.yaml | 7 + .../helm/node-feature-discovery/values.yaml | 15 + .../master-configuration-reference.md | 79 ++- examples/nodefeature.yaml | 2 +- go.mod | 2 - nfd-master.conf | 35 -- pkg/nfd-master/namespace-lister.go | 58 ++ pkg/nfd-master/nfd-api-controller.go | 66 +-- pkg/nfd-master/nfd-api-controller_test.go | 43 +- pkg/nfd-master/nfd-master-internal_test.go | 71 +-- pkg/nfd-master/nfd-master.go | 128 +++-- test/e2e/data/nodefeaturerule-6.yaml | 18 + test/e2e/node_feature_discovery_test.go | 498 ++++++++++-------- test/e2e/utils/rbac.go | 5 + 16 files changed, 582 insertions(+), 467 deletions(-) delete mode 100644 nfd-master.conf create mode 100644 pkg/nfd-master/namespace-lister.go create mode 100644 test/e2e/data/nodefeaturerule-6.yaml diff --git a/deployment/base/rbac/master-clusterrole.yaml b/deployment/base/rbac/master-clusterrole.yaml index 529f87e383..b87760d5ac 100644 --- a/deployment/base/rbac/master-clusterrole.yaml +++ b/deployment/base/rbac/master-clusterrole.yaml @@ -3,6 +3,13 @@ kind: ClusterRole metadata: name: nfd-master rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - watch + - list - apiGroups: - "" resources: diff --git a/deployment/components/master-config/nfd-master.conf.example b/deployment/components/master-config/nfd-master.conf.example index 8aa0cb29ce..96dd6d130a 100644 --- a/deployment/components/master-config/nfd-master.conf.example +++ b/deployment/components/master-config/nfd-master.conf.example @@ -6,6 +6,21 @@ # enableTaints: false # labelWhiteList: "foo" # resyncPeriod: "2h" +# restrictions: +# disableLabels: true +# disableTaints: true +# disableExtendedResources: true +# disableAnnotations: true +# allowOverwrite: false +# denyNodeFeatureLabels: true +# nodeFeatureNamespaceSelector: +# matchLabels: +# kubernetes.io/metadata.name: "node-feature-discovery" +# matchExpressions: +# - key: "kubernetes.io/metadata.name" +# operator: "In" +# values: +# - "node-feature-discovery" # klog: # addDirHeader: false # alsologtostderr: false diff --git a/deployment/helm/node-feature-discovery/templates/clusterrole.yaml b/deployment/helm/node-feature-discovery/templates/clusterrole.yaml index 958f043fe4..0b76e9afa9 100644 --- a/deployment/helm/node-feature-discovery/templates/clusterrole.yaml +++ b/deployment/helm/node-feature-discovery/templates/clusterrole.yaml @@ -6,6 +6,13 @@ metadata: labels: {{- include "node-feature-discovery.labels" . | nindent 4 }} rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - watch + - list - apiGroups: - "" resources: diff --git a/deployment/helm/node-feature-discovery/values.yaml b/deployment/helm/node-feature-discovery/values.yaml index 524421a058..452bcf1abf 100644 --- a/deployment/helm/node-feature-discovery/values.yaml +++ b/deployment/helm/node-feature-discovery/values.yaml @@ -28,6 +28,21 @@ master: # enableTaints: false # labelWhiteList: "foo" # resyncPeriod: "2h" + # restrictions: + # disableLabels: true + # disableTaints: true + # disableExtendedResources: true + # disableAnnotations: true + # allowOverwrite: false + # denyNodeFeatureLabels: true + # nodeFeatureNamespaceSelector: + # matchLabels: + # kubernetes.io/metadata.name: "node-feature-discovery" + # matchExpressions: + # - key: "kubernetes.io/metadata.name" + # operator: "In" + # values: + # - "node-feature-discovery" # klog: # addDirHeader: false # alsologtostderr: false diff --git a/docs/reference/master-configuration-reference.md b/docs/reference/master-configuration-reference.md index 3f04cbc0fb..b7a06fe0a4 100644 --- a/docs/reference/master-configuration-reference.md +++ b/docs/reference/master-configuration-reference.md @@ -339,25 +339,24 @@ Default: *empty* Run-time configurable: yes +## restrictions (EXPERIMENTAL) -## restrictions +The following options specify the restrictions that can be applied by the +nfd-master on the deployed Custom Resources in the cluster. -The following options specify the restrictions that can be applied by nfd-master -on the deployed Custom Resources in the cluster. +### restrictions.nodeFeatureNamespaceSelector -### restrictions.allowedNamespaces +The `nodeFeatureNamespaceSelector` option specifies the NodeFeatures namespaces +to watch, which can be selected by using `metav1.LabelSelector` as a type for +this option. An empty value selects all namespaces to be watched. -The `allowedNamespaces` option specifies the NodeFeatures namespaces to watch. -To select the appropriate namespaces to watch, you can use the `metav1.LabelSelector` -as a type for this option. - -Default: all namespaces are allowed to be watched. +Default: *empty* Example: ```yaml restrictions: - allowedNamespaces: + nodeFeatureNamespaceSelector: matchLabels: kubernetes.io/metadata.name: "node-feature-discovery" matchExpressions: @@ -367,66 +366,56 @@ restrictions: - "node-feature-discovery" ``` -### restrictions.maxLabelsPerCR - -The `maxLabelsPerCR` option specifies the maximum number of labels that can -be generated by a single CustomResource. - -Default: no limit - -Example: - -```yaml -restrictions: - maxLabelsPerCR: 20 -``` - -### restrictions.maxTaintsPerCR +### restrictions.disableLabels -The `maxTaintsPerCR` option specifies the maximum number of taints that can -be generated by a single CustomResource. +The `disableLabels` option controls whether to allow creation of node labels +from NodeFeature and NodeFeatureRule CRs or not. -Default: no limit +Default: false Example: ```yaml restrictions: - maxTaintsPerCR: 10 + disableLabels: true ``` -### restrictions.maxExtendedResourcesPerCR +### restrictions.disableExtendedResources -The `maxExtendedResourcesPerCR` option specifies the maximum number of extended -resources that can be generated by a single CustomResource. +The `disableExtendedResources` option controls whether to allow creation of +node extended resources from NodeFeatureRule CR or not. -Default: no limit +Default: false Example: ```yaml restrictions: - maxExtendedResourcesPerCR: 15 + disableExtendedResources: true ``` -### restrictions.maxExtendedResourcesPerCR +### restrictions.disableAnnotations -The `maxExtendedResourcesPerCR` option specifies the maximum number of extended -resources that can be generated by a single CustomResource. +he `disableAnnotations` option controls whether to allow creation of node annotations +from NodeFeatureRule CR or not. -Default: no limit +Default: false Example: ```yaml restrictions: - maxExtendedResourcesPerCR: 15 + disableAnnotations: true ``` -### restrictions.overwriteLabels +### restrictions.allowOverwrite -The `overwriteLabels` option specifies whether to overwrite existing -labels, if there's an overlap, or not. +The `allowOverwrite` option controls whether NFD is allowed to overwrite and +take over management of existing node labels, annotations, and extended resources. +Labels, annotations and extended resources created by NFD itself are not affected +(overwrite cannot be disabled). NFD tracks the labels, annotations and extended +resources that it manages with specific +[node annotations](../get-started/introduction.md#node-annotations). Default: true @@ -434,13 +423,13 @@ Example: ```yaml restrictions: - overwriteLabels: false + allowOverwrite: false ``` ### restrictions.denyNodeFeatureLabels -The `denyNodeFeatureLabels` option specifies whether to deny labels from NodeFeature -objects or not. +The `denyNodeFeatureLabels` option specifies whether to deny labels from 3rd party +NodeFeature objects or not. NodeFeature objects created by nfd-worker are not affected. Default: false diff --git a/examples/nodefeature.yaml b/examples/nodefeature.yaml index 71078c9e25..7ef4dd56c5 100644 --- a/examples/nodefeature.yaml +++ b/examples/nodefeature.yaml @@ -4,7 +4,7 @@ apiVersion: nfd.k8s-sigs.io/v1alpha1 kind: NodeFeature metadata: labels: - nfd.node.kubernetes.io/node-name: nfd-control-plane + nfd.node.kubernetes.io/node-name: example-node name: example-node namespace: node-feature-discovery spec: diff --git a/go.mod b/go.mod index be823b2d3c..7c25f60f55 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module sigs.k8s.io/node-feature-discovery go 1.22.2 -toolchain go1.22.0 - require ( github.com/fsnotify/fsnotify v1.7.0 github.com/golang/protobuf v1.5.4 diff --git a/nfd-master.conf b/nfd-master.conf deleted file mode 100644 index bea5ccb562..0000000000 --- a/nfd-master.conf +++ /dev/null @@ -1,35 +0,0 @@ -noPublish: false -autoDefaultNs: true -extraLabelNs: ["added.ns.io","added.kubernets.io"] -denyLabelNs: ["denied.ns.io","denied.kubernetes.io"] -resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"] -enableTaints: false -labelWhiteList: "" -resyncPeriod: "2h" -restrictions: - allowedNamespaces: - matchLabels: - kubernetes.io/metadata.name: "node-feature-discovery" - matchExpressions: - - key: "kubernetes.io/metadata.name" - operator: "In" - values: - - "node-feature-discovery" -klog: - addDirHeader: false - alsologtostderr: false - logBacktraceAt: - logtostderr: true - skipHeaders: false - stderrthreshold: 2 - v: 0 - vmodule: - logDir: - logFile: - logFileMaxSize: 1800 - skipLogHeaders: false -leaderElection: - leaseDuration: 15s - renewDeadline: 10s - retryPeriod: 2s -nfdApiParallelism: 10 diff --git a/pkg/nfd-master/namespace-lister.go b/pkg/nfd-master/namespace-lister.go new file mode 100644 index 0000000000..ea8b97a4c1 --- /dev/null +++ b/pkg/nfd-master/namespace-lister.go @@ -0,0 +1,58 @@ +/* +Copyright 2024 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 nfdmaster + +import ( + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/informers" + k8sclient "k8s.io/client-go/kubernetes" + v1lister "k8s.io/client-go/listers/core/v1" +) + +// NamespaceLister lists kubernetes namespaces. +type NamespaceLister struct { + namespaceLister v1lister.NamespaceLister + labelsSelector labels.Selector + stopChan chan struct{} +} + +func newNamespaceLister(k8sClient k8sclient.Interface, labelsSelector labels.Selector) *NamespaceLister { + factory := informers.NewSharedInformerFactory(k8sClient, time.Hour) + namespaceLister := factory.Core().V1().Namespaces().Lister() + + stopChan := make(chan struct{}) + factory.Start(stopChan) // runs in background + factory.WaitForCacheSync(stopChan) + + return &NamespaceLister{ + namespaceLister: namespaceLister, + labelsSelector: labelsSelector, + stopChan: stopChan, + } +} + +// list returns all kubernetes namespaces. +func (lister *NamespaceLister) list() ([]*corev1.Namespace, error) { + return lister.namespaceLister.List(lister.labelsSelector) +} + +// stop closes the channel used by the lister +func (lister *NamespaceLister) stop() { + close(lister.stopChan) +} diff --git a/pkg/nfd-master/nfd-api-controller.go b/pkg/nfd-master/nfd-api-controller.go index 905a2ed0c6..2b248c407b 100644 --- a/pkg/nfd-master/nfd-api-controller.go +++ b/pkg/nfd-master/nfd-api-controller.go @@ -17,16 +17,17 @@ limitations under the License. package nfdmaster import ( - "context" "fmt" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + k8sclient "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" + nfdclientset "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned" nfdscheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme" nfdinformers "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions" nfdinformersv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/nfd/v1alpha1" @@ -46,12 +47,16 @@ type nfdController struct { updateOneNodeChan chan string updateAllNodeFeatureGroupsChan chan struct{} updateNodeFeatureGroupChan chan string + + namespaceLister *NamespaceLister } type nfdApiControllerOptions struct { - DisableNodeFeature bool - DisableNodeFeatureGroup bool - ResyncPeriod time.Duration + DisableNodeFeature bool + DisableNodeFeatureGroup bool + ResyncPeriod time.Duration + K8sClient k8sclient.Interface + NodeFeatureNamespaceSelector *metav1.LabelSelector } func init() { @@ -65,12 +70,18 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC updateOneNodeChan: make(chan string), updateAllNodeFeatureGroupsChan: make(chan struct{}, 1), updateNodeFeatureGroupChan: make(chan string), - k8sClient: nfdApiControllerOptions.K8sClient, - nodeFeatureNamespaceSelector: nfdApiControllerOptions.NodeFeatureNamespaceSelector, } - nfdClient := nfdclientset.NewForConfigOrDie(config) + if nfdApiControllerOptions.NodeFeatureNamespaceSelector != nil { + labelMap, err := metav1.LabelSelectorAsSelector(nfdApiControllerOptions.NodeFeatureNamespaceSelector) + if err != nil { + klog.ErrorS(err, "failed to convert label selector to map", "selector", nfdApiControllerOptions.NodeFeatureNamespaceSelector) + return nil, err + } + c.namespaceLister = newNamespaceLister(nfdApiControllerOptions.K8sClient, labelMap) + } + nfdClient := nfdclientset.NewForConfigOrDie(config) klog.V(2).InfoS("initializing new NFD API controller", "options", utils.DelayedDumper(nfdApiControllerOptions)) informerFactory := nfdinformers.NewSharedInformerFactory(nfdClient, nfdApiControllerOptions.ResyncPeriod) @@ -94,25 +105,26 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC if c.isNamespaceSelected(nfr.Namespace) { c.updateOneNode("NodeFeature", nfr) } else { - klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) + klog.V(2).InfoS("NodeFeature namespace is not selected, skipping", "nodefeature", klog.KObj(nfr)) + } + if !nfdApiControllerOptions.DisableNodeFeatureGroup { + c.updateAllNodeFeatureGroups() } }, UpdateFunc: func(oldObj, newObj interface{}) { nfr := newObj.(*nfdv1alpha1.NodeFeature) klog.V(2).InfoS("NodeFeature updated", "nodefeature", klog.KObj(nfr)) - if c.isNamespaceSelected(nfr.Namespace) { - c.updateOneNode("NodeFeature", nfr) - } else { - klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) + c.updateOneNode("NodeFeature", nfr) + if !nfdApiControllerOptions.DisableNodeFeatureGroup { + c.updateAllNodeFeatureGroups() } }, DeleteFunc: func(obj interface{}) { nfr := obj.(*nfdv1alpha1.NodeFeature) klog.V(2).InfoS("NodeFeature deleted", "nodefeature", klog.KObj(nfr)) - if c.isNamespaceSelected(nfr.Namespace) { - c.updateOneNode("NodeFeature", nfr) - } else { - klog.InfoS("NodeFeature not in selected namespace", "namespace", nfr.Namespace, "name", nfr.Name) + c.updateOneNode("NodeFeature", nfr) + if !nfdApiControllerOptions.DisableNodeFeatureGroup { + c.updateAllNodeFeatureGroups() } }, }); err != nil { @@ -192,6 +204,7 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC func (c *nfdController) stop() { close(c.stopChan) + c.namespaceLister.stop() } func getNodeNameForObj(obj metav1.Object) (string, error) { @@ -215,28 +228,19 @@ func (c *nfdController) updateOneNode(typ string, obj metav1.Object) { } func (c *nfdController) isNamespaceSelected(namespace string) bool { - // no namespace restrictions are made here - if c.nodeFeatureNamespaceSelector == nil { + // this means that the user didn't specify any namespace selector + // which means that we allow all namespaces + if c.namespaceLister == nil { return true } - labelMap, err := metav1.LabelSelectorAsSelector(c.nodeFeatureNamespaceSelector) - if err != nil { - klog.ErrorS(err, "failed to convert label selector to map", "selector", c.nodeFeatureNamespaceSelector) - return false - } - - listOptions := metav1.ListOptions{ - LabelSelector: labelMap.String(), - } - - namespaces, err := c.k8sClient.CoreV1().Namespaces().List(context.Background(), listOptions) + namespaces, err := c.namespaceLister.list() if err != nil { - klog.ErrorS(err, "failed to query namespaces", "listOptions", listOptions) + klog.ErrorS(err, "failed to query namespaces by the namespace lister") return false } - for _, ns := range namespaces.Items { + for _, ns := range namespaces { if ns.Name == namespace { return true } diff --git a/pkg/nfd-master/nfd-api-controller_test.go b/pkg/nfd-master/nfd-api-controller_test.go index 21401d96c0..a49c4939b3 100644 --- a/pkg/nfd-master/nfd-api-controller_test.go +++ b/pkg/nfd-master/nfd-api-controller_test.go @@ -20,11 +20,13 @@ import ( "testing" "github.com/stretchr/testify/assert" - + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" + "k8s.io/apimachinery/pkg/watch" fakeclient "k8s.io/client-go/kubernetes/fake" - corev1 "k8s.io/api/core/v1" + clienttesting "k8s.io/client-go/testing" + + nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" ) func TestGetNodeNameForObj(t *testing.T) { @@ -45,7 +47,7 @@ func TestGetNodeNameForObj(t *testing.T) { assert.Equal(t, n, "node-1") } -func newTestNamespace(name string) *corev1.Namespace{ +func newTestNamespace(name string) *corev1.Namespace { return &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -56,11 +58,19 @@ func newTestNamespace(name string) *corev1.Namespace{ } } -func TestIsNamespaceAllowed(t *testing.T) { +func TestIsNamespaceSelected(t *testing.T) { fakeCli := fakeclient.NewSimpleClientset(newTestNamespace("fake")) - c := &nfdController{ - k8sClient: fakeCli, - } + fakeCli.PrependWatchReactor("*", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := fakeCli.Tracker().Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + c := &nfdController{} testcases := []struct { name string @@ -69,8 +79,8 @@ func TestIsNamespaceAllowed(t *testing.T) { expectedResult bool }{ { - name: "namespace not allowed", - objectNamespace: "random", + name: "namespace not selected", + objectNamespace: "random", nodeFeatureNamespaceSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { @@ -80,21 +90,22 @@ func TestIsNamespaceAllowed(t *testing.T) { }, }, }, - expectedResult: false, + expectedResult: false, }, { - name: "namespace is allowed", - objectNamespace: "fake", + name: "namespace is selected", + objectNamespace: "fake", nodeFeatureNamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"name": "fake"}, }, - expectedResult: false, + expectedResult: true, }, } for _, tc := range testcases { - c.nodeFeatureNamespaceSelector = tc.nodeFeatureNamespaceSelector - res := c.isNamespaceSelected(tc.name) + labelMap, _ := metav1.LabelSelectorAsSelector(tc.nodeFeatureNamespaceSelector) + c.namespaceLister = newNamespaceLister(fakeCli, labelMap) + res := c.isNamespaceSelected(tc.objectNamespace) assert.Equal(t, res, tc.expectedResult) } } diff --git a/pkg/nfd-master/nfd-master-internal_test.go b/pkg/nfd-master/nfd-master-internal_test.go index e6e73103e8..42504a6167 100644 --- a/pkg/nfd-master/nfd-master-internal_test.go +++ b/pkg/nfd-master/nfd-master-internal_test.go @@ -35,6 +35,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" fakeclient "k8s.io/client-go/kubernetes/fake" fakecorev1client "k8s.io/client-go/kubernetes/typed/core/v1/fake" clienttesting "k8s.io/client-go/testing" @@ -112,7 +113,7 @@ func withConfig(config *NFDConfig) NfdMasterOption { func newFakeMaster(opts ...NfdMasterOption) *nfdMaster { defaultOpts := []NfdMasterOption{ withNodeName(testNodeName), - withConfig(&NFDConfig{}), + withConfig(&NFDConfig{Restrictions: Restrictions{AllowOverwrite: true}}), WithKubernetesClient(fakeclient.NewSimpleClientset()), } m, err := NewNfdMaster(append(defaultOpts, opts...)...) @@ -513,12 +514,12 @@ func TestCreatePatches(t *testing.T) { jsonPath := "/root" Convey("When there are neither itmes to remoe nor to add or update", func() { - p := createPatches([]string{"foo", "bar"}, existingItems, map[string]string{}, jsonPath, overwriteKeys) + p := createPatches(sets.New([]string{"foo", "bar"}...), existingItems, map[string]string{}, jsonPath, overwriteKeys) So(len(p), ShouldEqual, 0) }) Convey("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, overwriteKeys) + p := createPatches(sets.New([]string{"key-2", "key-3", "foo"}...), existingItems, map[string]string{}, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("remove", jsonPath, "key-2", ""), utils.NewJsonPatch("remove", jsonPath, "key-3", ""), @@ -528,7 +529,7 @@ func TestCreatePatches(t *testing.T) { Convey("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, overwriteKeys) + p := createPatches(sets.New([]string{"key-1"}...), existingItems, newItems, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("add", jsonPath, "new-key", newItems["new-key"]), utils.NewJsonPatch("replace", jsonPath, "key-1", newItems["key-1"]), @@ -538,7 +539,7 @@ func TestCreatePatches(t *testing.T) { Convey("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, overwriteKeys) + p := createPatches(sets.New([]string{"key-1", "key-2", "key-3", "foo"}...), existingItems, newItems, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("add", jsonPath, "new-key", newItems["new-key"]), utils.NewJsonPatch("add", jsonPath, "key-4", newItems["key-4"]), @@ -552,9 +553,10 @@ func TestCreatePatches(t *testing.T) { Convey("When overwrite of keys is denied and there is already an existant key", func() { overwriteKeys = false newItems := map[string]string{"key-1": "new-2", "key-4": "val-4"} - p := createPatches([]string{}, existingItems, newItems, jsonPath, overwriteKeys) + p := createPatches(sets.New([]string{}...), existingItems, newItems, jsonPath, overwriteKeys) expected := []utils.JsonPatch{ utils.NewJsonPatch("add", jsonPath, "key-4", newItems["key-4"]), + utils.NewJsonPatch("replace", jsonPath, "key-1", newItems["key-1"]), } So(sortJsonPatches(p), ShouldResemble, sortJsonPatches(expected)) }) @@ -907,60 +909,3 @@ func TestGetDynamicValue(t *testing.T) { }) } } - -func TestFilterTaints(t *testing.T) { - testcases := []struct { - name string - taints []corev1.Taint - maxTaints int - expectedResult []corev1.Taint - }{ - { - name: "no restriction on the number of taints", - taints: []corev1.Taint{ - { - Key: "feature.node.kubernetes.io/key1", - Value: "dummy", - Effect: corev1.TaintEffectNoSchedule, - }, - }, - maxTaints: 0, - expectedResult: []corev1.Taint{ - { - Key: "feature.node.kubernetes.io/key1", - Value: "dummy", - Effect: corev1.TaintEffectNoSchedule, - }, - }, - }, - { - name: "max of 1 Taint should be generated", - taints: []corev1.Taint{ - { - Key: "feature.node.kubernetes.io/key1", - Value: "dummy", - Effect: corev1.TaintEffectNoSchedule, - }, - { - Key: "feature.node.kubernetes.io/key2", - Value: "dummy", - Effect: corev1.TaintEffectNoSchedule, - }, - }, - maxTaints: 1, - expectedResult: []corev1.Taint{}, - }, - } - - mockMaster := newFakeMaster(nil) - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - mockMaster.config.Restrictions.MaxTaintsPerCR = tc.maxTaints - res := mockMaster.filterTaints(tc.taints) - Convey("The expected number of taints should be correct", t, func() { - So(len(res), ShouldEqual, len(tc.expectedResult)) - }) - }) - } -} diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index b95685b3b9..4a21ca3b5c 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -45,14 +45,13 @@ import ( "k8s.io/apimachinery/pkg/labels" k8sLabels "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" k8sclient "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" "k8s.io/klog/v2" controller "k8s.io/kubernetes/pkg/controller" - klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" - taintutils "k8s.io/kubernetes/pkg/util/taints" "sigs.k8s.io/yaml" @@ -63,6 +62,7 @@ import ( nfdfeatures "sigs.k8s.io/node-feature-discovery/pkg/features" pb "sigs.k8s.io/node-feature-discovery/pkg/labeler" "sigs.k8s.io/node-feature-discovery/pkg/utils" + klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" "sigs.k8s.io/node-feature-discovery/pkg/version" ) @@ -77,12 +77,12 @@ type Annotations map[string]string // Restrictions contains the restrictions on the NF and NFR Crs type Restrictions struct { - AllowedNamespaces *metav1.LabelSelector - MaxLabelsPerCR int - MaxTaintsPerCR int - MaxExtendedResourcesPerCR int - DenyNodeFeatureLabels bool - OverwriteLabels bool + NodeFeatureNamespaceSelector *metav1.LabelSelector + DisableLabels bool + DisableExtendedResources bool + DisableAnnotations bool + DenyNodeFeatureLabels bool + AllowOverwrite bool } // NFDConfig contains the configuration settings of NfdMaster. @@ -285,11 +285,11 @@ func newDefaultConfig() *NFDConfig { }, Klog: make(map[string]string), Restrictions: Restrictions{ - MaxLabelsPerCR: 0, - MaxTaintsPerCR: 0, - MaxExtendedResourcesPerCR: 0, - OverwriteLabels: true, - DenyNodeFeatureLabels: false, + DisableLabels: false, + DisableExtendedResources: false, + DisableAnnotations: false, + AllowOverwrite: true, + DenyNodeFeatureLabels: false, }, } } @@ -635,10 +635,10 @@ func (m *nfdMaster) updateMasterNode() error { } // Advertise NFD version as an annotation - p := createPatches([]string{m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation)}, + p := createPatches(sets.New([]string{m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation)}...), node.Annotations, nil, - "/metadata/annotations", true) + "/metadata/annotations", m.config.Restrictions.AllowOverwrite) err = patchNode(m.k8sClient, node.Name, p) if err != nil { @@ -679,8 +679,8 @@ func (m *nfdMaster) filterFeatureLabels(labels Labels, features *nfdv1alpha1.Fea } } - if m.config.Restrictions.MaxLabelsPerCR > 0 && len(outLabels) > m.config.Restrictions.MaxLabelsPerCR { - klog.InfoS("number of labels in the request exceeds the restriction maximum labels per CR, skipping") + if len(outLabels) > 0 && m.config.Restrictions.DisableLabels { + klog.V(2).InfoS("node labels are disabled in configuration (restrictions.disableLabels=true)") outLabels = Labels{} } @@ -738,7 +738,7 @@ func getDynamicValue(value string, features *nfdv1alpha1.Features) (string, erro return element, nil } -func (m *nfdMaster) filterTaints(taints []corev1.Taint) []corev1.Taint { +func filterTaints(taints []corev1.Taint) []corev1.Taint { outTaints := []corev1.Taint{} for _, taint := range taints { @@ -750,11 +750,6 @@ func (m *nfdMaster) filterTaints(taints []corev1.Taint) []corev1.Taint { } } - if m.config.Restrictions.MaxTaintsPerCR > 0 && len(taints) > m.config.Restrictions.MaxTaintsPerCR { - klog.InfoS("number of taints in the request exceeds the restriction maximum taints per CR, skipping") - outTaints = []corev1.Taint{} - } - return outTaints } @@ -846,42 +841,62 @@ func (m *nfdMaster) getAndMergeNodeFeatures(nodeName string) (*nfdv1alpha1.NodeF return &nfdv1alpha1.NodeFeature{}, fmt.Errorf("failed to get NodeFeature resources for node %q: %w", nodeName, err) } + filteredObjs := []*nfdv1alpha1.NodeFeature{} + for _, obj := range objs { + if m.isNamespaceSelected(obj.Namespace) { + filteredObjs = append(filteredObjs, obj) + } + } + // Node without a running NFD-Worker - if len(objs) == 0 { + if len(filteredObjs) == 0 { return &nfdv1alpha1.NodeFeature{}, nil } // Sort our objects - sort.Slice(objs, func(i, j int) bool { + sort.Slice(filteredObjs, func(i, j int) bool { // Objects in our nfd namespace gets into the beginning of the list - if objs[i].Namespace == m.namespace && objs[j].Namespace != m.namespace { + if filteredObjs[i].Namespace == m.namespace && filteredObjs[j].Namespace != m.namespace { return true } - if objs[i].Namespace != m.namespace && objs[j].Namespace == m.namespace { + if filteredObjs[i].Namespace != m.namespace && filteredObjs[j].Namespace == m.namespace { return false } // After the nfd namespace, sort objects by their name - if objs[i].Name != objs[j].Name { - return objs[i].Name < objs[j].Name + if filteredObjs[i].Name != filteredObjs[j].Name { + return filteredObjs[i].Name < filteredObjs[j].Name } // Objects with the same name are sorted by their namespace - return objs[i].Namespace < objs[j].Namespace + return filteredObjs[i].Namespace < filteredObjs[j].Namespace }) - if len(objs) > 0 { + if len(filteredObjs) > 0 { // Merge in features // // NOTE: changing the rule api to support handle multiple objects instead // of merging would probably perform better with lot less data to copy. - features := objs[0].Spec.DeepCopy() + features := filteredObjs[0].Spec.DeepCopy() + + if m.config.Restrictions.DenyNodeFeatureLabels && m.isThirdPartyNodeFeature(*filteredObjs[0], nodeName, m.namespace) { + klog.V(2).InfoS("node feature labels are disabled in configuration (restrictions.denyNodeFeatureLabels=true)") + features.Labels = nil + } + if !nfdfeatures.NFDFeatureGate.Enabled(nfdfeatures.DisableAutoPrefix) && m.config.AutoDefaultNs { features.Labels = addNsToMapKeys(features.Labels, nfdv1alpha1.FeatureLabelNs) } - for _, o := range objs[1:] { + + for _, o := range filteredObjs[1:] { s := o.Spec.DeepCopy() + if m.config.Restrictions.DenyNodeFeatureLabels && m.isThirdPartyNodeFeature(*o, nodeName, m.namespace) { + klog.V(2).InfoS("node feature labels are disabled in configuration (restrictions.denyNodeFeatureLabels=true)") + s.Labels = nil + } + if !nfdfeatures.NFDFeatureGate.Enabled(nfdfeatures.DisableAutoPrefix) && m.config.AutoDefaultNs { s.Labels = addNsToMapKeys(s.Labels, nfdv1alpha1.FeatureLabelNs) } + s.MergeInto(features) } @@ -894,6 +909,11 @@ func (m *nfdMaster) getAndMergeNodeFeatures(nodeName string) (*nfdv1alpha1.NodeF return nodeFeatures, nil } +// isThirdPartyNodeFeature determines whether a node feature is a third party one or created by nfd-worker +func (m *nfdMaster) isThirdPartyNodeFeature(nodeFeature nfdv1alpha1.NodeFeature, nodeName, namespace string) bool { + return nodeFeature.Namespace != namespace || nodeFeature.Name != nodeName +} + func (m *nfdMaster) nfdAPIUpdateOneNode(cli k8sclient.Interface, node *corev1.Node) error { if m.nfdController == nil || m.nfdController.featureLister == nil { return nil @@ -1060,8 +1080,8 @@ func (m *nfdMaster) refreshNodeFeatures(cli k8sclient.Interface, node *corev1.No maps.Copy(extendedResources, crExtendedResources) extendedResources = m.filterExtendedResources(features, extendedResources) - if m.config.Restrictions.MaxExtendedResourcesPerCR > 0 && len(extendedResources) > m.config.Restrictions.MaxExtendedResourcesPerCR { - klog.InfoS("number of extended resources in the request exceeds the restriction maximum extended resources per CR, skipping") + if len(extendedResources) > 0 && m.config.Restrictions.DisableExtendedResources { + klog.V(2).InfoS("extended resources are disabled in configuration (restrictions.disableExtendedResources=true)") extendedResources = map[string]string{} } @@ -1071,13 +1091,7 @@ func (m *nfdMaster) refreshNodeFeatures(cli k8sclient.Interface, node *corev1.No // Taints var taints []corev1.Taint if m.config.EnableTaints { - taints = m.filterTaints(crTaints) - } - - // If we deny node feature labels, we'll empty the labels variable - if m.config.Restrictions.DenyNodeFeatureLabels { - klog.InfoS("node feature labels are denied, skipping...") - labels = map[string]string{} + taints = filterTaints(crTaints) } if m.config.NoPublish { @@ -1097,8 +1111,8 @@ func (m *nfdMaster) refreshNodeFeatures(cli k8sclient.Interface, node *corev1.No // setTaints sets node taints and annotations based on the taints passed via // nodeFeatureRule custom resorce. If empty list of taints is passed, currently // NFD owned taints and annotations are removed from the node. -func setTaints(cli k8sclient.Interface, taints []corev1.Taint, node *corev1.Node) error { - // De-serialize the taints annotation into corev1.Taint type for comparison below. +func (m *nfdMaster) setTaints(cli k8sclient.Interface, taints []corev1.Taint, node *corev1.Node) error { + // De-serialize the taints annotation into corev1.Taint type for comparision below. var err error oldTaints := []corev1.Taint{} if val, ok := node.Annotations[nfdv1alpha1.NodeTaintsAnnotation]; ok { @@ -1154,7 +1168,11 @@ func setTaints(cli k8sclient.Interface, taints []corev1.Taint, node *corev1.Node newAnnotations[nfdv1alpha1.NodeTaintsAnnotation] = strings.Join(taintStrs, ",") } - patches := createPatches([]string{nfdv1alpha1.NodeTaintsAnnotation}, node.Annotations, newAnnotations, "/metadata/annotations", true) + patches := createPatches(sets.New([]string{nfdv1alpha1.NodeTaintsAnnotation}...), + node.Annotations, newAnnotations, + "/metadata/annotations", + m.config.Restrictions.AllowOverwrite, + ) if len(patches) > 0 { if err := patchNode(cli, node.Name, patches); err != nil { return fmt.Errorf("error while patching node object: %w", err) @@ -1294,7 +1312,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, // Create JSON patches for changes in labels and annotations oldLabels := stringToNsNames(node.Annotations[m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation)], nfdv1alpha1.FeatureLabelNs) oldAnnotations := stringToNsNames(node.Annotations[m.instanceAnnotation(nfdv1alpha1.FeatureAnnotationsTrackingAnnotation)], nfdv1alpha1.FeatureAnnotationNs) - patches := createPatches(oldLabels, node.Labels, labels, "/metadata/labels", m.config.Restrictions.OverwriteLabels) + patches := createPatches(sets.New(oldLabels...), node.Labels, labels, "/metadata/labels", m.config.Restrictions.AllowOverwrite) oldAnnotations = append(oldAnnotations, []string{ m.instanceAnnotation(nfdv1alpha1.FeatureLabelsAnnotation), m.instanceAnnotation(nfdv1alpha1.ExtendedResourceAnnotation), @@ -1302,7 +1320,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, // Clean up deprecated/stale nfd version annotations m.instanceAnnotation(nfdv1alpha1.MasterVersionAnnotation), m.instanceAnnotation(nfdv1alpha1.WorkerVersionAnnotation)}...) - patches = append(patches, createPatches(oldAnnotations, node.Annotations, annotations, "/metadata/annotations", true)...) + patches = append(patches, createPatches(sets.New(oldAnnotations...), node.Annotations, annotations, "/metadata/annotations", m.config.Restrictions.AllowOverwrite)...) // patch node status with extended resource changes statusPatches := m.createExtendedResourcePatches(node, extendedResources) @@ -1325,7 +1343,7 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, } // Set taints - err = setTaints(cli, taints, node) + err = m.setTaints(cli, taints, node) if err != nil { return err } @@ -1334,11 +1352,11 @@ func (m *nfdMaster) updateNodeObject(cli k8sclient.Interface, node *corev1.Node, } // createPatches is a generic helper that returns json patch operations to perform -func createPatches(removeKeys []string, oldItems map[string]string, newItems map[string]string, jsonPath string, overwrite bool) []utils.JsonPatch { +func createPatches(removeKeys sets.Set[string], oldItems map[string]string, newItems map[string]string, jsonPath string, overwrite bool) []utils.JsonPatch { patches := []utils.JsonPatch{} // Determine items to remove - for _, key := range removeKeys { + for key := range removeKeys { if _, ok := oldItems[key]; ok { if _, ok := newItems[key]; !ok { patches = append(patches, utils.NewJsonPatch("remove", jsonPath, key, "")) @@ -1349,7 +1367,7 @@ func createPatches(removeKeys []string, oldItems map[string]string, newItems map // Determine items to add or replace for key, newVal := range newItems { if oldVal, ok := oldItems[key]; ok { - if newVal != oldVal && overwrite { + if newVal != oldVal && (!removeKeys.Has(key) || overwrite) { patches = append(patches, utils.NewJsonPatch("replace", jsonPath, key, newVal)) } } else { @@ -1554,7 +1572,7 @@ func (m *nfdMaster) startNfdApiController() error { DisableNodeFeature: !nfdfeatures.NFDFeatureGate.Enabled(nfdfeatures.NodeFeatureAPI), ResyncPeriod: m.config.ResyncPeriod.Duration, K8sClient: m.k8sClient, - NodeFeatureNamespaceSelector: m.config.Restrictions.AllowedNamespaces, + NodeFeatureNamespaceSelector: m.config.Restrictions.NodeFeatureNamespaceSelector, }) if err != nil { return fmt.Errorf("failed to initialize CRD controller: %w", err) @@ -1615,6 +1633,12 @@ func (m *nfdMaster) filterFeatureAnnotations(annotations map[string]string) map[ outAnnotations[annotation] = value } + + if len(outAnnotations) > 0 && m.config.Restrictions.DisableAnnotations { + klog.V(2).InfoS("node annotations are disabled in configuration (restrictions.disableAnnotations=true)") + outAnnotations = map[string]string{} + } + return outAnnotations } diff --git a/test/e2e/data/nodefeaturerule-6.yaml b/test/e2e/data/nodefeaturerule-6.yaml new file mode 100644 index 0000000000..d9dcb38367 --- /dev/null +++ b/test/e2e/data/nodefeaturerule-6.yaml @@ -0,0 +1,18 @@ +apiVersion: nfd.k8s-sigs.io/v1alpha1 +kind: NodeFeatureRule +metadata: + name: e2e-test-6 +spec: + rules: + - name: "e2e-restrictions-test-1" + taints: + - effect: PreferNoSchedule + key: "feature.node.kubernetes.io/fake-special-cpu" + value: "true" + labels: + e2e.feature.node.kubernetes.io/restricted-label-1: "true" + annotations: + e2e.feature.node.kubernetes.io/restricted-annoation-1: "yes" + extendedResources: + e2e.feature.node.kubernetes.io/restricted-er-1: "2" + matchFeatures: diff --git a/test/e2e/node_feature_discovery_test.go b/test/e2e/node_feature_discovery_test.go index dd692ce76c..affd9d22b0 100644 --- a/test/e2e/node_feature_discovery_test.go +++ b/test/e2e/node_feature_discovery_test.go @@ -28,7 +28,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" @@ -853,227 +852,6 @@ core: } eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchLabels(expectedLabels, nodes)) }) - - Context("allowed namespaces restriction is respected or not", func() { - BeforeEach(func(ctx context.Context) { - extraMasterPodSpecOpts = []testpod.SpecOption{ - testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), - } - cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` -restrictions: - allowedNamespaces: - matchLabels: - kubernetes.io/metadata.name: "fake" -`) - _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - It("Nothing should be created", func(ctx context.Context) { - // deploy node feature object - if !useNodeFeatureApi { - Skip("NodeFeature API not enabled") - } - - nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) - Expect(err).NotTo(HaveOccurred()) - - targetNodeName := nodes[0].Name - Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") - - // Apply Node Feature object - By("Creating NodeFeature object") - nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) - Expect(err).NotTo(HaveOccurred()) - - By("Verifying node labels from NodeFeature object #1 are not created") - // No labels should be created since the f.Namespace is not in the allowed Namespaces - expectedLabels := map[string]k8sLabels{} - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) - - By("Deleting NodeFeature object") - err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - }) - - Context("max labels, taints restrictions should be respected", func() { - BeforeEach(func(ctx context.Context) { - extraMasterPodSpecOpts = []testpod.SpecOption{ - testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), - } - cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` -enableTaints: true -restrictions: - maxLabelsPerCR: 1 - maxTaintsPerCR: 1 -`) - _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - It("No labels or taints should be created", func(ctx context.Context) { - nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) - Expect(err).NotTo(HaveOccurred()) - - targetNodeName := nodes[0].Name - Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") - - By("Creating nfd-worker config") - cm := testutils.NewConfigMap("nfd-worker-conf", "nfd-worker.conf", ` -core: - sleepInterval: "1s" - featureSources: ["fake"] - labelSources: [] -`) - cm, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - By("Creating nfd-worker daemonset") - podSpecOpts := createPodSpecOpts( - testpod.SpecWithContainerImage(dockerImage()), - testpod.SpecWithConfigMap(cm.Name, "/etc/kubernetes/node-feature-discovery"), - ) - workerDS := testds.NFDWorker(podSpecOpts...) - workerDS, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ctx, workerDS, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - - By("Waiting for worker daemonset pods to be ready") - Expect(testpod.WaitForReady(ctx, f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 2)).NotTo(HaveOccurred()) - - // Add features from NodeFeatureRule #3 - By("Creating NodeFeatureRules #3") - Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-3.yaml")).NotTo(HaveOccurred()) - - By("Verifying node taints and annotation from NodeFeatureRules #3") - expectedLabels := map[string]k8sLabels{} - - expectedTaints := map[string][]corev1.Taint{} - - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) - - By("Deleting NodeFeatureRule #3") - err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-test-3", metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) - By("Verifying taints from NodeFeatureRules #3 were removed") - expectedTaints["*"] = []corev1.Taint{} - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) - }) - }) - - Context("max extended resources restriction should be respected", func() { - BeforeEach(func(ctx context.Context) { - extraMasterPodSpecOpts = []testpod.SpecOption{ - testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), - } - cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` -restrictions: - maxExtendedResourcesPerCR: 1 -`) - _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - It("Nothing should be created", func(ctx context.Context) { - nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) - Expect(err).NotTo(HaveOccurred()) - - targetNodeName := nodes[0].Name - Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") - - By("Creating nfd-worker config") - cm := testutils.NewConfigMap("nfd-worker-conf", "nfd-worker.conf", ` -core: - sleepInterval: "1s" - featureSources: ["fake"] - labelSources: [] -`) - cm, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - By("Creating nfd-worker daemonset") - podSpecOpts := createPodSpecOpts( - testpod.SpecWithContainerImage(dockerImage()), - testpod.SpecWithConfigMap(cm.Name, "/etc/kubernetes/node-feature-discovery"), - ) - workerDS := testds.NFDWorker(podSpecOpts...) - workerDS, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ctx, workerDS, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - - By("Waiting for worker daemonset pods to be ready") - Expect(testpod.WaitForReady(ctx, f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 2)).NotTo(HaveOccurred()) - - expectedAnnotations := map[string]k8sAnnotations{ - "*": {}, - } - expectedCapacity := map[string]corev1.ResourceList{ - "*": {}, - } - - By("Creating NodeFeatureRules #4") - Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-4.yaml")).NotTo(HaveOccurred()) - - By("Verifying node annotations from NodeFeatureRules #4") - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes)) - - By("Verifying node status capacity from NodeFeatureRules #4") - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes)) - - By("Deleting NodeFeatureRules #4") - err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-extened-resource-test", metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) - - By("Deleting nfd-worker daemonset") - err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Delete(ctx, workerDS.Name, metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) - - if useNodeFeatureApi { - By("Verify that labels from nfd-worker are garbage-collected") - expectedLabels := map[string]k8sLabels{ - "*": {}, - } - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchLabels(expectedLabels, nodes)) - } - }) - }) - - Context("deny node feature labels restriction should be respected", func() { - BeforeEach(func(ctx context.Context) { - extraMasterPodSpecOpts = []testpod.SpecOption{ - testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), - } - cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` -restrictions: - denyNodeFeatureLabels: true -`) - _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - It("No labels should be created", func(ctx context.Context) { - // deploy node feature object - if !useNodeFeatureApi { - Skip("NodeFeature API not enabled") - } - - nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) - Expect(err).NotTo(HaveOccurred()) - - targetNodeName := nodes[0].Name - Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") - - // Apply Node Feature object - By("Creating NodeFeature object") - nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) - Expect(err).NotTo(HaveOccurred()) - - By("Verifying node labels from NodeFeature object #1 are not created") - - expectedLabels := map[string]k8sLabels{ - "*": {}, - } - eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) - - By("Deleting NodeFeature object") - err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) - }) - }) }) // Test NodeFeatureGroups @@ -1239,6 +1017,282 @@ resyncPeriod: "1s" Expect(err).NotTo(HaveOccurred()) }) }) + + Context("selected namespaces restriction is respected or not", Label("restrictions"), func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + nodeFeatureNamespaceSelector: + matchLabels: + e2etest: fake + +resyncPeriod: "1s" +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("Nothing should be created", func(ctx context.Context) { + // deploy node feature object + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + // label the namespace in which node feature object is created + // TODO(TessaIO): add a utility for this. + patches, err := json.Marshal( + []utils.JsonPatch{ + utils.NewJsonPatch( + "add", + "/metadata/labels", + "e2etest", + "fake", + ), + }, + ) + Expect(err).NotTo(HaveOccurred()) + + _, err = f.ClientSet.CoreV1().Namespaces().Patch(ctx, f.Namespace.Name, types.JSONPatchType, patches, metav1.PatchOptions{}) + Expect(err).NotTo(HaveOccurred()) + + // Apply Node Feature object + By("Creating NodeFeature object") + nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) + Expect(err).NotTo(HaveOccurred()) + + By("Verifying node labels from NodeFeature object #1 are created") + // No labels should be created since the f.Namespace is not in the selected Namespaces + expectedLabels := map[string]k8sLabels{ + targetNodeName: { + nfdv1alpha1.FeatureLabelNs + "/e2e-nodefeature-test-1": "obj-1", + nfdv1alpha1.FeatureLabelNs + "/e2e-nodefeature-test-2": "obj-1", + nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature3": "overridden", + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + // remove label the namespace in which node feature object is created + patches, err = json.Marshal( + []utils.JsonPatch{ + utils.NewJsonPatch( + "remove", + "/metadata/labels", + "e2etest", + "fake", + ), + }, + ) + Expect(err).NotTo(HaveOccurred()) + + _, err = f.ClientSet.CoreV1().Namespaces().Patch(ctx, f.Namespace.Name, types.JSONPatchType, patches, metav1.PatchOptions{}) + Expect(err).NotTo(HaveOccurred()) + By("Verifying node labels from NodeFeature object #1 are not created") + // No labels should be created since the f.Namespace is not in the selected Namespaces + expectedLabels = map[string]k8sLabels{ + targetNodeName: {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Deleting NodeFeature object") + err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + }) + + Context("disable labels restrictions should be respected", Label("restrictions"), func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + testpod.SpecWithContainerExtraArgs("-enable-taints"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + disableLabels: true +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("No labels should be created", func(ctx context.Context) { + // deploy node feature object + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + // Add features from NodeFeatureRule #6 + By("Creating NodeFeatureRules #6") + Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-6.yaml")).NotTo(HaveOccurred()) + + By("Verifying node taints, annotations, ERs and labels from NodeFeatureRules #6") + expectedTaints := map[string][]corev1.Taint{ + "*": { + { + Key: "feature.node.kubernetes.io/fake-special-cpu", + Value: "true", + Effect: "PreferNoSchedule", + }, + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) + + expectedAnnotations := map[string]k8sAnnotations{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-annoation-1": "yes", + "nfd.node.kubernetes.io/feature-annotations": "e2e.feature.node.kubernetes.io/restricted-annoation-1", + "nfd.node.kubernetes.io/extended-resources": "e2e.feature.node.kubernetes.io/restricted-er-1", + "nfd.node.kubernetes.io/taints": "feature.node.kubernetes.io/fake-special-cpu=true:PreferNoSchedule", + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes)) + + expectedCapacity := map[string]corev1.ResourceList{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-er-1": resourcev1.MustParse("2"), + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes)) + + expectedLabels := map[string]k8sLabels{ + "*": {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Deleting NodeFeatureRule #6") + err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-test-6", metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + }) + + Context("disable extended resources restriction should be respected", Label("restrictions"), func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + disableExtendedResources: true +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("Extended resources should not be created and Labels should be created", func(ctx context.Context) { + // deploy node feature object + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + expectedAnnotations := map[string]k8sAnnotations{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-annoation-1": "yes", + "nfd.node.kubernetes.io/feature-annotations": "e2e.feature.node.kubernetes.io/restricted-annoation-1", + "nfd.node.kubernetes.io/feature-labels": "e2e.feature.node.kubernetes.io/restricted-label-1", + }, + } + expectedCapacity := map[string]corev1.ResourceList{ + "*": {}, + } + + expectedLabels := map[string]k8sLabels{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-label-1": "true", + }, + } + + By("Creating NodeFeatureRules #6") + Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-6.yaml")).NotTo(HaveOccurred()) + + By("Verifying node labels from NodeFeatureRules #6") + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Verifying node annotations from NodeFeatureRules #6") + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes)) + + By("Verifying node status capacity from NodeFeatureRules #6") + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes)) + + By("Deleting NodeFeatureRules #6") + err = nfdClient.NfdV1alpha1().NodeFeatureRules().Delete(ctx, "e2e-test-6", metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + + By("Verify that labels from nfd-worker are garbage-collected") + expectedLabels = map[string]k8sLabels{ + "*": {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchLabels(expectedLabels, nodes)) + }) + }) + + Context("deny node feature labels restriction should be respected", Label("restrictions"), func() { + BeforeEach(func(ctx context.Context) { + extraMasterPodSpecOpts = []testpod.SpecOption{ + testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"), + } + cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", ` +restrictions: + denyNodeFeatureLabels: true +`) + _, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + It("No feature labels should be created", func(ctx context.Context) { + // deploy node feature object + nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet) + Expect(err).NotTo(HaveOccurred()) + + targetNodeName := nodes[0].Name + Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found") + + // Apply Node Feature object + By("Creating NodeFeature object") + nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName) + Expect(err).NotTo(HaveOccurred()) + + // Add features from NodeFeatureRule #6 + By("Creating NodeFeatureRules #6") + Expect(testutils.CreateNodeFeatureRulesFromFile(ctx, nfdClient, "nodefeaturerule-6.yaml")).NotTo(HaveOccurred()) + + By("Verifying node taints and labels from NodeFeatureRules #6") + expectedTaints := map[string][]corev1.Taint{ + "*": {}, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchTaints(expectedTaints, nodes)) + + expectedAnnotations := map[string]k8sAnnotations{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-annoation-1": "yes", + "nfd.node.kubernetes.io/feature-annotations": "e2e.feature.node.kubernetes.io/restricted-annoation-1", + "nfd.node.kubernetes.io/extended-resources": "e2e.feature.node.kubernetes.io/restricted-er-1", + "nfd.node.kubernetes.io/feature-labels": "e2e.feature.node.kubernetes.io/restricted-label-1", + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes)) + + expectedCapacity := map[string]corev1.ResourceList{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-er-1": resourcev1.MustParse("2"), + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes)) + + // TODO(TessaIO): we need one more test where we deploy nfd-worker that would create + // a non 3rd-party NF that shouldn't be ignored by this restriction + By("Verifying node labels from NodeFeature object #6 are not created") + expectedLabels := map[string]k8sLabels{ + "*": { + "e2e.feature.node.kubernetes.io/restricted-label-1": "true", + }, + } + eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + + By("Deleting NodeFeature object") + err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + }) }) }) diff --git a/test/e2e/utils/rbac.go b/test/e2e/utils/rbac.go index 67470e331d..5e57fe4ecb 100644 --- a/test/e2e/utils/rbac.go +++ b/test/e2e/utils/rbac.go @@ -176,6 +176,11 @@ func createClusterRoleMaster(ctx context.Context, cs clientset.Interface) (*rbac Name: "nfd-master-e2e", }, Rules: []rbacv1.PolicyRule{ + { + APIGroups: []string{""}, + Resources: []string{"namespaces"}, + Verbs: []string{"list", "watch"}, + }, { APIGroups: []string{""}, Resources: []string{"nodes", "nodes/status"}, From 901fbe2866b342913bc015fc020659f0d185d4f1 Mon Sep 17 00:00:00 2001 From: Tobias Giese Date: Fri, 18 Oct 2024 11:36:46 +0200 Subject: [PATCH 4/8] Format helm.md Signed-off-by: Tobias Giese --- docs/deployment/helm.md | 291 +++++++++++++++++++++------------------- 1 file changed, 153 insertions(+), 138 deletions(-) diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md index 9ac221f160..8a17ff5982 100644 --- a/docs/deployment/helm.md +++ b/docs/deployment/helm.md @@ -5,9 +5,11 @@ sort: 3 --- # Deployment with Helm + {: .no_toc} ## Table of contents + {: .no_toc .text-delta} 1. TOC @@ -71,7 +73,8 @@ To upgrade the `node-feature-discovery` deployment to {{ site.release }} via Hel ### From v0.7 and older -Please see the [uninstallation guide](https://kubernetes-sigs.github.io/node-feature-discovery/v0.7/get-started/deployment-and-usage.html#uninstallation). +Please see +the [uninstallation guide](https://kubernetes-sigs.github.io/node-feature-discovery/v0.7/get-started/deployment-and-usage.html#uninstallation). And then follow the standard [deployment instructions](#deployment). ### From v0.8 - v0.11 @@ -147,25 +150,25 @@ Chart parameters are available. ### General parameters -| Name | Type | Default | Description | -| --------------------------------------------------- | ------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `image.repository` | string | `{{ site.container_image \| split: ":" \| first }}` | NFD image repository | -| `image.tag` | string | `{{ site.release }}` | NFD image tag | -| `image.pullPolicy` | string | `Always` | Image pull policy | -| `imagePullSecrets` | array | [] | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. [More info](https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod). | -| `nameOverride` | string | | Override the name of the chart | -| `fullnameOverride` | string | | Override a default fully qualified app name | -| `tls.enable` | bool | false | Specifies whether to use TLS for communications between components. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release. | -| `tls.certManager` | bool | false | If enabled, requires [cert-manager](https://cert-manager.io/docs/) to be installed and will automatically create the required TLS certificates. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `tls.certManager.certManagerCertificate.issuerName` | string | | If specified, it will use a pre-existing issuer instead for the required TLS certificates. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release. | +| Name | Type | Default | Description | +|-----------------------------------------------------|--------|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `image.repository` | string | `{{ site.container_image \| split: ":" \| first }}` | NFD image repository | +| `image.tag` | string | `{{ site.release }}` | NFD image tag | +| `image.pullPolicy` | string | `Always` | Image pull policy | +| `imagePullSecrets` | array | [] | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. [More info](https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod). | +| `nameOverride` | string | | Override the name of the chart | +| `fullnameOverride` | string | | Override a default fully qualified app name | +| `tls.enable` | bool | false | Specifies whether to use TLS for communications between components. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release. | +| `tls.certManager` | bool | false | If enabled, requires [cert-manager](https://cert-manager.io/docs/) to be installed and will automatically create the required TLS certificates. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `tls.certManager.certManagerCertificate.issuerName` | string | | If specified, it will use a pre-existing issuer instead for the required TLS certificates. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release. | | `tls.certManager.certManagerCertificate.issuerKind` | string | | Specifies on what kind of issuer is used, can be either ClusterIssuer or Issuer (default). Requires `tls.certManager.certManagerCertificate.issuerName` to be set. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `featureGates.NodeFeatureAPI` | bool | true | Enable the [NodeFeature](../usage/custom-resources.md#nodefeature) CRD API for communicating node features. This will automatically disable the gRPC communication. | -| `featureGates.NodeFeatureGroupAPI` | bool | false | Enable the [NodeFeatureGroup](../usage/custom-resources.md#nodefeaturegroup) CRD API. | -| `featureGates.DisableAutoPrefix` | bool | false | Enable [DisableAutoPrefix](../reference/feature-gates.md#disableautoprefix) feature gate. Disables automatic prefixing of unprefixed labels, annotations and extended resources. | -| `prometheus.enable` | bool | false | Specifies whether to expose metrics using prometheus operator | -| `prometheus.labels` | dict | {} | Specifies labels for use with the prometheus operator to control how it is selected | -| `prometheus.scrapeInterval` | string | 10s | Specifies the interval by which metrics are scraped | -| `priorityClassName` | string | | The name of the PriorityClass to be used for the NFD pods. | +| `featureGates.NodeFeatureAPI` | bool | true | Enable the [NodeFeature](../usage/custom-resources.md#nodefeature) CRD API for communicating node features. This will automatically disable the gRPC communication. | +| `featureGates.NodeFeatureGroupAPI` | bool | false | Enable the [NodeFeatureGroup](../usage/custom-resources.md#nodefeaturegroup) CRD API. | +| `featureGates.DisableAutoPrefix` | bool | false | Enable [DisableAutoPrefix](../reference/feature-gates.md#disableautoprefix) feature gate. Disables automatic prefixing of unprefixed labels, annotations and extended resources. | +| `prometheus.enable` | bool | false | Specifies whether to expose metrics using prometheus operator | +| `prometheus.labels` | dict | {} | Specifies labels for use with the prometheus operator to control how it is selected | +| `prometheus.scrapeInterval` | string | 10s | Specifies the interval by which metrics are scraped | +| `priorityClassName` | string | | The name of the PriorityClass to be used for the NFD pods. | Metrics are configured to be exposed using prometheus operator API's by default. If you want to expose metrics using the prometheus operator @@ -173,134 +176,146 @@ API's you need to install the prometheus operator in your cluster. ### Master pod parameters -| Name | Type | Default | Description | -| ----------------------------------- | ------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `master.*` | dict | | NFD master deployment configuration | -| `master.enable` | bool | true | Specifies whether nfd-master should be deployed | -| `master.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `master.port` | integer | | Specifies the TCP port that nfd-master listens for incoming requests. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.metricsPort` | integer | 8081 | Port on which to expose metrics from components to prometheus operator | -| `master.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | -| `master.instance` | string | | Instance name. Used to separate annotation namespaces for multiple parallel deployments | -| `master.resyncPeriod` | string | | NFD API controller resync period. | -| `master.extraLabelNs` | array | [] | List of allowed extra label namespaces | -| `master.resourceLabels` | array | [] | List of labels to be registered as extended resources | -| `master.enableTaints` | bool | false | Specifies whether to enable or disable node tainting | -| `master.crdController` | bool | null | Specifies whether the NFD CRD API controller is enabled. If not set, controller will be enabled if `master.instance` is empty. | -| `master.featureRulesController` | bool | null | DEPRECATED: use `master.crdController` instead | -| `master.replicaCount` | integer | 1 | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified | -| `master.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | -| `master.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `master.serviceAccount.create` | bool | true | Specifies whether a service account should be created | -| `master.serviceAccount.annotations` | dict | {} | Annotations to add to the service account | -| `master.serviceAccount.name` | string | | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | -| `master.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-master | -| `master.service.type` | string | ClusterIP | NFD master service type. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.service.port` | integer | 8080 | NFD master service port. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.resources.limits` | dict | {memory: 4Gi} | NFD master pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `master.resources.requests` | dict | {cpu: 100m, memory: 128Mi} | NFD master pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits). You may want to use the same value for `requests.memory` and `limits.memory`. The “requests” value affects scheduling to accommodate pods on nodes. If there is a large difference between “requests” and “limits” and nodes experience memory pressure, the kernel may invoke the OOM Killer, even if the memory does not exceed the “limits” threshold. This can cause unexpected pod evictions. Memory cannot be compressed and once allocated to a pod, it can only be reclaimed by killing the pod. [Natan Yellin 22/09/2022](https://home.robusta.dev/blog/kubernetes-memory-limit) that discusses this issue. | -| `master.tolerations` | dict | _Schedule to control-plane node_ | NFD master pod [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `master.annotations` | dict | {} | NFD master pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `master.affinity` | dict | | NFD master pod required [node affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | -| `master.deploymentAnnotations` | dict | {} | NFD master deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `master.nfdApiParallelism` | integer | 10 | Specifies the maximum number of concurrent node updates. | -| `master.config` | dict | | NFD master [configuration](../reference/master-configuration-reference) | -| `master.extraArgs` | array | [] | Additional [command line arguments](../reference/master-commandline-reference.md) to pass to nfd-master | -| `master.extraEnvs` | array | [] | Additional environment variables to pass to nfd-master | -| `master.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | -| `master.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD master pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `master.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD master pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe)| +| Name | Type | Default | Description | +|-------------------------------------|---------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `master.*` | dict | | NFD master deployment configuration | +| `master.enable` | bool | true | Specifies whether nfd-master should be deployed | +| `master.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `master.port` | integer | | Specifies the TCP port that nfd-master listens for incoming requests. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.metricsPort` | integer | 8081 | Port on which to expose metrics from components to prometheus operator | +| `master.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | +| `master.instance` | string | | Instance name. Used to separate annotation namespaces for multiple parallel deployments | +| `master.resyncPeriod` | string | | NFD API controller resync period. | +| `master.extraLabelNs` | array | [] | List of allowed extra label namespaces | +| `master.resourceLabels` | array | [] | List of labels to be registered as extended resources | +| `master.enableTaints` | bool | false | Specifies whether to enable or disable node tainting | +| `master.crdController` | bool | null | Specifies whether the NFD CRD API controller is enabled. If not set, controller will be enabled if `master.instance` is empty. | +| `master.featureRulesController` | bool | null | DEPRECATED: use `master.crdController` instead | +| `master.replicaCount` | integer | 1 | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified | +| `master.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | +| `master.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `master.serviceAccount.create` | bool | true | Specifies whether a service account should be created | +| `master.serviceAccount.annotations` | dict | {} | Annotations to add to the service account | +| `master.serviceAccount.name` | string | | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| `master.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-master | +| `master.service.type` | string | ClusterIP | NFD master service type. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.service.port` | integer | 8080 | NFD master service port. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.resources.limits` | dict | {memory: 4Gi} | NFD master pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `master.resources.requests` | dict | {cpu: 100m, memory: 128Mi} | NFD master pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits). See `[0]` for more info | +| `master.tolerations` | dict | _Schedule to control-plane node_ | NFD master pod [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `master.annotations` | dict | {} | NFD master pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `master.affinity` | dict | | NFD master pod required [node affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | +| `master.deploymentAnnotations` | dict | {} | NFD master deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `master.nfdApiParallelism` | integer | 10 | Specifies the maximum number of concurrent node updates. | +| `master.config` | dict | | NFD master [configuration](../reference/master-configuration-reference) | +| `master.extraArgs` | array | [] | Additional [command line arguments](../reference/master-commandline-reference.md) to pass to nfd-master | +| `master.extraEnvs` | array | [] | Additional environment variables to pass to nfd-master | +| `master.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | +| `master.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD master pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | +| `master.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD master pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | + +> `[0]` Additional info for `master.resources.requests`: \ +> You may want to use the same value for `requests.memory` and `limits.memory`. +> The “requests” value affects scheduling to accommodate pods on nodes. +> If there is a large difference between “requests” and “limits” and nodes +> experience memory pressure, the kernel may invoke the OOM Killer, even if +> the memory does not exceed the “limits” threshold. +> This can cause unexpected pod evictions. Memory cannot be compressed and +> once allocated to a pod, it can only be reclaimed by killing the pod. +> [Natan Yellin 22/09/2022](https://home.robusta.dev/blog/kubernetes-memory-limit) +> that discusses this issue. ### Worker pod parameters -| Name | Type | Default | Description | -| ----------------------------------- | ------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `worker.*` | dict | | NFD worker daemonset configuration | -| `worker.enable` | bool | true | Specifies whether nfd-worker should be deployed | -| `worker.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `worker.metricsPort` | int | 8081 | Port on which to expose metrics from components to prometheus operator | -| `worker.healthPort` | int | 8082 | Port on which to expose the grpc health endpoint | -| `worker.config` | dict | | NFD worker [configuration](../reference/worker-configuration-reference) | -| `worker.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settins | -| `worker.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `worker.serviceAccount.create` | bool | true | Specifies whether a service account for nfd-worker should be created | -| `worker.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for nfd-worker | -| `worker.serviceAccount.name` | string | | The name of the service account to use for nfd-worker. If not set and create is true, a name is generated using the fullname template (suffixed with `-worker`) | -| `worker.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-worker | -| `worker.mountUsrSrc` | bool | false | Specifies whether to allow users to mount the hostpath /user/src. Does not work on systems without /usr/src AND a read-only /usr | -| `worker.resources.limits` | dict | {memory: 512Mi} | NFD worker pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `worker.resources.requests` | dict | {cpu: 5m, memory: 64Mi} | NFD worker pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `worker.nodeSelector` | dict | {} | NFD worker pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | -| `worker.tolerations` | dict | {} | NFD worker pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `worker.priorityClassName` | string | | NFD worker pod [priority class](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | -| `worker.annotations` | dict | {} | NFD worker pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `worker.daemonsetAnnotations` | dict | {} | NFD worker daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `worker.extraArgs` | array | [] | Additional [command line arguments](../reference/worker-commandline-reference.md) to pass to nfd-worker | -| `worker.extraEnvs` | array | [] | Additional environment variables to pass to nfd-worker | -| `worker.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/ #DaemonSetSpec) | -| `worker.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD worker pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `worker.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD worker pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe)| +| Name | Type | Default | Description | +|-------------------------------------|---------|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `worker.*` | dict | | NFD worker daemonset configuration | +| `worker.enable` | bool | true | Specifies whether nfd-worker should be deployed | +| `worker.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `worker.metricsPort` | int | 8081 | Port on which to expose metrics from components to prometheus operator | +| `worker.healthPort` | int | 8082 | Port on which to expose the grpc health endpoint | +| `worker.config` | dict | | NFD worker [configuration](../reference/worker-configuration-reference) | +| `worker.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settins | +| `worker.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `worker.serviceAccount.create` | bool | true | Specifies whether a service account for nfd-worker should be created | +| `worker.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for nfd-worker | +| `worker.serviceAccount.name` | string | | The name of the service account to use for nfd-worker. If not set and create is true, a name is generated using the fullname template (suffixed with `-worker`) | +| `worker.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-worker | +| `worker.mountUsrSrc` | bool | false | Specifies whether to allow users to mount the hostpath /user/src. Does not work on systems without /usr/src AND a read-only /usr | +| `worker.resources.limits` | dict | {memory: 512Mi} | NFD worker pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `worker.resources.requests` | dict | {cpu: 5m, memory: 64Mi} | NFD worker pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `worker.nodeSelector` | dict | {} | NFD worker pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | +| `worker.tolerations` | dict | {} | NFD worker pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `worker.priorityClassName` | string | | NFD worker pod [priority class](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | +| `worker.annotations` | dict | {} | NFD worker pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `worker.daemonsetAnnotations` | dict | {} | NFD worker daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `worker.extraArgs` | array | [] | Additional [command line arguments](../reference/worker-commandline-reference.md) to pass to nfd-worker | +| `worker.extraEnvs` | array | [] | Additional environment variables to pass to nfd-worker | +| `worker.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/ #DaemonSetSpec) | +| `worker.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD worker pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | +| `worker.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD worker pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | ### Topology updater parameters -| Name | Type | Default | Description | -| --------------------------------------------- | ------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `topologyUpdater.*` | dict | | NFD Topology Updater configuration | -| `topologyUpdater.enable` | bool | false | Specifies whether the NFD Topology Updater should be created | -| `topologyUpdater.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `topologyUpdater.createCRDs` | bool | false | Specifies whether the NFD Topology Updater CRDs should be created | -| `topologyUpdater.serviceAccount.create` | bool | true | Specifies whether the service account for topology updater should be created | -| `topologyUpdater.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for topology updater | -| `topologyUpdater.serviceAccount.name` | string | | The name of the service account for topology updater to use. If not set and create is true, a name is generated using the fullname template and `-topology-updater` suffix | -| `topologyUpdater.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for topology updater | -| `topologyUpdater.metricsPort` | integer | 8081 | Port on which to expose prometheus metrics | -| `topologyUpdater.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | -| `topologyUpdater.kubeletConfigPath` | string | "" | Specifies the kubelet config host path | -| `topologyUpdater.kubeletPodResourcesSockPath` | string | "" | Specifies the kubelet sock path to read pod resources | -| `topologyUpdater.updateInterval` | string | 60s | Time to sleep between CR updates. Non-positive value implies no CR update. | -| `topologyUpdater.watchNamespace` | string | `*` | Namespace to watch pods, `*` for all namespaces | -| `topologyUpdater.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container sett| -| `topologyUpdater.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `topologyUpdater.resources.limits` | dict | {memory: 60Mi} | NFD Topology Updater pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `topologyUpdater.resources.requests` | dict | {cpu: 50m, memory: 40Mi} | NFD Topology Updater pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `topologyUpdater.nodeSelector` | dict | {} | Topology updater pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | -| `topologyUpdater.tolerations` | dict | {} | Topology updater pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `topologyUpdater.annotations` | dict | {} | Topology updater pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `topologyUpdater.daemonsetAnnotations` | dict | {} | Topology updater daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `topologyUpdater.affinity` | dict | {} | Topology updater pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | -| `topologyUpdater.config` | dict | | [configuration](../reference/topology-updater-configuration-reference) | -| `topologyUpdater.podSetFingerprint` | bool | true | Enables compute and report of pod fingerprint in NRT objects. | -| `topologyUpdater.kubeletStateDir` | string | /var/lib/kubelet | Specifies kubelet state directory path for watching state and checkpoint files. Empty value disables kubelet state tracking. | -| `topologyUpdater.extraArgs` | array | [] | Additional [command line arguments](../reference/topology-updater-commandline-reference.md) to pass to nfd-topology-updater | -| `topologyUpdater.extraEnvs` | array | [] | Additional environment variables to pass to nfd-topology-updater | -| `topologyUpdater.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/#DaemonSetSpec) | -| `topologyUpdater.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | Topology updater pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `topologyUpdater.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | Topology updater pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe)| +| Name | Type | Default | Description | +|-----------------------------------------------|---------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `topologyUpdater.*` | dict | | NFD Topology Updater configuration | +| `topologyUpdater.enable` | bool | false | Specifies whether the NFD Topology Updater should be created | +| `topologyUpdater.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `topologyUpdater.createCRDs` | bool | false | Specifies whether the NFD Topology Updater CRDs should be created | +| `topologyUpdater.serviceAccount.create` | bool | true | Specifies whether the service account for topology updater should be created | +| `topologyUpdater.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for topology updater | +| `topologyUpdater.serviceAccount.name` | string | | The name of the service account for topology updater to use. If not set and create is true, a name is generated using the fullname template and `-topology-updater` suffix | +| `topologyUpdater.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for topology updater | +| `topologyUpdater.metricsPort` | integer | 8081 | Port on which to expose prometheus metrics | +| `topologyUpdater.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | +| `topologyUpdater.kubeletConfigPath` | string | "" | Specifies the kubelet config host path | +| `topologyUpdater.kubeletPodResourcesSockPath` | string | "" | Specifies the kubelet sock path to read pod resources | +| `topologyUpdater.updateInterval` | string | 60s | Time to sleep between CR updates. Non-positive value implies no CR update. | +| `topologyUpdater.watchNamespace` | string | `*` | Namespace to watch pods, `*` for all namespaces | +| `topologyUpdater.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container sett | +| `topologyUpdater.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `topologyUpdater.resources.limits` | dict | {memory: 60Mi} | NFD Topology Updater pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `topologyUpdater.resources.requests` | dict | {cpu: 50m, memory: 40Mi} | NFD Topology Updater pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `topologyUpdater.nodeSelector` | dict | {} | Topology updater pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | +| `topologyUpdater.tolerations` | dict | {} | Topology updater pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `topologyUpdater.annotations` | dict | {} | Topology updater pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `topologyUpdater.daemonsetAnnotations` | dict | {} | Topology updater daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `topologyUpdater.affinity` | dict | {} | Topology updater pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | +| `topologyUpdater.config` | dict | | [configuration](../reference/topology-updater-configuration-reference) | +| `topologyUpdater.podSetFingerprint` | bool | true | Enables compute and report of pod fingerprint in NRT objects. | +| `topologyUpdater.kubeletStateDir` | string | /var/lib/kubelet | Specifies kubelet state directory path for watching state and checkpoint files. Empty value disables kubelet state tracking. | +| `topologyUpdater.extraArgs` | array | [] | Additional [command line arguments](../reference/topology-updater-commandline-reference.md) to pass to nfd-topology-updater | +| `topologyUpdater.extraEnvs` | array | [] | Additional environment variables to pass to nfd-topology-updater | +| `topologyUpdater.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/#DaemonSetSpec) | +| `topologyUpdater.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | Topology updater pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | +| `topologyUpdater.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | Topology updater pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | ### Garbage collector parameters -| Name | Type | Default | Description | -| ------------------------------------- | ------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gc.*` | dict | | NFD Garbage Collector configuration | -| `gc.enable` | bool | true | Specifies whether the NFD Garbage Collector should be created | -| `gc.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `gc.serviceAccount.create` | bool | true | Specifies whether the service account for garbage collector should be created | -| `gc.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for garbage collector | -| `gc.serviceAccount.name` | string | | The name of the service account for garbage collector to use. If not set and create is true, a name is generated using the fullname template and `-gc` suffix | -| `gc.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for garbage collector | -| `gc.interval` | string | 1h | Time between periodic garbage collector runs | -| `gc.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | -| `gc.resources.limits` | dict | {memory: 1Gi} | NFD Garbage Collector pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `gc.resources.requests` | dict | {cpu: 10m, memory: 128Mi} | NFD Garbage Collector pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `gc.metricsPort` | integer | 8081 | Port on which to serve Prometheus metrics | -| `gc.nodeSelector` | dict | {} | Garbage collector pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | -| `gc.tolerations` | dict | {} | Garbage collector pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `gc.annotations` | dict | {} | Garbage collector pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `gc.deploymentAnnotations` | dict | {} | Garbage collector deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `gc.affinity` | dict | {} | Garbage collector pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | -| `gc.extraArgs` | array | [] | Additional [command line arguments](../reference/gc-commandline-reference.md) to pass to nfd-gc | -| `gc.extraEnvs` | array | [] | Additional environment variables to pass to nfd-gc | -| `gc.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | +| Name | Type | Default | Description | +|---------------------------------|---------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `gc.*` | dict | | NFD Garbage Collector configuration | +| `gc.enable` | bool | true | Specifies whether the NFD Garbage Collector should be created | +| `gc.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `gc.serviceAccount.create` | bool | true | Specifies whether the service account for garbage collector should be created | +| `gc.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for garbage collector | +| `gc.serviceAccount.name` | string | | The name of the service account for garbage collector to use. If not set and create is true, a name is generated using the fullname template and `-gc` suffix | +| `gc.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for garbage collector | +| `gc.interval` | string | 1h | Time between periodic garbage collector runs | +| `gc.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | +| `gc.resources.limits` | dict | {memory: 1Gi} | NFD Garbage Collector pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `gc.resources.requests` | dict | {cpu: 10m, memory: 128Mi} | NFD Garbage Collector pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `gc.metricsPort` | integer | 8081 | Port on which to serve Prometheus metrics | +| `gc.nodeSelector` | dict | {} | Garbage collector pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | +| `gc.tolerations` | dict | {} | Garbage collector pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `gc.annotations` | dict | {} | Garbage collector pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `gc.deploymentAnnotations` | dict | {} | Garbage collector deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `gc.affinity` | dict | {} | Garbage collector pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | +| `gc.extraArgs` | array | [] | Additional [command line arguments](../reference/gc-commandline-reference.md) to pass to nfd-gc | +| `gc.extraEnvs` | array | [] | Additional environment variables to pass to nfd-gc | +| `gc.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | + [rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/ From 52c2fc649831865eb6b999fa5909777cd2c2a26f Mon Sep 17 00:00:00 2001 From: Tobias Giese Date: Fri, 18 Oct 2024 12:42:42 +0200 Subject: [PATCH 5/8] Add separate helm values for the liveness and readiness probes Signed-off-by: Tobias Giese --- .../templates/master.yaml | 37 ++- .../templates/topologyupdater.yaml | 37 ++- .../templates/worker.yaml | 37 ++- .../helm/node-feature-discovery/values.yaml | 9 + docs/deployment/helm.md | 215 ++++++++++-------- 5 files changed, 226 insertions(+), 109 deletions(-) diff --git a/deployment/helm/node-feature-discovery/templates/master.yaml b/deployment/helm/node-feature-discovery/templates/master.yaml index c47086cc1f..d3d7b604a6 100644 --- a/deployment/helm/node-feature-discovery/templates/master.yaml +++ b/deployment/helm/node-feature-discovery/templates/master.yaml @@ -48,15 +48,44 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} livenessProbe: - {{- toYaml .Values.master.livenessProbe | nindent 12 }} + grpc: + port: {{ .Values.master.healthPort | default "8082" }} + {{- with .Values.master.livenessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.master.livenessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.master.livenessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.master.livenessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} readinessProbe: - {{- toYaml .Values.master.readinessProbe | nindent 12 }} + grpc: + port: {{ .Values.master.healthPort | default "8082" }} + {{- with .Values.master.readinessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.master.readinessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.master.readinessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.master.readinessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + {{- with .Values.master.readinessProbe.successThreshold }} + successThreshold: {{ . }} + {{- end }} ports: - containerPort: {{ .Values.master.port | default "8080" }} name: grpc - containerPort: {{ .Values.master.metricsPort | default "8081" }} name: metrics - - containerPort: {{ .Values.master.healthPort | default "8082" }} + - containerPort: {{ .Values.master.healthPort | default "8082" }} name: health env: - name: NODE_NAME @@ -116,7 +145,7 @@ spec: - "-feature-gates={{ $key }}={{ $value }}" {{- end }} - "-metrics={{ .Values.master.metricsPort | default "8081" }}" - - "-grpc-health={{ .Values.master.healthPort | default "8082" }}" + - "-grpc-health={{ .Values.master.healthPort | default "8082" }}" {{- with .Values.master.extraArgs }} {{- toYaml . | nindent 12 }} {{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml b/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml index 222e729806..da01b1e1eb 100644 --- a/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml +++ b/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml @@ -45,9 +45,38 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" livenessProbe: - {{- toYaml .Values.topologyUpdater.livenessProbe | nindent 10 }} + grpc: + port: {{ .Values.topologyUpdater.healthPort | default "8082" }} + {{- with .Values.topologyUpdater.livenessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.livenessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.livenessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.livenessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} readinessProbe: - {{- toYaml .Values.topologyUpdater.readinessProbe | nindent 10 }} + grpc: + port: {{ .Values.topologyUpdater.healthPort | default "8082" }} + {{- with .Values.topologyUpdater.readinessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.readinessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.readinessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.readinessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + {{- with .Values.topologyUpdater.readinessProbe.successThreshold }} + successThreshold: {{ . }} + {{- end }} env: - name: NODE_NAME valueFrom: @@ -90,14 +119,14 @@ spec: - "-kubelet-state-dir=" {{- end }} - "-metrics={{ .Values.topologyUpdater.metricsPort | default "8081"}}" - - "-grpc-health={{ .Values.topologyUpdater.healthPort | default "8082" }}" + - "-grpc-health={{ .Values.topologyUpdater.healthPort | default "8082" }}" {{- with .Values.topologyUpdater.extraArgs }} {{- toYaml . | nindent 10 }} {{- end }} ports: - containerPort: {{ .Values.topologyUpdater.metricsPort | default "8081"}} name: metrics - - containerPort: {{ .Values.topologyUpdater.healthPort | default "8082" }} + - containerPort: {{ .Values.topologyUpdater.healthPort | default "8082" }} name: health volumeMounts: {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} diff --git a/deployment/helm/node-feature-discovery/templates/worker.yaml b/deployment/helm/node-feature-discovery/templates/worker.yaml index 028b481ad3..c4fbc64678 100644 --- a/deployment/helm/node-feature-discovery/templates/worker.yaml +++ b/deployment/helm/node-feature-discovery/templates/worker.yaml @@ -47,9 +47,38 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} livenessProbe: - {{- toYaml .Values.worker.livenessProbe | nindent 12 }} + grpc: + port: {{ .Values.worker.healthPort | default "8082" }} + {{- with .Values.worker.livenessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.worker.livenessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.worker.livenessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.worker.livenessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} readinessProbe: - {{- toYaml .Values.worker.readinessProbe | nindent 12 }} + grpc: + port: {{ .Values.worker.healthPort | default "8082" }} + {{- with .Values.worker.readinessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ . }} + {{- end }} + {{- with .Values.worker.readinessProbe.failureThreshold }} + failureThreshold: {{ . }} + {{- end }} + {{- with .Values.worker.readinessProbe.periodSeconds }} + periodSeconds: {{ . }} + {{- end }} + {{- with .Values.worker.readinessProbe.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + {{- with .Values.worker.readinessProbe.successThreshold }} + successThreshold: {{ . }} + {{- end }} env: - name: NODE_NAME valueFrom: @@ -84,14 +113,14 @@ spec: - "-feature-gates={{ $key }}={{ $value }}" {{- end }} - "-metrics={{ .Values.worker.metricsPort | default "8081"}}" - - "-grpc-health={{ .Values.worker.healthPort | default "8082" }}" + - "-grpc-health={{ .Values.worker.healthPort | default "8082" }}" {{- with .Values.gc.extraArgs }} {{- toYaml . | nindent 8 }} {{- end }} ports: - containerPort: {{ .Values.worker.metricsPort | default "8081"}} name: metrics - - containerPort: {{ .Values.worker.healthPort | default "8082" }} + - containerPort: {{ .Values.worker.healthPort | default "8082" }} name: health volumeMounts: - name: host-boot diff --git a/deployment/helm/node-feature-discovery/values.yaml b/deployment/helm/node-feature-discovery/values.yaml index 37683b97c8..a9d4b6c9f9 100644 --- a/deployment/helm/node-feature-discovery/values.yaml +++ b/deployment/helm/node-feature-discovery/values.yaml @@ -150,12 +150,15 @@ master: initialDelaySeconds: 10 # failureThreshold: 3 # periodSeconds: 10 + # timeoutSeconds: 1 readinessProbe: grpc: port: 8082 initialDelaySeconds: 5 failureThreshold: 10 # periodSeconds: 10 + # timeoutSeconds: 1 + # successThreshold: 1 worker: enable: true @@ -426,12 +429,15 @@ worker: initialDelaySeconds: 10 # failureThreshold: 3 # periodSeconds: 10 + # timeoutSeconds: 1 readinessProbe: grpc: port: 8082 initialDelaySeconds: 5 failureThreshold: 10 # periodSeconds: 10 + # timeoutSeconds: 1 + # successThreshold: 1 serviceAccount: # Specifies whether a service account should be created. @@ -520,12 +526,15 @@ topologyUpdater: initialDelaySeconds: 10 # failureThreshold: 3 # periodSeconds: 10 + # timeoutSeconds: 1 readinessProbe: grpc: port: 8082 initialDelaySeconds: 5 failureThreshold: 10 # periodSeconds: 10 + # timeoutSeconds: 1 + # successThreshold: 1 resources: limits: diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md index 8a17ff5982..717fbf7061 100644 --- a/docs/deployment/helm.md +++ b/docs/deployment/helm.md @@ -176,43 +176,50 @@ API's you need to install the prometheus operator in your cluster. ### Master pod parameters -| Name | Type | Default | Description | -|-------------------------------------|---------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `master.*` | dict | | NFD master deployment configuration | -| `master.enable` | bool | true | Specifies whether nfd-master should be deployed | -| `master.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `master.port` | integer | | Specifies the TCP port that nfd-master listens for incoming requests. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.metricsPort` | integer | 8081 | Port on which to expose metrics from components to prometheus operator | -| `master.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | -| `master.instance` | string | | Instance name. Used to separate annotation namespaces for multiple parallel deployments | -| `master.resyncPeriod` | string | | NFD API controller resync period. | -| `master.extraLabelNs` | array | [] | List of allowed extra label namespaces | -| `master.resourceLabels` | array | [] | List of labels to be registered as extended resources | -| `master.enableTaints` | bool | false | Specifies whether to enable or disable node tainting | -| `master.crdController` | bool | null | Specifies whether the NFD CRD API controller is enabled. If not set, controller will be enabled if `master.instance` is empty. | -| `master.featureRulesController` | bool | null | DEPRECATED: use `master.crdController` instead | -| `master.replicaCount` | integer | 1 | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified | -| `master.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | -| `master.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `master.serviceAccount.create` | bool | true | Specifies whether a service account should be created | -| `master.serviceAccount.annotations` | dict | {} | Annotations to add to the service account | -| `master.serviceAccount.name` | string | | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | -| `master.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-master | -| `master.service.type` | string | ClusterIP | NFD master service type. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.service.port` | integer | 8080 | NFD master service port. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | -| `master.resources.limits` | dict | {memory: 4Gi} | NFD master pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `master.resources.requests` | dict | {cpu: 100m, memory: 128Mi} | NFD master pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits). See `[0]` for more info | -| `master.tolerations` | dict | _Schedule to control-plane node_ | NFD master pod [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `master.annotations` | dict | {} | NFD master pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `master.affinity` | dict | | NFD master pod required [node affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | -| `master.deploymentAnnotations` | dict | {} | NFD master deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `master.nfdApiParallelism` | integer | 10 | Specifies the maximum number of concurrent node updates. | -| `master.config` | dict | | NFD master [configuration](../reference/master-configuration-reference) | -| `master.extraArgs` | array | [] | Additional [command line arguments](../reference/master-commandline-reference.md) to pass to nfd-master | -| `master.extraEnvs` | array | [] | Additional environment variables to pass to nfd-master | -| `master.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | -| `master.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD master pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `master.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD master pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | +| Name | Type | Default | Description | +|---------------------------------------------|---------|----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `master.*` | dict | | NFD master deployment configuration | +| `master.enable` | bool | true | Specifies whether nfd-master should be deployed | +| `master.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `master.port` | integer | | Specifies the TCP port that nfd-master listens for incoming requests. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.metricsPort` | integer | 8081 | Port on which to expose metrics from components to prometheus operator | +| `master.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint, will be also used for the probes | +| `master.instance` | string | | Instance name. Used to separate annotation namespaces for multiple parallel deployments | +| `master.resyncPeriod` | string | | NFD API controller resync period. | +| `master.extraLabelNs` | array | [] | List of allowed extra label namespaces | +| `master.resourceLabels` | array | [] | List of labels to be registered as extended resources | +| `master.enableTaints` | bool | false | Specifies whether to enable or disable node tainting | +| `master.crdController` | bool | null | Specifies whether the NFD CRD API controller is enabled. If not set, controller will be enabled if `master.instance` is empty. | +| `master.featureRulesController` | bool | null | DEPRECATED: use `master.crdController` instead | +| `master.replicaCount` | integer | 1 | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified | +| `master.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings | +| `master.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `master.serviceAccount.create` | bool | true | Specifies whether a service account should be created | +| `master.serviceAccount.annotations` | dict | {} | Annotations to add to the service account | +| `master.serviceAccount.name` | string | | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| `master.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-master | +| `master.service.type` | string | ClusterIP | NFD master service type. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.service.port` | integer | 8080 | NFD master service port. **NOTE**: this parameter is related to the deprecated gRPC API and will be removed with it in a future release | +| `master.resources.limits` | dict | {memory: 4Gi} | NFD master pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `master.resources.requests` | dict | {cpu: 100m, memory: 128Mi} | NFD master pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits). See `[0]` for more info | +| `master.tolerations` | dict | _Schedule to control-plane node_ | NFD master pod [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `master.annotations` | dict | {} | NFD master pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `master.affinity` | dict | | NFD master pod required [node affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | +| `master.deploymentAnnotations` | dict | {} | NFD master deployment [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `master.nfdApiParallelism` | integer | 10 | Specifies the maximum number of concurrent node updates. | +| `master.config` | dict | | NFD master [configuration](../reference/master-configuration-reference) | +| `master.extraArgs` | array | [] | Additional [command line arguments](../reference/master-commandline-reference.md) to pass to nfd-master | +| `master.extraEnvs` | array | [] | Additional environment variables to pass to nfd-master | +| `master.revisionHistoryLimit` | integer | | Specify how many old ReplicaSets for this Deployment you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) | +| `master.livenessProbe.initialDelaySeconds` | integer | 10 | Specifies the number of seconds after the container has started before liveness probes are initiated. | +| `master.livenessProbe.failureThreshold` | integer | 3 (by Kubernetes) | Specifies the number of consecutive failures of liveness probes before considering the pod as not ready. | +| `master.livenessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the liveness probe. | +| `master.livenessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `master.readinessProbe.initialDelaySeconds` | integer | 5 | Specifies the number of seconds after the container has started before readiness probes are initiated. | +| `master.readinessProbe.failureThreshold` | integer | 10 | Specifies the number of consecutive failures of readiness probes before considering the pod as not ready. | +| `master.readinessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the readiness probe. | +| `master.readinessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `master.readinessProbe.successThreshold` | integer | 1 (by Kubernetes) | Specifies the number of consecutive successes of readiness probes before considering the pod as ready. | > `[0]` Additional info for `master.resources.requests`: \ > You may want to use the same value for `requests.memory` and `limits.memory`. @@ -227,69 +234,83 @@ API's you need to install the prometheus operator in your cluster. ### Worker pod parameters -| Name | Type | Default | Description | -|-------------------------------------|---------|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `worker.*` | dict | | NFD worker daemonset configuration | -| `worker.enable` | bool | true | Specifies whether nfd-worker should be deployed | -| `worker.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `worker.metricsPort` | int | 8081 | Port on which to expose metrics from components to prometheus operator | -| `worker.healthPort` | int | 8082 | Port on which to expose the grpc health endpoint | -| `worker.config` | dict | | NFD worker [configuration](../reference/worker-configuration-reference) | -| `worker.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settins | -| `worker.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `worker.serviceAccount.create` | bool | true | Specifies whether a service account for nfd-worker should be created | -| `worker.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for nfd-worker | -| `worker.serviceAccount.name` | string | | The name of the service account to use for nfd-worker. If not set and create is true, a name is generated using the fullname template (suffixed with `-worker`) | -| `worker.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-worker | -| `worker.mountUsrSrc` | bool | false | Specifies whether to allow users to mount the hostpath /user/src. Does not work on systems without /usr/src AND a read-only /usr | -| `worker.resources.limits` | dict | {memory: 512Mi} | NFD worker pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `worker.resources.requests` | dict | {cpu: 5m, memory: 64Mi} | NFD worker pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `worker.nodeSelector` | dict | {} | NFD worker pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | -| `worker.tolerations` | dict | {} | NFD worker pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `worker.priorityClassName` | string | | NFD worker pod [priority class](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | -| `worker.annotations` | dict | {} | NFD worker pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `worker.daemonsetAnnotations` | dict | {} | NFD worker daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `worker.extraArgs` | array | [] | Additional [command line arguments](../reference/worker-commandline-reference.md) to pass to nfd-worker | -| `worker.extraEnvs` | array | [] | Additional environment variables to pass to nfd-worker | -| `worker.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/ #DaemonSetSpec) | -| `worker.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | NFD worker pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `worker.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | NFD worker pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | +| Name | Type | Default | Description | +|---------------------------------------------|---------|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `worker.*` | dict | | NFD worker daemonset configuration | +| `worker.enable` | bool | true | Specifies whether nfd-worker should be deployed | +| `worker.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `worker.metricsPort` | int | 8081 | Port on which to expose metrics from components to prometheus operator | +| `worker.healthPort` | int | 8082 | Port on which to expose the grpc health endpoint, will be also used for the probes | +| `worker.config` | dict | | NFD worker [configuration](../reference/worker-configuration-reference) | +| `worker.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settins | +| `worker.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `worker.serviceAccount.create` | bool | true | Specifies whether a service account for nfd-worker should be created | +| `worker.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for nfd-worker | +| `worker.serviceAccount.name` | string | | The name of the service account to use for nfd-worker. If not set and create is true, a name is generated using the fullname template (suffixed with `-worker`) | +| `worker.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-worker | +| `worker.mountUsrSrc` | bool | false | Specifies whether to allow users to mount the hostpath /user/src. Does not work on systems without /usr/src AND a read-only /usr | +| `worker.resources.limits` | dict | {memory: 512Mi} | NFD worker pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `worker.resources.requests` | dict | {cpu: 5m, memory: 64Mi} | NFD worker pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `worker.nodeSelector` | dict | {} | NFD worker pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | +| `worker.tolerations` | dict | {} | NFD worker pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `worker.priorityClassName` | string | | NFD worker pod [priority class](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | +| `worker.annotations` | dict | {} | NFD worker pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `worker.daemonsetAnnotations` | dict | {} | NFD worker daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `worker.extraArgs` | array | [] | Additional [command line arguments](../reference/worker-commandline-reference.md) to pass to nfd-worker | +| `worker.extraEnvs` | array | [] | Additional environment variables to pass to nfd-worker | +| `worker.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/ #DaemonSetSpec) | +| `worker.livenessProbe.initialDelaySeconds` | integer | 10 | Specifies the number of seconds after the container has started before liveness probes are initiated. | +| `worker.livenessProbe.failureThreshold` | integer | 3 (by Kubernetes) | Specifies the number of consecutive failures of liveness probes before considering the pod as not ready. | +| `worker.livenessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the liveness probe. | +| `worker.livenessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `worker.readinessProbe.initialDelaySeconds` | integer | 5 | Specifies the number of seconds after the container has started before readiness probes are initiated. | +| `worker.readinessProbe.failureThreshold` | integer | 10 | Specifies the number of consecutive failures of readiness probes before considering the pod as not ready. | +| `worker.readinessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the readiness probe. | +| `worker.readinessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `worker.readinessProbe.successThreshold` | integer | 1 (by Kubernetes) | Specifies the number of consecutive successes of readiness probes before considering the pod as ready. | ### Topology updater parameters -| Name | Type | Default | Description | -|-----------------------------------------------|---------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `topologyUpdater.*` | dict | | NFD Topology Updater configuration | -| `topologyUpdater.enable` | bool | false | Specifies whether the NFD Topology Updater should be created | -| `topologyUpdater.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | -| `topologyUpdater.createCRDs` | bool | false | Specifies whether the NFD Topology Updater CRDs should be created | -| `topologyUpdater.serviceAccount.create` | bool | true | Specifies whether the service account for topology updater should be created | -| `topologyUpdater.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for topology updater | -| `topologyUpdater.serviceAccount.name` | string | | The name of the service account for topology updater to use. If not set and create is true, a name is generated using the fullname template and `-topology-updater` suffix | -| `topologyUpdater.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for topology updater | -| `topologyUpdater.metricsPort` | integer | 8081 | Port on which to expose prometheus metrics | -| `topologyUpdater.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint | -| `topologyUpdater.kubeletConfigPath` | string | "" | Specifies the kubelet config host path | -| `topologyUpdater.kubeletPodResourcesSockPath` | string | "" | Specifies the kubelet sock path to read pod resources | -| `topologyUpdater.updateInterval` | string | 60s | Time to sleep between CR updates. Non-positive value implies no CR update. | -| `topologyUpdater.watchNamespace` | string | `*` | Namespace to watch pods, `*` for all namespaces | -| `topologyUpdater.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container sett | -| `topologyUpdater.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | -| `topologyUpdater.resources.limits` | dict | {memory: 60Mi} | NFD Topology Updater pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `topologyUpdater.resources.requests` | dict | {cpu: 50m, memory: 40Mi} | NFD Topology Updater pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | -| `topologyUpdater.nodeSelector` | dict | {} | Topology updater pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | -| `topologyUpdater.tolerations` | dict | {} | Topology updater pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | -| `topologyUpdater.annotations` | dict | {} | Topology updater pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `topologyUpdater.daemonsetAnnotations` | dict | {} | Topology updater daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | -| `topologyUpdater.affinity` | dict | {} | Topology updater pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | -| `topologyUpdater.config` | dict | | [configuration](../reference/topology-updater-configuration-reference) | -| `topologyUpdater.podSetFingerprint` | bool | true | Enables compute and report of pod fingerprint in NRT objects. | -| `topologyUpdater.kubeletStateDir` | string | /var/lib/kubelet | Specifies kubelet state directory path for watching state and checkpoint files. Empty value disables kubelet state tracking. | -| `topologyUpdater.extraArgs` | array | [] | Additional [command line arguments](../reference/topology-updater-commandline-reference.md) to pass to nfd-topology-updater | -| `topologyUpdater.extraEnvs` | array | [] | Additional environment variables to pass to nfd-topology-updater | -| `topologyUpdater.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/#DaemonSetSpec) | -| `topologyUpdater.livenessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":10} | Topology updater pod [liveness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#liveness-probe) | -| `topologyUpdater.readinessProbe` | dict | {"grpc":{"port":8082},"initialDelaySeconds":5,"failureThreshold": 10} | Topology updater pod [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe) | +| Name | Type | Default | Description | +|------------------------------------------------------|---------|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `topologyUpdater.*` | dict | | NFD Topology Updater configuration | +| `topologyUpdater.enable` | bool | false | Specifies whether the NFD Topology Updater should be created | +| `topologyUpdater.hostNetwork` | bool | false | Specifies whether to enable or disable running the container in the host's network namespace | +| `topologyUpdater.createCRDs` | bool | false | Specifies whether the NFD Topology Updater CRDs should be created | +| `topologyUpdater.serviceAccount.create` | bool | true | Specifies whether the service account for topology updater should be created | +| `topologyUpdater.serviceAccount.annotations` | dict | {} | Annotations to add to the service account for topology updater | +| `topologyUpdater.serviceAccount.name` | string | | The name of the service account for topology updater to use. If not set and create is true, a name is generated using the fullname template and `-topology-updater` suffix | +| `topologyUpdater.rbac.create` | bool | true | Specifies whether to create [RBAC][rbac] configuration for topology updater | +| `topologyUpdater.metricsPort` | integer | 8081 | Port on which to expose prometheus metrics | +| `topologyUpdater.healthPort` | integer | 8082 | Port on which to expose the grpc health endpoint, will be also used for the probes | +| `topologyUpdater.kubeletConfigPath` | string | "" | Specifies the kubelet config host path | +| `topologyUpdater.kubeletPodResourcesSockPath` | string | "" | Specifies the kubelet sock path to read pod resources | +| `topologyUpdater.updateInterval` | string | 60s | Time to sleep between CR updates. Non-positive value implies no CR update. | +| `topologyUpdater.watchNamespace` | string | `*` | Namespace to watch pods, `*` for all namespaces | +| `topologyUpdater.podSecurityContext` | dict | {} | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container sett | +| `topologyUpdater.securityContext` | dict | {} | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) | +| `topologyUpdater.resources.limits` | dict | {memory: 60Mi} | NFD Topology Updater pod [resources limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `topologyUpdater.resources.requests` | dict | {cpu: 50m, memory: 40Mi} | NFD Topology Updater pod [resources requests](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits) | +| `topologyUpdater.nodeSelector` | dict | {} | Topology updater pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) | +| `topologyUpdater.tolerations` | dict | {} | Topology updater pod [node tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) | +| `topologyUpdater.annotations` | dict | {} | Topology updater pod [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `topologyUpdater.daemonsetAnnotations` | dict | {} | Topology updater daemonset [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) | +| `topologyUpdater.affinity` | dict | {} | Topology updater pod [affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) | +| `topologyUpdater.config` | dict | | [configuration](../reference/topology-updater-configuration-reference) | +| `topologyUpdater.podSetFingerprint` | bool | true | Enables compute and report of pod fingerprint in NRT objects. | +| `topologyUpdater.kubeletStateDir` | string | /var/lib/kubelet | Specifies kubelet state directory path for watching state and checkpoint files. Empty value disables kubelet state tracking. | +| `topologyUpdater.extraArgs` | array | [] | Additional [command line arguments](../reference/topology-updater-commandline-reference.md) to pass to nfd-topology-updater | +| `topologyUpdater.extraEnvs` | array | [] | Additional environment variables to pass to nfd-topology-updater | +| `topologyUpdater.revisionHistoryLimit` | integer | | Specify how many old ControllerRevisions for this DaemonSet you want to retain. [revisionHistoryLimit](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/#DaemonSetSpec) | +| `topologyUpdater.livenessProbe.initialDelaySeconds` | integer | 10 | Specifies the number of seconds after the container has started before liveness probes are initiated. | +| `topologyUpdater.livenessProbe.failureThreshold` | integer | 3 (by Kubernetes) | Specifies the number of consecutive failures of liveness probes before considering the pod as not ready. | +| `topologyUpdater.livenessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the liveness probe. | +| `topologyUpdater.livenessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `topologyUpdater.readinessProbe.initialDelaySeconds` | integer | 5 | Specifies the number of seconds after the container has started before readiness probes are initiated. | +| `topologyUpdater.readinessProbe.failureThreshold` | integer | 10 | Specifies the number of consecutive failures of readiness probes before considering the pod as not ready. | +| `topologyUpdater.readinessProbe.periodSeconds` | integer | 10 (by Kubernetes) | Specifies how often (in seconds) to perform the readiness probe. | +| `topologyUpdater.readinessProbe.timeoutSeconds` | integer | 1 (by Kubernetes) | Specifies the number of seconds after which the probe times out. | +| `topologyUpdater.readinessProbe.successThreshold` | integer | 1 (by Kubernetes) | Specifies the number of consecutive successes of readiness probes before considering the pod as ready. | ### Garbage collector parameters From 3b65c40e3bd8dee32740f86d8fcca5c010f1c3af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 20 Oct 2024 09:14:06 +0000 Subject: [PATCH 6/8] build(deps): bump github.com/opencontainers/runc from 1.1.14 to 1.1.15 Bumps [github.com/opencontainers/runc](https://github.com/opencontainers/runc) from 1.1.14 to 1.1.15. - [Release notes](https://github.com/opencontainers/runc/releases) - [Changelog](https://github.com/opencontainers/runc/blob/v1.1.15/CHANGELOG.md) - [Commits](https://github.com/opencontainers/runc/compare/v1.1.14...v1.1.15) --- updated-dependencies: - dependency-name: github.com/opencontainers/runc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 04f2de5247..838d2d50f1 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/klauspost/cpuid/v2 v2.2.8 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 - github.com/opencontainers/runc v1.1.14 + github.com/opencontainers/runc v1.1.15 github.com/prometheus/client_golang v1.18.0 github.com/smartystreets/goconvey v1.8.1 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 28404c15dc..373028b421 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= -github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= +github.com/opencontainers/runc v1.1.15 h1:QMmSU2q1YUg3iOJX11phnaDi2A5/zhx4BR6h+XZ1DMA= +github.com/opencontainers/runc v1.1.15/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8= github.com/opencontainers/runtime-spec v1.1.0-rc.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= From b6b1335ec152210866bd2af4d20bd3ea958fa0ba Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Mon, 21 Oct 2024 16:49:32 +0200 Subject: [PATCH 7/8] Move testdata to root Go mod automatically ignores the /testdata directory. This change ensures that the rootfs for source/pci tests are not included in the module definition. Signed-off-by: Evan Lezar --- source/pci/pci_test.go | 11 ++--------- .../sys/bus/pci/devices/0000:00:04.0/ari_enabled | 0 .../pci/devices/0000:00:04.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:04.0/class | 0 .../sys/bus/pci/devices/0000:00:04.0/config | Bin .../devices/0000:00:04.0/consistent_dma_mask_bits | 0 .../bus/pci/devices/0000:00:04.0/current_link_speed | 0 .../bus/pci/devices/0000:00:04.0/current_link_width | 0 .../sys/bus/pci/devices/0000:00:04.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:04.0/device | 0 .../sys/bus/pci/devices/0000:00:04.0/dma_mask_bits | 0 .../bus/pci/devices/0000:00:04.0/driver_override | 0 .../sys/bus/pci/devices/0000:00:04.0/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq | 0 .../sys/bus/pci/devices/0000:00:04.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:04.0/local_cpus | 0 .../sys/bus/pci/devices/0000:00:04.0/max_link_speed | 0 .../sys/bus/pci/devices/0000:00:04.0/max_link_width | 0 .../sys/bus/pci/devices/0000:00:04.0/modalias | 0 .../sys/bus/pci/devices/0000:00:04.0/msi_bus | 0 .../sys/bus/pci/devices/0000:00:04.0/numa_node | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools | 0 .../sys/bus/pci/devices/0000:00:04.0/power_state | 0 .../sys/bus/pci/devices/0000:00:04.0/revision | 0 .../bus/pci/devices/0000:00:04.0/subsystem_device | 0 .../bus/pci/devices/0000:00:04.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:04.0/vendor | 0 .../sys/bus/pci/devices/0000:00:11.1/ari_enabled | 0 .../pci/devices/0000:00:11.1/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.1/class | 0 .../sys/bus/pci/devices/0000:00:11.1/config | Bin .../devices/0000:00:11.1/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:00:11.1/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:11.1/device | 0 .../sys/bus/pci/devices/0000:00:11.1/dma_mask_bits | 0 .../bus/pci/devices/0000:00:11.1/driver_override | 0 .../sys/bus/pci/devices/0000:00:11.1/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq | 0 .../sys/bus/pci/devices/0000:00:11.1/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:11.1/local_cpus | 0 .../sys/bus/pci/devices/0000:00:11.1/modalias | 0 .../sys/bus/pci/devices/0000:00:11.1/msi_bus | 0 .../sys/bus/pci/devices/0000:00:11.1/numa_node | 0 .../sys/bus/pci/devices/0000:00:11.1/power_state | 0 .../sys/bus/pci/devices/0000:00:11.1/revision | 0 .../bus/pci/devices/0000:00:11.1/subsystem_device | 0 .../bus/pci/devices/0000:00:11.1/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:11.1/vendor | 0 .../pci/devices/0000:00:11.1/waiting_for_supplier | 0 .../sys/bus/pci/devices/0000:00:11.5/ari_enabled | 0 .../pci/devices/0000:00:11.5/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.5/class | 0 .../sys/bus/pci/devices/0000:00:11.5/config | Bin .../devices/0000:00:11.5/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:00:11.5/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:11.5/device | 0 .../sys/bus/pci/devices/0000:00:11.5/dma_mask_bits | 0 .../bus/pci/devices/0000:00:11.5/driver_override | 0 .../sys/bus/pci/devices/0000:00:11.5/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.5/index | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:11.5/label | 0 .../sys/bus/pci/devices/0000:00:11.5/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:11.5/local_cpus | 0 .../sys/bus/pci/devices/0000:00:11.5/modalias | 0 .../sys/bus/pci/devices/0000:00:11.5/msi_bus | 0 .../sys/bus/pci/devices/0000:00:11.5/numa_node | 0 .../sys/bus/pci/devices/0000:00:11.5/power_state | 0 .../sys/bus/pci/devices/0000:00:11.5/remapped_nvme | 0 .../sys/bus/pci/devices/0000:00:11.5/revision | 0 .../bus/pci/devices/0000:00:11.5/subsystem_device | 0 .../bus/pci/devices/0000:00:11.5/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:11.5/vendor | 0 .../sys/bus/pci/devices/0000:00:14.2/ari_enabled | 0 .../pci/devices/0000:00:14.2/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:14.2/class | 0 .../sys/bus/pci/devices/0000:00:14.2/config | Bin .../devices/0000:00:14.2/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:00:14.2/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:14.2/device | 0 .../sys/bus/pci/devices/0000:00:14.2/dma_mask_bits | 0 .../bus/pci/devices/0000:00:14.2/driver_override | 0 .../sys/bus/pci/devices/0000:00:14.2/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq | 0 .../sys/bus/pci/devices/0000:00:14.2/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:14.2/local_cpus | 0 .../sys/bus/pci/devices/0000:00:14.2/modalias | 0 .../sys/bus/pci/devices/0000:00:14.2/msi_bus | 0 .../sys/bus/pci/devices/0000:00:14.2/numa_node | 0 .../sys/bus/pci/devices/0000:00:14.2/power_state | 0 .../sys/bus/pci/devices/0000:00:14.2/revision | 0 .../bus/pci/devices/0000:00:14.2/subsystem_device | 0 .../bus/pci/devices/0000:00:14.2/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:14.2/vendor | 0 .../sys/bus/pci/devices/0000:00:16.0/ari_enabled | 0 .../pci/devices/0000:00:16.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:16.0/class | 0 .../sys/bus/pci/devices/0000:00:16.0/config | Bin .../devices/0000:00:16.0/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:00:16.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:16.0/device | 0 .../sys/bus/pci/devices/0000:00:16.0/dma_mask_bits | 0 .../bus/pci/devices/0000:00:16.0/driver_override | 0 .../sys/bus/pci/devices/0000:00:16.0/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq | 0 .../sys/bus/pci/devices/0000:00:16.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:16.0/local_cpus | 0 .../sys/bus/pci/devices/0000:00:16.0/modalias | 0 .../sys/bus/pci/devices/0000:00:16.0/msi_bus | 0 .../sys/bus/pci/devices/0000:00:16.0/numa_node | 0 .../sys/bus/pci/devices/0000:00:16.0/power_state | 0 .../sys/bus/pci/devices/0000:00:16.0/revision | 0 .../bus/pci/devices/0000:00:16.0/subsystem_device | 0 .../bus/pci/devices/0000:00:16.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:16.0/vendor | 0 .../pci/devices/0000:00:16.0/waiting_for_supplier | 0 .../sys/bus/pci/devices/0000:00:1c.0/ari_enabled | 0 .../pci/devices/0000:00:1c.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class | 0 .../sys/bus/pci/devices/0000:00:1c.0/config | Bin .../devices/0000:00:1c.0/consistent_dma_mask_bits | 0 .../bus/pci/devices/0000:00:1c.0/current_link_speed | 0 .../bus/pci/devices/0000:00:1c.0/current_link_width | 0 .../sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:1c.0/device | 0 .../sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits | 0 .../bus/pci/devices/0000:00:1c.0/driver_override | 0 .../sys/bus/pci/devices/0000:00:1c.0/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq | 0 .../sys/bus/pci/devices/0000:00:1c.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:1c.0/local_cpus | 0 .../sys/bus/pci/devices/0000:00:1c.0/max_link_speed | 0 .../sys/bus/pci/devices/0000:00:1c.0/max_link_width | 0 .../sys/bus/pci/devices/0000:00:1c.0/modalias | 0 .../sys/bus/pci/devices/0000:00:1c.0/msi_bus | 0 .../sys/bus/pci/devices/0000:00:1c.0/numa_node | 0 .../sys/bus/pci/devices/0000:00:1c.0/power_state | 0 .../sys/bus/pci/devices/0000:00:1c.0/reset_method | 0 .../sys/bus/pci/devices/0000:00:1c.0/revision | 0 .../pci/devices/0000:00:1c.0/secondary_bus_number | 0 .../pci/devices/0000:00:1c.0/subordinate_bus_number | 0 .../bus/pci/devices/0000:00:1c.0/subsystem_device | 0 .../bus/pci/devices/0000:00:1c.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:1c.0/vendor | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class | 0 .../sys/bus/pci/devices/0000:00:1f.5/ari_enabled | 0 .../pci/devices/0000:00:1f.5/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class | 0 .../sys/bus/pci/devices/0000:00:1f.5/config | Bin .../devices/0000:00:1f.5/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:00:1f.5/device | 0 .../sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits | 0 .../bus/pci/devices/0000:00:1f.5/driver_override | 0 .../sys/bus/pci/devices/0000:00:1f.5/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq | 0 .../sys/bus/pci/devices/0000:00:1f.5/local_cpulist | 0 .../sys/bus/pci/devices/0000:00:1f.5/local_cpus | 0 .../sys/bus/pci/devices/0000:00:1f.5/modalias | 0 .../sys/bus/pci/devices/0000:00:1f.5/msi_bus | 0 .../sys/bus/pci/devices/0000:00:1f.5/numa_node | 0 .../sys/bus/pci/devices/0000:00:1f.5/power_state | 0 .../sys/bus/pci/devices/0000:00:1f.5/revision | 0 .../bus/pci/devices/0000:00:1f.5/subsystem_device | 0 .../bus/pci/devices/0000:00:1f.5/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:00:1f.5/vendor | 0 .../pci/devices/0000:00:1f.5/waiting_for_supplier | 0 .../sys/bus/pci/devices/0000:02:00.0/ari_enabled | 0 .../sys/bus/pci/devices/0000:02:00.0/boot_vga | 0 .../pci/devices/0000:02:00.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:02:00.0/class | 0 .../sys/bus/pci/devices/0000:02:00.0/config | Bin .../devices/0000:02:00.0/consistent_dma_mask_bits | 0 .../sys/bus/pci/devices/0000:02:00.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:02:00.0/device | 0 .../sys/bus/pci/devices/0000:02:00.0/dma_mask_bits | 0 .../bus/pci/devices/0000:02:00.0/driver_override | 0 .../sys/bus/pci/devices/0000:02:00.0/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:02:00.0/index | 0 .../rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq | 0 .../rootfs-1/sys/bus/pci/devices/0000:02:00.0/label | 0 .../sys/bus/pci/devices/0000:02:00.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:02:00.0/local_cpus | 0 .../sys/bus/pci/devices/0000:02:00.0/modalias | 0 .../sys/bus/pci/devices/0000:02:00.0/msi_bus | 0 .../sys/bus/pci/devices/0000:02:00.0/numa_node | 0 .../sys/bus/pci/devices/0000:02:00.0/power_state | 0 .../sys/bus/pci/devices/0000:02:00.0/reset_method | 0 .../sys/bus/pci/devices/0000:02:00.0/revision | 0 .../bus/pci/devices/0000:02:00.0/subsystem_device | 0 .../bus/pci/devices/0000:02:00.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:02:00.0/vendor | 0 .../sys/bus/pci/devices/0000:3b:00.0/ari_enabled | 0 .../pci/devices/0000:3b:00.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class | 0 .../sys/bus/pci/devices/0000:3b:00.0/config | Bin .../devices/0000:3b:00.0/consistent_dma_mask_bits | 0 .../bus/pci/devices/0000:3b:00.0/current_link_speed | 0 .../bus/pci/devices/0000:3b:00.0/current_link_width | 0 .../sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:3b:00.0/device | 0 .../sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits | 0 .../bus/pci/devices/0000:3b:00.0/driver_override | 0 .../sys/bus/pci/devices/0000:3b:00.0/enable | 0 .../devices/0000:3b:00.0/iommu/intel-iommu/version | 0 .../bus/pci/devices/0000:3b:00.0/iommu_group/type | 0 .../rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq | 0 .../sys/bus/pci/devices/0000:3b:00.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:3b:00.0/local_cpus | 0 .../sys/bus/pci/devices/0000:3b:00.0/max_link_speed | 0 .../sys/bus/pci/devices/0000:3b:00.0/max_link_width | 0 .../sys/bus/pci/devices/0000:3b:00.0/modalias | 0 .../sys/bus/pci/devices/0000:3b:00.0/msi_bus | 0 .../sys/bus/pci/devices/0000:3b:00.0/numa_node | 0 .../sys/bus/pci/devices/0000:3b:00.0/power_state | 0 .../sys/bus/pci/devices/0000:3b:00.0/reset_method | 0 .../sys/bus/pci/devices/0000:3b:00.0/revision | 0 .../devices/0000:3b:00.0/sriov_drivers_autoprobe | 0 .../sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs | 0 .../sys/bus/pci/devices/0000:3b:00.0/sriov_offset | 0 .../sys/bus/pci/devices/0000:3b:00.0/sriov_stride | 0 .../sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs | 0 .../bus/pci/devices/0000:3b:00.0/sriov_vf_device | 0 .../pci/devices/0000:3b:00.0/sriov_vf_total_msix | 0 .../bus/pci/devices/0000:3b:00.0/subsystem_device | 0 .../bus/pci/devices/0000:3b:00.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:3b:00.0/vendor | 0 .../sys/bus/pci/devices/0000:3f:00.0/ari_enabled | 0 .../pci/devices/0000:3f:00.0/broken_parity_status | 0 .../rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class | 0 .../sys/bus/pci/devices/0000:3f:00.0/config | Bin .../devices/0000:3f:00.0/consistent_dma_mask_bits | 0 .../bus/pci/devices/0000:3f:00.0/current_link_speed | 0 .../bus/pci/devices/0000:3f:00.0/current_link_width | 0 .../sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed | 0 .../sys/bus/pci/devices/0000:3f:00.0/device | 0 .../sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits | 0 .../bus/pci/devices/0000:3f:00.0/driver_override | 0 .../sys/bus/pci/devices/0000:3f:00.0/enable | 0 .../rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index | 0 .../rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq | 0 .../rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label | 0 .../sys/bus/pci/devices/0000:3f:00.0/local_cpulist | 0 .../sys/bus/pci/devices/0000:3f:00.0/local_cpus | 0 .../sys/bus/pci/devices/0000:3f:00.0/max_link_speed | 0 .../sys/bus/pci/devices/0000:3f:00.0/max_link_width | 0 .../sys/bus/pci/devices/0000:3f:00.0/modalias | 0 .../sys/bus/pci/devices/0000:3f:00.0/msi_bus | 0 .../sys/bus/pci/devices/0000:3f:00.0/numa_node | 0 .../sys/bus/pci/devices/0000:3f:00.0/power_state | 0 .../sys/bus/pci/devices/0000:3f:00.0/reset_method | 0 .../sys/bus/pci/devices/0000:3f:00.0/revision | 0 .../devices/0000:3f:00.0/sriov_drivers_autoprobe | 0 .../sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs | 0 .../sys/bus/pci/devices/0000:3f:00.0/sriov_offset | 0 .../sys/bus/pci/devices/0000:3f:00.0/sriov_stride | 0 .../sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs | 0 .../bus/pci/devices/0000:3f:00.0/sriov_vf_device | 0 .../pci/devices/0000:3f:00.0/sriov_vf_total_msix | 0 .../bus/pci/devices/0000:3f:00.0/subsystem_device | 0 .../bus/pci/devices/0000:3f:00.0/subsystem_vendor | 0 .../sys/bus/pci/devices/0000:3f:00.0/vendor | 0 263 files changed, 2 insertions(+), 9 deletions(-) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:04.0/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.1/waiting_for_supplier (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/index (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/label (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/remapped_nvme (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:11.5/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:14.2/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:16.0/waiting_for_supplier (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/reset_method (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/secondary_bus_number (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subordinate_bus_number (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/waiting_for_supplier (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/boot_vga (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/index (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/label (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/reset_method (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:02:00.0/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu/intel-iommu/version (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu_group/type (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/reset_method (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_drivers_autoprobe (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_offset (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_stride (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_total_msix (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/ari_enabled (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/broken_parity_status (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/config (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/consistent_dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/driver_override (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/enable (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpulist (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_speed (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_width (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/modalias (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/msi_bus (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/numa_node (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/power_state (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/reset_method (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/revision (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_drivers_autoprobe (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_offset (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_stride (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_total_msix (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_device (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_vendor (100%) rename {source/pci/testdata => testdata/source/pci}/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/vendor (100%) diff --git a/source/pci/pci_test.go b/source/pci/pci_test.go index 778b961e63..5390a8a5d6 100644 --- a/source/pci/pci_test.go +++ b/source/pci/pci_test.go @@ -18,7 +18,6 @@ package pci import ( "path/filepath" - "runtime" "testing" "github.com/stretchr/testify/assert" @@ -27,13 +26,6 @@ import ( "sigs.k8s.io/node-feature-discovery/source" ) -var packagePath string - -func init() { - _, thisFile, _, _ := runtime.Caller(0) - packagePath = filepath.Dir(thisFile) -} - func TestSingletonPciSource(t *testing.T) { assert.Equal(t, src.Name(), Name) @@ -232,7 +224,8 @@ func TestPciSource(t *testing.T) { // Run test cases for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - hostpath.SysfsDir = hostpath.HostDir(filepath.Join(packagePath, "testdata", tc.rootfs, "sys")) + mockSysfsPath := filepath.Join("..", "..", "testdata", "source", "pci", tc.rootfs, "sys") + hostpath.SysfsDir = hostpath.HostDir(mockSysfsPath) config := tc.config if config == nil { diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/current_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/max_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/pools diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:04.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:04.0/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/waiting_for_supplier b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/waiting_for_supplier similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.1/waiting_for_supplier rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.1/waiting_for_supplier diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/index b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/index similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/index rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/index diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/label b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/label similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/label rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/label diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/remapped_nvme b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/remapped_nvme similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/remapped_nvme rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/remapped_nvme diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:11.5/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:11.5/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:14.2/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:14.2/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/waiting_for_supplier b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/waiting_for_supplier similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:16.0/waiting_for_supplier rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:16.0/waiting_for_supplier diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/current_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/max_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/reset_method b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/reset_method similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/reset_method rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/reset_method diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/secondary_bus_number b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/secondary_bus_number similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/secondary_bus_number rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/secondary_bus_number diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subordinate_bus_number b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subordinate_bus_number similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subordinate_bus_number rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subordinate_bus_number diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1c.0/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/REAME diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.2/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/waiting_for_supplier b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/waiting_for_supplier similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/waiting_for_supplier rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:00:1f.5/waiting_for_supplier diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/boot_vga b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/boot_vga similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/boot_vga rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/boot_vga diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/index b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/index similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/index rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/index diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/label b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/label similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/label rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/label diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/reset_method b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/reset_method similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/reset_method rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/reset_method diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:02:00.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:02:00.0/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/current_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu/intel-iommu/version b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu/intel-iommu/version similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu/intel-iommu/version rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu/intel-iommu/version diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu_group/type b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu_group/type similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu_group/type rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/iommu_group/type diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/max_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/reset_method b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/reset_method similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/reset_method rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/reset_method diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_drivers_autoprobe b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_drivers_autoprobe similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_drivers_autoprobe rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_drivers_autoprobe diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_offset b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_offset similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_offset rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_offset diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_stride b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_stride similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_stride rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_stride diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_total_msix b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_total_msix similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_total_msix rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/sriov_vf_total_msix diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3b:00.0/vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/ari_enabled b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/ari_enabled similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/ari_enabled rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/ari_enabled diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/broken_parity_status b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/broken_parity_status similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/broken_parity_status rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/broken_parity_status diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/class diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/config b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/config similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/config rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/config diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/consistent_dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/consistent_dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/consistent_dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/consistent_dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/current_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/d3cold_allowed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/dma_mask_bits diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/driver_override b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/driver_override similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/driver_override rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/driver_override diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/enable b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/enable similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/enable rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/enable diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/index diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/irq diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/label diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpulist b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpulist similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpulist rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpulist diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/local_cpus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_speed b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_speed similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_speed rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_speed diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_width b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_width similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_width rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/max_link_width diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/modalias b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/modalias similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/modalias rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/modalias diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/msi_bus b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/msi_bus similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/msi_bus rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/msi_bus diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/numa_node b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/numa_node similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/numa_node rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/numa_node diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/power_state b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/power_state similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/power_state rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/power_state diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/reset_method b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/reset_method similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/reset_method rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/reset_method diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/revision b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/revision similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/revision rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/revision diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_drivers_autoprobe b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_drivers_autoprobe similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_drivers_autoprobe rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_drivers_autoprobe diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_numvfs diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_offset b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_offset similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_offset rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_offset diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_stride b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_stride similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_stride rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_stride diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_totalvfs diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_total_msix b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_total_msix similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_total_msix rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/sriov_vf_total_msix diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_device b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_device similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_device rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_device diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/subsystem_vendor diff --git a/source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/vendor b/testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/vendor similarity index 100% rename from source/pci/testdata/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/vendor rename to testdata/source/pci/rootfs-1/sys/bus/pci/devices/0000:3f:00.0/vendor From 8ada0b04affae174d00c35bbfca2d1f5dbc1cc7f Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Tue, 22 Oct 2024 18:14:54 +0200 Subject: [PATCH 8/8] Convert testdata to an empty go module This ensures that the testdata folder is not included in the top-level module and prevents issues such as unsupported characters in path names. Signed-off-by: Evan Lezar --- testdata/README.md | 3 +++ testdata/go.mod | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 testdata/README.md create mode 100644 testdata/go.mod diff --git a/testdata/README.md b/testdata/README.md new file mode 100644 index 0000000000..ff08cb1de6 --- /dev/null +++ b/testdata/README.md @@ -0,0 +1,3 @@ +Some of the test data in this folder contains colon characters which causes "go get" commands to fail with "invalid char ':'". +The empty go.mod file is a workaround to prevent this error. This effectively makes this folder its own go module, so it will be +ignored when "go get" is executed. diff --git a/testdata/go.mod b/testdata/go.mod new file mode 100644 index 0000000000..effa259575 --- /dev/null +++ b/testdata/go.mod @@ -0,0 +1,3 @@ +// This empty go.mod file ensures that the testdata folder is not included +// in the top-level module. This prevents issues such as unsupported characters +// in path names.