From cb5a902f6d356e5dee02d4a47c44d4d4be1d7386 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakivskyy Date: Fri, 4 Oct 2024 14:37:47 +0300 Subject: [PATCH] nfd-master: Add status for NodeFeatureRule CRD Signed-off-by: Oleg Zhurakivskyy --- .../nfd/v1alpha1/fake/fake_nfd_client.go | 4 + .../nfd/v1alpha1/fake/fake_nodefeaturerule.go | 11 ++ .../fake/fake_nodefeaturerulestatus.go | 129 +++++++++++++ .../typed/nfd/v1alpha1/generated_expansion.go | 2 + .../typed/nfd/v1alpha1/nfd_client.go | 5 + .../typed/nfd/v1alpha1/nodefeaturerule.go | 16 ++ .../nfd/v1alpha1/nodefeaturerulestatus.go | 178 ++++++++++++++++++ .../informers/externalversions/generic.go | 2 + .../nfd/v1alpha1/interface.go | 7 + .../nfd/v1alpha1/nodefeaturerulestatus.go | 90 +++++++++ .../nfd/v1alpha1/expansion_generated.go | 8 + .../nfd/v1alpha1/nodefeaturerulestatus.go | 99 ++++++++++ api/nfd/v1alpha1/types.go | 32 ++++ api/nfd/v1alpha1/zz_generated.deepcopy.go | 88 +++++++++ deployment/base/nfd-crds/nfd-api-crds.yaml | 97 ++++++++++ .../crds/nfd-api-crds.yaml | 97 ++++++++++ pkg/apis/nfd/nodefeaturerule/rule.go | 2 + pkg/nfd-master/nfd-master.go | 95 +++++++++- 18 files changed, 957 insertions(+), 5 deletions(-) create mode 100644 api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerulestatus.go create mode 100644 api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerulestatus.go create mode 100644 api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturerulestatus.go create mode 100644 api/generated/listers/nfd/v1alpha1/nodefeaturerulestatus.go diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go index 282a6e717b..51d607f35d 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go @@ -40,6 +40,10 @@ func (c *FakeNfdV1alpha1) NodeFeatureRules() v1alpha1.NodeFeatureRuleInterface { return &FakeNodeFeatureRules{c} } +func (c *FakeNfdV1alpha1) NodeFeatureRuleStatuses(namespace string) v1alpha1.NodeFeatureRuleStatusInterface { + return &FakeNodeFeatureRuleStatuses{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeNfdV1alpha1) RESTClient() rest.Interface { diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go index f096ae5e3d..8edd86eae2 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go @@ -95,6 +95,17 @@ func (c *FakeNodeFeatureRules) Update(ctx context.Context, nodeFeatureRule *v1al return obj.(*v1alpha1.NodeFeatureRule), err } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeNodeFeatureRules) UpdateStatus(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureRule, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(nodefeaturerulesResource, "status", nodeFeatureRule), &v1alpha1.NodeFeatureRule{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureRule), err +} + // Delete takes name of the nodeFeatureRule and deletes it. Returns an error if one occurs. func (c *FakeNodeFeatureRules) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { _, err := c.Fake. diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerulestatus.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerulestatus.go new file mode 100644 index 0000000000..6933d8f2a5 --- /dev/null +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerulestatus.go @@ -0,0 +1,129 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" +) + +// FakeNodeFeatureRuleStatuses implements NodeFeatureRuleStatusInterface +type FakeNodeFeatureRuleStatuses struct { + Fake *FakeNfdV1alpha1 + ns string +} + +var nodefeaturerulestatusesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerulestatuses") + +var nodefeaturerulestatusesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRuleStatus") + +// Get takes name of the nodeFeatureRuleStatus, and returns the corresponding nodeFeatureRuleStatus object, and an error if there is any. +func (c *FakeNodeFeatureRuleStatuses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(nodefeaturerulestatusesResource, c.ns, name), &v1alpha1.NodeFeatureRuleStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureRuleStatus), err +} + +// List takes label and field selectors, and returns the list of NodeFeatureRuleStatuses that match those selectors. +func (c *FakeNodeFeatureRuleStatuses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureRuleStatusList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(nodefeaturerulestatusesResource, nodefeaturerulestatusesKind, c.ns, opts), &v1alpha1.NodeFeatureRuleStatusList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.NodeFeatureRuleStatusList{ListMeta: obj.(*v1alpha1.NodeFeatureRuleStatusList).ListMeta} + for _, item := range obj.(*v1alpha1.NodeFeatureRuleStatusList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested nodeFeatureRuleStatuses. +func (c *FakeNodeFeatureRuleStatuses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(nodefeaturerulestatusesResource, c.ns, opts)) + +} + +// Create takes the representation of a nodeFeatureRuleStatus and creates it. Returns the server's representation of the nodeFeatureRuleStatus, and an error, if there is any. +func (c *FakeNodeFeatureRuleStatuses) Create(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(nodefeaturerulestatusesResource, c.ns, nodeFeatureRuleStatus), &v1alpha1.NodeFeatureRuleStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureRuleStatus), err +} + +// Update takes the representation of a nodeFeatureRuleStatus and updates it. Returns the server's representation of the nodeFeatureRuleStatus, and an error, if there is any. +func (c *FakeNodeFeatureRuleStatuses) Update(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(nodefeaturerulestatusesResource, c.ns, nodeFeatureRuleStatus), &v1alpha1.NodeFeatureRuleStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureRuleStatus), err +} + +// Delete takes name of the nodeFeatureRuleStatus and deletes it. Returns an error if one occurs. +func (c *FakeNodeFeatureRuleStatuses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(nodefeaturerulestatusesResource, c.ns, name, opts), &v1alpha1.NodeFeatureRuleStatus{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeNodeFeatureRuleStatuses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(nodefeaturerulestatusesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureRuleStatusList{}) + return err +} + +// Patch applies the patch and returns the patched nodeFeatureRuleStatus. +func (c *FakeNodeFeatureRuleStatuses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(nodefeaturerulestatusesResource, c.ns, name, pt, data, subresources...), &v1alpha1.NodeFeatureRuleStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureRuleStatus), err +} diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go index 02d3e35186..950352df8a 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go @@ -23,3 +23,5 @@ type NodeFeatureExpansion interface{} type NodeFeatureGroupExpansion interface{} type NodeFeatureRuleExpansion interface{} + +type NodeFeatureRuleStatusExpansion interface{} diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go index 37a6f340aa..9ae99c5cca 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go @@ -31,6 +31,7 @@ type NfdV1alpha1Interface interface { NodeFeaturesGetter NodeFeatureGroupsGetter NodeFeatureRulesGetter + NodeFeatureRuleStatusesGetter } // NfdV1alpha1Client is used to interact with features provided by the nfd.k8s-sigs.io group. @@ -50,6 +51,10 @@ func (c *NfdV1alpha1Client) NodeFeatureRules() NodeFeatureRuleInterface { return newNodeFeatureRules(c) } +func (c *NfdV1alpha1Client) NodeFeatureRuleStatuses(namespace string) NodeFeatureRuleStatusInterface { + return newNodeFeatureRuleStatuses(c, namespace) +} + // NewForConfig creates a new NfdV1alpha1Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerule.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerule.go index 843c13768e..8fddf4262b 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerule.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerule.go @@ -40,6 +40,7 @@ type NodeFeatureRulesGetter interface { type NodeFeatureRuleInterface interface { Create(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.CreateOptions) (*v1alpha1.NodeFeatureRule, error) Update(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureRule, error) + UpdateStatus(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureRule, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeatureRule, error) @@ -128,6 +129,21 @@ func (c *nodeFeatureRules) Update(ctx context.Context, nodeFeatureRule *v1alpha1 return } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *nodeFeatureRules) UpdateStatus(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureRule, err error) { + result = &v1alpha1.NodeFeatureRule{} + err = c.client.Put(). + Resource("nodefeaturerules"). + Name(nodeFeatureRule.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeatureRule). + Do(ctx). + Into(result) + return +} + // Delete takes name of the nodeFeatureRule and deletes it. Returns an error if one occurs. func (c *nodeFeatureRules) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { return c.client.Delete(). diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerulestatus.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerulestatus.go new file mode 100644 index 0000000000..e58f428ceb --- /dev/null +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturerulestatus.go @@ -0,0 +1,178 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme" + v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" +) + +// NodeFeatureRuleStatusesGetter has a method to return a NodeFeatureRuleStatusInterface. +// A group's client should implement this interface. +type NodeFeatureRuleStatusesGetter interface { + NodeFeatureRuleStatuses(namespace string) NodeFeatureRuleStatusInterface +} + +// NodeFeatureRuleStatusInterface has methods to work with NodeFeatureRuleStatus resources. +type NodeFeatureRuleStatusInterface interface { + Create(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.CreateOptions) (*v1alpha1.NodeFeatureRuleStatus, error) + Update(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureRuleStatus, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeatureRuleStatus, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureRuleStatusList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureRuleStatus, err error) + NodeFeatureRuleStatusExpansion +} + +// nodeFeatureRuleStatuses implements NodeFeatureRuleStatusInterface +type nodeFeatureRuleStatuses struct { + client rest.Interface + ns string +} + +// newNodeFeatureRuleStatuses returns a NodeFeatureRuleStatuses +func newNodeFeatureRuleStatuses(c *NfdV1alpha1Client, namespace string) *nodeFeatureRuleStatuses { + return &nodeFeatureRuleStatuses{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the nodeFeatureRuleStatus, and returns the corresponding nodeFeatureRuleStatus object, and an error if there is any. +func (c *nodeFeatureRuleStatuses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + result = &v1alpha1.NodeFeatureRuleStatus{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of NodeFeatureRuleStatuses that match those selectors. +func (c *nodeFeatureRuleStatuses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureRuleStatusList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.NodeFeatureRuleStatusList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested nodeFeatureRuleStatuses. +func (c *nodeFeatureRuleStatuses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a nodeFeatureRuleStatus and creates it. Returns the server's representation of the nodeFeatureRuleStatus, and an error, if there is any. +func (c *nodeFeatureRuleStatuses) Create(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + result = &v1alpha1.NodeFeatureRuleStatus{} + err = c.client.Post(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeatureRuleStatus). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a nodeFeatureRuleStatus and updates it. Returns the server's representation of the nodeFeatureRuleStatus, and an error, if there is any. +func (c *nodeFeatureRuleStatuses) Update(ctx context.Context, nodeFeatureRuleStatus *v1alpha1.NodeFeatureRuleStatus, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + result = &v1alpha1.NodeFeatureRuleStatus{} + err = c.client.Put(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + Name(nodeFeatureRuleStatus.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeatureRuleStatus). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the nodeFeatureRuleStatus and deletes it. Returns an error if one occurs. +func (c *nodeFeatureRuleStatuses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *nodeFeatureRuleStatuses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched nodeFeatureRuleStatus. +func (c *nodeFeatureRuleStatuses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureRuleStatus, err error) { + result = &v1alpha1.NodeFeatureRuleStatus{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("nodefeaturerulestatuses"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/api/generated/informers/externalversions/generic.go b/api/generated/informers/externalversions/generic.go index 86577fff52..f51ec850a8 100644 --- a/api/generated/informers/externalversions/generic.go +++ b/api/generated/informers/externalversions/generic.go @@ -59,6 +59,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatureGroups().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules"): return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatureRules().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerulestatuses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatureRuleStatuses().Informer()}, nil } diff --git a/api/generated/informers/externalversions/nfd/v1alpha1/interface.go b/api/generated/informers/externalversions/nfd/v1alpha1/interface.go index ea861a472f..4d6c6a0c6b 100644 --- a/api/generated/informers/externalversions/nfd/v1alpha1/interface.go +++ b/api/generated/informers/externalversions/nfd/v1alpha1/interface.go @@ -30,6 +30,8 @@ type Interface interface { NodeFeatureGroups() NodeFeatureGroupInformer // NodeFeatureRules returns a NodeFeatureRuleInformer. NodeFeatureRules() NodeFeatureRuleInformer + // NodeFeatureRuleStatuses returns a NodeFeatureRuleStatusInformer. + NodeFeatureRuleStatuses() NodeFeatureRuleStatusInformer } type version struct { @@ -57,3 +59,8 @@ func (v *version) NodeFeatureGroups() NodeFeatureGroupInformer { func (v *version) NodeFeatureRules() NodeFeatureRuleInformer { return &nodeFeatureRuleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } + +// NodeFeatureRuleStatuses returns a NodeFeatureRuleStatusInformer. +func (v *version) NodeFeatureRuleStatuses() NodeFeatureRuleStatusInformer { + return &nodeFeatureRuleStatusInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturerulestatus.go b/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturerulestatus.go new file mode 100644 index 0000000000..68759f66d3 --- /dev/null +++ b/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturerulestatus.go @@ -0,0 +1,90 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned" + internalinterfaces "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/internalinterfaces" + v1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/listers/nfd/v1alpha1" + nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" +) + +// NodeFeatureRuleStatusInformer provides access to a shared informer and lister for +// NodeFeatureRuleStatuses. +type NodeFeatureRuleStatusInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.NodeFeatureRuleStatusLister +} + +type nodeFeatureRuleStatusInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNodeFeatureRuleStatusInformer constructs a new informer for NodeFeatureRuleStatus type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNodeFeatureRuleStatusInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNodeFeatureRuleStatusInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNodeFeatureRuleStatusInformer constructs a new informer for NodeFeatureRuleStatus type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNodeFeatureRuleStatusInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NfdV1alpha1().NodeFeatureRuleStatuses(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NfdV1alpha1().NodeFeatureRuleStatuses(namespace).Watch(context.TODO(), options) + }, + }, + &nfdv1alpha1.NodeFeatureRuleStatus{}, + resyncPeriod, + indexers, + ) +} + +func (f *nodeFeatureRuleStatusInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNodeFeatureRuleStatusInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *nodeFeatureRuleStatusInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&nfdv1alpha1.NodeFeatureRuleStatus{}, f.defaultInformer) +} + +func (f *nodeFeatureRuleStatusInformer) Lister() v1alpha1.NodeFeatureRuleStatusLister { + return v1alpha1.NewNodeFeatureRuleStatusLister(f.Informer().GetIndexer()) +} diff --git a/api/generated/listers/nfd/v1alpha1/expansion_generated.go b/api/generated/listers/nfd/v1alpha1/expansion_generated.go index 5890048ee1..d3e48d9886 100644 --- a/api/generated/listers/nfd/v1alpha1/expansion_generated.go +++ b/api/generated/listers/nfd/v1alpha1/expansion_generated.go @@ -37,3 +37,11 @@ type NodeFeatureGroupNamespaceListerExpansion interface{} // NodeFeatureRuleListerExpansion allows custom methods to be added to // NodeFeatureRuleLister. type NodeFeatureRuleListerExpansion interface{} + +// NodeFeatureRuleStatusListerExpansion allows custom methods to be added to +// NodeFeatureRuleStatusLister. +type NodeFeatureRuleStatusListerExpansion interface{} + +// NodeFeatureRuleStatusNamespaceListerExpansion allows custom methods to be added to +// NodeFeatureRuleStatusNamespaceLister. +type NodeFeatureRuleStatusNamespaceListerExpansion interface{} diff --git a/api/generated/listers/nfd/v1alpha1/nodefeaturerulestatus.go b/api/generated/listers/nfd/v1alpha1/nodefeaturerulestatus.go new file mode 100644 index 0000000000..992f627357 --- /dev/null +++ b/api/generated/listers/nfd/v1alpha1/nodefeaturerulestatus.go @@ -0,0 +1,99 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" +) + +// NodeFeatureRuleStatusLister helps list NodeFeatureRuleStatuses. +// All objects returned here must be treated as read-only. +type NodeFeatureRuleStatusLister interface { + // List lists all NodeFeatureRuleStatuses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureRuleStatus, err error) + // NodeFeatureRuleStatuses returns an object that can list and get NodeFeatureRuleStatuses. + NodeFeatureRuleStatuses(namespace string) NodeFeatureRuleStatusNamespaceLister + NodeFeatureRuleStatusListerExpansion +} + +// nodeFeatureRuleStatusLister implements the NodeFeatureRuleStatusLister interface. +type nodeFeatureRuleStatusLister struct { + indexer cache.Indexer +} + +// NewNodeFeatureRuleStatusLister returns a new NodeFeatureRuleStatusLister. +func NewNodeFeatureRuleStatusLister(indexer cache.Indexer) NodeFeatureRuleStatusLister { + return &nodeFeatureRuleStatusLister{indexer: indexer} +} + +// List lists all NodeFeatureRuleStatuses in the indexer. +func (s *nodeFeatureRuleStatusLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureRuleStatus, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeFeatureRuleStatus)) + }) + return ret, err +} + +// NodeFeatureRuleStatuses returns an object that can list and get NodeFeatureRuleStatuses. +func (s *nodeFeatureRuleStatusLister) NodeFeatureRuleStatuses(namespace string) NodeFeatureRuleStatusNamespaceLister { + return nodeFeatureRuleStatusNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// NodeFeatureRuleStatusNamespaceLister helps list and get NodeFeatureRuleStatuses. +// All objects returned here must be treated as read-only. +type NodeFeatureRuleStatusNamespaceLister interface { + // List lists all NodeFeatureRuleStatuses in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureRuleStatus, err error) + // Get retrieves the NodeFeatureRuleStatus from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.NodeFeatureRuleStatus, error) + NodeFeatureRuleStatusNamespaceListerExpansion +} + +// nodeFeatureRuleStatusNamespaceLister implements the NodeFeatureRuleStatusNamespaceLister +// interface. +type nodeFeatureRuleStatusNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all NodeFeatureRuleStatuses in the indexer for a given namespace. +func (s nodeFeatureRuleStatusNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureRuleStatus, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeFeatureRuleStatus)) + }) + return ret, err +} + +// Get retrieves the NodeFeatureRuleStatus from the indexer for a given namespace and name. +func (s nodeFeatureRuleStatusNamespaceLister) Get(name string) (*v1alpha1.NodeFeatureRuleStatus, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("nodefeaturerulestatus"), name) + } + return obj.(*v1alpha1.NodeFeatureRuleStatus), nil +} diff --git a/api/nfd/v1alpha1/types.go b/api/nfd/v1alpha1/types.go index c89efd8185..7a5e8c06df 100644 --- a/api/nfd/v1alpha1/types.go +++ b/api/nfd/v1alpha1/types.go @@ -131,6 +131,8 @@ type NodeFeatureRule struct { // Spec defines the rules to be evaluated. Spec NodeFeatureRuleSpec `json:"spec"` + // +optional + Status NodeFeatureRuleStatus `json:"status"` } // NodeFeatureRuleSpec describes a NodeFeatureRule. @@ -139,6 +141,36 @@ type NodeFeatureRuleSpec struct { Rules []Rule `json:"rules"` } +// NodeFeatureRuleStatus represents the status of a NodeFeatureRule +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,shortName=nfs +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type NodeFeatureRuleStatus struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Rules []RuleStatus `json:"rules"` +} + +// RuleStatus contains information on matched rules and nodes +type RuleStatus struct { + Name string `json:"name"` + MatchedNodes []string `json:"matchedNodes"` +} + +// NodeFeatureRuleStatusList contains a list of NodeFeatureRuleStatus objects. +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type NodeFeatureRuleStatusList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []NodeFeatureRuleStatus `json:"items"` +} + // NodeFeatureGroup resource holds Node pools by featureGroup // +kubebuilder:object:root=true // +kubebuilder:resource:scope=Namespaced,shortName=nfg diff --git a/api/nfd/v1alpha1/zz_generated.deepcopy.go b/api/nfd/v1alpha1/zz_generated.deepcopy.go index 491d9866c4..06887f2b58 100644 --- a/api/nfd/v1alpha1/zz_generated.deepcopy.go +++ b/api/nfd/v1alpha1/zz_generated.deepcopy.go @@ -544,6 +544,7 @@ func (in *NodeFeatureRule) DeepCopyInto(out *NodeFeatureRule) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) return } @@ -621,6 +622,72 @@ func (in *NodeFeatureRuleSpec) DeepCopy() *NodeFeatureRuleSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeFeatureRuleStatus) DeepCopyInto(out *NodeFeatureRuleStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]RuleStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureRuleStatus. +func (in *NodeFeatureRuleStatus) DeepCopy() *NodeFeatureRuleStatus { + if in == nil { + return nil + } + out := new(NodeFeatureRuleStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeFeatureRuleStatus) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeFeatureRuleStatusList) DeepCopyInto(out *NodeFeatureRuleStatusList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NodeFeatureRuleStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureRuleStatusList. +func (in *NodeFeatureRuleStatusList) DeepCopy() *NodeFeatureRuleStatusList { + if in == nil { + return nil + } + out := new(NodeFeatureRuleStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeFeatureRuleStatusList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeFeatureSpec) DeepCopyInto(out *NodeFeatureSpec) { *out = *in @@ -709,3 +776,24 @@ func (in *Rule) DeepCopy() *Rule { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleStatus) DeepCopyInto(out *RuleStatus) { + *out = *in + if in.MatchedNodes != nil { + in, out := &in.MatchedNodes, &out.MatchedNodes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleStatus. +func (in *RuleStatus) DeepCopy() *RuleStatus { + if in == nil { + return nil + } + out := new(RuleStatus) + in.DeepCopyInto(out) + return out +} diff --git a/deployment/base/nfd-crds/nfd-api-crds.yaml b/deployment/base/nfd-crds/nfd-api-crds.yaml index 0a73c5dcae..2db0ec5916 100644 --- a/deployment/base/nfd-crds/nfd-api-crds.yaml +++ b/deployment/base/nfd-crds/nfd-api-crds.yaml @@ -703,8 +703,105 @@ spec: required: - rules type: object + status: + description: NodeFeatureRuleStatus represents the status of a NodeFeatureRule + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + rules: + items: + description: RuleStatus contains information on matched rules and + nodes + properties: + matchedNodes: + items: + type: string + type: array + name: + type: string + required: + - matchedNodes + - name + type: object + type: array + type: object required: - spec type: object served: true storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nodefeaturerulestatuses.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureRuleStatus + listKind: NodeFeatureRuleStatusList + plural: nodefeaturerulestatuses + shortNames: + - nfs + singular: nodefeaturerulestatus + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeatureRuleStatus represents the status of a NodeFeatureRule + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + rules: + items: + description: RuleStatus contains information on matched rules and nodes + properties: + matchedNodes: + items: + type: string + type: array + name: + type: string + required: + - matchedNodes + - name + type: object + type: array + type: object + served: true + storage: true + subresources: + status: {} diff --git a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml b/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml index 0a73c5dcae..2db0ec5916 100644 --- a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml +++ b/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml @@ -703,8 +703,105 @@ spec: required: - rules type: object + status: + description: NodeFeatureRuleStatus represents the status of a NodeFeatureRule + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + rules: + items: + description: RuleStatus contains information on matched rules and + nodes + properties: + matchedNodes: + items: + type: string + type: array + name: + type: string + required: + - matchedNodes + - name + type: object + type: array + type: object required: - spec type: object served: true storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nodefeaturerulestatuses.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureRuleStatus + listKind: NodeFeatureRuleStatusList + plural: nodefeaturerulestatuses + shortNames: + - nfs + singular: nodefeaturerulestatus + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeatureRuleStatus represents the status of a NodeFeatureRule + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + rules: + items: + description: RuleStatus contains information on matched rules and nodes + properties: + matchedNodes: + items: + type: string + type: array + name: + type: string + required: + - matchedNodes + - name + type: object + type: array + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/apis/nfd/nodefeaturerule/rule.go b/pkg/apis/nfd/nodefeaturerule/rule.go index b9a5629246..edc23fc064 100644 --- a/pkg/apis/nfd/nodefeaturerule/rule.go +++ b/pkg/apis/nfd/nodefeaturerule/rule.go @@ -39,6 +39,7 @@ type RuleOutput struct { Annotations map[string]string Vars map[string]string Taints []corev1.Taint + Matched bool } // Execute the rule against a set of input features. @@ -103,6 +104,7 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, e Annotations: maps.Clone(r.Annotations), ExtendedResources: maps.Clone(r.ExtendedResources), Taints: slices.Clone(r.Taints), + Matched: true, } klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret)) return ret, nil diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index 5babc12081..ffbddc1ff9 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -763,6 +763,12 @@ func (m *nfdMaster) nfdAPIUpdateAllNodes() error { m.updaterPool.addNode(node.Name) } + err = m.updateRuleStatus() + if err != nil { + klog.ErrorS(err, "failed to update rule status") + return err + } + return nil } @@ -982,7 +988,7 @@ func (m *nfdMaster) refreshNodeFeatures(cli k8sclient.Interface, node *corev1.No labels = make(map[string]string) } - crLabels, crAnnotations, crExtendedResources, crTaints := m.processNodeFeatureRule(node.Name, features) + crLabels, crAnnotations, crExtendedResources, crTaints, _ := m.processNodeFeatureRule(node.Name, features) // Mix in CR-originated labels maps.Copy(labels, crLabels) @@ -1112,9 +1118,9 @@ func authorizeClient(c context.Context, checkNodeName bool, nodeName string) err return nil } -func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha1.Features) (Labels, Annotations, ExtendedResources, []corev1.Taint) { +func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha1.Features) (Labels, Annotations, ExtendedResources, []corev1.Taint, []*nfdv1alpha1.NodeFeatureRule) { if m.nfdController == nil { - return nil, nil, nil, nil + return nil, nil, nil, nil, nil } extendedResources := ExtendedResources{} @@ -1128,12 +1134,13 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha if err != nil { klog.ErrorS(err, "failed to list NodeFeatureRule resources") - return nil, nil, nil, nil + return nil, nil, nil, nil, nil } // Process all rule CRs processStart := time.Now() for _, spec := range ruleSpecs { + spec.Status.Rules = []nfdv1alpha1.RuleStatus{} t := time.Now() switch { case klog.V(3).Enabled(): @@ -1165,13 +1172,91 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha // Feed back rule output to features map for subsequent rules to match features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Labels) features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Vars) + + if ruleOut.Matched { + r := nfdv1alpha1.RuleStatus{ + Name: rule.Name, + MatchedNodes: []string{ + nodeName, + }, + } + spec.Status.Rules = append(spec.Status.Rules, r) + } } nfrProcessingTime.WithLabelValues(spec.Name, nodeName).Observe(time.Since(t).Seconds()) } processingTime := time.Since(processStart) klog.V(2).InfoS("processed NodeFeatureRule objects", "nodeName", nodeName, "objectCount", len(ruleSpecs), "duration", processingTime) - return labels, annotations, extendedResources, taints + return labels, annotations, extendedResources, taints, ruleSpecs +} + +func findRuleByName(ruleSpecs []*nfdv1alpha1.NodeFeatureRule, name string) *nfdv1alpha1.NodeFeatureRule { + var spec *nfdv1alpha1.NodeFeatureRule + for _, r := range ruleSpecs { + if r.Name == name { + spec = r + break + } + } + return spec +} + +func findStatusRuleByName(status *[]nfdv1alpha1.RuleStatus, name string) *nfdv1alpha1.RuleStatus { + var rule *nfdv1alpha1.RuleStatus + for _, r := range *status { + if r.Name == name { + rule = &r + break + } + } + return rule +} + +func (m *nfdMaster) updateRuleStatus() error { + nodes, err := getNodes(m.k8sClient) + if err != nil { + return err + } + + var ruleSpecs []*nfdv1alpha1.NodeFeatureRule + var outSpecs []*nfdv1alpha1.NodeFeatureRule + + for _, node := range nodes.Items { + nodeFeatures, err := m.getAndMergeNodeFeatures(node.Name) + if err != nil { + return fmt.Errorf("failed to merge NodeFeature objects for node %q: %w", node.Name, err) + } + + _, _, _, _, ruleSpecs = m.processNodeFeatureRule(node.Name, &nodeFeatures.Spec.Features) + } + + for _, spec := range ruleSpecs { + if len(spec.Status.Rules) > 0 { + s := findRuleByName(outSpecs, spec.Name) + if s != nil { + for _, r := range spec.Status.Rules { + s.Status.Rules = append(s.Status.Rules, r) + + sr := findStatusRuleByName(&s.Status.Rules, r.Name) + if sr != nil { + sr.MatchedNodes = append(sr.MatchedNodes, r.MatchedNodes...) + } + } + } else { + outSpecs = append(outSpecs, spec) + } + } + } + + for _, spec := range outSpecs { + _, err = m.nfdClient.NfdV1alpha1().NodeFeatureRules().Update(context.TODO(), spec, metav1.UpdateOptions{}) + if err != nil { + klog.ErrorS(err, "failed to update rule status", "nodefeaturerule", klog.KObj(spec)) + } + } + + return nil } // updateNodeObject ensures the Kubernetes node object is up to date,