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..dac073505b 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) NodeFeatureStatuses(namespace string) v1alpha1.NodeFeatureStatusInterface { + return &FakeNodeFeatureStatuses{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_nodefeature.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go index f956c8217b..48b7212745 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go @@ -101,6 +101,18 @@ func (c *FakeNodeFeatures) Update(ctx context.Context, nodeFeature *v1alpha1.Nod return obj.(*v1alpha1.NodeFeature), 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 *FakeNodeFeatures) UpdateStatus(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (*v1alpha1.NodeFeature, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(nodefeaturesResource, "status", c.ns, nodeFeature), &v1alpha1.NodeFeature{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeature), err +} + // Delete takes name of the nodeFeature and deletes it. Returns an error if one occurs. func (c *FakeNodeFeatures) 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_nodefeaturestatus.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturestatus.go new file mode 100644 index 0000000000..6f91e066d3 --- /dev/null +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturestatus.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" +) + +// FakeNodeFeatureStatuses implements NodeFeatureStatusInterface +type FakeNodeFeatureStatuses struct { + Fake *FakeNfdV1alpha1 + ns string +} + +var nodefeaturestatusesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturestatuses") + +var nodefeaturestatusesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureStatus") + +// Get takes name of the nodeFeatureStatus, and returns the corresponding nodeFeatureStatus object, and an error if there is any. +func (c *FakeNodeFeatureStatuses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(nodefeaturestatusesResource, c.ns, name), &v1alpha1.NodeFeatureStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureStatus), err +} + +// List takes label and field selectors, and returns the list of NodeFeatureStatuses that match those selectors. +func (c *FakeNodeFeatureStatuses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureStatusList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(nodefeaturestatusesResource, nodefeaturestatusesKind, c.ns, opts), &v1alpha1.NodeFeatureStatusList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.NodeFeatureStatusList{ListMeta: obj.(*v1alpha1.NodeFeatureStatusList).ListMeta} + for _, item := range obj.(*v1alpha1.NodeFeatureStatusList).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 nodeFeatureStatuses. +func (c *FakeNodeFeatureStatuses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(nodefeaturestatusesResource, c.ns, opts)) + +} + +// Create takes the representation of a nodeFeatureStatus and creates it. Returns the server's representation of the nodeFeatureStatus, and an error, if there is any. +func (c *FakeNodeFeatureStatuses) Create(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(nodefeaturestatusesResource, c.ns, nodeFeatureStatus), &v1alpha1.NodeFeatureStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureStatus), err +} + +// Update takes the representation of a nodeFeatureStatus and updates it. Returns the server's representation of the nodeFeatureStatus, and an error, if there is any. +func (c *FakeNodeFeatureStatuses) Update(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(nodefeaturestatusesResource, c.ns, nodeFeatureStatus), &v1alpha1.NodeFeatureStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureStatus), err +} + +// Delete takes name of the nodeFeatureStatus and deletes it. Returns an error if one occurs. +func (c *FakeNodeFeatureStatuses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(nodefeaturestatusesResource, c.ns, name, opts), &v1alpha1.NodeFeatureStatus{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeNodeFeatureStatuses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(nodefeaturestatusesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureStatusList{}) + return err +} + +// Patch applies the patch and returns the patched nodeFeatureStatus. +func (c *FakeNodeFeatureStatuses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureStatus, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(nodefeaturestatusesResource, c.ns, name, pt, data, subresources...), &v1alpha1.NodeFeatureStatus{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeFeatureStatus), 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..def95c2ab6 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 NodeFeatureStatusExpansion 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..25f8cbc640 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 + NodeFeatureStatusesGetter } // 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) NodeFeatureStatuses(namespace string) NodeFeatureStatusInterface { + return newNodeFeatureStatuses(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/nodefeature.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go index f159be8670..f4a317e3d5 100644 --- a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go @@ -40,6 +40,7 @@ type NodeFeaturesGetter interface { type NodeFeatureInterface interface { Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (*v1alpha1.NodeFeature, error) Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (*v1alpha1.NodeFeature, error) + UpdateStatus(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (*v1alpha1.NodeFeature, 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.NodeFeature, error) @@ -135,6 +136,22 @@ func (c *nodeFeatures) Update(ctx context.Context, nodeFeature *v1alpha1.NodeFea 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 *nodeFeatures) UpdateStatus(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (result *v1alpha1.NodeFeature, err error) { + result = &v1alpha1.NodeFeature{} + err = c.client.Put(). + Namespace(c.ns). + Resource("nodefeatures"). + Name(nodeFeature.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeature). + Do(ctx). + Into(result) + return +} + // Delete takes name of the nodeFeature and deletes it. Returns an error if one occurs. func (c *nodeFeatures) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { return c.client.Delete(). diff --git a/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturestatus.go b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturestatus.go new file mode 100644 index 0000000000..20f53cb4fa --- /dev/null +++ b/api/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeaturestatus.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" +) + +// NodeFeatureStatusesGetter has a method to return a NodeFeatureStatusInterface. +// A group's client should implement this interface. +type NodeFeatureStatusesGetter interface { + NodeFeatureStatuses(namespace string) NodeFeatureStatusInterface +} + +// NodeFeatureStatusInterface has methods to work with NodeFeatureStatus resources. +type NodeFeatureStatusInterface interface { + Create(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.CreateOptions) (*v1alpha1.NodeFeatureStatus, error) + Update(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureStatus, 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.NodeFeatureStatus, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureStatusList, 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.NodeFeatureStatus, err error) + NodeFeatureStatusExpansion +} + +// nodeFeatureStatuses implements NodeFeatureStatusInterface +type nodeFeatureStatuses struct { + client rest.Interface + ns string +} + +// newNodeFeatureStatuses returns a NodeFeatureStatuses +func newNodeFeatureStatuses(c *NfdV1alpha1Client, namespace string) *nodeFeatureStatuses { + return &nodeFeatureStatuses{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the nodeFeatureStatus, and returns the corresponding nodeFeatureStatus object, and an error if there is any. +func (c *nodeFeatureStatuses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + result = &v1alpha1.NodeFeatureStatus{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of NodeFeatureStatuses that match those selectors. +func (c *nodeFeatureStatuses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureStatusList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.NodeFeatureStatusList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested nodeFeatureStatuses. +func (c *nodeFeatureStatuses) 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("nodefeaturestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a nodeFeatureStatus and creates it. Returns the server's representation of the nodeFeatureStatus, and an error, if there is any. +func (c *nodeFeatureStatuses) Create(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + result = &v1alpha1.NodeFeatureStatus{} + err = c.client.Post(). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeatureStatus). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a nodeFeatureStatus and updates it. Returns the server's representation of the nodeFeatureStatus, and an error, if there is any. +func (c *nodeFeatureStatuses) Update(ctx context.Context, nodeFeatureStatus *v1alpha1.NodeFeatureStatus, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureStatus, err error) { + result = &v1alpha1.NodeFeatureStatus{} + err = c.client.Put(). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + Name(nodeFeatureStatus.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeFeatureStatus). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the nodeFeatureStatus and deletes it. Returns an error if one occurs. +func (c *nodeFeatureStatuses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *nodeFeatureStatuses) 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("nodefeaturestatuses"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched nodeFeatureStatus. +func (c *nodeFeatureStatuses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureStatus, err error) { + result = &v1alpha1.NodeFeatureStatus{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("nodefeaturestatuses"). + 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..b3a351ad81 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("nodefeaturestatuses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatureStatuses().Informer()}, nil } diff --git a/api/generated/informers/externalversions/nfd/v1alpha1/interface.go b/api/generated/informers/externalversions/nfd/v1alpha1/interface.go index ea861a472f..e972bc28a4 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 + // NodeFeatureStatuses returns a NodeFeatureStatusInformer. + NodeFeatureStatuses() NodeFeatureStatusInformer } 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} } + +// NodeFeatureStatuses returns a NodeFeatureStatusInformer. +func (v *version) NodeFeatureStatuses() NodeFeatureStatusInformer { + return &nodeFeatureStatusInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturestatus.go b/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturestatus.go new file mode 100644 index 0000000000..288f319e47 --- /dev/null +++ b/api/generated/informers/externalversions/nfd/v1alpha1/nodefeaturestatus.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" +) + +// NodeFeatureStatusInformer provides access to a shared informer and lister for +// NodeFeatureStatuses. +type NodeFeatureStatusInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.NodeFeatureStatusLister +} + +type nodeFeatureStatusInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNodeFeatureStatusInformer constructs a new informer for NodeFeatureStatus 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 NewNodeFeatureStatusInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNodeFeatureStatusInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNodeFeatureStatusInformer constructs a new informer for NodeFeatureStatus 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 NewFilteredNodeFeatureStatusInformer(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().NodeFeatureStatuses(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NfdV1alpha1().NodeFeatureStatuses(namespace).Watch(context.TODO(), options) + }, + }, + &nfdv1alpha1.NodeFeatureStatus{}, + resyncPeriod, + indexers, + ) +} + +func (f *nodeFeatureStatusInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNodeFeatureStatusInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *nodeFeatureStatusInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&nfdv1alpha1.NodeFeatureStatus{}, f.defaultInformer) +} + +func (f *nodeFeatureStatusInformer) Lister() v1alpha1.NodeFeatureStatusLister { + return v1alpha1.NewNodeFeatureStatusLister(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..69daff4c27 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{} + +// NodeFeatureStatusListerExpansion allows custom methods to be added to +// NodeFeatureStatusLister. +type NodeFeatureStatusListerExpansion interface{} + +// NodeFeatureStatusNamespaceListerExpansion allows custom methods to be added to +// NodeFeatureStatusNamespaceLister. +type NodeFeatureStatusNamespaceListerExpansion interface{} diff --git a/api/generated/listers/nfd/v1alpha1/nodefeaturestatus.go b/api/generated/listers/nfd/v1alpha1/nodefeaturestatus.go new file mode 100644 index 0000000000..eea0a19877 --- /dev/null +++ b/api/generated/listers/nfd/v1alpha1/nodefeaturestatus.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" +) + +// NodeFeatureStatusLister helps list NodeFeatureStatuses. +// All objects returned here must be treated as read-only. +type NodeFeatureStatusLister interface { + // List lists all NodeFeatureStatuses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureStatus, err error) + // NodeFeatureStatuses returns an object that can list and get NodeFeatureStatuses. + NodeFeatureStatuses(namespace string) NodeFeatureStatusNamespaceLister + NodeFeatureStatusListerExpansion +} + +// nodeFeatureStatusLister implements the NodeFeatureStatusLister interface. +type nodeFeatureStatusLister struct { + indexer cache.Indexer +} + +// NewNodeFeatureStatusLister returns a new NodeFeatureStatusLister. +func NewNodeFeatureStatusLister(indexer cache.Indexer) NodeFeatureStatusLister { + return &nodeFeatureStatusLister{indexer: indexer} +} + +// List lists all NodeFeatureStatuses in the indexer. +func (s *nodeFeatureStatusLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureStatus, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeFeatureStatus)) + }) + return ret, err +} + +// NodeFeatureStatuses returns an object that can list and get NodeFeatureStatuses. +func (s *nodeFeatureStatusLister) NodeFeatureStatuses(namespace string) NodeFeatureStatusNamespaceLister { + return nodeFeatureStatusNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// NodeFeatureStatusNamespaceLister helps list and get NodeFeatureStatuses. +// All objects returned here must be treated as read-only. +type NodeFeatureStatusNamespaceLister interface { + // List lists all NodeFeatureStatuses in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureStatus, err error) + // Get retrieves the NodeFeatureStatus from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.NodeFeatureStatus, error) + NodeFeatureStatusNamespaceListerExpansion +} + +// nodeFeatureStatusNamespaceLister implements the NodeFeatureStatusNamespaceLister +// interface. +type nodeFeatureStatusNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all NodeFeatureStatuses in the indexer for a given namespace. +func (s nodeFeatureStatusNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureStatus, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeFeatureStatus)) + }) + return ret, err +} + +// Get retrieves the NodeFeatureStatus from the indexer for a given namespace and name. +func (s nodeFeatureStatusNamespaceLister) Get(name string) (*v1alpha1.NodeFeatureStatus, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("nodefeaturestatus"), name) + } + return obj.(*v1alpha1.NodeFeatureStatus), nil +} diff --git a/api/nfd/v1alpha1/types.go b/api/nfd/v1alpha1/types.go index c89efd8185..7b988ff99c 100644 --- a/api/nfd/v1alpha1/types.go +++ b/api/nfd/v1alpha1/types.go @@ -42,7 +42,8 @@ type NodeFeature struct { metav1.ObjectMeta `json:"metadata,omitempty"` // Specification of the NodeFeature, containing features discovered for a node. - Spec NodeFeatureSpec `json:"spec"` + Spec NodeFeatureSpec `json:"spec"` + Status NodeFeatureStatus `json:"status"` } // NodeFeatureSpec describes a NodeFeature object. @@ -55,6 +56,37 @@ type NodeFeatureSpec struct { Labels map[string]string `json:"labels"` } +// Status of a NodeFeature object +// +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 NodeFeatureStatus struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // UTC time when the NodeFeature object was last updated. + // +optional + LastAppliedAt metav1.Time `json:"lastAppliedAt,omitempty"` + // +optional + // Number of features discovered. + NumberOfFeatures int `json:"numberOfFeatures,omitempty"` + // +optional + // Number of labels created. + NumberOfLabels int `json:"numberOfLabels,omitempty"` +} + +// NodeFeatureStatusList contains a list of NodeFeatureStatus objects. +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type NodeFeatureStatusList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []NodeFeatureStatus `json:"items"` +} + // Features is the collection of all discovered features. // // +protobuf=true diff --git a/api/nfd/v1alpha1/zz_generated.deepcopy.go b/api/nfd/v1alpha1/zz_generated.deepcopy.go index 491d9866c4..69aca54a4d 100644 --- a/api/nfd/v1alpha1/zz_generated.deepcopy.go +++ b/api/nfd/v1alpha1/zz_generated.deepcopy.go @@ -379,6 +379,7 @@ func (in *NodeFeature) DeepCopyInto(out *NodeFeature) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) return } @@ -645,6 +646,66 @@ func (in *NodeFeatureSpec) DeepCopy() *NodeFeatureSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeFeatureStatus) DeepCopyInto(out *NodeFeatureStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.LastAppliedAt.DeepCopyInto(&out.LastAppliedAt) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureStatus. +func (in *NodeFeatureStatus) DeepCopy() *NodeFeatureStatus { + if in == nil { + return nil + } + out := new(NodeFeatureStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeFeatureStatus) 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 *NodeFeatureStatusList) DeepCopyInto(out *NodeFeatureStatusList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NodeFeatureStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureStatusList. +func (in *NodeFeatureStatusList) DeepCopy() *NodeFeatureStatusList { + if in == nil { + return nil + } + out := new(NodeFeatureStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeFeatureStatusList) 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 *Rule) DeepCopyInto(out *Rule) { *out = *in diff --git a/deployment/base/nfd-crds/nfd-api-crds.yaml b/deployment/base/nfd-crds/nfd-api-crds.yaml index 0a73c5dcae..f70ed95465 100644 --- a/deployment/base/nfd-crds/nfd-api-crds.yaml +++ b/deployment/base/nfd-crds/nfd-api-crds.yaml @@ -114,8 +114,40 @@ spec: be created. type: object type: object + status: + description: Status of a NodeFeature object + 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 + lastAppliedAt: + description: UTC time when the NodeFeature object was last updated. + format: date-time + type: string + metadata: + type: object + numberOfFeatures: + description: Number of features discovered. + type: integer + numberOfLabels: + description: Number of labels created. + type: integer + type: object required: - spec + - status type: object served: true storage: true @@ -708,3 +740,58 @@ 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: nodefeaturestatuses.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureStatus + listKind: NodeFeatureStatusList + plural: nodefeaturestatuses + shortNames: + - nfs + singular: nodefeaturestatus + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Status of a NodeFeature object + 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 + lastAppliedAt: + description: UTC time when the NodeFeature object was last updated. + format: date-time + type: string + metadata: + type: object + numberOfFeatures: + description: Number of features discovered. + type: integer + numberOfLabels: + description: Number of labels created. + type: integer + 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..f70ed95465 100644 --- a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml +++ b/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml @@ -114,8 +114,40 @@ spec: be created. type: object type: object + status: + description: Status of a NodeFeature object + 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 + lastAppliedAt: + description: UTC time when the NodeFeature object was last updated. + format: date-time + type: string + metadata: + type: object + numberOfFeatures: + description: Number of features discovered. + type: integer + numberOfLabels: + description: Number of labels created. + type: integer + type: object required: - spec + - status type: object served: true storage: true @@ -708,3 +740,58 @@ 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: nodefeaturestatuses.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureStatus + listKind: NodeFeatureStatusList + plural: nodefeaturestatuses + shortNames: + - nfs + singular: nodefeaturestatus + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Status of a NodeFeature object + 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 + lastAppliedAt: + description: UTC time when the NodeFeature object was last updated. + format: date-time + type: string + metadata: + type: object + numberOfFeatures: + description: Number of features discovered. + type: integer + numberOfLabels: + description: Number of labels created. + type: integer + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/nfd-worker/nfd-worker.go b/pkg/nfd-worker/nfd-worker.go index 1c728771db..d7c9ea2363 100644 --- a/pkg/nfd-worker/nfd-worker.go +++ b/pkg/nfd-worker/nfd-worker.go @@ -122,18 +122,19 @@ type ConfigOverrideArgs struct { } type nfdWorker struct { - args Args - certWatch *utils.FsWatcher - clientConn *grpc.ClientConn - configFilePath string - config *NFDConfig - kubernetesNamespace string - grpcClient pb.LabelerClient - healthServer *grpc.Server - nfdClient *nfdclient.Clientset - stop chan struct{} // channel for signaling stop - featureSources []source.FeatureSource - labelSources []source.LabelSource + args Args + certWatch *utils.FsWatcher + clientConn *grpc.ClientConn + configFilePath string + config *NFDConfig + kubernetesNamespace string + grpcClient pb.LabelerClient + healthServer *grpc.Server + nfdClient *nfdclient.Clientset + stop chan struct{} // channel for signaling stop + featureSources []source.FeatureSource + numberOfFeatureSourceErrors int + labelSources []source.LabelSource } // This ticker can represent infinite and normal intervals. @@ -219,9 +220,11 @@ func (w *nfdWorker) startGrpcHealthServer(errChan chan<- error) error { // Run feature discovery. func (w *nfdWorker) runFeatureDiscovery() error { discoveryStart := time.Now() + w.numberOfFeatureSourceErrors = 0 for _, s := range w.featureSources { currentSourceStart := time.Now() if err := s.Discover(); err != nil { + w.numberOfFeatureSourceErrors++ klog.ErrorS(err, "feature discovery failed", "source", s.Name()) } klog.V(3).InfoS("feature discovery completed", "featureSource", s.Name(), "duration", time.Since(currentSourceStart)) @@ -747,6 +750,13 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error { Labels: labels, }, } + + nfr.Status = nfdv1alpha1.NodeFeatureStatus{ + LastAppliedAt: metav1.Time{Time: time.Now().UTC()}, + NumberOfFeatures: len(m.featureSources), + NumberOfLabels: len(m.labelSources), + } + klog.InfoS("creating NodeFeature object", "nodefeature", klog.KObj(nfr)) nfrCreated, err := cli.NfdV1alpha1().NodeFeatures(namespace).Create(context.TODO(), nfr, metav1.CreateOptions{}) @@ -766,7 +776,11 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error { Features: *features, Labels: labels, } - + nfrUpdated.Status = nfdv1alpha1.NodeFeatureStatus{ + LastAppliedAt: metav1.Time{Time: time.Now().UTC()}, + NumberOfFeatures: len(m.featureSources), + NumberOfLabels: len(m.labelSources), + } if !apiequality.Semantic.DeepEqual(nfr, nfrUpdated) { klog.InfoS("updating NodeFeature object", "nodefeature", klog.KObj(nfr)) nfrUpdated, err = cli.NfdV1alpha1().NodeFeatures(namespace).Update(context.TODO(), nfrUpdated, metav1.UpdateOptions{}) diff --git a/test/e2e/node_feature_discovery_test.go b/test/e2e/node_feature_discovery_test.go index c15b97049b..9e26c09bde 100644 --- a/test/e2e/node_feature_discovery_test.go +++ b/test/e2e/node_feature_discovery_test.go @@ -514,6 +514,19 @@ var _ = NFDDescribe(Label("nfd-master"), func() { } eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes)) + By("Verifying the CRD status") + nf, err := nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Get(ctx, targetNodeName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred(), "Error getting NodeFeature object: %q", err) + + expectedStatus := nfdv1alpha1.NodeFeatureStatus{ + LastAppliedAt: nf.Status.LastAppliedAt, + NumberOfFeatures: nf.Status.NumberOfFeatures, + NumberOfLabels: len(expectedLabels[targetNodeName]) - 1, + } + isEqual := (expectedStatus.NumberOfFeatures == nf.Status.NumberOfFeatures && + expectedStatus.NumberOfLabels == nf.Status.NumberOfLabels) + Expect(isEqual).To(BeTrue()) + By("Deleting nfd-worker daemonset") err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Delete(ctx, workerDS.Name, metav1.DeleteOptions{}) Expect(err).NotTo(HaveOccurred())