1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-14 11:57:51 +00:00

apis/nfd: Add Status to NodeFeature CRD

Signed-off-by: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
This commit is contained in:
Oleg Zhurakivskyy 2024-04-16 20:26:34 +03:00
parent 620e16e334
commit d699a77700
19 changed files with 716 additions and 13 deletions

View file

@ -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 {

View file

@ -105,6 +105,19 @@ 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) (result *v1alpha1.NodeFeature, err error) {
emptyResult := &v1alpha1.NodeFeature{}
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceActionWithOptions(nodefeaturesResource, "status", c.ns, nodeFeature, opts), emptyResult)
if obj == nil {
return emptyResult, 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.

View file

@ -0,0 +1,134 @@
/*
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) {
emptyResult := &v1alpha1.NodeFeatureStatus{}
obj, err := c.Fake.
Invokes(testing.NewGetActionWithOptions(nodefeaturestatusesResource, c.ns, name, options), emptyResult)
if obj == nil {
return emptyResult, 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) {
emptyResult := &v1alpha1.NodeFeatureStatusList{}
obj, err := c.Fake.
Invokes(testing.NewListActionWithOptions(nodefeaturestatusesResource, nodefeaturestatusesKind, c.ns, opts), emptyResult)
if obj == nil {
return emptyResult, 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.NewWatchActionWithOptions(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) {
emptyResult := &v1alpha1.NodeFeatureStatus{}
obj, err := c.Fake.
Invokes(testing.NewCreateActionWithOptions(nodefeaturestatusesResource, c.ns, nodeFeatureStatus, opts), emptyResult)
if obj == nil {
return emptyResult, 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) {
emptyResult := &v1alpha1.NodeFeatureStatus{}
obj, err := c.Fake.
Invokes(testing.NewUpdateActionWithOptions(nodefeaturestatusesResource, c.ns, nodeFeatureStatus, opts), emptyResult)
if obj == nil {
return emptyResult, 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.NewDeleteCollectionActionWithOptions(nodefeaturestatusesResource, c.ns, opts, 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) {
emptyResult := &v1alpha1.NodeFeatureStatus{}
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceActionWithOptions(nodefeaturestatusesResource, c.ns, name, pt, data, opts, subresources...), emptyResult)
if obj == nil {
return emptyResult, err
}
return obj.(*v1alpha1.NodeFeatureStatus), err
}

View file

@ -23,3 +23,5 @@ type NodeFeatureExpansion interface{}
type NodeFeatureGroupExpansion interface{}
type NodeFeatureRuleExpansion interface{}
type NodeFeatureStatusExpansion interface{}

View file

@ -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).

View file

@ -39,6 +39,8 @@ 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)
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
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)

View file

@ -0,0 +1,67 @@
/*
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"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
gentype "k8s.io/client-go/gentype"
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 {
*gentype.ClientWithList[*v1alpha1.NodeFeatureStatus, *v1alpha1.NodeFeatureStatusList]
}
// newNodeFeatureStatuses returns a NodeFeatureStatuses
func newNodeFeatureStatuses(c *NfdV1alpha1Client, namespace string) *nodeFeatureStatuses {
return &nodeFeatureStatuses{
gentype.NewClientWithList[*v1alpha1.NodeFeatureStatus, *v1alpha1.NodeFeatureStatusList](
"nodefeaturestatuses",
c.RESTClient(),
scheme.ParameterCodec,
namespace,
func() *v1alpha1.NodeFeatureStatus { return &v1alpha1.NodeFeatureStatus{} },
func() *v1alpha1.NodeFeatureStatusList { return &v1alpha1.NodeFeatureStatusList{} }),
}
}

View file

@ -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
}

View file

@ -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}
}

View file

@ -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())
}

View file

@ -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{}

View file

@ -0,0 +1,70 @@
/*
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/labels"
"k8s.io/client-go/listers"
"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 {
listers.ResourceIndexer[*v1alpha1.NodeFeatureStatus]
}
// NewNodeFeatureStatusLister returns a new NodeFeatureStatusLister.
func NewNodeFeatureStatusLister(indexer cache.Indexer) NodeFeatureStatusLister {
return &nodeFeatureStatusLister{listers.New[*v1alpha1.NodeFeatureStatus](indexer, v1alpha1.Resource("nodefeaturestatus"))}
}
// NodeFeatureStatuses returns an object that can list and get NodeFeatureStatuses.
func (s *nodeFeatureStatusLister) NodeFeatureStatuses(namespace string) NodeFeatureStatusNamespaceLister {
return nodeFeatureStatusNamespaceLister{listers.NewNamespaced[*v1alpha1.NodeFeatureStatus](s.ResourceIndexer, 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 {
listers.ResourceIndexer[*v1alpha1.NodeFeatureStatus]
}

View file

@ -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"`
}
// NodeFeatureStatus holds the 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

View file

@ -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

View file

@ -114,8 +114,40 @@ spec:
be created.
type: object
type: object
status:
description: NodeFeatureStatus holds the 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.16.3
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: NodeFeatureStatus holds the 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: {}

View file

@ -114,8 +114,40 @@ spec:
be created.
type: object
type: object
status:
description: NodeFeatureStatus holds the 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.16.3
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: NodeFeatureStatus holds the 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: {}

View file

@ -111,17 +111,18 @@ type ConfigOverrideArgs struct {
}
type nfdWorker struct {
args Args
configFilePath string
config *NFDConfig
kubernetesNamespace string
healthServer *grpc.Server
k8sClient k8sclient.Interface
nfdClient nfdclient.Interface
stop chan struct{} // channel for signaling stop
featureSources []source.FeatureSource
labelSources []source.LabelSource
ownerReference []metav1.OwnerReference
args Args
configFilePath string
config *NFDConfig
kubernetesNamespace string
healthServer *grpc.Server
k8sClient k8sclient.Interface
nfdClient nfdclient.Interface
stop chan struct{} // channel for signaling stop
featureSources []source.FeatureSource
numberOfFeatureSourceErrors int
labelSources []source.LabelSource
ownerReference []metav1.OwnerReference
}
// This ticker can represent infinite and normal intervals.
@ -240,9 +241,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))
@ -649,6 +652,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{})
@ -668,7 +678,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{})

View file

@ -128,6 +128,11 @@ func TestRun(t *testing.T) {
},
},
},
Status: v1alpha1.NodeFeatureStatus{
LastAppliedAt: nf.Status.LastAppliedAt,
NumberOfFeatures: 1,
NumberOfLabels: 1,
},
}
So(nf, ShouldResemble, nfExpected)
})

View file

@ -486,6 +486,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())