Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding nfd feature rule package and new builder #882

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ require (
gopkg.in/k8snetworkplumbingwg/multus-cni.v4 v4.0.2
gopkg.in/yaml.v2 v2.4.0
gorm.io/gorm v1.24.5
k8s.io/api v0.30.5
k8s.io/api v0.30.7
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the k8s go.mod changes have to happen here? We have an automated job to keep them up to date.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add new package by run make and make install maybe in the process this lib version changed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebrandon1 It seems that NFD is not part of the sync job, thus it is causing this problem. What is currently the procedure? Should @ggordaniRed add config for the sync ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure how that sync all works. @kononovn?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need a sync config for this operator unless it's causing issues with dependencies. There doesn't seem to be any actual changes between 0.30.5 and 0.30.7 of these libraries though

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay sounds good. 👍

k8s.io/apiextensions-apiserver v0.30.5
k8s.io/apimachinery v0.30.5
k8s.io/apimachinery v0.30.7
k8s.io/client-go v12.0.0+incompatible
k8s.io/klog/v2 v2.130.1
k8s.io/kubectl v0.30.5
Expand Down Expand Up @@ -203,6 +203,8 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)

require github.com/openshift/node-feature-discovery/api/nfd v0.0.0-20250103121957-354b94ed3e55

replace (
github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
github.com/k8snetworkplumbingwg/sriov-network-operator => github.com/openshift/sriov-network-operator v0.0.0-20241111131739-45f22daa4ca8 // release-4.17
Expand Down
10 changes: 6 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,8 @@ github.com/openshift/local-storage-operator v0.0.0-20240712213037-f7a4384c92bb h
github.com/openshift/local-storage-operator v0.0.0-20240712213037-f7a4384c92bb/go.mod h1:Xd0acgr/PW7GbqjF/vM9cK0h+0XZyQgZj5w4GJ3GKoU=
github.com/openshift/machine-config-operator v0.0.1-0.20231024085435-7e1fb719c1ba h1:WM6K+m2xMAwbQDetKGhV/Rd8yukF3AsU1z74cqoWrz0=
github.com/openshift/machine-config-operator v0.0.1-0.20231024085435-7e1fb719c1ba/go.mod h1:mSt3ACow31pa1hTRONn+yT5e+KFkgi7G2bFEx5Nj+n0=
github.com/openshift/node-feature-discovery/api/nfd v0.0.0-20250103121957-354b94ed3e55 h1:WEb5qycjzpGADIS3oMdr702qR9jh/mgquMz6ji5rE8I=
github.com/openshift/node-feature-discovery/api/nfd v0.0.0-20250103121957-354b94ed3e55/go.mod h1:juZkfV/wKZg53G1YjG7O++JoTrrVnDrwUbHT5N1ab4g=
github.com/openshift/sriov-network-operator v0.0.0-20241111131739-45f22daa4ca8 h1:IfgOgyfzDy8Z3kUlRQxFP5+iGjqExlsdZu5e/xnFL/0=
github.com/openshift/sriov-network-operator v0.0.0-20241111131739-45f22daa4ca8/go.mod h1:eCMvvm0oS0HnfrjOCNcqvrSsf0mzQJ2k+0M+r/5M2ho=
github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20240614144800-61d5c5937bd4 h1:rqCh/Kh/7ityDsd1tIh1EjLxJ7ie7J8pH9/nxLZURWc=
Expand Down Expand Up @@ -2266,16 +2268,16 @@ k8s.io/api v0.22.7/go.mod h1:7hejA1BgBEiSsWljUyRkIjj+AISXO16IwsaDgFjJsQE=
k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ=
k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
k8s.io/api v0.29.9/go.mod h1:fNhmzRfKaSEHCmczA/jRx6CiDKhYOnFLJBERMJAXEk8=
k8s.io/api v0.30.5 h1:Coz05sfEVywzGcA96AJPUfs2B8LBMnh+IIsM+HCfaz8=
k8s.io/api v0.30.5/go.mod h1:HfNBGFvq9iNK8dmTKjYIdAtMxu8BXTb9c1SJyO6QjKs=
k8s.io/api v0.30.7 h1:wB2eHI+IptVYsz5WsAQpI6+Dqi3+11wEWBqIh4fh980=
k8s.io/api v0.30.7/go.mod h1:bR0EwbmhYmJvUoeza7ZzBUmYCrVXccQ9JOdfv0BxhH0=
k8s.io/apiextensions-apiserver v0.30.5 h1:JfXTIyzXf5+ryncbp7T/uaVjLdvkwtqoNG2vo7S2a6M=
k8s.io/apiextensions-apiserver v0.30.5/go.mod h1:uVLEME2UPA6UN22i+jTu66B9/0CnsjlHkId+Awo0lvs=
k8s.io/apimachinery v0.22.7/go.mod h1:ZvVLP5iLhwVFg2Yx9Gh5W0um0DUauExbRhe+2Z8I1EU=
k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apimachinery v0.29.9/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/apimachinery v0.30.5 h1:CQZO19GFgw4zcOjY2H+mJ3k1u1o7zFACTNCB7nu4O18=
k8s.io/apimachinery v0.30.5/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/apimachinery v0.30.7 h1:CoQFxvzPFKwU1eJGN/8LgM3ZJBC3hKgvwGqRrL43uIY=
k8s.io/apimachinery v0.30.7/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/apiserver v0.30.5 h1:roo3cfvUS7zvI6u+bY35Xv3rSDXbY9dwl1gN+rxx0S4=
k8s.io/apiserver v0.30.5/go.mod h1:p5UqIn1WPdOFo7uO/ZUdX464hHZy1DP384znr7FOIXA=
k8s.io/cli-runtime v0.30.5 h1:MWY6efoBVH3h0O6p2DgaQszabV5ZntHZwTHBkiz+PSI=
Expand Down
198 changes: 198 additions & 0 deletions pkg/nfd/nodefeaturerule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package nfd

import (
"context"
"fmt"

"github.com/golang/glog"
"github.com/openshift-kni/eco-goinfra/pkg/clients"
"github.com/openshift-kni/eco-goinfra/pkg/msg"
nfdv1 "github.com/openshift/node-feature-discovery/api/nfd/v1alpha1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/json"
goclient "sigs.k8s.io/controller-runtime/pkg/client"
)

// NodeFeatureRuleBuilder provides a struct for NodeFeatureRule object
// from the cluster and a NodeFeatureRule definition.
type NodeFeatureRuleBuilder struct {
// Builder definition. Used to create
// Builder object with minimum set of required elements.
Definition *nfdv1.NodeFeatureRule
// Created Builder object on the cluster.
Object *nfdv1.NodeFeatureRule
// api client to interact with the cluster.
apiClient *clients.Settings
// errorMsg is processed before Builder object is created.
errorMsg string
}

// NewnodeFeatureRuleBuilderFromObjectString creates a Builder object from CSV alm-examples.
func NewnodeFeatureRuleBuilderFromObjectString(apiClient *clients.Settings, almExample string) *NodeFeatureRuleBuilder {
glog.V(100).Infof(
"Initializing new Builder structure from almExample string")

if apiClient == nil {
glog.V(100).Info("The apiClient of the Policy is nil")

return nil
}

err := apiClient.AttachScheme(nfdv1.AddToScheme)
if err != nil {
glog.V(100).Info("Failed to add nfd v1 scheme to client schemes")

return nil
}

nodeFeatureRule, err := getNodeFeatureRuleFromAlmExample(almExample)

glog.V(100).Infof(
"Initializing Builder definition to NodeFeatureRule object")

nodeFeatureRuleBuilder := NodeFeatureRuleBuilder{
apiClient: apiClient,
Definition: nodeFeatureRule,
Object: nodeFeatureRule,
}

if err != nil {
glog.V(100).Infof(
"Error initializing NodeFeatureRule from alm-examples: %s", err.Error())

nodeFeatureRuleBuilder.errorMsg = fmt.Sprintf("Error initializing NodeFeatureRule from alm-examples: %s",
err.Error())
}

if nodeFeatureRuleBuilder.Definition == nil {
glog.V(100).Infof("The NodeFeatureRule object definition is nil")

nodeFeatureRuleBuilder.errorMsg = "NodeFeatureRule definition is nil"
}

return &nodeFeatureRuleBuilder
}

// getNodeFeatureRuleFromAlmExample extracts the NodeFeatureRule from the alm-examples block.
func getNodeFeatureRuleFromAlmExample(almExample string) (*nfdv1.NodeFeatureRule, error) {
nodeFeatureRuleList := &nfdv1.NodeFeatureRuleList{}

if almExample == "" {
return nil, fmt.Errorf("almExample is an empty string")
}

err := json.Unmarshal([]byte(almExample), &nodeFeatureRuleList.Items)

if err != nil {
return nil, err
}

if len(nodeFeatureRuleList.Items) == 0 {
return nil, fmt.Errorf("failed to get alm examples")
}

for i, item := range nodeFeatureRuleList.Items {
if item.Kind == "NodeFeatureRule" {
return &nodeFeatureRuleList.Items[i], nil
}
}

return nil, fmt.Errorf("NodeFeatureRule is missing in alm-examples ")
}

// Create makes a NodeFeatureRule in the cluster and stores the created object in struct.
func (builder *NodeFeatureRuleBuilder) Create() (*NodeFeatureRuleBuilder, error) {
if valid, err := builder.validate(); !valid {
return builder, err
}

glog.V(100).Infof("Creating the NodeFeatureRule %s in namespace %s", builder.Definition.Name,
builder.Definition.Namespace)

var err error
if !builder.Exists() {
err = builder.apiClient.Create(context.TODO(), builder.Definition)

if err == nil {
builder.Object = builder.Definition
}
}

return builder, err
}

// Exists checks whether the given NodeFeatureRule exists.
func (builder *NodeFeatureRuleBuilder) Exists() bool {
if valid, _ := builder.validate(); !valid {
return false
}

glog.V(100).Infof(
"Checking if NodeFeatureRule %s exists in namespace %s", builder.Definition.Name,
builder.Definition.Namespace)

var err error
builder.Object, err = builder.Get()

if err != nil {
glog.V(100).Infof("Failed to collect NodeFeatureRule object due to %s", err.Error())
}

return err == nil || !k8serrors.IsNotFound(err)
}

// validate will check that the builder and builder definition are properly initialized before
// accessing any member fields.
func (builder *NodeFeatureRuleBuilder) validate() (bool, error) {
resourceCRD := "NodeFeatureRule"

if builder == nil {
glog.V(100).Infof("The %s builder is uninitialized", resourceCRD)

return false, fmt.Errorf("error: received nil %s builder", resourceCRD)
}

if builder.Definition == nil {
glog.V(100).Infof("The %s is undefined", resourceCRD)

return false, fmt.Errorf(msg.UndefinedCrdObjectErrString(resourceCRD))
}

if builder.apiClient == nil {
glog.V(100).Infof("The %s builder apiclient is nil", resourceCRD)

return false, fmt.Errorf("%s builder cannot have nil apiClient", resourceCRD)
}

return true, nil
}

// Get returns NodeFeatureRule object if found.
func (builder *NodeFeatureRuleBuilder) Get() (*nfdv1.NodeFeatureRule, error) {
if valid, err := builder.validate(); !valid {
return nil, err
}

glog.V(100).Infof("Collecting NodeFeatureRule object %s in namespace %s",
builder.Definition.Name, builder.Definition.Namespace)

NodeFeatureRule := &nfdv1.NodeFeatureRule{}
err := builder.apiClient.Get(context.TODO(), goclient.ObjectKey{
Name: builder.Definition.Name,
Namespace: builder.Definition.Namespace,
}, NodeFeatureRule)

if err != nil {
glog.V(100).Infof("NodeFeatureRule object %s does not exist in namespace %s",
builder.Definition.Name, builder.Definition.Namespace)

return nil, err
}

return NodeFeatureRule, err
}

// GetErrorMessage returns builder's error message.
func (builder *NodeFeatureRuleBuilder) GetErrorMessage() string {
return builder.errorMsg
}
Loading