mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-06 08:47:04 +00:00
Merge branch 'master' into feat/skip-nodes
This commit is contained in:
commit
97345a4a96
53 changed files with 2386 additions and 2913 deletions
|
@ -5,18 +5,7 @@ FROM ${BUILDER_IMAGE} as builder
|
|||
RUN --mount=type=cache,target=/go/pkg/mod/ \
|
||||
go install github.com/vektra/mockery/v2@v2.42.0 && \
|
||||
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.3 && \
|
||||
go install golang.org/x/tools/cmd/goimports@v0.25.0 && \
|
||||
go install github.com/golang/protobuf/protoc-gen-go@v1.4.3
|
||||
|
||||
RUN apt-get update && apt-get install unzip
|
||||
|
||||
RUN curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v25.3/protoc-25.3-linux-x86_64.zip && \
|
||||
unzip protoc-25.3-linux-x86_64.zip -d /usr/local && \
|
||||
rm protoc-25.3-linux-x86_64.zip && \
|
||||
chmod a+x /usr/local/bin/protoc && \
|
||||
find /usr/local -type d | xargs chmod 755 && \
|
||||
find /usr/local -type f | xargs chmod a+r
|
||||
|
||||
go install golang.org/x/tools/cmd/goimports@v0.25.0
|
||||
|
||||
# Expect to be working with nfd
|
||||
WORKDIR /go/node-feature-discovery
|
||||
|
|
2
Makefile
2
Makefile
|
@ -90,7 +90,7 @@ IMAGE_BUILD_ARGS_MINIMAL = --target minimal \
|
|||
|
||||
all: image
|
||||
|
||||
BUILD_BINARIES := nfd-master nfd-worker nfd-topology-updater nfd-gc kubectl-nfd
|
||||
BUILD_BINARIES := nfd-master nfd-worker nfd-topology-updater nfd-gc kubectl-nfd nfd
|
||||
|
||||
build-%:
|
||||
$(GO_CMD) build -v -o bin/ $(BUILD_FLAGS) ./cmd/$*
|
||||
|
|
|
@ -19,8 +19,8 @@ limitations under the License.
|
|||
package versioned
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
fmt "fmt"
|
||||
http "net/http"
|
||||
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
|
|
|
@ -29,15 +29,15 @@ type FakeNfdV1alpha1 struct {
|
|||
}
|
||||
|
||||
func (c *FakeNfdV1alpha1) NodeFeatures(namespace string) v1alpha1.NodeFeatureInterface {
|
||||
return &FakeNodeFeatures{c, namespace}
|
||||
return newFakeNodeFeatures(c, namespace)
|
||||
}
|
||||
|
||||
func (c *FakeNfdV1alpha1) NodeFeatureGroups(namespace string) v1alpha1.NodeFeatureGroupInterface {
|
||||
return &FakeNodeFeatureGroups{c, namespace}
|
||||
return newFakeNodeFeatureGroups(c, namespace)
|
||||
}
|
||||
|
||||
func (c *FakeNfdV1alpha1) NodeFeatureRules() v1alpha1.NodeFeatureRuleInterface {
|
||||
return &FakeNodeFeatureRules{c}
|
||||
return newFakeNodeFeatureRules(c)
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
|
|
|
@ -19,116 +19,34 @@ limitations under the License.
|
|||
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"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeNodeFeatures implements NodeFeatureInterface
|
||||
type FakeNodeFeatures struct {
|
||||
// fakeNodeFeatures implements NodeFeatureInterface
|
||||
type fakeNodeFeatures struct {
|
||||
*gentype.FakeClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList]
|
||||
Fake *FakeNfdV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var nodefeaturesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeatures")
|
||||
|
||||
var nodefeaturesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeature")
|
||||
|
||||
// Get takes name of the nodeFeature, and returns the corresponding nodeFeature object, and an error if there is any.
|
||||
func (c *FakeNodeFeatures) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeature, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeature{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetActionWithOptions(nodefeaturesResource, c.ns, name, options), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
func newFakeNodeFeatures(fake *FakeNfdV1alpha1, namespace string) nfdv1alpha1.NodeFeatureInterface {
|
||||
return &fakeNodeFeatures{
|
||||
gentype.NewFakeClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList](
|
||||
fake.Fake,
|
||||
namespace,
|
||||
v1alpha1.SchemeGroupVersion.WithResource("nodefeatures"),
|
||||
v1alpha1.SchemeGroupVersion.WithKind("NodeFeature"),
|
||||
func() *v1alpha1.NodeFeature { return &v1alpha1.NodeFeature{} },
|
||||
func() *v1alpha1.NodeFeatureList { return &v1alpha1.NodeFeatureList{} },
|
||||
func(dst, src *v1alpha1.NodeFeatureList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1alpha1.NodeFeatureList) []*v1alpha1.NodeFeature {
|
||||
return gentype.ToPointerSlice(list.Items)
|
||||
},
|
||||
func(list *v1alpha1.NodeFeatureList, items []*v1alpha1.NodeFeature) {
|
||||
list.Items = gentype.FromPointerSlice(items)
|
||||
},
|
||||
),
|
||||
fake,
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeature), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of NodeFeatures that match those selectors.
|
||||
func (c *FakeNodeFeatures) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureList, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureList{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListActionWithOptions(nodefeaturesResource, nodefeaturesKind, c.ns, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.NodeFeatureList{ListMeta: obj.(*v1alpha1.NodeFeatureList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.NodeFeatureList).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 nodeFeatures.
|
||||
func (c *FakeNodeFeatures) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchActionWithOptions(nodefeaturesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a nodeFeature and creates it. Returns the server's representation of the nodeFeature, and an error, if there is any.
|
||||
func (c *FakeNodeFeatures) Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (result *v1alpha1.NodeFeature, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeature{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateActionWithOptions(nodefeaturesResource, c.ns, nodeFeature, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeature), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a nodeFeature and updates it. Returns the server's representation of the nodeFeature, and an error, if there is any.
|
||||
func (c *FakeNodeFeatures) Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (result *v1alpha1.NodeFeature, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeature{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateActionWithOptions(nodefeaturesResource, 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.
|
||||
Invokes(testing.NewDeleteActionWithOptions(nodefeaturesResource, c.ns, name, opts), &v1alpha1.NodeFeature{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeNodeFeatures) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionActionWithOptions(nodefeaturesResource, c.ns, opts, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched nodeFeature.
|
||||
func (c *FakeNodeFeatures) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeature, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeature{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceActionWithOptions(nodefeaturesResource, c.ns, name, pt, data, opts, subresources...), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeature), err
|
||||
}
|
||||
|
|
|
@ -19,129 +19,34 @@ limitations under the License.
|
|||
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"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeNodeFeatureGroups implements NodeFeatureGroupInterface
|
||||
type FakeNodeFeatureGroups struct {
|
||||
// fakeNodeFeatureGroups implements NodeFeatureGroupInterface
|
||||
type fakeNodeFeatureGroups struct {
|
||||
*gentype.FakeClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList]
|
||||
Fake *FakeNfdV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var nodefeaturegroupsResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturegroups")
|
||||
|
||||
var nodefeaturegroupsKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureGroup")
|
||||
|
||||
// Get takes name of the nodeFeatureGroup, and returns the corresponding nodeFeatureGroup object, and an error if there is any.
|
||||
func (c *FakeNodeFeatureGroups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureGroup, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetActionWithOptions(nodefeaturegroupsResource, c.ns, name, options), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
func newFakeNodeFeatureGroups(fake *FakeNfdV1alpha1, namespace string) nfdv1alpha1.NodeFeatureGroupInterface {
|
||||
return &fakeNodeFeatureGroups{
|
||||
gentype.NewFakeClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList](
|
||||
fake.Fake,
|
||||
namespace,
|
||||
v1alpha1.SchemeGroupVersion.WithResource("nodefeaturegroups"),
|
||||
v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureGroup"),
|
||||
func() *v1alpha1.NodeFeatureGroup { return &v1alpha1.NodeFeatureGroup{} },
|
||||
func() *v1alpha1.NodeFeatureGroupList { return &v1alpha1.NodeFeatureGroupList{} },
|
||||
func(dst, src *v1alpha1.NodeFeatureGroupList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1alpha1.NodeFeatureGroupList) []*v1alpha1.NodeFeatureGroup {
|
||||
return gentype.ToPointerSlice(list.Items)
|
||||
},
|
||||
func(list *v1alpha1.NodeFeatureGroupList, items []*v1alpha1.NodeFeatureGroup) {
|
||||
list.Items = gentype.FromPointerSlice(items)
|
||||
},
|
||||
),
|
||||
fake,
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureGroup), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of NodeFeatureGroups that match those selectors.
|
||||
func (c *FakeNodeFeatureGroups) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureGroupList, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroupList{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListActionWithOptions(nodefeaturegroupsResource, nodefeaturegroupsKind, c.ns, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.NodeFeatureGroupList{ListMeta: obj.(*v1alpha1.NodeFeatureGroupList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.NodeFeatureGroupList).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 nodeFeatureGroups.
|
||||
func (c *FakeNodeFeatureGroups) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchActionWithOptions(nodefeaturegroupsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a nodeFeatureGroup and creates it. Returns the server's representation of the nodeFeatureGroup, and an error, if there is any.
|
||||
func (c *FakeNodeFeatureGroups) Create(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureGroup, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateActionWithOptions(nodefeaturegroupsResource, c.ns, nodeFeatureGroup, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureGroup), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a nodeFeatureGroup and updates it. Returns the server's representation of the nodeFeatureGroup, and an error, if there is any.
|
||||
func (c *FakeNodeFeatureGroups) Update(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureGroup, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateActionWithOptions(nodefeaturegroupsResource, c.ns, nodeFeatureGroup, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureGroup), 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 *FakeNodeFeatureGroups) UpdateStatus(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureGroup, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceActionWithOptions(nodefeaturegroupsResource, "status", c.ns, nodeFeatureGroup, opts), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureGroup), err
|
||||
}
|
||||
|
||||
// Delete takes name of the nodeFeatureGroup and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeNodeFeatureGroups) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteActionWithOptions(nodefeaturegroupsResource, c.ns, name, opts), &v1alpha1.NodeFeatureGroup{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeNodeFeatureGroups) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionActionWithOptions(nodefeaturegroupsResource, c.ns, opts, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureGroupList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched nodeFeatureGroup.
|
||||
func (c *FakeNodeFeatureGroups) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureGroup, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceActionWithOptions(nodefeaturegroupsResource, c.ns, name, pt, data, opts, subresources...), emptyResult)
|
||||
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureGroup), err
|
||||
}
|
||||
|
|
|
@ -19,108 +19,34 @@ limitations under the License.
|
|||
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"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeNodeFeatureRules implements NodeFeatureRuleInterface
|
||||
type FakeNodeFeatureRules struct {
|
||||
// fakeNodeFeatureRules implements NodeFeatureRuleInterface
|
||||
type fakeNodeFeatureRules struct {
|
||||
*gentype.FakeClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList]
|
||||
Fake *FakeNfdV1alpha1
|
||||
}
|
||||
|
||||
var nodefeaturerulesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules")
|
||||
|
||||
var nodefeaturerulesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRule")
|
||||
|
||||
// Get takes name of the nodeFeatureRule, and returns the corresponding nodeFeatureRule object, and an error if there is any.
|
||||
func (c *FakeNodeFeatureRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureRule, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureRule{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetActionWithOptions(nodefeaturerulesResource, name, options), emptyResult)
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
func newFakeNodeFeatureRules(fake *FakeNfdV1alpha1) nfdv1alpha1.NodeFeatureRuleInterface {
|
||||
return &fakeNodeFeatureRules{
|
||||
gentype.NewFakeClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList](
|
||||
fake.Fake,
|
||||
"",
|
||||
v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules"),
|
||||
v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRule"),
|
||||
func() *v1alpha1.NodeFeatureRule { return &v1alpha1.NodeFeatureRule{} },
|
||||
func() *v1alpha1.NodeFeatureRuleList { return &v1alpha1.NodeFeatureRuleList{} },
|
||||
func(dst, src *v1alpha1.NodeFeatureRuleList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1alpha1.NodeFeatureRuleList) []*v1alpha1.NodeFeatureRule {
|
||||
return gentype.ToPointerSlice(list.Items)
|
||||
},
|
||||
func(list *v1alpha1.NodeFeatureRuleList, items []*v1alpha1.NodeFeatureRule) {
|
||||
list.Items = gentype.FromPointerSlice(items)
|
||||
},
|
||||
),
|
||||
fake,
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureRule), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of NodeFeatureRules that match those selectors.
|
||||
func (c *FakeNodeFeatureRules) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureRuleList, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureRuleList{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListActionWithOptions(nodefeaturerulesResource, nodefeaturerulesKind, opts), emptyResult)
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.NodeFeatureRuleList{ListMeta: obj.(*v1alpha1.NodeFeatureRuleList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.NodeFeatureRuleList).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 nodeFeatureRules.
|
||||
func (c *FakeNodeFeatureRules) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchActionWithOptions(nodefeaturerulesResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a nodeFeatureRule and creates it. Returns the server's representation of the nodeFeatureRule, and an error, if there is any.
|
||||
func (c *FakeNodeFeatureRules) Create(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.CreateOptions) (result *v1alpha1.NodeFeatureRule, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureRule{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateActionWithOptions(nodefeaturerulesResource, nodeFeatureRule, opts), emptyResult)
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureRule), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a nodeFeatureRule and updates it. Returns the server's representation of the nodeFeatureRule, and an error, if there is any.
|
||||
func (c *FakeNodeFeatureRules) Update(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (result *v1alpha1.NodeFeatureRule, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureRule{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateActionWithOptions(nodefeaturerulesResource, nodeFeatureRule, opts), emptyResult)
|
||||
if obj == nil {
|
||||
return emptyResult, 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.
|
||||
Invokes(testing.NewRootDeleteActionWithOptions(nodefeaturerulesResource, name, opts), &v1alpha1.NodeFeatureRule{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeNodeFeatureRules) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionActionWithOptions(nodefeaturerulesResource, opts, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureRuleList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched nodeFeatureRule.
|
||||
func (c *FakeNodeFeatureRules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeatureRule, err error) {
|
||||
emptyResult := &v1alpha1.NodeFeatureRule{}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceActionWithOptions(nodefeaturerulesResource, name, pt, data, opts, subresources...), emptyResult)
|
||||
if obj == nil {
|
||||
return emptyResult, err
|
||||
}
|
||||
return obj.(*v1alpha1.NodeFeatureRule), err
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
http "net/http"
|
||||
|
||||
rest "k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
scheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
type NfdV1alpha1Interface interface {
|
||||
|
@ -95,10 +95,10 @@ func New(c rest.Interface) *NfdV1alpha1Client {
|
|||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1alpha1.SchemeGroupVersion
|
||||
gv := nfdv1alpha1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeaturesGetter has a method to return a NodeFeatureInterface.
|
||||
|
@ -37,31 +37,32 @@ type NodeFeaturesGetter interface {
|
|||
|
||||
// NodeFeatureInterface has methods to work with NodeFeature resources.
|
||||
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)
|
||||
Create(ctx context.Context, nodeFeature *nfdv1alpha1.NodeFeature, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeature, error)
|
||||
Update(ctx context.Context, nodeFeature *nfdv1alpha1.NodeFeature, opts v1.UpdateOptions) (*nfdv1alpha1.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)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureList, error)
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeature, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureList, 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.NodeFeature, err error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *nfdv1alpha1.NodeFeature, err error)
|
||||
NodeFeatureExpansion
|
||||
}
|
||||
|
||||
// nodeFeatures implements NodeFeatureInterface
|
||||
type nodeFeatures struct {
|
||||
*gentype.ClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList]
|
||||
*gentype.ClientWithList[*nfdv1alpha1.NodeFeature, *nfdv1alpha1.NodeFeatureList]
|
||||
}
|
||||
|
||||
// newNodeFeatures returns a NodeFeatures
|
||||
func newNodeFeatures(c *NfdV1alpha1Client, namespace string) *nodeFeatures {
|
||||
return &nodeFeatures{
|
||||
gentype.NewClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList](
|
||||
gentype.NewClientWithList[*nfdv1alpha1.NodeFeature, *nfdv1alpha1.NodeFeatureList](
|
||||
"nodefeatures",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
namespace,
|
||||
func() *v1alpha1.NodeFeature { return &v1alpha1.NodeFeature{} },
|
||||
func() *v1alpha1.NodeFeatureList { return &v1alpha1.NodeFeatureList{} }),
|
||||
func() *nfdv1alpha1.NodeFeature { return &nfdv1alpha1.NodeFeature{} },
|
||||
func() *nfdv1alpha1.NodeFeatureList { return &nfdv1alpha1.NodeFeatureList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureGroupsGetter has a method to return a NodeFeatureGroupInterface.
|
||||
|
@ -37,33 +37,34 @@ type NodeFeatureGroupsGetter interface {
|
|||
|
||||
// NodeFeatureGroupInterface has methods to work with NodeFeatureGroup resources.
|
||||
type NodeFeatureGroupInterface interface {
|
||||
Create(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.CreateOptions) (*v1alpha1.NodeFeatureGroup, error)
|
||||
Update(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureGroup, error)
|
||||
Create(ctx context.Context, nodeFeatureGroup *nfdv1alpha1.NodeFeatureGroup, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||
Update(ctx context.Context, nodeFeatureGroup *nfdv1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
UpdateStatus(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (*v1alpha1.NodeFeatureGroup, error)
|
||||
UpdateStatus(ctx context.Context, nodeFeatureGroup *nfdv1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (*nfdv1alpha1.NodeFeatureGroup, 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.NodeFeatureGroup, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureGroupList, error)
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureGroupList, 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.NodeFeatureGroup, err error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *nfdv1alpha1.NodeFeatureGroup, err error)
|
||||
NodeFeatureGroupExpansion
|
||||
}
|
||||
|
||||
// nodeFeatureGroups implements NodeFeatureGroupInterface
|
||||
type nodeFeatureGroups struct {
|
||||
*gentype.ClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList]
|
||||
*gentype.ClientWithList[*nfdv1alpha1.NodeFeatureGroup, *nfdv1alpha1.NodeFeatureGroupList]
|
||||
}
|
||||
|
||||
// newNodeFeatureGroups returns a NodeFeatureGroups
|
||||
func newNodeFeatureGroups(c *NfdV1alpha1Client, namespace string) *nodeFeatureGroups {
|
||||
return &nodeFeatureGroups{
|
||||
gentype.NewClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList](
|
||||
gentype.NewClientWithList[*nfdv1alpha1.NodeFeatureGroup, *nfdv1alpha1.NodeFeatureGroupList](
|
||||
"nodefeaturegroups",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
namespace,
|
||||
func() *v1alpha1.NodeFeatureGroup { return &v1alpha1.NodeFeatureGroup{} },
|
||||
func() *v1alpha1.NodeFeatureGroupList { return &v1alpha1.NodeFeatureGroupList{} }),
|
||||
func() *nfdv1alpha1.NodeFeatureGroup { return &nfdv1alpha1.NodeFeatureGroup{} },
|
||||
func() *nfdv1alpha1.NodeFeatureGroupList { return &nfdv1alpha1.NodeFeatureGroupList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureRulesGetter has a method to return a NodeFeatureRuleInterface.
|
||||
|
@ -37,31 +37,32 @@ type NodeFeatureRulesGetter interface {
|
|||
|
||||
// NodeFeatureRuleInterface has methods to work with NodeFeatureRule resources.
|
||||
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)
|
||||
Create(ctx context.Context, nodeFeatureRule *nfdv1alpha1.NodeFeatureRule, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||
Update(ctx context.Context, nodeFeatureRule *nfdv1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (*nfdv1alpha1.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)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureRuleList, error)
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureRuleList, 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.NodeFeatureRule, err error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *nfdv1alpha1.NodeFeatureRule, err error)
|
||||
NodeFeatureRuleExpansion
|
||||
}
|
||||
|
||||
// nodeFeatureRules implements NodeFeatureRuleInterface
|
||||
type nodeFeatureRules struct {
|
||||
*gentype.ClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList]
|
||||
*gentype.ClientWithList[*nfdv1alpha1.NodeFeatureRule, *nfdv1alpha1.NodeFeatureRuleList]
|
||||
}
|
||||
|
||||
// newNodeFeatureRules returns a NodeFeatureRules
|
||||
func newNodeFeatureRules(c *NfdV1alpha1Client) *nodeFeatureRules {
|
||||
return &nodeFeatureRules{
|
||||
gentype.NewClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList](
|
||||
gentype.NewClientWithList[*nfdv1alpha1.NodeFeatureRule, *nfdv1alpha1.NodeFeatureRuleList](
|
||||
"nodefeaturerules",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
"",
|
||||
func() *v1alpha1.NodeFeatureRule { return &v1alpha1.NodeFeatureRule{} },
|
||||
func() *v1alpha1.NodeFeatureRuleList { return &v1alpha1.NodeFeatureRuleList{} }),
|
||||
func() *nfdv1alpha1.NodeFeatureRule { return &nfdv1alpha1.NodeFeatureRule{} },
|
||||
func() *nfdv1alpha1.NodeFeatureRuleList { return &nfdv1alpha1.NodeFeatureRuleList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
fmt "fmt"
|
||||
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -28,15 +28,15 @@ import (
|
|||
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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/listers/nfd/v1alpha1"
|
||||
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureInformer provides access to a shared informer and lister for
|
||||
// NodeFeatures.
|
||||
type NodeFeatureInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.NodeFeatureLister
|
||||
Lister() nfdv1alpha1.NodeFeatureLister
|
||||
}
|
||||
|
||||
type nodeFeatureInformer struct {
|
||||
|
@ -71,7 +71,7 @@ func NewFilteredNodeFeatureInformer(client versioned.Interface, namespace string
|
|||
return client.NfdV1alpha1().NodeFeatures(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&nfdv1alpha1.NodeFeature{},
|
||||
&apinfdv1alpha1.NodeFeature{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
|
@ -82,9 +82,9 @@ func (f *nodeFeatureInformer) defaultInformer(client versioned.Interface, resync
|
|||
}
|
||||
|
||||
func (f *nodeFeatureInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&nfdv1alpha1.NodeFeature{}, f.defaultInformer)
|
||||
return f.factory.InformerFor(&apinfdv1alpha1.NodeFeature{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *nodeFeatureInformer) Lister() v1alpha1.NodeFeatureLister {
|
||||
return v1alpha1.NewNodeFeatureLister(f.Informer().GetIndexer())
|
||||
func (f *nodeFeatureInformer) Lister() nfdv1alpha1.NodeFeatureLister {
|
||||
return nfdv1alpha1.NewNodeFeatureLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -28,15 +28,15 @@ import (
|
|||
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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/listers/nfd/v1alpha1"
|
||||
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureGroupInformer provides access to a shared informer and lister for
|
||||
// NodeFeatureGroups.
|
||||
type NodeFeatureGroupInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.NodeFeatureGroupLister
|
||||
Lister() nfdv1alpha1.NodeFeatureGroupLister
|
||||
}
|
||||
|
||||
type nodeFeatureGroupInformer struct {
|
||||
|
@ -71,7 +71,7 @@ func NewFilteredNodeFeatureGroupInformer(client versioned.Interface, namespace s
|
|||
return client.NfdV1alpha1().NodeFeatureGroups(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&nfdv1alpha1.NodeFeatureGroup{},
|
||||
&apinfdv1alpha1.NodeFeatureGroup{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
|
@ -82,9 +82,9 @@ func (f *nodeFeatureGroupInformer) defaultInformer(client versioned.Interface, r
|
|||
}
|
||||
|
||||
func (f *nodeFeatureGroupInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&nfdv1alpha1.NodeFeatureGroup{}, f.defaultInformer)
|
||||
return f.factory.InformerFor(&apinfdv1alpha1.NodeFeatureGroup{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *nodeFeatureGroupInformer) Lister() v1alpha1.NodeFeatureGroupLister {
|
||||
return v1alpha1.NewNodeFeatureGroupLister(f.Informer().GetIndexer())
|
||||
func (f *nodeFeatureGroupInformer) Lister() nfdv1alpha1.NodeFeatureGroupLister {
|
||||
return nfdv1alpha1.NewNodeFeatureGroupLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -28,15 +28,15 @@ import (
|
|||
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"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/listers/nfd/v1alpha1"
|
||||
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureRuleInformer provides access to a shared informer and lister for
|
||||
// NodeFeatureRules.
|
||||
type NodeFeatureRuleInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.NodeFeatureRuleLister
|
||||
Lister() nfdv1alpha1.NodeFeatureRuleLister
|
||||
}
|
||||
|
||||
type nodeFeatureRuleInformer struct {
|
||||
|
@ -70,7 +70,7 @@ func NewFilteredNodeFeatureRuleInformer(client versioned.Interface, resyncPeriod
|
|||
return client.NfdV1alpha1().NodeFeatureRules().Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&nfdv1alpha1.NodeFeatureRule{},
|
||||
&apinfdv1alpha1.NodeFeatureRule{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
|
@ -81,9 +81,9 @@ func (f *nodeFeatureRuleInformer) defaultInformer(client versioned.Interface, re
|
|||
}
|
||||
|
||||
func (f *nodeFeatureRuleInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&nfdv1alpha1.NodeFeatureRule{}, f.defaultInformer)
|
||||
return f.factory.InformerFor(&apinfdv1alpha1.NodeFeatureRule{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *nodeFeatureRuleInformer) Lister() v1alpha1.NodeFeatureRuleLister {
|
||||
return v1alpha1.NewNodeFeatureRuleLister(f.Informer().GetIndexer())
|
||||
func (f *nodeFeatureRuleInformer) Lister() nfdv1alpha1.NodeFeatureRuleLister {
|
||||
return nfdv1alpha1.NewNodeFeatureRuleLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
|||
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"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureLister helps list NodeFeatures.
|
||||
|
@ -30,7 +30,7 @@ import (
|
|||
type NodeFeatureLister interface {
|
||||
// List lists all NodeFeatures in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error)
|
||||
List(selector labels.Selector) (ret []*nfdv1alpha1.NodeFeature, err error)
|
||||
// NodeFeatures returns an object that can list and get NodeFeatures.
|
||||
NodeFeatures(namespace string) NodeFeatureNamespaceLister
|
||||
NodeFeatureListerExpansion
|
||||
|
@ -38,17 +38,17 @@ type NodeFeatureLister interface {
|
|||
|
||||
// nodeFeatureLister implements the NodeFeatureLister interface.
|
||||
type nodeFeatureLister struct {
|
||||
listers.ResourceIndexer[*v1alpha1.NodeFeature]
|
||||
listers.ResourceIndexer[*nfdv1alpha1.NodeFeature]
|
||||
}
|
||||
|
||||
// NewNodeFeatureLister returns a new NodeFeatureLister.
|
||||
func NewNodeFeatureLister(indexer cache.Indexer) NodeFeatureLister {
|
||||
return &nodeFeatureLister{listers.New[*v1alpha1.NodeFeature](indexer, v1alpha1.Resource("nodefeature"))}
|
||||
return &nodeFeatureLister{listers.New[*nfdv1alpha1.NodeFeature](indexer, nfdv1alpha1.Resource("nodefeature"))}
|
||||
}
|
||||
|
||||
// NodeFeatures returns an object that can list and get NodeFeatures.
|
||||
func (s *nodeFeatureLister) NodeFeatures(namespace string) NodeFeatureNamespaceLister {
|
||||
return nodeFeatureNamespaceLister{listers.NewNamespaced[*v1alpha1.NodeFeature](s.ResourceIndexer, namespace)}
|
||||
return nodeFeatureNamespaceLister{listers.NewNamespaced[*nfdv1alpha1.NodeFeature](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
|
||||
// NodeFeatureNamespaceLister helps list and get NodeFeatures.
|
||||
|
@ -56,15 +56,15 @@ func (s *nodeFeatureLister) NodeFeatures(namespace string) NodeFeatureNamespaceL
|
|||
type NodeFeatureNamespaceLister interface {
|
||||
// List lists all NodeFeatures in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error)
|
||||
List(selector labels.Selector) (ret []*nfdv1alpha1.NodeFeature, err error)
|
||||
// Get retrieves the NodeFeature from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.NodeFeature, error)
|
||||
Get(name string) (*nfdv1alpha1.NodeFeature, error)
|
||||
NodeFeatureNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// nodeFeatureNamespaceLister implements the NodeFeatureNamespaceLister
|
||||
// interface.
|
||||
type nodeFeatureNamespaceLister struct {
|
||||
listers.ResourceIndexer[*v1alpha1.NodeFeature]
|
||||
listers.ResourceIndexer[*nfdv1alpha1.NodeFeature]
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
|||
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"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureGroupLister helps list NodeFeatureGroups.
|
||||
|
@ -30,7 +30,7 @@ import (
|
|||
type NodeFeatureGroupLister interface {
|
||||
// List lists all NodeFeatureGroups in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureGroup, err error)
|
||||
List(selector labels.Selector) (ret []*nfdv1alpha1.NodeFeatureGroup, err error)
|
||||
// NodeFeatureGroups returns an object that can list and get NodeFeatureGroups.
|
||||
NodeFeatureGroups(namespace string) NodeFeatureGroupNamespaceLister
|
||||
NodeFeatureGroupListerExpansion
|
||||
|
@ -38,17 +38,17 @@ type NodeFeatureGroupLister interface {
|
|||
|
||||
// nodeFeatureGroupLister implements the NodeFeatureGroupLister interface.
|
||||
type nodeFeatureGroupLister struct {
|
||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureGroup]
|
||||
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureGroup]
|
||||
}
|
||||
|
||||
// NewNodeFeatureGroupLister returns a new NodeFeatureGroupLister.
|
||||
func NewNodeFeatureGroupLister(indexer cache.Indexer) NodeFeatureGroupLister {
|
||||
return &nodeFeatureGroupLister{listers.New[*v1alpha1.NodeFeatureGroup](indexer, v1alpha1.Resource("nodefeaturegroup"))}
|
||||
return &nodeFeatureGroupLister{listers.New[*nfdv1alpha1.NodeFeatureGroup](indexer, nfdv1alpha1.Resource("nodefeaturegroup"))}
|
||||
}
|
||||
|
||||
// NodeFeatureGroups returns an object that can list and get NodeFeatureGroups.
|
||||
func (s *nodeFeatureGroupLister) NodeFeatureGroups(namespace string) NodeFeatureGroupNamespaceLister {
|
||||
return nodeFeatureGroupNamespaceLister{listers.NewNamespaced[*v1alpha1.NodeFeatureGroup](s.ResourceIndexer, namespace)}
|
||||
return nodeFeatureGroupNamespaceLister{listers.NewNamespaced[*nfdv1alpha1.NodeFeatureGroup](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
|
||||
// NodeFeatureGroupNamespaceLister helps list and get NodeFeatureGroups.
|
||||
|
@ -56,15 +56,15 @@ func (s *nodeFeatureGroupLister) NodeFeatureGroups(namespace string) NodeFeature
|
|||
type NodeFeatureGroupNamespaceLister interface {
|
||||
// List lists all NodeFeatureGroups in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureGroup, err error)
|
||||
List(selector labels.Selector) (ret []*nfdv1alpha1.NodeFeatureGroup, err error)
|
||||
// Get retrieves the NodeFeatureGroup from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.NodeFeatureGroup, error)
|
||||
Get(name string) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||
NodeFeatureGroupNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// nodeFeatureGroupNamespaceLister implements the NodeFeatureGroupNamespaceLister
|
||||
// interface.
|
||||
type nodeFeatureGroupNamespaceLister struct {
|
||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureGroup]
|
||||
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureGroup]
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
|||
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"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// NodeFeatureRuleLister helps list NodeFeatureRules.
|
||||
|
@ -30,19 +30,19 @@ import (
|
|||
type NodeFeatureRuleLister interface {
|
||||
// List lists all NodeFeatureRules in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.NodeFeatureRule, err error)
|
||||
List(selector labels.Selector) (ret []*nfdv1alpha1.NodeFeatureRule, err error)
|
||||
// Get retrieves the NodeFeatureRule from the index for a given name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.NodeFeatureRule, error)
|
||||
Get(name string) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||
NodeFeatureRuleListerExpansion
|
||||
}
|
||||
|
||||
// nodeFeatureRuleLister implements the NodeFeatureRuleLister interface.
|
||||
type nodeFeatureRuleLister struct {
|
||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureRule]
|
||||
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureRule]
|
||||
}
|
||||
|
||||
// NewNodeFeatureRuleLister returns a new NodeFeatureRuleLister.
|
||||
func NewNodeFeatureRuleLister(indexer cache.Indexer) NodeFeatureRuleLister {
|
||||
return &nodeFeatureRuleLister{listers.New[*v1alpha1.NodeFeatureRule](indexer, v1alpha1.Resource("nodefeaturerule"))}
|
||||
return &nodeFeatureRuleLister{listers.New[*nfdv1alpha1.NodeFeatureRule](indexer, nfdv1alpha1.Resource("nodefeaturerule"))}
|
||||
}
|
||||
|
|
48
api/image-compatibility/v1alpha1/spec.go
Normal file
48
api/image-compatibility/v1alpha1/spec.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// ArtifactType is a type of OCI artifact that contains image compatibility metadata.
|
||||
const (
|
||||
ArtifactType = "application/vnd.nfd.image-compatibility.v1alpha1"
|
||||
Version = "v1alpha1"
|
||||
)
|
||||
|
||||
// Spec represents image compatibility metadata.
|
||||
type Spec struct {
|
||||
// Version of the spec.
|
||||
Version string `json:"version"`
|
||||
// Compatibilities contains list of compatibility sets.
|
||||
Compatibilties []Compatibility `json:"compatibilities"`
|
||||
}
|
||||
|
||||
// Compatibility represents image compatibility metadata
|
||||
// that describe the image requirements for the host and OS.
|
||||
type Compatibility struct {
|
||||
// Rules represents a list of Node Feature Rules.
|
||||
Rules []nfdv1alpha1.Rule `json:"rules"`
|
||||
// Weight indicates the priority of the compatibility set.
|
||||
Weight int `json:"weight,omitempty"`
|
||||
// Tag enables grouping or distinguishing between compatibility sets.
|
||||
Tag string `json:"tag,omitempty"`
|
||||
// Description of the compatibility set.
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
|
@ -5,8 +5,8 @@ go 1.22.2
|
|||
require (
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/stretchr/testify v1.8.4
|
||||
k8s.io/api v0.30.7
|
||||
k8s.io/apimachinery v0.30.7
|
||||
k8s.io/api v0.30.8
|
||||
k8s.io/apimachinery v0.30.8
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
@ -75,10 +75,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.30.7 h1:wB2eHI+IptVYsz5WsAQpI6+Dqi3+11wEWBqIh4fh980=
|
||||
k8s.io/api v0.30.7/go.mod h1:bR0EwbmhYmJvUoeza7ZzBUmYCrVXccQ9JOdfv0BxhH0=
|
||||
k8s.io/apimachinery v0.30.7 h1:CoQFxvzPFKwU1eJGN/8LgM3ZJBC3hKgvwGqRrL43uIY=
|
||||
k8s.io/apimachinery v0.30.7/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/api v0.30.8 h1:Y+yZRF3c1WC0MTkLe0qBkiLCquRNa4I21/iDioGMCbo=
|
||||
k8s.io/api v0.30.8/go.mod h1:89IE5MzirZ5HHxU/Hq1/KWGqXkhXClu/FHGesFhQ0A4=
|
||||
k8s.io/apimachinery v0.30.8 h1:9jyTItYzmJc00cBDxZC5ArFNxUeKCwbw0m760iFUMKY=
|
||||
k8s.io/apimachinery v0.30.8/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
|
|
|
@ -19,5 +19,3 @@ limitations under the License.
|
|||
// +kubebuilder:object:generate=true
|
||||
// +groupName=nfd.k8s-sigs.io
|
||||
package v1alpha1
|
||||
|
||||
//go:generate ./generate.sh
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
go-to-protobuf \
|
||||
--output-base=. \
|
||||
--go-header-file ../../../../hack/boilerplate.go.txt \
|
||||
--proto-import ../../../../vendor/ \
|
||||
--packages +sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1=v1alpha1 \
|
||||
--keep-gogoproto=false \
|
||||
--apimachinery-packages "-k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
mv sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1/* .
|
||||
rm -rf sigs.k8s.io
|
File diff suppressed because it is too large
Load diff
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package v1alpha1;
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1";
|
||||
|
||||
// AttributeFeatureSet is a set of features having string value.
|
||||
//
|
||||
// +protobuf=true
|
||||
message AttributeFeatureSet {
|
||||
map<string, string> elements = 1;
|
||||
}
|
||||
|
||||
// Features is the collection of all discovered features.
|
||||
//
|
||||
// +protobuf=true
|
||||
message Features {
|
||||
// Flags contains all the flag-type features of the node.
|
||||
// +optional
|
||||
map<string, FlagFeatureSet> flags = 1;
|
||||
|
||||
// Attributes contains all the attribute-type features of the node.
|
||||
// +optional
|
||||
map<string, AttributeFeatureSet> vattributes = 2;
|
||||
|
||||
// Instances contains all the instance-type features of the node.
|
||||
// +optional
|
||||
map<string, InstanceFeatureSet> instances = 3;
|
||||
}
|
||||
|
||||
// FlagFeatureSet is a set of simple features only containing names without values.
|
||||
//
|
||||
// +protobuf=true
|
||||
message FlagFeatureSet {
|
||||
map<string, Nil> elements = 1;
|
||||
}
|
||||
|
||||
// InstanceFeature represents one instance of a complex features, e.g. a device.
|
||||
//
|
||||
// +protobuf=true
|
||||
message InstanceFeature {
|
||||
map<string, string> attributes = 1;
|
||||
}
|
||||
|
||||
// InstanceFeatureSet is a set of features each of which is an instance having multiple attributes.
|
||||
//
|
||||
// +protobuf=true
|
||||
message InstanceFeatureSet {
|
||||
repeated InstanceFeature elements = 1;
|
||||
}
|
||||
|
||||
// Nil is a dummy empty struct for protobuf compatibility
|
||||
//
|
||||
// +protobuf=true
|
||||
message Nil {
|
||||
}
|
||||
|
|
@ -56,55 +56,44 @@ type NodeFeatureSpec struct {
|
|||
}
|
||||
|
||||
// Features is the collection of all discovered features.
|
||||
//
|
||||
// +protobuf=true
|
||||
type Features struct {
|
||||
// Flags contains all the flag-type features of the node.
|
||||
// +optional
|
||||
Flags map[string]FlagFeatureSet `json:"flags" protobuf:"bytes,1,rep,name=flags"`
|
||||
Flags map[string]FlagFeatureSet `json:"flags"`
|
||||
// Attributes contains all the attribute-type features of the node.
|
||||
// +optional
|
||||
Attributes map[string]AttributeFeatureSet `json:"attributes" protobuf:"bytes,2,rep,name=vattributes"`
|
||||
Attributes map[string]AttributeFeatureSet `json:"attributes"`
|
||||
// Instances contains all the instance-type features of the node.
|
||||
// +optional
|
||||
Instances map[string]InstanceFeatureSet `json:"instances" protobuf:"bytes,3,rep,name=instances"`
|
||||
Instances map[string]InstanceFeatureSet `json:"instances"`
|
||||
}
|
||||
|
||||
// FlagFeatureSet is a set of simple features only containing names without values.
|
||||
//
|
||||
// +protobuf=true
|
||||
type FlagFeatureSet struct {
|
||||
// Individual features of the feature set.
|
||||
Elements map[string]Nil `json:"elements" protobuf:"bytes,1,rep,name=elements"`
|
||||
Elements map[string]Nil `json:"elements"`
|
||||
}
|
||||
|
||||
// AttributeFeatureSet is a set of features having string value.
|
||||
//
|
||||
// +protobuf=true
|
||||
type AttributeFeatureSet struct {
|
||||
// Individual features of the feature set.
|
||||
Elements map[string]string `json:"elements" protobuf:"bytes,1,rep,name=elements"`
|
||||
Elements map[string]string `json:"elements"`
|
||||
}
|
||||
|
||||
// InstanceFeatureSet is a set of features each of which is an instance having multiple attributes.
|
||||
//
|
||||
// +protobuf=true
|
||||
type InstanceFeatureSet struct {
|
||||
// Individual features of the feature set.
|
||||
Elements []InstanceFeature `json:"elements" protobuf:"bytes,1,rep,name=elements"`
|
||||
Elements []InstanceFeature `json:"elements"`
|
||||
}
|
||||
|
||||
// InstanceFeature represents one instance of a complex features, e.g. a device.
|
||||
//
|
||||
// +protobuf=true
|
||||
type InstanceFeature struct {
|
||||
// Attributes of the instance feature.
|
||||
Attributes map[string]string `json:"attributes" protobuf:"bytes,1,rep,name=attributes"`
|
||||
Attributes map[string]string `json:"attributes"`
|
||||
}
|
||||
|
||||
// Nil is a dummy empty struct for protobuf compatibility
|
||||
//
|
||||
// +protobuf=true
|
||||
// Nil is a dummy empty struct for protobuf compatibility.
|
||||
// NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||
type Nil struct{}
|
||||
|
||||
// NodeFeatureRuleList contains a list of NodeFeatureRule objects.
|
||||
|
|
29
api/nfd/v1alpha1/utils.go
Normal file
29
api/nfd/v1alpha1/utils.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// String represents the match expression as a string type.
|
||||
func (m MatchExpression) String() string {
|
||||
if len(m.Value) < 1 {
|
||||
return fmt.Sprintf("{op: %q}", m.Op)
|
||||
}
|
||||
return fmt.Sprintf("{op: %q, value: %q}", m.Op, m.Value)
|
||||
}
|
27
cmd/nfd/main.go
Normal file
27
cmd/nfd/main.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/node-feature-discovery/cmd/nfd/subcmd"
|
||||
)
|
||||
|
||||
const ProgramName = "nfd"
|
||||
|
||||
func main() {
|
||||
subcmd.Execute()
|
||||
}
|
36
cmd/nfd/subcmd/compat/compat.go
Normal file
36
cmd/nfd/subcmd/compat/compat.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var CompatCmd = &cobra.Command{
|
||||
Use: "compat",
|
||||
Short: "Image compatibility commands",
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := CompatCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
70
cmd/nfd/subcmd/compat/options/platform.go
Normal file
70
cmd/nfd/subcmd/compat/options/platform.go
Normal 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.
|
||||
*/
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// PlatformOption represents
|
||||
type PlatformOption struct {
|
||||
// PlatformStr contains the raw platform argument provided by the user.
|
||||
PlatformStr string
|
||||
// Platform represents the OCI platform specification, built from PlatformStr.
|
||||
Platform *ocispec.Platform
|
||||
}
|
||||
|
||||
// Parse takes the PlatformStr argument provided by the user
|
||||
// to build OCI platform specification.
|
||||
func (opt *PlatformOption) Parse(*cobra.Command) error {
|
||||
var pStr string
|
||||
|
||||
if opt.PlatformStr == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
platform := &ocispec.Platform{}
|
||||
pStr, platform.OSVersion, _ = strings.Cut(opt.PlatformStr, ":")
|
||||
parts := strings.Split(pStr, "/")
|
||||
|
||||
switch len(parts) {
|
||||
case 3:
|
||||
platform.Variant = parts[2]
|
||||
fallthrough
|
||||
case 2:
|
||||
platform.Architecture = parts[1]
|
||||
case 1:
|
||||
platform.Architecture = runtime.GOARCH
|
||||
default:
|
||||
return fmt.Errorf("failed to parse platform %q: expected format os[/arch[/variant]]", opt.PlatformStr)
|
||||
}
|
||||
|
||||
platform.OS = parts[0]
|
||||
if platform.OS == "" {
|
||||
return fmt.Errorf("invalid platform: OS cannot be empty")
|
||||
}
|
||||
if platform.Architecture == "" {
|
||||
return fmt.Errorf("invalid platform: Architecture cannot be empty")
|
||||
}
|
||||
opt.Platform = platform
|
||||
return nil
|
||||
}
|
224
cmd/nfd/subcmd/compat/validate-node.go
Normal file
224
cmd/nfd/subcmd/compat/validate-node.go
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/jedib0t/go-pretty/v6/text"
|
||||
"github.com/spf13/cobra"
|
||||
"oras.land/oras-go/v2/registry"
|
||||
|
||||
"sigs.k8s.io/node-feature-discovery/cmd/nfd/subcmd/compat/options"
|
||||
artifactcli "sigs.k8s.io/node-feature-discovery/pkg/client-nfd/compat/artifact-client"
|
||||
nodevalidator "sigs.k8s.io/node-feature-discovery/pkg/client-nfd/compat/node-validator"
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
)
|
||||
|
||||
var (
|
||||
image string
|
||||
tags []string
|
||||
platform options.PlatformOption
|
||||
plainHTTP bool
|
||||
outputJSON bool
|
||||
|
||||
// secrets
|
||||
readPassword bool
|
||||
readAccessToken bool
|
||||
username string
|
||||
password string
|
||||
accessToken string
|
||||
)
|
||||
|
||||
var validateNodeCmd = &cobra.Command{
|
||||
Use: "validate-node",
|
||||
Short: "Perform node validation based on its associated image compatibility artifact",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
|
||||
if err = platform.Parse(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if readAccessToken && readPassword {
|
||||
return fmt.Errorf("cannot use --registry-token-stdin and --registry-password-stdin at the same time")
|
||||
} else if readAccessToken {
|
||||
accessToken, err = readStdin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if readPassword {
|
||||
password, err = readStdin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
ref, err := registry.ParseReference(image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sources := map[string]source.FeatureSource{}
|
||||
for k, v := range source.GetAllFeatureSources() {
|
||||
if ts, ok := v.(source.SupplementalSource); ok && ts.DisableByDefault() {
|
||||
continue
|
||||
}
|
||||
sources[k] = v
|
||||
}
|
||||
|
||||
authOpt := artifactcli.WithAuthDefault()
|
||||
if username != "" && password != "" {
|
||||
authOpt = artifactcli.WithAuthPassword(username, password)
|
||||
} else if accessToken != "" {
|
||||
authOpt = artifactcli.WithAuthToken(accessToken)
|
||||
}
|
||||
|
||||
ac := artifactcli.New(
|
||||
&ref,
|
||||
artifactcli.WithArgs(artifactcli.Args{PlainHttp: plainHTTP}),
|
||||
artifactcli.WithPlatform(platform.Platform),
|
||||
authOpt,
|
||||
)
|
||||
|
||||
nv := nodevalidator.New(
|
||||
nodevalidator.WithArgs(&nodevalidator.Args{Tags: tags}),
|
||||
nodevalidator.WithArtifactClient(ac),
|
||||
nodevalidator.WithSources(sources),
|
||||
)
|
||||
|
||||
out, err := nv.Execute(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if outputJSON {
|
||||
b, err := json.Marshal(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s", b)
|
||||
} else {
|
||||
pprintResult(out)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func readStdin() (string, error) {
|
||||
secretRaw, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
secret := strings.TrimSuffix(string(secretRaw), "\n")
|
||||
secret = strings.TrimSuffix(secret, "\r")
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func pprintResult(css []*nodevalidator.CompatibilityStatus) {
|
||||
for i, cs := range css {
|
||||
fmt.Print(text.Colors{text.FgCyan, text.Bold}.Sprintf("COMPATIBILITY SET #%d ", i+1))
|
||||
fmt.Print(text.FgCyan.Sprintf("Weight: %d", cs.Weight))
|
||||
if cs.Tag != "" {
|
||||
fmt.Print(text.FgCyan.Sprintf("; Tag: %s", cs.Tag))
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println(text.FgWhite.Sprintf("Description: %s", cs.Description))
|
||||
|
||||
for _, r := range cs.Rules {
|
||||
printTable(r)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func printTable(rs nodevalidator.ProcessedRuleStatus) {
|
||||
t := table.NewWriter()
|
||||
t.SetStyle(table.StyleLight)
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.Style().Format.Header = text.FormatDefault
|
||||
t.SetAutoIndex(true)
|
||||
|
||||
validTxt := text.BgRed.Sprint(" FAIL ")
|
||||
if rs.IsMatch {
|
||||
validTxt = text.BgGreen.Sprint(" OK ")
|
||||
}
|
||||
ruleTxt := strings.ToUpper(fmt.Sprintf("rule: %s", rs.Name))
|
||||
|
||||
t.SetTitle(text.Bold.Sprintf("%s - %s", ruleTxt, validTxt))
|
||||
t.AppendHeader(table.Row{"Feature", "Expression", "Matcher Type", "Status"})
|
||||
|
||||
if mf := rs.MatchedExpressions; len(mf) > 0 {
|
||||
renderMatchFeatures(t, mf)
|
||||
}
|
||||
if ma := rs.MatchedAny; len(ma) > 0 {
|
||||
for _, elem := range ma {
|
||||
t.AppendSeparator()
|
||||
renderMatchFeatures(t, elem.MatchedExpressions)
|
||||
}
|
||||
}
|
||||
t.Render()
|
||||
}
|
||||
|
||||
func renderMatchFeatures(t table.Writer, matchedExpressions []nodevalidator.MatchedExpression) {
|
||||
for _, fm := range matchedExpressions {
|
||||
fullFeatureDomain := fm.Feature
|
||||
if fm.Name != "" {
|
||||
fullFeatureDomain = fmt.Sprintf("%s.%s", fm.Feature, fm.Name)
|
||||
}
|
||||
|
||||
addTableRows(t, fullFeatureDomain, fm.Expression.String(), fm.MatcherType, fm.IsMatch)
|
||||
}
|
||||
}
|
||||
|
||||
func addTableRows(t table.Writer, fullFeatureDomain, expression string, matcherType nodevalidator.MatcherType, isMatch bool) {
|
||||
status := text.FgHiRed.Sprint("FAIL")
|
||||
if isMatch {
|
||||
status = text.FgHiGreen.Sprint("OK")
|
||||
}
|
||||
t.AppendRow(table.Row{fullFeatureDomain, expression, matcherType, status})
|
||||
}
|
||||
|
||||
func init() {
|
||||
CompatCmd.AddCommand(validateNodeCmd)
|
||||
validateNodeCmd.Flags().StringVar(&image, "image", "", "the URL of the image containing compatibility metadata")
|
||||
validateNodeCmd.Flags().StringSliceVar(&tags, "tags", []string{}, "a list of tags that must match the tags set on the compatibility objects")
|
||||
validateNodeCmd.Flags().StringVar(&platform.PlatformStr, "platform", "", "the artifact platform in the format os[/arch][/variant][:os_version]")
|
||||
validateNodeCmd.Flags().BoolVar(&plainHTTP, "plain-http", false, "use of HTTP protocol for all registry communications")
|
||||
validateNodeCmd.Flags().BoolVar(&outputJSON, "output-json", false, "print a JSON object")
|
||||
validateNodeCmd.Flags().StringVar(&username, "registry-username", "", "registry username")
|
||||
validateNodeCmd.Flags().BoolVar(&readPassword, "registry-password-stdin", false, "read registry password from stdin")
|
||||
validateNodeCmd.Flags().BoolVar(&readAccessToken, "registry-token-stdin", false, "read registry access token from stdin")
|
||||
|
||||
if err := validateNodeCmd.MarkFlagRequired("image"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
45
cmd/nfd/subcmd/root.go
Normal file
45
cmd/nfd/subcmd/root.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package subcmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"sigs.k8s.io/node-feature-discovery/cmd/nfd/subcmd/compat"
|
||||
)
|
||||
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "nfd",
|
||||
Short: "Node Feature Discovery client",
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(compat.CompatCmd)
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -69,8 +69,9 @@ spec:
|
|||
properties:
|
||||
elements:
|
||||
additionalProperties:
|
||||
description: Nil is a dummy empty struct for protobuf
|
||||
compatibility
|
||||
description: |-
|
||||
Nil is a dummy empty struct for protobuf compatibility.
|
||||
NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||
type: object
|
||||
description: Individual features of the feature set.
|
||||
type: object
|
||||
|
|
|
@ -69,8 +69,9 @@ spec:
|
|||
properties:
|
||||
elements:
|
||||
additionalProperties:
|
||||
description: Nil is a dummy empty struct for protobuf
|
||||
compatibility
|
||||
description: |-
|
||||
Nil is a dummy empty struct for protobuf compatibility.
|
||||
NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||
type: object
|
||||
description: Individual features of the feature set.
|
||||
type: object
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "Feature Gates"
|
||||
layout: default
|
||||
sort: 10
|
||||
sort: 11
|
||||
---
|
||||
|
||||
# Feature Gates
|
||||
|
|
65
docs/reference/node-feature-client-reference.md
Normal file
65
docs/reference/node-feature-client-reference.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
title: "Node Feature client cmdline reference"
|
||||
layout: default
|
||||
sort: 9
|
||||
---
|
||||
|
||||
# Commandline flags of nfd client
|
||||
{: .no_toc}
|
||||
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta}
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
---
|
||||
**The client is in the experimental `v1alpha1` version.**
|
||||
|
||||
To quickly view available command line flags execute `nfd --help`.
|
||||
|
||||
### -h, --help
|
||||
|
||||
Print usage and exit.
|
||||
|
||||
## compat
|
||||
|
||||
Image Compatibility commands.
|
||||
|
||||
### validate-node
|
||||
|
||||
Perform node validation based on its associated image compatibility artifact.
|
||||
|
||||
#### --image
|
||||
|
||||
The `--image` flag specifies the URL of the image containing compatibility metadata.
|
||||
|
||||
#### --plain-http
|
||||
|
||||
The `--plain-http` flag forces the use of HTTP protocol for all registry communications.
|
||||
Default: `false`
|
||||
|
||||
#### --platform
|
||||
|
||||
The `--platform` flag specifies the artifact platform in the format `os[/arch][/variant][:os_version]`.
|
||||
|
||||
#### --tags
|
||||
|
||||
The `--tags` flag specifies a list of tags that must match the tags
|
||||
set on the compatibility objects.
|
||||
|
||||
#### --output-json
|
||||
|
||||
The `--output-json` flag prints the output as a JSON object.
|
||||
|
||||
#### --registry-username
|
||||
|
||||
The `--registry-username` flag specifies the username for the registry.
|
||||
|
||||
#### --registry-password-stdin
|
||||
|
||||
The `--registry-password-stdin` flag enables reading of registry password from stdin.
|
||||
|
||||
#### --registry-token-stdin
|
||||
|
||||
The `--registry-token-stdin` flag enables reading of registry token from stdin.
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "Versions"
|
||||
layout: default
|
||||
sort: 9
|
||||
sort: 10
|
||||
---
|
||||
|
||||
# Versions and deprecation
|
||||
|
|
226
docs/usage/image-compatibility.md
Normal file
226
docs/usage/image-compatibility.md
Normal file
|
@ -0,0 +1,226 @@
|
|||
---
|
||||
title: "Image Compatibility Artifact"
|
||||
layout: default
|
||||
sort: 11
|
||||
---
|
||||
|
||||
# Image Compatibility Artifact
|
||||
{: .no_toc}
|
||||
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta}
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
---
|
||||
|
||||
## Image Compatibility
|
||||
|
||||
**Image Compatibility is in the experimental `v1alpha1` version.**
|
||||
|
||||
Image compatibility metadata enables container image authors to define their
|
||||
image requirements using [Node Feature Rules](./custom-resources.md#nodefeaturerule).
|
||||
This complementary solution allows features discovered on nodes to be matched
|
||||
directly from images. As a result, container requirements become discoverable
|
||||
and programmable, supporting various consumers and use cases where applications
|
||||
need a specific compatible environment.
|
||||
|
||||
### Compatibility Specification
|
||||
|
||||
The compatibility specification is a list of compatibility objects that contain
|
||||
[Node Feature Rules](./custom-resources.md#nodefeaturerule), along with
|
||||
additional fields to control the execution of validation between the image and
|
||||
the host.
|
||||
|
||||
### Schema
|
||||
|
||||
- **version** - *string*
|
||||
This REQUIRED property specifies the version of the API in use.
|
||||
|
||||
- **compatibilities** - *array of object*
|
||||
This REQUIRED property is a list of compatibility sets.
|
||||
|
||||
- **rules** - *object*
|
||||
This REQUIRED property is a reference to the spec of the [NodeFeatureRule API](./custom-resources.md#nodefeaturerule).
|
||||
The spec allows image requirements to be described using the features
|
||||
discovered from NFD sources. For more details, please refer to [the documentation](./custom-resources.md#nodefeaturerule).
|
||||
|
||||
- **weight** - *int*
|
||||
This OPTIONAL property specifies the [node affinity weight](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity-weight).
|
||||
|
||||
- **tag** - *string*
|
||||
This OPTIONAL property allows for the grouping or separation of
|
||||
compatibility sets.
|
||||
|
||||
- **description** - *string*
|
||||
This OPTIONAL property provides a brief description of a compatibility set.
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
version: v1alpha1
|
||||
compatibilities:
|
||||
- description: "My image requirements"
|
||||
rules:
|
||||
- name: "kernel and cpu"
|
||||
matchFeatures:
|
||||
- feature: kernel.loadedmodule
|
||||
matchExpressions:
|
||||
vfio-pci: {op: Exists}
|
||||
- feature: cpu.model
|
||||
matchExpressions:
|
||||
vendor_id: {op: In, value: ["Intel", "AMD"]}
|
||||
- name: "one of available nics"
|
||||
matchAny:
|
||||
- matchFeatures:
|
||||
- feature: pci.device
|
||||
matchExpressions:
|
||||
vendor: {op: In, value: ["0eee"]}
|
||||
class: {op: In, value: ["0200"]}
|
||||
- matchFeatures:
|
||||
- feature: pci.device
|
||||
matchExpressions:
|
||||
vendor: {op: In, value: ["0fff"]}
|
||||
class: {op: In, value: ["0200"]}
|
||||
```
|
||||
|
||||
### OCI Artifact
|
||||
|
||||
An [OCI artifact](https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage)
|
||||
is used to store image compatibility metadata.
|
||||
The artifact can be associated with a specific image through [the subject field](https://github.com/opencontainers/distribution-spec/blob/11b8e3fba7d2d7329513d0cff53058243c334858/spec.md#pushing-manifests-with-subject)
|
||||
and pushed to the registry along with the image.
|
||||
|
||||
Example manifest:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"artifactType": "application/vnd.nfd.image-compatibility.v1alpha1",
|
||||
"config": {
|
||||
"mediaType": "application/vnd.oci.empty.v1+json",
|
||||
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
||||
"size": 2
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.nfd.image-compatibility.spec.v1alpha1+yaml",
|
||||
"digest": "sha256:4a47f8ae4c713906618413cb9795824d09eeadf948729e213a1ba11a1e31d052",
|
||||
"size": 1710
|
||||
}
|
||||
],
|
||||
"subject": {
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
|
||||
"size": 7682
|
||||
},
|
||||
"annotations": {
|
||||
"oci.opencontainers.image.created": "2024-03-27T08:08:08Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Attach the artifact to the image
|
||||
|
||||
Create an image compatibility specification for the image, then install the
|
||||
[ORAS](https://github.com/oras-project/oras/) tool and execute `oras attach`
|
||||
command.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
oras attach --artifact-type application/vnd.nfd.image-compatibility.v1alpha1 \
|
||||
<image-url> <path-to-spec>.yaml:application/vnd.nfd.image-compatibility.spec.v1alpha1+yaml
|
||||
```
|
||||
|
||||
**Note**: The attach command is planned to be integrated into the `nfd` client
|
||||
tool. This will streamline the process, allowing you to perform the operation
|
||||
directly within the tool rather than using a separate command.
|
||||
|
||||
### Validate the host against the image compatibility specification
|
||||
|
||||
1. Build `nfd` client: `make build`
|
||||
1. Run `./bin/nfd compat validate-node --image <image-url>`
|
||||
|
||||
For more information about the available commands and flags, refer to
|
||||
[the client documentation](../reference/node-feature-client-reference.md).
|
||||
|
||||
### Validate the k8s cluster node with the validate-image Job
|
||||
|
||||
**Note**: This does not require installation of NFD master and workers.
|
||||
Additionally, public registry certificates must be included in the job.
|
||||
In the example below, this is done using hostPath,
|
||||
but it can be done using any Kubernetes-supported method.
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: validate-image
|
||||
spec:
|
||||
backoffLimit: 1
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: image-compatibility
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
image: <image-with-nfd-client>
|
||||
command: ["nfd", "compat", "validate-node", "--image", "<image-to-be-validated>"]
|
||||
volumeMounts:
|
||||
- mountPath: /host-boot
|
||||
name: host-boot
|
||||
readOnly: true
|
||||
- mountPath: /host-etc/os-release
|
||||
name: host-os-release
|
||||
readOnly: true
|
||||
- mountPath: /host-sys
|
||||
name: host-sys
|
||||
readOnly: true
|
||||
- mountPath: /host-usr/lib
|
||||
name: host-usr-lib
|
||||
readOnly: true
|
||||
- mountPath: /host-lib
|
||||
name: host-lib
|
||||
readOnly: true
|
||||
- mountPath: /host-proc
|
||||
name: host-proc
|
||||
readOnly: true
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /boot
|
||||
type: ""
|
||||
name: host-boot
|
||||
- hostPath:
|
||||
path: /etc/os-release
|
||||
type: ""
|
||||
name: host-os-release
|
||||
- hostPath:
|
||||
path: /sys
|
||||
type: ""
|
||||
name: host-sys
|
||||
- hostPath:
|
||||
path: /usr/lib
|
||||
type: ""
|
||||
name: host-usr-lib
|
||||
- hostPath:
|
||||
path: /lib
|
||||
type: ""
|
||||
name: host-lib
|
||||
- hostPath:
|
||||
path: /proc
|
||||
type: ""
|
||||
name: host-proc
|
||||
- hostPath:
|
||||
path: "<path-to-registry-public-certs>"
|
||||
type: ""
|
||||
name: certs
|
||||
```
|
27
examples/image-compatibility.yaml
Normal file
27
examples/image-compatibility.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
version: v1alpha1
|
||||
compatibilities:
|
||||
- description: "my image requirements"
|
||||
rules:
|
||||
- name: "kernel and cpu"
|
||||
matchFeatures:
|
||||
- feature: kernel.loadedmodule
|
||||
matchExpressions:
|
||||
vfio-pci: {op: Exists}
|
||||
ip_tables: {op: Exists}
|
||||
- feature: cpu.model
|
||||
matchExpressions:
|
||||
vendor_id: {op: In, value: ["Intel", "AMD"]}
|
||||
- feature: cpu.cpuid
|
||||
matchName: {op: InRegexp, value: ["^AVX"]}
|
||||
- name: "one of available nics"
|
||||
matchAny:
|
||||
- matchFeatures:
|
||||
- feature: pci.device
|
||||
matchExpressions:
|
||||
vendor: {op: In, value: ["0eee"]}
|
||||
class: {op: In, value: ["0200"]}
|
||||
- matchFeatures:
|
||||
- feature: pci.device
|
||||
matchExpressions:
|
||||
vendor: {op: In, value: ["0fff"]}
|
||||
class: {op: In, value: ["0200"]}
|
152
go.mod
152
go.mod
|
@ -7,12 +7,14 @@ require (
|
|||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jaypipes/ghw v0.13.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1
|
||||
github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.1.2
|
||||
github.com/k8stopologyawareschedwg/podfingerprint v0.2.2
|
||||
github.com/klauspost/cpuid/v2 v2.2.9
|
||||
github.com/onsi/ginkgo/v2 v2.22.0
|
||||
github.com/onsi/gomega v1.36.1
|
||||
github.com/opencontainers/runc v1.2.2
|
||||
github.com/opencontainers/image-spec v1.1.0
|
||||
github.com/opencontainers/runc v1.2.3
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
|
@ -22,24 +24,27 @@ require (
|
|||
golang.org/x/net v0.32.0
|
||||
golang.org/x/time v0.8.0
|
||||
google.golang.org/grpc v1.69.0
|
||||
k8s.io/api v0.31.3
|
||||
k8s.io/apiextensions-apiserver v0.31.3
|
||||
k8s.io/apimachinery v0.31.3
|
||||
k8s.io/client-go v0.31.3
|
||||
k8s.io/code-generator v0.31.3
|
||||
k8s.io/component-base v0.31.3
|
||||
k8s.io/api v0.32.0
|
||||
k8s.io/apiextensions-apiserver v0.32.0
|
||||
k8s.io/apimachinery v0.32.0
|
||||
k8s.io/client-go v0.32.0
|
||||
k8s.io/code-generator v0.32.0
|
||||
k8s.io/component-base v0.32.0
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubectl v0.31.3
|
||||
k8s.io/kubelet v0.31.3
|
||||
k8s.io/kubernetes v1.31.3
|
||||
k8s.io/pod-security-admission v0.31.3
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
|
||||
k8s.io/kubectl v0.32.0
|
||||
k8s.io/kubelet v0.32.0
|
||||
k8s.io/kubernetes v1.32.0
|
||||
k8s.io/pod-security-admission v0.32.0
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
|
||||
oras.land/oras-go/v2 v2.5.0
|
||||
sigs.k8s.io/node-feature-discovery/api/nfd v0.0.0-00010101000000-000000000000
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
cel.dev/expr v0.18.0 // indirect
|
||||
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
|
@ -49,26 +54,33 @@ require (
|
|||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/containerd/api v1.7.19 // indirect
|
||||
github.com/containerd/errdefs v0.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/ttrpc v1.2.5 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/cel-go v0.20.1 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/cadvisor v0.51.0 // indirect
|
||||
github.com/google/cel-go v0.22.0 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
|
||||
|
@ -76,16 +88,18 @@ require (
|
|||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||
github.com/imdario/mergo v0.3.6 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jaypipes/pcidb v1.0.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/karrick/godirwalk v1.17.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/moby/spdystream v0.4.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
|
@ -93,20 +107,22 @@ require (
|
|||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||
github.com/opencontainers/selinux v1.11.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/smarty/assertions v1.15.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stoewer/go-strcase v1.2.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.16 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||
|
@ -117,7 +133,7 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
|
@ -133,55 +149,55 @@ require (
|
|||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
k8s.io/apiserver v0.31.3 // indirect
|
||||
k8s.io/cloud-provider v0.31.3 // indirect
|
||||
k8s.io/component-helpers v0.31.3 // indirect
|
||||
k8s.io/controller-manager v0.31.3 // indirect
|
||||
k8s.io/cri-api v0.31.3 // indirect
|
||||
k8s.io/apiserver v0.32.0 // indirect
|
||||
k8s.io/cloud-provider v0.32.0 // indirect
|
||||
k8s.io/component-helpers v0.32.0 // indirect
|
||||
k8s.io/controller-manager v0.32.0 // indirect
|
||||
k8s.io/cri-api v0.32.0 // indirect
|
||||
k8s.io/cri-client v0.0.0 // indirect
|
||||
k8s.io/csi-translation-lib v0.31.3 // indirect
|
||||
k8s.io/dynamic-resource-allocation v0.31.3 // indirect
|
||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
|
||||
k8s.io/kms v0.31.3 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||
k8s.io/mount-utils v0.31.3 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
k8s.io/csi-translation-lib v0.32.0 // indirect
|
||||
k8s.io/dynamic-resource-allocation v0.32.0 // indirect
|
||||
k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 // indirect
|
||||
k8s.io/kms v0.32.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
|
||||
k8s.io/kube-scheduler v0.0.0 // indirect
|
||||
k8s.io/mount-utils v0.32.0 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
|
||||
)
|
||||
|
||||
// The k8s "sub-"packages do not have 'semver' compatible versions. Thus, we
|
||||
// need to override with commits (corresponding their kubernetes-* tags)
|
||||
replace (
|
||||
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
|
||||
k8s.io/api => k8s.io/api v0.31.3
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.31.3
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.31.3
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.31.3
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.31.3
|
||||
k8s.io/client-go => k8s.io/client-go v0.31.3
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.31.3
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.31.3
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.31.3
|
||||
k8s.io/component-base => k8s.io/component-base v0.31.3
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.31.3
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.31.3
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.31.3
|
||||
k8s.io/cri-client => k8s.io/cri-client v0.31.3
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.31.3
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.31.3
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.31.3
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.31.3
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.31.3
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.31.3
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.31.3
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.31.3
|
||||
k8s.io/metrics => k8s.io/metrics v0.31.3
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.31.3
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.31.3
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.31.3
|
||||
k8s.io/api => k8s.io/api v0.32.0
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.0
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.32.0
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.32.0
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.0
|
||||
k8s.io/client-go => k8s.io/client-go v0.32.0
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.32.0
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.32.0
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.32.0
|
||||
k8s.io/component-base => k8s.io/component-base v0.32.0
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.32.0
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.32.0
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.32.0
|
||||
k8s.io/cri-client => k8s.io/cri-client v0.32.0
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.0
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.0
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.0
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.32.0
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.0
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.32.0
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.32.0
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.32.0
|
||||
k8s.io/metrics => k8s.io/metrics v0.32.0
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.32.0
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.0
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.0
|
||||
sigs.k8s.io/node-feature-discovery/api/nfd => ./api/nfd
|
||||
)
|
||||
|
|
255
go.sum
255
go.sum
|
@ -1,7 +1,9 @@
|
|||
cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
|
||||
cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
|
||||
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab h1:UKkYhof1njT1/xq4SEg5z+VpTgjmNeHwPGRQl7takDI=
|
||||
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
||||
|
@ -22,26 +24,34 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3
|
|||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA=
|
||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
|
||||
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
||||
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
|
||||
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
|
||||
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
|
||||
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
|
||||
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
|
||||
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
||||
github.com/cyphar/filepath-securejoin v0.3.5 h1:L81NHjquoQmcPgXcttUS9qTSR/+bXry6pbSINQGpjj4=
|
||||
github.com/cyphar/filepath-securejoin v0.3.5/go.mod h1:edhVd3c6OXKjUmSrVa/tGJRS9joFTxlslFCAyaxigkE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
|
||||
github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
|
@ -66,13 +76,14 @@ github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR
|
|||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
|
@ -82,16 +93,14 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/cadvisor v0.49.0 h1:1PYeiORXmcFYi609M4Qvq5IzcvcVaWgYxDt78uH8jYA=
|
||||
github.com/google/cadvisor v0.49.0/go.mod h1:s6Fqwb2KiWG6leCegVhw4KW40tf9f7m+SF1aXiE8Wsk=
|
||||
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
|
||||
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
||||
github.com/google/cadvisor v0.51.0 h1:BspqSPdZoLKrnvuZNOvM/KiJ/A+RdixwagN20n+2H8k=
|
||||
github.com/google/cadvisor v0.51.0/go.mod h1:czGE/c/P/i0QFpVNKTFrIEzord9Y10YfpwuaSWXELc0=
|
||||
github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g=
|
||||
github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
|
@ -116,17 +125,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4
|
|||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jaypipes/ghw v0.13.0 h1:log8MXuB8hzTNnSktqpXMHc0c/2k/WgjOMSUtnI1RV4=
|
||||
github.com/jaypipes/ghw v0.13.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8=
|
||||
github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic=
|
||||
github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
@ -152,16 +161,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
|
||||
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -169,8 +180,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q=
|
||||
github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
|
@ -181,12 +190,14 @@ github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
|
|||
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/runc v1.2.2 h1:jTg3Vw2A5f0N9PoxFTEwUhvpANGaNPT3689Yfd/zaX0=
|
||||
github.com/opencontainers/runc v1.2.2/go.mod h1:/PXzF0h531HTMsYQnmxXkBD7YaGShm/2zcRB79dksUc=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80=
|
||||
github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM=
|
||||
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
|
||||
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
|
@ -200,11 +211,11 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
|
|||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY=
|
||||
github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smarty/assertions v1.15.1 h1:812oFiXI+G55vxsFf+8bIZ1ux30qtkdqzKbEFwyX3Tk=
|
||||
|
@ -217,53 +228,46 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
|||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
|
||||
github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a h1:lUVfiMMY/te9icPKBqOKkBIMZNxSpM90dxokDeCcfBg=
|
||||
github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a/go.mod h1:KUxJS71XlMs+ztT+RzsLRoWUQRUpECo/+Rb0EBk8/Wc=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0=
|
||||
go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI=
|
||||
go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8=
|
||||
go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg=
|
||||
go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg=
|
||||
go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0=
|
||||
go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E=
|
||||
go.etcd.io/etcd/client/v2 v2.305.16 h1:kQrn9o5czVNaukf2A2At43cE9ZtWauOtf9vRZuiKXow=
|
||||
go.etcd.io/etcd/client/v2 v2.305.16/go.mod h1:h9YxWCzcdvZENbfzBTFCnoNumr2ax3F19sKMqHFmXHE=
|
||||
go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE=
|
||||
go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.16 h1:cnavs5WSPWeK4TYwPYfmcr3Joz9BH+TZ6qoUtz6/+mc=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.16/go.mod h1:+lutCZHG5MBBFI/U4eYT5yL7sJfnexsoM20Y0t2uNuY=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.16 h1:zBXA3ZUpYs1AwiLGPafYAKKl/CORn/uaxYDwlNwndAk=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.16/go.mod h1:P4UP14AxofMJ/54boWilabqqWoW9eLodl6I5GdGzazI=
|
||||
go.etcd.io/etcd/server/v3 v3.5.16 h1:d0/SAdJ3vVsZvF8IFVb1k8zqMZ+heGcNfft71ul9GWE=
|
||||
go.etcd.io/etcd/server/v3 v3.5.16/go.mod h1:ynhyZZpdDp1Gq49jkUg5mfkDWZwXnn3eIqCqtJnrD/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
|
@ -288,8 +292,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -318,7 +322,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
@ -360,70 +363,68 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
|||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
|
||||
k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
|
||||
k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE=
|
||||
k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4=
|
||||
k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
|
||||
k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/apiserver v0.31.3 h1:+1oHTtCB+OheqFEz375D0IlzHZ5VeQKX1KGXnx+TTuY=
|
||||
k8s.io/apiserver v0.31.3/go.mod h1:PrxVbebxrxQPFhJk4powDISIROkNMKHibTg9lTRQ0Qg=
|
||||
k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4=
|
||||
k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs=
|
||||
k8s.io/cloud-provider v0.31.3 h1:7C3CHQUUwnv/HWWVIaibZH06iPg663RYQ6C6Zy4FnO8=
|
||||
k8s.io/cloud-provider v0.31.3/go.mod h1:c7csKppoVb9Ej6upJ28AvHy4B3BtlRMzXfgezsDdPKw=
|
||||
k8s.io/code-generator v0.31.3 h1:Pj0fYOBms+ZrsulLi4DMsCEx1jG8fWKRLy44onHsLBI=
|
||||
k8s.io/code-generator v0.31.3/go.mod h1:/umCIlT84g1+Yu5ZXtP1KGSRTnGiIzzX5AzUAxsNlts=
|
||||
k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ=
|
||||
k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU=
|
||||
k8s.io/component-helpers v0.31.3 h1:0zGPD2PrekhFWgmz85XxlMEl7dfhlKC1tERZDe3onQc=
|
||||
k8s.io/component-helpers v0.31.3/go.mod h1:HZ1HZx2TKXM7xSUV2cR9L5yDoyZPhhHQNaE3BPBLPUQ=
|
||||
k8s.io/controller-manager v0.31.3 h1:TyUav69iNYwLGwA96JDhusoZoGRdh1sdrLjXmWTcPgs=
|
||||
k8s.io/controller-manager v0.31.3/go.mod h1:yuhec+dbXmBz+4c32kxJxmcauB+1pjO2ttfYODWuv18=
|
||||
k8s.io/cri-api v0.31.3 h1:dsZXzrGrCEwHjsTDlAV7rutEplpMLY8bfNRMIqrtXjo=
|
||||
k8s.io/cri-api v0.31.3/go.mod h1:Po3TMAYH/+KrZabi7QiwQI4a692oZcUOUThd/rqwxrI=
|
||||
k8s.io/cri-client v0.31.3 h1:9ZwddaNJomqkTBYQqSmB+Ccns3beY4HyYDwmRtWTCJM=
|
||||
k8s.io/cri-client v0.31.3/go.mod h1:klbWiYkOatOQOkXOYZMZMGSTM8q9eC/efsYGuXcgPes=
|
||||
k8s.io/csi-translation-lib v0.31.3 h1:hxcPRNdtEsk766jCXSKjgH1V8jUNx5tVqdooQ1Ars/M=
|
||||
k8s.io/csi-translation-lib v0.31.3/go.mod h1:0B1gQwd868XUIDwJYy5gB2jDXWEwlcWvSsfcQEgzbRk=
|
||||
k8s.io/dynamic-resource-allocation v0.31.3 h1:hiQMhyxrm7WA6tWJCLINE2P11Ii3rCVw+YzV3B6+eWo=
|
||||
k8s.io/dynamic-resource-allocation v0.31.3/go.mod h1:l7OvYDokvnXhFAOhInQUY/z0/HezzmRuLlspld4Xfg4=
|
||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
|
||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
|
||||
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
|
||||
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
|
||||
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
|
||||
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
|
||||
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
|
||||
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs=
|
||||
k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag=
|
||||
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
|
||||
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
|
||||
k8s.io/cloud-provider v0.32.0 h1:QXYJGmwME2q2rprymbmw2GroMChQYc/MWN6l/I4Kgp8=
|
||||
k8s.io/cloud-provider v0.32.0/go.mod h1:cz3gVodkhgwi2ugj/JUPglIruLSdDaThxawuDyCHfr8=
|
||||
k8s.io/code-generator v0.32.0 h1:s0lNN8VSWny8LBz5t5iy7MCdgwdOhdg7vAGVxvS+VWU=
|
||||
k8s.io/code-generator v0.32.0/go.mod h1:b7Q7KMZkvsYFy72A79QYjiv4aTz3GvW0f1T3UfhFq4s=
|
||||
k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
|
||||
k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
|
||||
k8s.io/component-helpers v0.32.0 h1:pQEEBmRt3pDJJX98cQvZshDgJFeKRM4YtYkMmfOlczw=
|
||||
k8s.io/component-helpers v0.32.0/go.mod h1:9RuClQatbClcokXOcDWSzFKQm1huIf0FzQlPRpizlMc=
|
||||
k8s.io/controller-manager v0.32.0 h1:tpQl1rvH4huFB6Avl1nhowZHtZoCNWqn6OYdZPl7Ybc=
|
||||
k8s.io/controller-manager v0.32.0/go.mod h1:JRuYnYCkKj3NgBTy+KNQKIUm/lJRoDAvGbfdEmk9LhY=
|
||||
k8s.io/cri-api v0.32.0 h1:pzXJfyG7Tm4acrEt5HPqAq3r4cN5guLeapAN/NM2b70=
|
||||
k8s.io/cri-api v0.32.0/go.mod h1:DCzMuTh2padoinefWME0G678Mc3QFbLMF2vEweGzBAI=
|
||||
k8s.io/cri-client v0.32.0 h1:K6aTYDyS2AS8O4h79eI5r26562xstdybprtaaszjn+E=
|
||||
k8s.io/cri-client v0.32.0/go.mod h1:FB8qZNj8KrwIFfVIR2zBGb+l6KUhrp+k8YFsVp3D+kw=
|
||||
k8s.io/csi-translation-lib v0.32.0 h1:RAn9RGgYXHJQtDSb6qQ7zvq6QObOejzmsXDARI+f4OQ=
|
||||
k8s.io/csi-translation-lib v0.32.0/go.mod h1:TjCJzkTNstdOESAXNnEImrYOMIEzP14aqM7H+vkehqw=
|
||||
k8s.io/dynamic-resource-allocation v0.32.0 h1:0ZLSCKzlLZLVwKHxg6vafpd2U8b7jPMO3k8bbMFodis=
|
||||
k8s.io/dynamic-resource-allocation v0.32.0/go.mod h1:MfoAUi0vCJtchNirAVk7c3IYfGGB3n+zbZ9GuyX4eeo=
|
||||
k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 h1:si3PfKm8dDYxgfbeA6orqrtLkvvIeH8UqffFJDl0bz4=
|
||||
k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kms v0.31.3 h1:XCFmiJn5CCKs8xoOLpCmu42Ubm/KW85wNHybGFcSAYc=
|
||||
k8s.io/kms v0.31.3/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/kube-scheduler v0.31.3 h1:indE2jtvbwyyEYDrQMjPR2EmnoM1pd4L6cK8r2/KY0I=
|
||||
k8s.io/kube-scheduler v0.31.3/go.mod h1:vhDtABcWycLi8139K5ScOg54WKlbEZJRgtQmLhW0Wjo=
|
||||
k8s.io/kubectl v0.31.3 h1:3r111pCjPsvnR98oLLxDMwAeM6OPGmPty6gSKaLTQes=
|
||||
k8s.io/kubectl v0.31.3/go.mod h1:lhMECDCbJN8He12qcKqs2QfmVo9Pue30geovBVpH5fs=
|
||||
k8s.io/kubelet v0.31.3 h1:DIXRAmvVGp42mV2vpA1GCLU6oO8who0/vp3Oq6kSpbI=
|
||||
k8s.io/kubelet v0.31.3/go.mod h1:KSdbEfNy5VzqUlAHlytA/fH12s+sE1u8fb/8JY9sL/8=
|
||||
k8s.io/kubernetes v1.31.3 h1:oqb7HdfnTelrGlZ6ziNugvQ/L/aJWR704114EAhUn9Q=
|
||||
k8s.io/kubernetes v1.31.3/go.mod h1:9xmT2buyTYj8TRKwRae7FcuY8k5+xlxv7VivvO0KKfs=
|
||||
k8s.io/mount-utils v0.31.3 h1:CANy3prUYvvDCc2X7ZKgpjpDhAidx4gjGh/WwDrCPq8=
|
||||
k8s.io/mount-utils v0.31.3/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU=
|
||||
k8s.io/pod-security-admission v0.31.3 h1:8NzEV0HtdStX367AuSKfRMIZHn0hT4xuz8xNEf7/zO8=
|
||||
k8s.io/pod-security-admission v0.31.3/go.mod h1:YMIcTe/7f9R9d+3ErCMMM3Wtbj9ejKo7Z9S0OxZQrRg=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
k8s.io/kms v0.32.0 h1:jwOfunHIrcdYl5FRcA+uUKKtg6qiqoPCwmS2T3XTYL4=
|
||||
k8s.io/kms v0.32.0/go.mod h1:Bk2evz/Yvk0oVrvm4MvZbgq8BD34Ksxs2SRHn4/UiOM=
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
|
||||
k8s.io/kube-scheduler v0.32.0 h1:FCsF/3TPvR51ptx/gLUrqcoKqAMhQKrydYCJzPz9VGM=
|
||||
k8s.io/kube-scheduler v0.32.0/go.mod h1:yof3vmyx70TWoQ6XZruYEGIUT/r0H/ELGdnWiqPF5EE=
|
||||
k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw=
|
||||
k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE=
|
||||
k8s.io/kubelet v0.32.0 h1:uLyiKlz195Wo4an/K2tyge8o3QHx0ZkhVN3pevvp59A=
|
||||
k8s.io/kubelet v0.32.0/go.mod h1:lAwuVZT/Hm7EdLn0jW2D+WdrJoorjJL2rVSdhOFnegw=
|
||||
k8s.io/kubernetes v1.32.0 h1:4BDBWSolqPrv8GC3YfZw0CJvh5kA1TPnoX0FxDVd+qc=
|
||||
k8s.io/kubernetes v1.32.0/go.mod h1:tiIKO63GcdPRBHW2WiUFm3C0eoLczl3f7qi56Dm1W8I=
|
||||
k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4=
|
||||
k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0=
|
||||
k8s.io/pod-security-admission v0.32.0 h1:I+Og0uZIiMpIgTgPrTbW4jlwRI5RWazi8y+jrx1v10w=
|
||||
k8s.io/pod-security-admission v0.32.0/go.mod h1:RvrcY0+5UAoCIJ7BscgDF3nbmXprgfnjTW+byCyXDvA=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
|
||||
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
|
@ -116,7 +116,7 @@ bar: { op: Exists }
|
|||
t.Fatal("failed to parse data of test case")
|
||||
}
|
||||
|
||||
res, out, err := api.MatchGetKeys(mes, tc.input)
|
||||
res, out, _, err := api.MatchGetKeys(mes, tc.input)
|
||||
tc.result(t, res)
|
||||
assert.Equal(t, tc.output, out)
|
||||
tc.err(t, err)
|
||||
|
@ -183,12 +183,12 @@ baz: { op: Gt, value: ["10"] }
|
|||
t.Fatal("failed to parse data of test case")
|
||||
}
|
||||
|
||||
res, out, err := api.MatchGetValues(mes, tc.input)
|
||||
res, out, _, err := api.MatchGetValues(mes, tc.input, true)
|
||||
tc.result(t, res)
|
||||
assert.Equal(t, tc.output, out)
|
||||
tc.err(t, err)
|
||||
|
||||
res, err = api.MatchValues(mes, tc.input)
|
||||
res, _, err = api.MatchValues(mes, tc.input, true)
|
||||
tc.result(t, res)
|
||||
tc.err(t, err)
|
||||
})
|
||||
|
@ -248,12 +248,12 @@ bar: { op: Lt, value: ["10"] }
|
|||
t.Fatal("failed to parse data of test case")
|
||||
}
|
||||
|
||||
res, out, err := api.MatchGetInstances(mes, tc.input)
|
||||
res, out, _, err := api.MatchGetInstances(mes, tc.input, true)
|
||||
assert.Equal(t, tc.output, out)
|
||||
tc.result(t, res)
|
||||
tc.err(t, err)
|
||||
|
||||
res, err = api.MatchInstances(mes, tc.input)
|
||||
res, err = api.MatchInstances(mes, tc.input, true)
|
||||
tc.result(t, res)
|
||||
tc.err(t, err)
|
||||
})
|
||||
|
@ -745,7 +745,7 @@ func TestMatchMulti(t *testing.T) {
|
|||
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, out, err := api.MatchMulti(tc.mes, tc.inputKeys, tc.inputValues, tc.inputInstances)
|
||||
res, out, _, err := api.MatchMulti(tc.mes, tc.inputKeys, tc.inputValues, tc.inputInstances, true)
|
||||
if tc.expectErr {
|
||||
assert.NotNil(t, err)
|
||||
} else {
|
||||
|
|
|
@ -29,6 +29,13 @@ import (
|
|||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
// MatchedKeyName is the name of the matched flag/attribute element.
|
||||
MatchedKeyName = "Name"
|
||||
// MatchedKeyValue is the value of the matched attribute element.
|
||||
MatchedKeyValue = "Value"
|
||||
)
|
||||
|
||||
var matchOps = map[nfdv1alpha1.MatchOp]struct{}{
|
||||
nfdv1alpha1.MatchAny: {},
|
||||
nfdv1alpha1.MatchIn: {},
|
||||
|
@ -202,16 +209,16 @@ func MatchKeyNames(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1.N
|
|||
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||
return false, nil, err
|
||||
} else if match {
|
||||
ret = append(ret, MatchedElement{"Name": k})
|
||||
ret = append(ret, MatchedElement{MatchedKeyName: k})
|
||||
}
|
||||
}
|
||||
// Sort for reproducible output
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i][MatchedKeyName] < ret[j][MatchedKeyName] })
|
||||
|
||||
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||
mk := make([]string, len(ret))
|
||||
for i, v := range ret {
|
||||
mk[i] = v["Name"]
|
||||
mk[i] = v[MatchedKeyName]
|
||||
}
|
||||
mkMsg := strings.Join(mk, ", ")
|
||||
|
||||
|
@ -238,16 +245,16 @@ func MatchValueNames(m *nfdv1alpha1.MatchExpression, values map[string]string) (
|
|||
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||
return false, nil, err
|
||||
} else if match {
|
||||
ret = append(ret, MatchedElement{"Name": k, "Value": v})
|
||||
ret = append(ret, MatchedElement{MatchedKeyName: k, MatchedKeyValue: v})
|
||||
}
|
||||
}
|
||||
// Sort for reproducible output
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i][MatchedKeyName] < ret[j][MatchedKeyName] })
|
||||
|
||||
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||
mk := make([]string, len(ret))
|
||||
for i, v := range ret {
|
||||
mk[i] = v["Name"]
|
||||
mk[i] = v[MatchedKeyName]
|
||||
}
|
||||
mkMsg := strings.Join(mk, ", ")
|
||||
|
||||
|
@ -278,7 +285,7 @@ func MatchInstanceAttributeNames(m *nfdv1alpha1.MatchExpression, instances []nfd
|
|||
|
||||
// MatchKeys evaluates the MatchExpressionSet against a set of keys.
|
||||
func MatchKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, error) {
|
||||
matched, _, err := MatchGetKeys(m, keys)
|
||||
matched, _, _, err := MatchGetKeys(m, keys)
|
||||
return matched, err
|
||||
}
|
||||
|
||||
|
@ -288,56 +295,65 @@ type MatchedElement map[string]string
|
|||
// MatchGetKeys evaluates the MatchExpressionSet against a set of keys and
|
||||
// returns all matched keys or nil if no match was found. Note that an empty
|
||||
// MatchExpressionSet returns a match with an empty slice of matched features.
|
||||
func MatchGetKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, []MatchedElement, error) {
|
||||
ret := make([]MatchedElement, 0, len(*m))
|
||||
func MatchGetKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||
matchedElements := make([]MatchedElement, 0, len(*m))
|
||||
matchedExpressions := make(nfdv1alpha1.MatchExpressionSet)
|
||||
|
||||
for n, e := range *m {
|
||||
match, err := evaluateMatchExpressionKeys(e, n, keys)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return false, nil, nil, err
|
||||
}
|
||||
if !match {
|
||||
return false, nil, nil
|
||||
return false, nil, nil, nil
|
||||
}
|
||||
ret = append(ret, MatchedElement{"Name": n})
|
||||
matchedElements = append(matchedElements, MatchedElement{MatchedKeyName: n})
|
||||
matchedExpressions[n] = e
|
||||
}
|
||||
// Sort for reproducible output
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
||||
return true, ret, nil
|
||||
sort.Slice(matchedElements, func(i, j int) bool { return matchedElements[i][MatchedKeyName] < matchedElements[j][MatchedKeyName] })
|
||||
return true, matchedElements, &matchedExpressions, nil
|
||||
}
|
||||
|
||||
// MatchValues evaluates the MatchExpressionSet against a set of key-value pairs.
|
||||
func MatchValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string) (bool, error) {
|
||||
matched, _, err := MatchGetValues(m, values)
|
||||
return matched, err
|
||||
func MatchValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string, failFast bool) (bool, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||
matched, _, matchedExpressions, err := MatchGetValues(m, values, failFast)
|
||||
return matched, matchedExpressions, err
|
||||
}
|
||||
|
||||
// MatchGetValues evaluates the MatchExpressionSet against a set of key-value
|
||||
// pairs and returns all matched key-value pairs. Note that an empty
|
||||
// MatchExpressionSet returns a match with an empty slice of matched features.
|
||||
func MatchGetValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string) (bool, []MatchedElement, error) {
|
||||
ret := make([]MatchedElement, 0, len(*m))
|
||||
func MatchGetValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string, failFast bool) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||
matchedElements := make([]MatchedElement, 0, len(*m))
|
||||
matchedExpressions := make(nfdv1alpha1.MatchExpressionSet)
|
||||
isMatch := true
|
||||
|
||||
for n, e := range *m {
|
||||
match, err := evaluateMatchExpressionValues(e, n, values)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return false, nil, nil, err
|
||||
}
|
||||
if !match {
|
||||
return false, nil, nil
|
||||
if match {
|
||||
matchedElements = append(matchedElements, MatchedElement{MatchedKeyName: n, MatchedKeyValue: values[n]})
|
||||
matchedExpressions[n] = e
|
||||
} else {
|
||||
if failFast {
|
||||
return false, nil, nil, nil
|
||||
}
|
||||
isMatch = false
|
||||
}
|
||||
ret = append(ret, MatchedElement{"Name": n, "Value": values[n]})
|
||||
}
|
||||
// Sort for reproducible output
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
||||
return true, ret, nil
|
||||
sort.Slice(matchedElements, func(i, j int) bool { return matchedElements[i][MatchedKeyName] < matchedElements[j][MatchedKeyName] })
|
||||
return isMatch, matchedElements, &matchedExpressions, nil
|
||||
}
|
||||
|
||||
// MatchInstances evaluates the MatchExpressionSet against a set of instance
|
||||
// features, each of which is an individual set of key-value pairs
|
||||
// (attributes).
|
||||
func MatchInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature) (bool, error) {
|
||||
isMatch, _, err := MatchGetInstances(m, instances)
|
||||
func MatchInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature, failFast bool) (bool, error) {
|
||||
isMatch, _, _, err := MatchGetInstances(m, instances, failFast)
|
||||
return isMatch, err
|
||||
}
|
||||
|
||||
|
@ -346,17 +362,28 @@ func MatchInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.I
|
|||
// (attributes). Returns a boolean that reports whether the expression matched.
|
||||
// Also, returns a slice containing all matching instances. An empty (non-nil)
|
||||
// slice is returned if no matching instances were found.
|
||||
func MatchGetInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature) (bool, []MatchedElement, error) {
|
||||
ret := []MatchedElement{}
|
||||
func MatchGetInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature, failFast bool) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||
var (
|
||||
match bool
|
||||
err error
|
||||
expressionSet *nfdv1alpha1.MatchExpressionSet
|
||||
)
|
||||
matchedElements := []MatchedElement{}
|
||||
matchedExpressions := &nfdv1alpha1.MatchExpressionSet{}
|
||||
|
||||
for _, i := range instances {
|
||||
if match, err := MatchValues(m, i.Attributes); err != nil {
|
||||
return false, nil, err
|
||||
if match, expressionSet, err = MatchValues(m, i.Attributes, failFast); err != nil {
|
||||
return false, nil, nil, err
|
||||
} else if match {
|
||||
ret = append(ret, i.Attributes)
|
||||
matchedElements = append(matchedElements, i.Attributes)
|
||||
}
|
||||
if expressionSet != nil {
|
||||
for name, exp := range *expressionSet {
|
||||
(*matchedExpressions)[name] = exp
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(ret) > 0, ret, nil
|
||||
return len(matchedElements) > 0, matchedElements, matchedExpressions, nil
|
||||
}
|
||||
|
||||
// MatchMulti evaluates a MatchExpressionSet against key, value and instance
|
||||
|
@ -365,8 +392,9 @@ func MatchGetInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha
|
|||
// handled separately as the way of evaluating match expressions is different.
|
||||
// This function is written to handle "multi-type" features where one feature
|
||||
// (say "cpu.cpuid") contains multiple types (flag, attribute and/or instance).
|
||||
func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil, values map[string]string, instances []nfdv1alpha1.InstanceFeature) (bool, []MatchedElement, error) {
|
||||
func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil, values map[string]string, instances []nfdv1alpha1.InstanceFeature, failFast bool) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||
matchedElems := []MatchedElement{}
|
||||
matchedExpressions := nfdv1alpha1.MatchExpressionSet{}
|
||||
isMatch := false
|
||||
|
||||
// Keys and values are handled as a union, it is enough to find a match in
|
||||
|
@ -384,14 +412,19 @@ func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.N
|
|||
if keys != nil {
|
||||
matchK, err = evaluateMatchExpressionKeys(e, n, keys)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return false, nil, nil, err
|
||||
}
|
||||
if matchK {
|
||||
matchedElems = append(matchedElems, MatchedElement{"Name": n})
|
||||
matchedElems = append(matchedElems, MatchedElement{MatchedKeyName: n})
|
||||
matchedExpressions[n] = e
|
||||
} else if e.Op == nfdv1alpha1.MatchDoesNotExist {
|
||||
// DoesNotExist is special in that both "keys" and "values" should match (i.e. the name is not found in either of them).
|
||||
isMatch = false
|
||||
if !failFast {
|
||||
continue
|
||||
}
|
||||
matchedElems = []MatchedElement{}
|
||||
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -399,39 +432,53 @@ func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.N
|
|||
if values != nil {
|
||||
matchV, err = evaluateMatchExpressionValues(e, n, values)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return false, nil, nil, err
|
||||
}
|
||||
if matchV {
|
||||
matchedElems = append(matchedElems, MatchedElement{"Name": n, "Value": values[n]})
|
||||
matchedElems = append(matchedElems, MatchedElement{MatchedKeyName: n, MatchedKeyValue: values[n]})
|
||||
matchedExpressions[n] = e
|
||||
} else if e.Op == nfdv1alpha1.MatchDoesNotExist {
|
||||
// DoesNotExist is special in that both "keys" and "values" should match (i.e. the name is not found in either of them).
|
||||
isMatch = false
|
||||
if !failFast {
|
||||
continue
|
||||
}
|
||||
matchedElems = []MatchedElement{}
|
||||
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !matchK && !matchV {
|
||||
isMatch = false
|
||||
if !failFast {
|
||||
continue
|
||||
}
|
||||
matchedElems = []MatchedElement{}
|
||||
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||
break
|
||||
}
|
||||
}
|
||||
// Sort for reproducible output
|
||||
sort.Slice(matchedElems, func(i, j int) bool { return matchedElems[i]["Name"] < matchedElems[j]["Name"] })
|
||||
sort.Slice(matchedElems, func(i, j int) bool { return matchedElems[i][MatchedKeyName] < matchedElems[j][MatchedKeyName] })
|
||||
|
||||
// Instances are handled separately as the logic is fundamentally different
|
||||
// from keys and values and cannot be combined with them. We want to find
|
||||
// instance(s) that match all match expressions. I.e. the set of all match
|
||||
// expressions are evaluated against every instance separately.
|
||||
ma, me, err := MatchGetInstances(m, instances)
|
||||
ma, melems, mexps, err := MatchGetInstances(m, instances, failFast)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return false, nil, nil, err
|
||||
}
|
||||
isMatch = isMatch || ma
|
||||
matchedElems = append(matchedElems, me...)
|
||||
matchedElems = append(matchedElems, melems...)
|
||||
if mexps != nil {
|
||||
for k, v := range *mexps {
|
||||
matchedExpressions[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return isMatch, matchedElems, nil
|
||||
return isMatch, matchedElems, &matchedExpressions, nil
|
||||
}
|
||||
|
||||
// MatchNamesMulti evaluates the MatchExpression against the names of key,
|
||||
|
@ -440,12 +487,11 @@ func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.N
|
|||
// types (flag, attribute and/or instance).
|
||||
func MatchNamesMulti(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1.Nil, values map[string]string, instances []nfdv1alpha1.InstanceFeature) (bool, []MatchedElement, error) {
|
||||
ret := []MatchedElement{}
|
||||
|
||||
for k := range keys {
|
||||
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||
return false, nil, err
|
||||
} else if match {
|
||||
ret = append(ret, MatchedElement{"Name": k})
|
||||
ret = append(ret, MatchedElement{MatchedKeyName: k})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,12 +499,12 @@ func MatchNamesMulti(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1
|
|||
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||
return false, nil, err
|
||||
} else if match {
|
||||
ret = append(ret, MatchedElement{"Name": k, "Value": v})
|
||||
ret = append(ret, MatchedElement{MatchedKeyName: k, MatchedKeyValue: v})
|
||||
}
|
||||
}
|
||||
|
||||
// Sort for reproducible output
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
||||
sort.Slice(ret, func(i, j int) bool { return ret[i][MatchedKeyName] < ret[j][MatchedKeyName] })
|
||||
|
||||
_, me, err := MatchInstanceAttributeNames(m, instances)
|
||||
if err != nil {
|
||||
|
@ -469,7 +515,7 @@ func MatchNamesMulti(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1
|
|||
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||
mk := make([]string, len(ret))
|
||||
for i, v := range ret {
|
||||
mk[i] = v["Name"]
|
||||
mk[i] = v[MatchedKeyName]
|
||||
}
|
||||
mkMsg := strings.Join(mk, ", ")
|
||||
|
||||
|
|
|
@ -31,6 +31,31 @@ import (
|
|||
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||
)
|
||||
|
||||
// MatchStatus represents the status of a processed rule.
|
||||
// It includes information about successful expressions and their results, which are the matched host features.
|
||||
// For example, for the expression: cpu.cpuid: {op: "InRegexp", value: ["^AVX"]},
|
||||
// the result could include matched host features such as AVX, AVX2, AVX512 etc.
|
||||
// +k8s:deepcopy-gen=false
|
||||
type MatchStatus struct {
|
||||
*MatchFeatureStatus
|
||||
|
||||
// IsMatch informes whether a rule succeeded or failed.
|
||||
IsMatch bool
|
||||
// MatchAny represents an array of logical OR conditions between MatchFeatureStatus entries.
|
||||
MatchAny []*MatchFeatureStatus
|
||||
}
|
||||
|
||||
// MatchFeatureStatus represents a matched expression
|
||||
// with its result, which is matched host features.
|
||||
// +k8s:deepcopy-gen=false
|
||||
type MatchFeatureStatus struct {
|
||||
// MatchedFeatures represents the features matched on the host,
|
||||
// which is a result of the FeatureMatcher.
|
||||
MatchedFeatures matchedFeatures
|
||||
// MatchedFeaturesTerms represents the expressions that successfully matched on the host.
|
||||
MatchedFeaturesTerms nfdv1alpha1.FeatureMatcher
|
||||
}
|
||||
|
||||
// RuleOutput contains the output out rule execution.
|
||||
// +k8s:deepcopy-gen=false
|
||||
type RuleOutput struct {
|
||||
|
@ -39,56 +64,69 @@ type RuleOutput struct {
|
|||
Annotations map[string]string
|
||||
Vars map[string]string
|
||||
Taints []corev1.Taint
|
||||
MatchStatus *MatchStatus
|
||||
}
|
||||
|
||||
// Execute the rule against a set of input features.
|
||||
func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, error) {
|
||||
func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features, failFast bool) (RuleOutput, error) {
|
||||
var (
|
||||
matchStatus MatchStatus
|
||||
isMatch bool
|
||||
err error
|
||||
)
|
||||
labels := make(map[string]string)
|
||||
vars := make(map[string]string)
|
||||
|
||||
if len(r.MatchAny) > 0 {
|
||||
if n := len(r.MatchAny); n > 0 {
|
||||
matchStatus.MatchAny = make([]*MatchFeatureStatus, 0, n)
|
||||
// Logical OR over the matchAny matchers
|
||||
matched := false
|
||||
var (
|
||||
featureStatus *MatchFeatureStatus
|
||||
matched bool
|
||||
)
|
||||
for _, matcher := range r.MatchAny {
|
||||
if isMatch, matches, err := evaluateMatchAnyElem(&matcher, features); err != nil {
|
||||
if matched, featureStatus, err = evaluateMatchAnyElem(&matcher, features, failFast); err != nil {
|
||||
return RuleOutput{}, err
|
||||
} else if isMatch {
|
||||
matched = true
|
||||
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches))
|
||||
} else if matched {
|
||||
isMatch = true
|
||||
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(featureStatus.MatchedFeatures))
|
||||
|
||||
if r.LabelsTemplate == "" && r.VarsTemplate == "" {
|
||||
if r.LabelsTemplate == "" && r.VarsTemplate == "" && failFast {
|
||||
// there's no need to evaluate other matchers in MatchAny
|
||||
// if there are no templates to be executed on them - so
|
||||
// short-circuit and stop on first match here
|
||||
break
|
||||
}
|
||||
|
||||
if err := executeLabelsTemplate(r, matches, labels); err != nil {
|
||||
if err := executeLabelsTemplate(r, featureStatus.MatchedFeatures, labels); err != nil {
|
||||
return RuleOutput{}, err
|
||||
}
|
||||
if err := executeVarsTemplate(r, matches, vars); err != nil {
|
||||
if err := executeVarsTemplate(r, featureStatus.MatchedFeatures, vars); err != nil {
|
||||
return RuleOutput{}, err
|
||||
}
|
||||
}
|
||||
|
||||
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
|
||||
}
|
||||
if !matched {
|
||||
|
||||
if !isMatch {
|
||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
||||
return RuleOutput{}, nil
|
||||
return RuleOutput{MatchStatus: &matchStatus}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.MatchFeatures) > 0 {
|
||||
if isMatch, matches, err := evaluateFeatureMatcher(&r.MatchFeatures, features); err != nil {
|
||||
if isMatch, matchStatus.MatchFeatureStatus, err = evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
|
||||
return RuleOutput{}, err
|
||||
} else if !isMatch {
|
||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
||||
return RuleOutput{}, nil
|
||||
return RuleOutput{MatchStatus: &matchStatus}, nil
|
||||
} else {
|
||||
klog.V(4).InfoS("matchFeatures matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches))
|
||||
if err := executeLabelsTemplate(r, matches, labels); err != nil {
|
||||
klog.V(4).InfoS("matchFeatures matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matchStatus.MatchedFeatures))
|
||||
if err := executeLabelsTemplate(r, matchStatus.MatchedFeatures, labels); err != nil {
|
||||
return RuleOutput{}, err
|
||||
}
|
||||
if err := executeVarsTemplate(r, matches, vars); err != nil {
|
||||
if err := executeVarsTemplate(r, matchStatus.MatchedFeatures, vars); err != nil {
|
||||
return RuleOutput{}, err
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +134,7 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, e
|
|||
|
||||
maps.Copy(labels, r.Labels)
|
||||
maps.Copy(vars, r.Vars)
|
||||
matchStatus.IsMatch = true
|
||||
|
||||
ret := RuleOutput{
|
||||
Labels: labels,
|
||||
|
@ -103,6 +142,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),
|
||||
MatchStatus: &matchStatus,
|
||||
}
|
||||
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
|
||||
return ret, nil
|
||||
|
@ -110,12 +150,12 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, e
|
|||
|
||||
// ExecuteGroupRule executes the GroupRule against a set of input features, and return true if the
|
||||
// rule matches.
|
||||
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features) (bool, error) {
|
||||
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features, failFast bool) (bool, error) {
|
||||
matched := false
|
||||
if len(r.MatchAny) > 0 {
|
||||
// Logical OR over the matchAny matchers
|
||||
for _, matcher := range r.MatchAny {
|
||||
if isMatch, matches, err := evaluateMatchAnyElem(&matcher, features); err != nil {
|
||||
if isMatch, matches, err := evaluateMatchAnyElem(&matcher, features, failFast); err != nil {
|
||||
return false, err
|
||||
} else if isMatch {
|
||||
matched = true
|
||||
|
@ -131,7 +171,7 @@ func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features)
|
|||
}
|
||||
|
||||
if len(r.MatchFeatures) > 0 {
|
||||
if isMatch, _, err := evaluateFeatureMatcher(&r.MatchFeatures, features); err != nil {
|
||||
if isMatch, _, err := evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
|
||||
return false, err
|
||||
} else if !isMatch {
|
||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
||||
|
@ -187,12 +227,18 @@ type matchedFeatures map[string]domainMatchedFeatures
|
|||
|
||||
type domainMatchedFeatures map[string][]MatchedElement
|
||||
|
||||
func evaluateMatchAnyElem(e *nfdv1alpha1.MatchAnyElem, features *nfdv1alpha1.Features) (bool, matchedFeatures, error) {
|
||||
return evaluateFeatureMatcher(&e.MatchFeatures, features)
|
||||
func evaluateMatchAnyElem(e *nfdv1alpha1.MatchAnyElem, features *nfdv1alpha1.Features, failFast bool) (bool, *MatchFeatureStatus, error) {
|
||||
return evaluateFeatureMatcher(&e.MatchFeatures, features, failFast)
|
||||
}
|
||||
|
||||
func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1.Features) (bool, matchedFeatures, error) {
|
||||
matches := make(matchedFeatures, len(*m))
|
||||
func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1.Features, failFast bool) (bool, *MatchFeatureStatus, error) {
|
||||
var (
|
||||
isMatch = true
|
||||
isTermMatch = true
|
||||
)
|
||||
status := &MatchFeatureStatus{
|
||||
MatchedFeatures: make(matchedFeatures, len(*m)),
|
||||
}
|
||||
|
||||
// Logical AND over the terms
|
||||
for _, term := range *m {
|
||||
|
@ -207,14 +253,17 @@ func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1
|
|||
|
||||
dom := nameSplit[0]
|
||||
nam := nameSplit[1]
|
||||
if _, ok := matches[dom]; !ok {
|
||||
matches[dom] = make(domainMatchedFeatures)
|
||||
if _, ok := status.MatchedFeatures[dom]; !ok {
|
||||
status.MatchedFeatures[dom] = make(domainMatchedFeatures)
|
||||
}
|
||||
|
||||
var isMatch = true
|
||||
var matchedElems []MatchedElement
|
||||
var matchedExpressions *nfdv1alpha1.MatchExpressionSet
|
||||
var err error
|
||||
|
||||
matchedFeatureTerm := nfdv1alpha1.FeatureMatcherTerm{
|
||||
Feature: featureName,
|
||||
}
|
||||
fF, okF := features.Flags[featureName]
|
||||
fA, okA := features.Attributes[featureName]
|
||||
fI, okI := features.Instances[featureName]
|
||||
|
@ -224,24 +273,37 @@ func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1
|
|||
}
|
||||
|
||||
if term.MatchExpressions != nil {
|
||||
isMatch, matchedElems, err = MatchMulti(term.MatchExpressions, fF.Elements, fA.Elements, fI.Elements)
|
||||
isTermMatch, matchedElems, matchedExpressions, err = MatchMulti(term.MatchExpressions, fF.Elements, fA.Elements, fI.Elements, failFast)
|
||||
matchedFeatureTerm.MatchExpressions = matchedExpressions
|
||||
}
|
||||
|
||||
if err == nil && isMatch && term.MatchName != nil {
|
||||
if err == nil && isTermMatch && term.MatchName != nil {
|
||||
var meTmp []MatchedElement
|
||||
isMatch, meTmp, err = MatchNamesMulti(term.MatchName, fF.Elements, fA.Elements, fI.Elements)
|
||||
isTermMatch, meTmp, err = MatchNamesMulti(term.MatchName, fF.Elements, fA.Elements, fI.Elements)
|
||||
matchedElems = append(matchedElems, meTmp...)
|
||||
// MatchName has only one expression, in this case it's enough to check the isTermMatch flag
|
||||
// to judge if the expression succeeded on the host.
|
||||
if isTermMatch {
|
||||
matchedFeatureTerm.MatchName = term.MatchName
|
||||
}
|
||||
}
|
||||
|
||||
matches[dom][nam] = append(matches[dom][nam], matchedElems...)
|
||||
status.MatchedFeatures[dom][nam] = append(status.MatchedFeatures[dom][nam], matchedElems...)
|
||||
if matchedFeatureTerm.MatchName != nil || (matchedFeatureTerm.MatchExpressions != nil && len(*matchedFeatureTerm.MatchExpressions) > 0) {
|
||||
status.MatchedFeaturesTerms = append(status.MatchedFeaturesTerms, matchedFeatureTerm)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
} else if !isMatch {
|
||||
return false, nil, nil
|
||||
} else if !isTermMatch {
|
||||
if !failFast {
|
||||
isMatch = false
|
||||
} else {
|
||||
return false, status, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, matches, nil
|
||||
return isMatch, status, nil
|
||||
}
|
||||
|
||||
type templateHelper struct {
|
||||
|
|
|
@ -49,11 +49,11 @@ func TestRule(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test totally empty features
|
||||
m, err := Execute(r1, f)
|
||||
m, err := Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
||||
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.NoError(t, err, "matching against a missing feature should not have returned an error")
|
||||
assert.Empty(t, m.Labels)
|
||||
assert.Empty(t, m.Vars)
|
||||
|
@ -61,12 +61,12 @@ func TestRule(t *testing.T) {
|
|||
// Test properly initialized empty features
|
||||
f = nfdv1alpha1.NewFeatures()
|
||||
|
||||
m, err = Execute(r1, f)
|
||||
m, err = Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
||||
assert.Empty(t, r1.Vars, "vars should be empty")
|
||||
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.NoError(t, err, "matching against a missing feature should not have returned an error")
|
||||
assert.Empty(t, m.Labels)
|
||||
assert.Empty(t, m.Vars)
|
||||
|
@ -76,11 +76,11 @@ func TestRule(t *testing.T) {
|
|||
f.Attributes["domain-1.vf-1"] = nfdv1alpha1.NewAttributeFeatures(nil)
|
||||
f.Instances["domain-1.if-1"] = nfdv1alpha1.NewInstanceFeatures()
|
||||
|
||||
m, err = Execute(r1, f)
|
||||
m, err = Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
||||
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "unexpected match")
|
||||
|
||||
|
@ -89,7 +89,7 @@ func TestRule(t *testing.T) {
|
|||
f.Attributes["domain-1.vf-1"].Elements["key-1"] = "val-x"
|
||||
f.Instances["domain-1.if-1"] = nfdv1alpha1.NewInstanceFeatures(*nfdv1alpha1.NewInstanceFeature(map[string]string{"attr-1": "val-x"}))
|
||||
|
||||
m, err = Execute(r1, f)
|
||||
m, err = Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
||||
|
||||
|
@ -100,17 +100,17 @@ func TestRule(t *testing.T) {
|
|||
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r1, f)
|
||||
m, err = Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r1.Labels, m.Labels, "empty match expression set mathces anything")
|
||||
|
||||
// Match "key" features
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "keys should not have matched")
|
||||
|
||||
f.Flags["domain-1.kf-1"].Elements["key-1"] = nfdv1alpha1.Nil{}
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r2.Labels, m.Labels, "keys should have matched")
|
||||
assert.Equal(t, r2.Vars, m.Vars, "vars should be present")
|
||||
|
@ -127,12 +127,12 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "values should not have matched")
|
||||
|
||||
f.Attributes["domain-1.vf-1"].Elements["key-1"] = "val-1"
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "values should have matched")
|
||||
|
||||
|
@ -148,12 +148,12 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
||||
|
||||
f.Instances["domain-1.if-1"].Elements[0].Attributes["attr-1"] = "val-1"
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
||||
|
||||
|
@ -177,7 +177,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f2)
|
||||
m, err = Execute(r3, f2, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "key in multi-type feature should have matched")
|
||||
|
||||
|
@ -189,7 +189,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f2)
|
||||
m, err = Execute(r3, f2, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "attribute in multi-type feature should have matched")
|
||||
|
||||
|
@ -201,7 +201,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f2)
|
||||
m, err = Execute(r3, f2, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "attribute in multi-type feature should have matched")
|
||||
|
||||
|
@ -214,7 +214,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f2)
|
||||
m, err = Execute(r3, f2, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "features in multi-type feature should have matched flags and attributes")
|
||||
|
||||
|
@ -226,7 +226,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f2)
|
||||
m, err = Execute(r3, f2, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "features in multi-type feature should have matched instance")
|
||||
|
||||
|
@ -248,12 +248,12 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
||||
|
||||
(*r3.MatchFeatures[0].MatchExpressions)["key-1"] = newMatchExpression(nfdv1alpha1.MatchIn, "val-1")
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
||||
|
||||
|
@ -270,7 +270,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
||||
|
||||
|
@ -286,7 +286,7 @@ func TestRule(t *testing.T) {
|
|||
},
|
||||
})
|
||||
(*r3.MatchFeatures[0].MatchExpressions)["key-1"] = newMatchExpression(nfdv1alpha1.MatchIn, "val-1")
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
||||
}
|
||||
|
@ -437,12 +437,12 @@ var-2=
|
|||
"kf-foo": "true",
|
||||
}
|
||||
|
||||
m, err := Execute(r1, f)
|
||||
m, err := Execute(r1, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
||||
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
||||
|
@ -468,7 +468,7 @@ var-2=
|
|||
"mf-key-d": "found",
|
||||
}
|
||||
expectedVars = map[string]string{}
|
||||
m, err = Execute(r3, f)
|
||||
m, err = Execute(r3, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
||||
|
@ -490,32 +490,32 @@ var-2=
|
|||
}
|
||||
|
||||
r2.LabelsTemplate = "foo=bar"
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, map[string]string{"foo": "bar"}, m.Labels, "instances should have matched")
|
||||
assert.Empty(t, m.Vars)
|
||||
|
||||
r2.LabelsTemplate = "foo"
|
||||
_, err = Execute(r2, f)
|
||||
_, err = Execute(r2, f, true)
|
||||
assert.Error(t, err)
|
||||
|
||||
r2.LabelsTemplate = "{{"
|
||||
_, err = Execute(r2, f)
|
||||
_, err = Execute(r2, f, true)
|
||||
assert.Error(t, err)
|
||||
|
||||
r2.LabelsTemplate = ""
|
||||
r2.VarsTemplate = "bar=baz"
|
||||
m, err = Execute(r2, f)
|
||||
m, err = Execute(r2, f, true)
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, m.Labels)
|
||||
assert.Equal(t, map[string]string{"bar": "baz"}, m.Vars, "instances should have matched")
|
||||
|
||||
r2.VarsTemplate = "bar"
|
||||
_, err = Execute(r2, f)
|
||||
_, err = Execute(r2, f, true)
|
||||
assert.Error(t, err)
|
||||
|
||||
r2.VarsTemplate = "{{"
|
||||
_, err = Execute(r2, f)
|
||||
_, err = Execute(r2, f, true)
|
||||
assert.Error(t, err)
|
||||
|
||||
//
|
||||
|
@ -539,7 +539,7 @@ var-2=
|
|||
"key-5": "",
|
||||
}
|
||||
|
||||
m, err = Execute(r4, f)
|
||||
m, err = Execute(r4, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||
|
||||
|
@ -553,7 +553,7 @@ var-2=
|
|||
},
|
||||
}
|
||||
|
||||
m, err = Execute(r4, f)
|
||||
m, err = Execute(r4, f, true)
|
||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||
assert.Equal(t, map[string]string(nil), m.Labels, "instances should have matched")
|
||||
}
|
||||
|
|
178
pkg/client-nfd/compat/artifact-client/client.go
Normal file
178
pkg/client-nfd/compat/artifact-client/client.go
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
package compat
|
||||
|
||||
//go:generate mockery --name=ArtifactClient --inpackage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
oras "oras.land/oras-go/v2"
|
||||
"oras.land/oras-go/v2/registry"
|
||||
"oras.land/oras-go/v2/registry/remote"
|
||||
"oras.land/oras-go/v2/registry/remote/auth"
|
||||
"oras.land/oras-go/v2/registry/remote/retry"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
compatv1alpha1 "sigs.k8s.io/node-feature-discovery/api/image-compatibility/v1alpha1"
|
||||
)
|
||||
|
||||
// ArtifactClient interface contain set of functions to manipulate compatibility artfact.
|
||||
type ArtifactClient interface {
|
||||
// FetchCompatibilitySpec downloads the compatibility specifcation associated with the image.
|
||||
FetchCompatibilitySpec(ctx context.Context) (*compatv1alpha1.Spec, error)
|
||||
}
|
||||
|
||||
// Args holds command line arguments.
|
||||
type Args struct {
|
||||
PlainHttp bool
|
||||
}
|
||||
|
||||
// Client represents a client that is reposnible for all artifact operations.
|
||||
type Client struct {
|
||||
Args Args
|
||||
RegReference *registry.Reference
|
||||
Platform *ocispec.Platform
|
||||
|
||||
orasClient *auth.Client
|
||||
}
|
||||
|
||||
// New returns a new compatibility spec object.
|
||||
func New(regReference *registry.Reference, opts ...ArtifactClientOpts) *Client {
|
||||
c := &Client{
|
||||
RegReference: regReference,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.apply(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// FetchCompatibilitySpec pulls the image compatibility specification associated with the image.
|
||||
func (c *Client) FetchCompatibilitySpec(ctx context.Context) (*compatv1alpha1.Spec, error) {
|
||||
repo, err := remote.NewRepository(c.RegReference.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.Client = c.orasClient
|
||||
repo.PlainHTTP = c.Args.PlainHttp
|
||||
|
||||
opts := oras.DefaultResolveOptions
|
||||
if c.Platform != nil {
|
||||
opts.TargetPlatform = c.Platform
|
||||
}
|
||||
|
||||
targetDesc, err := oras.Resolve(ctx, repo, c.RegReference.Reference, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
descs, err := registry.Referrers(ctx, repo, targetDesc, compatv1alpha1.ArtifactType)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
} else if len(descs) < 1 {
|
||||
return nil, fmt.Errorf("compatibility artifact not found")
|
||||
}
|
||||
artifactDesc := descs[len(descs)-1]
|
||||
|
||||
_, content, err := oras.FetchBytes(ctx, repo.Manifests(), artifactDesc.Digest.String(), oras.DefaultFetchBytesOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
manifest := ocispec.Manifest{}
|
||||
if err := json.Unmarshal(content, &manifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: now it's a lazy check, verify in the future the media types and number of layers
|
||||
if len(manifest.Layers) < 1 {
|
||||
return nil, fmt.Errorf("compatibility layer not found")
|
||||
}
|
||||
specDesc := manifest.Layers[0]
|
||||
|
||||
_, compatSpecRaw, err := oras.FetchBytes(ctx, repo.Blobs(), specDesc.Digest.String(), oras.DefaultFetchBytesOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
compatSpec := compatv1alpha1.Spec{}
|
||||
err = yaml.Unmarshal(compatSpecRaw, &compatSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &compatSpec, nil
|
||||
}
|
||||
|
||||
// NodeValidatorOpts applies certain options to the node validator.
|
||||
type ArtifactClientOpts interface {
|
||||
apply(*Client)
|
||||
}
|
||||
|
||||
type artifactClientOpt struct {
|
||||
f func(*Client)
|
||||
}
|
||||
|
||||
func (o *artifactClientOpt) apply(nv *Client) {
|
||||
o.f(nv)
|
||||
}
|
||||
|
||||
// WithArgs applies arguments to the artifact client.
|
||||
func WithArgs(args Args) ArtifactClientOpts {
|
||||
return &artifactClientOpt{f: func(c *Client) { c.Args = args }}
|
||||
}
|
||||
|
||||
// WithPlatform applies OCI platform spec to the artifact client.
|
||||
func WithPlatform(platform *ocispec.Platform) ArtifactClientOpts {
|
||||
return &artifactClientOpt{f: func(c *Client) { c.Platform = platform }}
|
||||
}
|
||||
|
||||
// WithAuthPassword initializes oras client with user and password.
|
||||
func WithAuthPassword(username, password string) ArtifactClientOpts {
|
||||
return &artifactClientOpt{f: func(c *Client) {
|
||||
c.orasClient = &auth.Client{
|
||||
Client: retry.DefaultClient,
|
||||
Cache: auth.NewCache(),
|
||||
Credential: auth.StaticCredential(c.RegReference.Registry, auth.Credential{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}),
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
// WithAuthToken initializes oras client with auth token.
|
||||
func WithAuthToken(token string) ArtifactClientOpts {
|
||||
return &artifactClientOpt{f: func(c *Client) {
|
||||
c.orasClient = &auth.Client{
|
||||
Client: retry.DefaultClient,
|
||||
Cache: auth.NewCache(),
|
||||
Credential: auth.StaticCredential(c.RegReference.Registry, auth.Credential{
|
||||
AccessToken: token,
|
||||
}),
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
// WithAuthDefault initializes the default oras client that does not authenticate.
|
||||
func WithAuthDefault() ArtifactClientOpts {
|
||||
return &artifactClientOpt{f: func(c *Client) { c.orasClient = auth.DefaultClient }}
|
||||
}
|
59
pkg/client-nfd/compat/artifact-client/mock_ArtifactClient.go
Normal file
59
pkg/client-nfd/compat/artifact-client/mock_ArtifactClient.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
|
||||
package compat
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/image-compatibility/v1alpha1"
|
||||
)
|
||||
|
||||
// MockArtifactClient is an autogenerated mock type for the ArtifactClient type
|
||||
type MockArtifactClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// FetchCompatibilitySpec provides a mock function with given fields: ctx
|
||||
func (_m *MockArtifactClient) FetchCompatibilitySpec(ctx context.Context) (*v1alpha1.Spec, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for FetchCompatibilitySpec")
|
||||
}
|
||||
|
||||
var r0 *v1alpha1.Spec
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) (*v1alpha1.Spec, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) *v1alpha1.Spec); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v1alpha1.Spec)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// NewMockArtifactClient creates a new instance of MockArtifactClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockArtifactClient(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockArtifactClient {
|
||||
mock := &MockArtifactClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
203
pkg/client-nfd/compat/node-validator/node-validator.go
Normal file
203
pkg/client-nfd/compat/node-validator/node-validator.go
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nodevalidator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
"sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/nodefeaturerule"
|
||||
artifactcli "sigs.k8s.io/node-feature-discovery/pkg/client-nfd/compat/artifact-client"
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
|
||||
// register sources
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/cpu"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/kernel"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/memory"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/network"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/pci"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/storage"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/system"
|
||||
_ "sigs.k8s.io/node-feature-discovery/source/usb"
|
||||
)
|
||||
|
||||
// Args holds command line arguments.
|
||||
type Args struct {
|
||||
Tags []string
|
||||
}
|
||||
|
||||
type nodeValidator struct {
|
||||
args Args
|
||||
|
||||
artifactClient artifactcli.ArtifactClient
|
||||
sources map[string]source.FeatureSource
|
||||
}
|
||||
|
||||
// New builds a node validator with specified options.
|
||||
func New(opts ...NodeValidatorOpts) nodeValidator {
|
||||
n := nodeValidator{}
|
||||
for _, opt := range opts {
|
||||
opt.apply(&n)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Execute pulls the compatibility artifact to compare described features with the ones discovered on the node.
|
||||
func (nv *nodeValidator) Execute(ctx context.Context) ([]*CompatibilityStatus, error) {
|
||||
spec, err := nv.artifactClient.FetchCompatibilitySpec(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, s := range nv.sources {
|
||||
if err := s.Discover(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
features := source.GetAllFeatures()
|
||||
|
||||
compats := []*CompatibilityStatus{}
|
||||
for _, c := range spec.Compatibilties {
|
||||
if len(nv.args.Tags) > 0 && !slices.Contains(nv.args.Tags, c.Tag) {
|
||||
continue
|
||||
}
|
||||
compat := newCompatibilityStatus(&c)
|
||||
|
||||
for _, r := range c.Rules {
|
||||
ruleOut, err := nodefeaturerule.Execute(&r, features, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compat.Rules = append(compat.Rules, evaluateRuleStatus(&r, ruleOut.MatchStatus))
|
||||
|
||||
// Add the 'rule.matched' feature for backreference functionality
|
||||
features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Labels)
|
||||
features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Vars)
|
||||
}
|
||||
compats = append(compats, &compat)
|
||||
}
|
||||
|
||||
return compats, nil
|
||||
}
|
||||
|
||||
func evaluateRuleStatus(rule *nfdv1alpha1.Rule, matchStatus *nodefeaturerule.MatchStatus) ProcessedRuleStatus {
|
||||
out := ProcessedRuleStatus{Name: rule.Name, IsMatch: matchStatus.IsMatch}
|
||||
|
||||
evaluateFeatureMatcher := func(featureMatcher, matchedFeatureTerms nfdv1alpha1.FeatureMatcher) []MatchedExpression {
|
||||
out := []MatchedExpression{}
|
||||
for _, term := range featureMatcher {
|
||||
if term.MatchExpressions != nil {
|
||||
for name, exp := range *term.MatchExpressions {
|
||||
isMatch := false
|
||||
|
||||
// Check if the expression matches
|
||||
for _, processedTerm := range matchedFeatureTerms {
|
||||
if term.Feature != processedTerm.Feature || processedTerm.MatchExpressions == nil {
|
||||
continue
|
||||
}
|
||||
pexp, ok := (*processedTerm.MatchExpressions)[name]
|
||||
if isMatch = ok && exp.Op == pexp.Op && slices.Equal(exp.Value, pexp.Value); isMatch {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
out = append(out, MatchedExpression{
|
||||
Feature: term.Feature,
|
||||
Name: name,
|
||||
Expression: exp,
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: isMatch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if term.MatchName != nil {
|
||||
isMatch := false
|
||||
for _, processedTerm := range matchStatus.MatchedFeaturesTerms {
|
||||
if term.Feature != processedTerm.Feature || processedTerm.MatchName == nil {
|
||||
continue
|
||||
}
|
||||
isMatch = term.MatchName.Op == processedTerm.MatchName.Op && slices.Equal(term.MatchName.Value, processedTerm.MatchName.Value)
|
||||
if isMatch {
|
||||
break
|
||||
}
|
||||
}
|
||||
out = append(out, MatchedExpression{
|
||||
Feature: term.Feature,
|
||||
Name: "",
|
||||
Expression: term.MatchName,
|
||||
MatcherType: MatchNameType,
|
||||
IsMatch: isMatch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// For reproducible output sort by name, feature, expression.
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
if out[i].Feature != out[j].Feature {
|
||||
return out[i].Feature < out[j].Feature
|
||||
}
|
||||
if out[i].Name != out[j].Name {
|
||||
return out[i].Name < out[j].Name
|
||||
}
|
||||
return out[i].Expression.String() < out[j].Expression.String()
|
||||
})
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
if matchFeatures := rule.MatchFeatures; matchFeatures != nil {
|
||||
out.MatchedExpressions = evaluateFeatureMatcher(matchFeatures, matchStatus.MatchedFeaturesTerms)
|
||||
}
|
||||
|
||||
for i, matchAnyElem := range rule.MatchAny {
|
||||
matchedExpressions := evaluateFeatureMatcher(matchAnyElem.MatchFeatures, matchStatus.MatchAny[i].MatchedFeaturesTerms)
|
||||
out.MatchedAny = append(out.MatchedAny, MatchAnyElem{MatchedExpressions: matchedExpressions})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// NodeValidatorOpts applies certain options to the node validator.
|
||||
type NodeValidatorOpts interface {
|
||||
apply(*nodeValidator)
|
||||
}
|
||||
|
||||
type nodeValidatorOpt struct {
|
||||
f func(*nodeValidator)
|
||||
}
|
||||
|
||||
func (o *nodeValidatorOpt) apply(nv *nodeValidator) {
|
||||
o.f(nv)
|
||||
}
|
||||
|
||||
// WithArgs applies command line arguments to the node validator object.
|
||||
func WithArgs(args *Args) NodeValidatorOpts {
|
||||
return &nodeValidatorOpt{f: func(nv *nodeValidator) { nv.args = *args }}
|
||||
}
|
||||
|
||||
// WithArtifactClient applies the client for all artifact operations.
|
||||
func WithArtifactClient(cli artifactcli.ArtifactClient) NodeValidatorOpts {
|
||||
return &nodeValidatorOpt{f: func(nv *nodeValidator) { nv.artifactClient = cli }}
|
||||
}
|
||||
|
||||
// WithSources applies the list of enabled feature sources.
|
||||
func WithSources(sources map[string]source.FeatureSource) NodeValidatorOpts {
|
||||
return &nodeValidatorOpt{f: func(nv *nodeValidator) { nv.sources = sources }}
|
||||
}
|
418
pkg/client-nfd/compat/node-validator/node-validator_test.go
Normal file
418
pkg/client-nfd/compat/node-validator/node-validator_test.go
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nodevalidator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
compatv1alpha1 "sigs.k8s.io/node-feature-discovery/api/image-compatibility/v1alpha1"
|
||||
"sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
artifactcli "sigs.k8s.io/node-feature-discovery/pkg/client-nfd/compat/artifact-client"
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
"sigs.k8s.io/node-feature-discovery/source/fake"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fs := source.GetConfigurableSource(fake.Name)
|
||||
fs.SetConfig(fs.NewConfig())
|
||||
}
|
||||
|
||||
func TestNodeValidator(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
Convey("With a single compatibility set that contains flags, attributes and instances", t, func() {
|
||||
spec := &compatv1alpha1.Spec{
|
||||
Version: compatv1alpha1.Version,
|
||||
Compatibilties: []compatv1alpha1.Compatibility{
|
||||
{
|
||||
Description: "Fake compatibility",
|
||||
Rules: []v1alpha1.Rule{
|
||||
{
|
||||
Name: "fake_1",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.flag",
|
||||
MatchName: &v1alpha1.MatchExpression{Op: v1alpha1.MatchInRegexp, Value: v1alpha1.MatchValue{"^flag"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_2",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.flag",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"flag_unknown": &v1alpha1.MatchExpression{Op: v1alpha1.MatchExists},
|
||||
},
|
||||
},
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"attr_1": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"true"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_3",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"name": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_1"}},
|
||||
"attr_1": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"true"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"name": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_2"}},
|
||||
"attr_1": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_4",
|
||||
MatchAny: []v1alpha1.MatchAnyElem{
|
||||
{
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"name": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_1"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"name": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_unknown"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// The output contains expressions in alphabetical order over the feature, name and expression string.
|
||||
expectedOutput := []*CompatibilityStatus{
|
||||
{
|
||||
Description: "Fake compatibility",
|
||||
Rules: []ProcessedRuleStatus{
|
||||
{
|
||||
Name: "fake_1",
|
||||
IsMatch: true,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.flag",
|
||||
Name: "",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchInRegexp, Value: v1alpha1.MatchValue{"^flag"}},
|
||||
MatcherType: MatchNameType,
|
||||
IsMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_2",
|
||||
IsMatch: false,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
Name: "attr_1",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"true"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
{
|
||||
Feature: "fake.flag",
|
||||
Name: "flag_unknown",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchExists},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_3",
|
||||
IsMatch: false,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "attr_1",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: false,
|
||||
},
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "attr_1",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"true"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "name",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_1"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "name",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_2"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fake_4",
|
||||
IsMatch: true,
|
||||
MatchedAny: []MatchAnyElem{
|
||||
{
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "name",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_1"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.instance",
|
||||
Name: "name",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"instance_unknown"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
validator := New(
|
||||
WithArgs(&Args{}),
|
||||
WithArtifactClient(newMock(ctx, spec)),
|
||||
WithSources(map[string]source.FeatureSource{fake.Name: source.GetFeatureSource(fake.Name)}),
|
||||
)
|
||||
output, err := validator.Execute(ctx)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, expectedOutput)
|
||||
})
|
||||
|
||||
Convey("With multiple compatibility sets", t, func() {
|
||||
spec := &compatv1alpha1.Spec{
|
||||
Version: compatv1alpha1.Version,
|
||||
Compatibilties: []compatv1alpha1.Compatibility{
|
||||
{
|
||||
Tag: "prefered",
|
||||
Weight: 90,
|
||||
Description: "Fake compatibility 1",
|
||||
Rules: []v1alpha1.Rule{
|
||||
{
|
||||
Name: "fake_1",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"attr_1": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Tag: "fallback",
|
||||
Weight: 40,
|
||||
Description: "Fake compatibility 2",
|
||||
Rules: []v1alpha1.Rule{
|
||||
{
|
||||
Name: "fake_1",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"attr_2": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedOutput := []*CompatibilityStatus{
|
||||
{
|
||||
Tag: "prefered",
|
||||
Weight: 90,
|
||||
Description: "Fake compatibility 1",
|
||||
Rules: []ProcessedRuleStatus{
|
||||
{
|
||||
Name: "fake_1",
|
||||
IsMatch: false,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
Name: "attr_1",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Tag: "fallback",
|
||||
Weight: 40,
|
||||
Description: "Fake compatibility 2",
|
||||
Rules: []ProcessedRuleStatus{
|
||||
{
|
||||
Name: "fake_1",
|
||||
IsMatch: true,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
Name: "attr_2",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
validator := New(
|
||||
WithArgs(&Args{}),
|
||||
WithArtifactClient(newMock(ctx, spec)),
|
||||
WithSources(map[string]source.FeatureSource{fake.Name: source.GetFeatureSource(fake.Name)}),
|
||||
)
|
||||
output, err := validator.Execute(ctx)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, expectedOutput)
|
||||
})
|
||||
|
||||
Convey("With compatibility sets filtered out by tags", t, func() {
|
||||
spec := &compatv1alpha1.Spec{
|
||||
Version: compatv1alpha1.Version,
|
||||
Compatibilties: []compatv1alpha1.Compatibility{
|
||||
{
|
||||
Tag: "prefered",
|
||||
Weight: 90,
|
||||
Description: "Fake compatibility 1",
|
||||
Rules: []v1alpha1.Rule{
|
||||
{
|
||||
Name: "fake_1",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"attr_1": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Tag: "fallback",
|
||||
Weight: 40,
|
||||
Description: "Fake compatibility 2",
|
||||
Rules: []v1alpha1.Rule{
|
||||
{
|
||||
Name: "fake_1",
|
||||
MatchFeatures: v1alpha1.FeatureMatcher{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
MatchExpressions: &v1alpha1.MatchExpressionSet{
|
||||
"attr_2": &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedOutput := []*CompatibilityStatus{
|
||||
{
|
||||
Tag: "prefered",
|
||||
Weight: 90,
|
||||
Description: "Fake compatibility 1",
|
||||
Rules: []ProcessedRuleStatus{
|
||||
{
|
||||
Name: "fake_1",
|
||||
IsMatch: false,
|
||||
MatchedExpressions: []MatchedExpression{
|
||||
{
|
||||
Feature: "fake.attribute",
|
||||
Name: "attr_1",
|
||||
Expression: &v1alpha1.MatchExpression{Op: v1alpha1.MatchIn, Value: v1alpha1.MatchValue{"false"}},
|
||||
MatcherType: MatchExpressionType,
|
||||
IsMatch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
validator := New(
|
||||
WithArgs(&Args{
|
||||
Tags: []string{"prefered"},
|
||||
}),
|
||||
WithArtifactClient(newMock(ctx, spec)),
|
||||
WithSources(map[string]source.FeatureSource{fake.Name: source.GetFeatureSource(fake.Name)}),
|
||||
)
|
||||
output, err := validator.Execute(ctx)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, expectedOutput)
|
||||
})
|
||||
}
|
||||
|
||||
func newMock(ctx context.Context, result *compatv1alpha1.Spec) *artifactcli.MockArtifactClient {
|
||||
artifactClient := &artifactcli.MockArtifactClient{}
|
||||
artifactClient.On("FetchCompatibilitySpec", ctx).Return(result, nil)
|
||||
return artifactClient
|
||||
}
|
89
pkg/client-nfd/compat/node-validator/status.go
Normal file
89
pkg/client-nfd/compat/node-validator/status.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nodevalidator
|
||||
|
||||
import (
|
||||
compatv1alpha1 "sigs.k8s.io/node-feature-discovery/api/image-compatibility/v1alpha1"
|
||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||
)
|
||||
|
||||
// MatcherType represents a type of the used matcher.
|
||||
type MatcherType string
|
||||
|
||||
const (
|
||||
// MatchExpressionType represents a matchExpression type.
|
||||
MatchExpressionType MatcherType = "matchExpression"
|
||||
// MatchNameType represents a matchName type.
|
||||
MatchNameType MatcherType = "matchName"
|
||||
)
|
||||
|
||||
// CompatibilityStatus represents the state of
|
||||
// feature matching between the image and the host.
|
||||
type CompatibilityStatus struct {
|
||||
// Rules contain information about the matching status
|
||||
// of all Node Feature Rules.
|
||||
Rules []ProcessedRuleStatus `json:"rules"`
|
||||
// Description of the compatibility set.
|
||||
Description string `json:"description,omitempty"`
|
||||
// Weight provides information about the priority of the compatibility set.
|
||||
Weight int `json:"weight,omitempty"`
|
||||
// Tag provides information about the tag assigned to the compatibility set.
|
||||
Tag string `json:"tag,omitempty"`
|
||||
}
|
||||
|
||||
func newCompatibilityStatus(c *compatv1alpha1.Compatibility) CompatibilityStatus {
|
||||
cs := CompatibilityStatus{
|
||||
Description: c.Description,
|
||||
Weight: c.Weight,
|
||||
Tag: c.Tag,
|
||||
}
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// ProcessedRuleStatus provides information whether the expressions succeeded on the host.
|
||||
type ProcessedRuleStatus struct {
|
||||
// Name of the rule.
|
||||
Name string `json:"name"`
|
||||
// IsMatch provides information if the rule matches with the host.
|
||||
IsMatch bool `json:"isMatch"`
|
||||
|
||||
// MatchedExpressions represents the expressions that succeed on the host.
|
||||
MatchedExpressions []MatchedExpression `json:"matchedExpressions,omitempty"`
|
||||
// MatchAny represents an array of logical OR conditions between MatchedExpressions entries.
|
||||
MatchedAny []MatchAnyElem `json:"matchedAny,omitempty"`
|
||||
}
|
||||
|
||||
// MatchAnyElem represents a single object of MatchAny that contains MatchedExpression entries.
|
||||
type MatchAnyElem struct {
|
||||
// MatchedExpressions contains MatchedExpression entries.
|
||||
MatchedExpressions []MatchedExpression `json:"matchedExpressions"`
|
||||
}
|
||||
|
||||
// MatchedExpression represent all details about the expression that succeeded on the host.
|
||||
type MatchedExpression struct {
|
||||
// Feature which is available to be evaluated on the host.
|
||||
Feature string `json:"feature"`
|
||||
// Name of the element.
|
||||
Name string `json:"name"`
|
||||
// Expression represents the expression provided by users.
|
||||
Expression *nfdv1alpha1.MatchExpression `json:"expression"`
|
||||
// MatcherType represents the matcher type, e.g. MatchExpression, MatchName.
|
||||
MatcherType MatcherType `json:"matcherType"`
|
||||
// IsMatch provides information whether the expression suceeded on the host.
|
||||
IsMatch bool `json:"isMatch"`
|
||||
}
|
|
@ -70,7 +70,7 @@ func processNodeFeatureRule(nodeFeatureRule nfdv1alpha1.NodeFeatureRule, nodeFea
|
|||
|
||||
for _, rule := range nodeFeatureRule.Spec.Rules {
|
||||
fmt.Println("Processing rule: ", rule.Name)
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, &nodeFeature.Features)
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, &nodeFeature.Features, true)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to process rule: %q - %w", rule.Name, err))
|
||||
continue
|
||||
|
|
|
@ -794,7 +794,7 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
|
|||
nodeGroupValidator := make(map[string]bool)
|
||||
for _, rule := range nodeFeatureGroup.Spec.Rules {
|
||||
for _, feature := range nodeFeaturesList {
|
||||
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features)
|
||||
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
|
||||
continue
|
||||
|
@ -1018,7 +1018,7 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha
|
|||
klog.InfoS("executing NodeFeatureRule", "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
||||
}
|
||||
for _, rule := range spec.Spec.Rules {
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, features)
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, features, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to process rule", "ruleName", rule.Name, "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
||||
nfrProcessingErrors.Inc()
|
||||
|
|
|
@ -93,7 +93,7 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) {
|
|||
klog.V(2).InfoS("resolving custom features", "configuration", utils.DelayedDumper(allFeatureConfig))
|
||||
// Iterate over features
|
||||
for _, rule := range allFeatureConfig {
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, features)
|
||||
ruleOut, err := nodefeaturerule.Execute(&rule, features, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to execute rule")
|
||||
continue
|
||||
|
|
Loading…
Add table
Reference in a new issue