mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-06 16:57:10 +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/ \
|
RUN --mount=type=cache,target=/go/pkg/mod/ \
|
||||||
go install github.com/vektra/mockery/v2@v2.42.0 && \
|
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 sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.3 && \
|
||||||
go install golang.org/x/tools/cmd/goimports@v0.25.0 && \
|
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
|
|
||||||
|
|
||||||
|
|
||||||
# Expect to be working with nfd
|
# Expect to be working with nfd
|
||||||
WORKDIR /go/node-feature-discovery
|
WORKDIR /go/node-feature-discovery
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -90,7 +90,7 @@ IMAGE_BUILD_ARGS_MINIMAL = --target minimal \
|
||||||
|
|
||||||
all: image
|
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-%:
|
build-%:
|
||||||
$(GO_CMD) build -v -o bin/ $(BUILD_FLAGS) ./cmd/$*
|
$(GO_CMD) build -v -o bin/ $(BUILD_FLAGS) ./cmd/$*
|
||||||
|
|
|
@ -19,8 +19,8 @@ limitations under the License.
|
||||||
package versioned
|
package versioned
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
fmt "fmt"
|
||||||
"net/http"
|
http "net/http"
|
||||||
|
|
||||||
discovery "k8s.io/client-go/discovery"
|
discovery "k8s.io/client-go/discovery"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
|
|
@ -29,15 +29,15 @@ type FakeNfdV1alpha1 struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeNfdV1alpha1) NodeFeatures(namespace string) v1alpha1.NodeFeatureInterface {
|
func (c *FakeNfdV1alpha1) NodeFeatures(namespace string) v1alpha1.NodeFeatureInterface {
|
||||||
return &FakeNodeFeatures{c, namespace}
|
return newFakeNodeFeatures(c, namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeNfdV1alpha1) NodeFeatureGroups(namespace string) v1alpha1.NodeFeatureGroupInterface {
|
func (c *FakeNfdV1alpha1) NodeFeatureGroups(namespace string) v1alpha1.NodeFeatureGroupInterface {
|
||||||
return &FakeNodeFeatureGroups{c, namespace}
|
return newFakeNodeFeatureGroups(c, namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeNfdV1alpha1) NodeFeatureRules() v1alpha1.NodeFeatureRuleInterface {
|
func (c *FakeNfdV1alpha1) NodeFeatureRules() v1alpha1.NodeFeatureRuleInterface {
|
||||||
return &FakeNodeFeatureRules{c}
|
return newFakeNodeFeatureRules(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RESTClient returns a RESTClient that is used to communicate
|
// RESTClient returns a RESTClient that is used to communicate
|
||||||
|
|
|
@ -19,116 +19,34 @@ limitations under the License.
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
labels "k8s.io/apimachinery/pkg/labels"
|
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
|
||||||
testing "k8s.io/client-go/testing"
|
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakeNodeFeatures implements NodeFeatureInterface
|
// fakeNodeFeatures implements NodeFeatureInterface
|
||||||
type FakeNodeFeatures struct {
|
type fakeNodeFeatures struct {
|
||||||
|
*gentype.FakeClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList]
|
||||||
Fake *FakeNfdV1alpha1
|
Fake *FakeNfdV1alpha1
|
||||||
ns string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodefeaturesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeatures")
|
func newFakeNodeFeatures(fake *FakeNfdV1alpha1, namespace string) nfdv1alpha1.NodeFeatureInterface {
|
||||||
|
return &fakeNodeFeatures{
|
||||||
var nodefeaturesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeature")
|
gentype.NewFakeClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList](
|
||||||
|
fake.Fake,
|
||||||
// Get takes name of the nodeFeature, and returns the corresponding nodeFeature object, and an error if there is any.
|
namespace,
|
||||||
func (c *FakeNodeFeatures) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeature, err error) {
|
v1alpha1.SchemeGroupVersion.WithResource("nodefeatures"),
|
||||||
emptyResult := &v1alpha1.NodeFeature{}
|
v1alpha1.SchemeGroupVersion.WithKind("NodeFeature"),
|
||||||
obj, err := c.Fake.
|
func() *v1alpha1.NodeFeature { return &v1alpha1.NodeFeature{} },
|
||||||
Invokes(testing.NewGetActionWithOptions(nodefeaturesResource, c.ns, name, options), emptyResult)
|
func() *v1alpha1.NodeFeatureList { return &v1alpha1.NodeFeatureList{} },
|
||||||
|
func(dst, src *v1alpha1.NodeFeatureList) { dst.ListMeta = src.ListMeta },
|
||||||
if obj == nil {
|
func(list *v1alpha1.NodeFeatureList) []*v1alpha1.NodeFeature {
|
||||||
return emptyResult, err
|
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
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
labels "k8s.io/apimachinery/pkg/labels"
|
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
|
||||||
testing "k8s.io/client-go/testing"
|
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakeNodeFeatureGroups implements NodeFeatureGroupInterface
|
// fakeNodeFeatureGroups implements NodeFeatureGroupInterface
|
||||||
type FakeNodeFeatureGroups struct {
|
type fakeNodeFeatureGroups struct {
|
||||||
|
*gentype.FakeClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList]
|
||||||
Fake *FakeNfdV1alpha1
|
Fake *FakeNfdV1alpha1
|
||||||
ns string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodefeaturegroupsResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturegroups")
|
func newFakeNodeFeatureGroups(fake *FakeNfdV1alpha1, namespace string) nfdv1alpha1.NodeFeatureGroupInterface {
|
||||||
|
return &fakeNodeFeatureGroups{
|
||||||
var nodefeaturegroupsKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureGroup")
|
gentype.NewFakeClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList](
|
||||||
|
fake.Fake,
|
||||||
// Get takes name of the nodeFeatureGroup, and returns the corresponding nodeFeatureGroup object, and an error if there is any.
|
namespace,
|
||||||
func (c *FakeNodeFeatureGroups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureGroup, err error) {
|
v1alpha1.SchemeGroupVersion.WithResource("nodefeaturegroups"),
|
||||||
emptyResult := &v1alpha1.NodeFeatureGroup{}
|
v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureGroup"),
|
||||||
obj, err := c.Fake.
|
func() *v1alpha1.NodeFeatureGroup { return &v1alpha1.NodeFeatureGroup{} },
|
||||||
Invokes(testing.NewGetActionWithOptions(nodefeaturegroupsResource, c.ns, name, options), emptyResult)
|
func() *v1alpha1.NodeFeatureGroupList { return &v1alpha1.NodeFeatureGroupList{} },
|
||||||
|
func(dst, src *v1alpha1.NodeFeatureGroupList) { dst.ListMeta = src.ListMeta },
|
||||||
if obj == nil {
|
func(list *v1alpha1.NodeFeatureGroupList) []*v1alpha1.NodeFeatureGroup {
|
||||||
return emptyResult, err
|
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
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/typed/nfd/v1alpha1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
labels "k8s.io/apimachinery/pkg/labels"
|
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
|
||||||
testing "k8s.io/client-go/testing"
|
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakeNodeFeatureRules implements NodeFeatureRuleInterface
|
// fakeNodeFeatureRules implements NodeFeatureRuleInterface
|
||||||
type FakeNodeFeatureRules struct {
|
type fakeNodeFeatureRules struct {
|
||||||
|
*gentype.FakeClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList]
|
||||||
Fake *FakeNfdV1alpha1
|
Fake *FakeNfdV1alpha1
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodefeaturerulesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules")
|
func newFakeNodeFeatureRules(fake *FakeNfdV1alpha1) nfdv1alpha1.NodeFeatureRuleInterface {
|
||||||
|
return &fakeNodeFeatureRules{
|
||||||
var nodefeaturerulesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRule")
|
gentype.NewFakeClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList](
|
||||||
|
fake.Fake,
|
||||||
// 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) {
|
v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules"),
|
||||||
emptyResult := &v1alpha1.NodeFeatureRule{}
|
v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRule"),
|
||||||
obj, err := c.Fake.
|
func() *v1alpha1.NodeFeatureRule { return &v1alpha1.NodeFeatureRule{} },
|
||||||
Invokes(testing.NewRootGetActionWithOptions(nodefeaturerulesResource, name, options), emptyResult)
|
func() *v1alpha1.NodeFeatureRuleList { return &v1alpha1.NodeFeatureRuleList{} },
|
||||||
if obj == nil {
|
func(dst, src *v1alpha1.NodeFeatureRuleList) { dst.ListMeta = src.ListMeta },
|
||||||
return emptyResult, err
|
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
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
http "net/http"
|
||||||
|
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NfdV1alpha1Interface interface {
|
type NfdV1alpha1Interface interface {
|
||||||
|
@ -95,10 +95,10 @@ func New(c rest.Interface) *NfdV1alpha1Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConfigDefaults(config *rest.Config) error {
|
func setConfigDefaults(config *rest.Config) error {
|
||||||
gv := v1alpha1.SchemeGroupVersion
|
gv := nfdv1alpha1.SchemeGroupVersion
|
||||||
config.GroupVersion = &gv
|
config.GroupVersion = &gv
|
||||||
config.APIPath = "/apis"
|
config.APIPath = "/apis"
|
||||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
|
||||||
|
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
gentype "k8s.io/client-go/gentype"
|
gentype "k8s.io/client-go/gentype"
|
||||||
scheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
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.
|
// NodeFeaturesGetter has a method to return a NodeFeatureInterface.
|
||||||
|
@ -37,31 +37,32 @@ type NodeFeaturesGetter interface {
|
||||||
|
|
||||||
// NodeFeatureInterface has methods to work with NodeFeature resources.
|
// NodeFeatureInterface has methods to work with NodeFeature resources.
|
||||||
type NodeFeatureInterface interface {
|
type NodeFeatureInterface interface {
|
||||||
Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (*v1alpha1.NodeFeature, error)
|
Create(ctx context.Context, nodeFeature *nfdv1alpha1.NodeFeature, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeature, error)
|
||||||
Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (*v1alpha1.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
|
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeature, error)
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeature, error)
|
||||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureList, error)
|
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureList, error)
|
||||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, 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
|
NodeFeatureExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatures implements NodeFeatureInterface
|
// nodeFeatures implements NodeFeatureInterface
|
||||||
type nodeFeatures struct {
|
type nodeFeatures struct {
|
||||||
*gentype.ClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList]
|
*gentype.ClientWithList[*nfdv1alpha1.NodeFeature, *nfdv1alpha1.NodeFeatureList]
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNodeFeatures returns a NodeFeatures
|
// newNodeFeatures returns a NodeFeatures
|
||||||
func newNodeFeatures(c *NfdV1alpha1Client, namespace string) *nodeFeatures {
|
func newNodeFeatures(c *NfdV1alpha1Client, namespace string) *nodeFeatures {
|
||||||
return &nodeFeatures{
|
return &nodeFeatures{
|
||||||
gentype.NewClientWithList[*v1alpha1.NodeFeature, *v1alpha1.NodeFeatureList](
|
gentype.NewClientWithList[*nfdv1alpha1.NodeFeature, *nfdv1alpha1.NodeFeatureList](
|
||||||
"nodefeatures",
|
"nodefeatures",
|
||||||
c.RESTClient(),
|
c.RESTClient(),
|
||||||
scheme.ParameterCodec,
|
scheme.ParameterCodec,
|
||||||
namespace,
|
namespace,
|
||||||
func() *v1alpha1.NodeFeature { return &v1alpha1.NodeFeature{} },
|
func() *nfdv1alpha1.NodeFeature { return &nfdv1alpha1.NodeFeature{} },
|
||||||
func() *v1alpha1.NodeFeatureList { return &v1alpha1.NodeFeatureList{} }),
|
func() *nfdv1alpha1.NodeFeatureList { return &nfdv1alpha1.NodeFeatureList{} },
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
gentype "k8s.io/client-go/gentype"
|
gentype "k8s.io/client-go/gentype"
|
||||||
scheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
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.
|
// NodeFeatureGroupsGetter has a method to return a NodeFeatureGroupInterface.
|
||||||
|
@ -37,33 +37,34 @@ type NodeFeatureGroupsGetter interface {
|
||||||
|
|
||||||
// NodeFeatureGroupInterface has methods to work with NodeFeatureGroup resources.
|
// NodeFeatureGroupInterface has methods to work with NodeFeatureGroup resources.
|
||||||
type NodeFeatureGroupInterface interface {
|
type NodeFeatureGroupInterface interface {
|
||||||
Create(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.CreateOptions) (*v1alpha1.NodeFeatureGroup, error)
|
Create(ctx context.Context, nodeFeatureGroup *nfdv1alpha1.NodeFeatureGroup, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||||
Update(ctx context.Context, nodeFeatureGroup *v1alpha1.NodeFeatureGroup, opts v1.UpdateOptions) (*v1alpha1.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().
|
// 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
|
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeatureGroup, error)
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureGroupList, error)
|
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureGroupList, error)
|
||||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, 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
|
NodeFeatureGroupExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatureGroups implements NodeFeatureGroupInterface
|
// nodeFeatureGroups implements NodeFeatureGroupInterface
|
||||||
type nodeFeatureGroups struct {
|
type nodeFeatureGroups struct {
|
||||||
*gentype.ClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList]
|
*gentype.ClientWithList[*nfdv1alpha1.NodeFeatureGroup, *nfdv1alpha1.NodeFeatureGroupList]
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNodeFeatureGroups returns a NodeFeatureGroups
|
// newNodeFeatureGroups returns a NodeFeatureGroups
|
||||||
func newNodeFeatureGroups(c *NfdV1alpha1Client, namespace string) *nodeFeatureGroups {
|
func newNodeFeatureGroups(c *NfdV1alpha1Client, namespace string) *nodeFeatureGroups {
|
||||||
return &nodeFeatureGroups{
|
return &nodeFeatureGroups{
|
||||||
gentype.NewClientWithList[*v1alpha1.NodeFeatureGroup, *v1alpha1.NodeFeatureGroupList](
|
gentype.NewClientWithList[*nfdv1alpha1.NodeFeatureGroup, *nfdv1alpha1.NodeFeatureGroupList](
|
||||||
"nodefeaturegroups",
|
"nodefeaturegroups",
|
||||||
c.RESTClient(),
|
c.RESTClient(),
|
||||||
scheme.ParameterCodec,
|
scheme.ParameterCodec,
|
||||||
namespace,
|
namespace,
|
||||||
func() *v1alpha1.NodeFeatureGroup { return &v1alpha1.NodeFeatureGroup{} },
|
func() *nfdv1alpha1.NodeFeatureGroup { return &nfdv1alpha1.NodeFeatureGroup{} },
|
||||||
func() *v1alpha1.NodeFeatureGroupList { return &v1alpha1.NodeFeatureGroupList{} }),
|
func() *nfdv1alpha1.NodeFeatureGroupList { return &nfdv1alpha1.NodeFeatureGroupList{} },
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,14 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
gentype "k8s.io/client-go/gentype"
|
gentype "k8s.io/client-go/gentype"
|
||||||
scheme "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned/scheme"
|
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.
|
// NodeFeatureRulesGetter has a method to return a NodeFeatureRuleInterface.
|
||||||
|
@ -37,31 +37,32 @@ type NodeFeatureRulesGetter interface {
|
||||||
|
|
||||||
// NodeFeatureRuleInterface has methods to work with NodeFeatureRule resources.
|
// NodeFeatureRuleInterface has methods to work with NodeFeatureRule resources.
|
||||||
type NodeFeatureRuleInterface interface {
|
type NodeFeatureRuleInterface interface {
|
||||||
Create(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.CreateOptions) (*v1alpha1.NodeFeatureRule, error)
|
Create(ctx context.Context, nodeFeatureRule *nfdv1alpha1.NodeFeatureRule, opts v1.CreateOptions) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||||
Update(ctx context.Context, nodeFeatureRule *v1alpha1.NodeFeatureRule, opts v1.UpdateOptions) (*v1alpha1.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
|
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeatureRule, error)
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureRuleList, error)
|
List(ctx context.Context, opts v1.ListOptions) (*nfdv1alpha1.NodeFeatureRuleList, error)
|
||||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, 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
|
NodeFeatureRuleExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatureRules implements NodeFeatureRuleInterface
|
// nodeFeatureRules implements NodeFeatureRuleInterface
|
||||||
type nodeFeatureRules struct {
|
type nodeFeatureRules struct {
|
||||||
*gentype.ClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList]
|
*gentype.ClientWithList[*nfdv1alpha1.NodeFeatureRule, *nfdv1alpha1.NodeFeatureRuleList]
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNodeFeatureRules returns a NodeFeatureRules
|
// newNodeFeatureRules returns a NodeFeatureRules
|
||||||
func newNodeFeatureRules(c *NfdV1alpha1Client) *nodeFeatureRules {
|
func newNodeFeatureRules(c *NfdV1alpha1Client) *nodeFeatureRules {
|
||||||
return &nodeFeatureRules{
|
return &nodeFeatureRules{
|
||||||
gentype.NewClientWithList[*v1alpha1.NodeFeatureRule, *v1alpha1.NodeFeatureRuleList](
|
gentype.NewClientWithList[*nfdv1alpha1.NodeFeatureRule, *nfdv1alpha1.NodeFeatureRuleList](
|
||||||
"nodefeaturerules",
|
"nodefeaturerules",
|
||||||
c.RESTClient(),
|
c.RESTClient(),
|
||||||
scheme.ParameterCodec,
|
scheme.ParameterCodec,
|
||||||
"",
|
"",
|
||||||
func() *v1alpha1.NodeFeatureRule { return &v1alpha1.NodeFeatureRule{} },
|
func() *nfdv1alpha1.NodeFeatureRule { return &nfdv1alpha1.NodeFeatureRule{} },
|
||||||
func() *v1alpha1.NodeFeatureRuleList { return &v1alpha1.NodeFeatureRuleList{} }),
|
func() *nfdv1alpha1.NodeFeatureRuleList { return &nfdv1alpha1.NodeFeatureRuleList{} },
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
package externalversions
|
package externalversions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
fmt "fmt"
|
||||||
|
|
||||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -28,15 +28,15 @@ import (
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
||||||
internalinterfaces "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/internalinterfaces"
|
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/generated/listers/nfd/v1alpha1"
|
||||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureInformer provides access to a shared informer and lister for
|
// NodeFeatureInformer provides access to a shared informer and lister for
|
||||||
// NodeFeatures.
|
// NodeFeatures.
|
||||||
type NodeFeatureInformer interface {
|
type NodeFeatureInformer interface {
|
||||||
Informer() cache.SharedIndexInformer
|
Informer() cache.SharedIndexInformer
|
||||||
Lister() v1alpha1.NodeFeatureLister
|
Lister() nfdv1alpha1.NodeFeatureLister
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeFeatureInformer struct {
|
type nodeFeatureInformer struct {
|
||||||
|
@ -71,7 +71,7 @@ func NewFilteredNodeFeatureInformer(client versioned.Interface, namespace string
|
||||||
return client.NfdV1alpha1().NodeFeatures(namespace).Watch(context.TODO(), options)
|
return client.NfdV1alpha1().NodeFeatures(namespace).Watch(context.TODO(), options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&nfdv1alpha1.NodeFeature{},
|
&apinfdv1alpha1.NodeFeature{},
|
||||||
resyncPeriod,
|
resyncPeriod,
|
||||||
indexers,
|
indexers,
|
||||||
)
|
)
|
||||||
|
@ -82,9 +82,9 @@ func (f *nodeFeatureInformer) defaultInformer(client versioned.Interface, resync
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *nodeFeatureInformer) Informer() cache.SharedIndexInformer {
|
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 {
|
func (f *nodeFeatureInformer) Lister() nfdv1alpha1.NodeFeatureLister {
|
||||||
return v1alpha1.NewNodeFeatureLister(f.Informer().GetIndexer())
|
return nfdv1alpha1.NewNodeFeatureLister(f.Informer().GetIndexer())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -28,15 +28,15 @@ import (
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
||||||
internalinterfaces "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/internalinterfaces"
|
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/generated/listers/nfd/v1alpha1"
|
||||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureGroupInformer provides access to a shared informer and lister for
|
// NodeFeatureGroupInformer provides access to a shared informer and lister for
|
||||||
// NodeFeatureGroups.
|
// NodeFeatureGroups.
|
||||||
type NodeFeatureGroupInformer interface {
|
type NodeFeatureGroupInformer interface {
|
||||||
Informer() cache.SharedIndexInformer
|
Informer() cache.SharedIndexInformer
|
||||||
Lister() v1alpha1.NodeFeatureGroupLister
|
Lister() nfdv1alpha1.NodeFeatureGroupLister
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeFeatureGroupInformer struct {
|
type nodeFeatureGroupInformer struct {
|
||||||
|
@ -71,7 +71,7 @@ func NewFilteredNodeFeatureGroupInformer(client versioned.Interface, namespace s
|
||||||
return client.NfdV1alpha1().NodeFeatureGroups(namespace).Watch(context.TODO(), options)
|
return client.NfdV1alpha1().NodeFeatureGroups(namespace).Watch(context.TODO(), options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&nfdv1alpha1.NodeFeatureGroup{},
|
&apinfdv1alpha1.NodeFeatureGroup{},
|
||||||
resyncPeriod,
|
resyncPeriod,
|
||||||
indexers,
|
indexers,
|
||||||
)
|
)
|
||||||
|
@ -82,9 +82,9 @@ func (f *nodeFeatureGroupInformer) defaultInformer(client versioned.Interface, r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *nodeFeatureGroupInformer) Informer() cache.SharedIndexInformer {
|
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 {
|
func (f *nodeFeatureGroupInformer) Lister() nfdv1alpha1.NodeFeatureGroupLister {
|
||||||
return v1alpha1.NewNodeFeatureGroupLister(f.Informer().GetIndexer())
|
return nfdv1alpha1.NewNodeFeatureGroupLister(f.Informer().GetIndexer())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
context "context"
|
||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -28,15 +28,15 @@ import (
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
versioned "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned"
|
||||||
internalinterfaces "sigs.k8s.io/node-feature-discovery/api/generated/informers/externalversions/internalinterfaces"
|
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/generated/listers/nfd/v1alpha1"
|
||||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
apinfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureRuleInformer provides access to a shared informer and lister for
|
// NodeFeatureRuleInformer provides access to a shared informer and lister for
|
||||||
// NodeFeatureRules.
|
// NodeFeatureRules.
|
||||||
type NodeFeatureRuleInformer interface {
|
type NodeFeatureRuleInformer interface {
|
||||||
Informer() cache.SharedIndexInformer
|
Informer() cache.SharedIndexInformer
|
||||||
Lister() v1alpha1.NodeFeatureRuleLister
|
Lister() nfdv1alpha1.NodeFeatureRuleLister
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeFeatureRuleInformer struct {
|
type nodeFeatureRuleInformer struct {
|
||||||
|
@ -70,7 +70,7 @@ func NewFilteredNodeFeatureRuleInformer(client versioned.Interface, resyncPeriod
|
||||||
return client.NfdV1alpha1().NodeFeatureRules().Watch(context.TODO(), options)
|
return client.NfdV1alpha1().NodeFeatureRules().Watch(context.TODO(), options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&nfdv1alpha1.NodeFeatureRule{},
|
&apinfdv1alpha1.NodeFeatureRule{},
|
||||||
resyncPeriod,
|
resyncPeriod,
|
||||||
indexers,
|
indexers,
|
||||||
)
|
)
|
||||||
|
@ -81,9 +81,9 @@ func (f *nodeFeatureRuleInformer) defaultInformer(client versioned.Interface, re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *nodeFeatureRuleInformer) Informer() cache.SharedIndexInformer {
|
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 {
|
func (f *nodeFeatureRuleInformer) Lister() nfdv1alpha1.NodeFeatureRuleLister {
|
||||||
return v1alpha1.NewNodeFeatureRuleLister(f.Informer().GetIndexer())
|
return nfdv1alpha1.NewNodeFeatureRuleLister(f.Informer().GetIndexer())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/listers"
|
listers "k8s.io/client-go/listers"
|
||||||
"k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureLister helps list NodeFeatures.
|
// NodeFeatureLister helps list NodeFeatures.
|
||||||
|
@ -30,7 +30,7 @@ import (
|
||||||
type NodeFeatureLister interface {
|
type NodeFeatureLister interface {
|
||||||
// List lists all NodeFeatures in the indexer.
|
// List lists all NodeFeatures in the indexer.
|
||||||
// Objects returned here must be treated as read-only.
|
// 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 returns an object that can list and get NodeFeatures.
|
||||||
NodeFeatures(namespace string) NodeFeatureNamespaceLister
|
NodeFeatures(namespace string) NodeFeatureNamespaceLister
|
||||||
NodeFeatureListerExpansion
|
NodeFeatureListerExpansion
|
||||||
|
@ -38,17 +38,17 @@ type NodeFeatureLister interface {
|
||||||
|
|
||||||
// nodeFeatureLister implements the NodeFeatureLister interface.
|
// nodeFeatureLister implements the NodeFeatureLister interface.
|
||||||
type nodeFeatureLister struct {
|
type nodeFeatureLister struct {
|
||||||
listers.ResourceIndexer[*v1alpha1.NodeFeature]
|
listers.ResourceIndexer[*nfdv1alpha1.NodeFeature]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeFeatureLister returns a new NodeFeatureLister.
|
// NewNodeFeatureLister returns a new NodeFeatureLister.
|
||||||
func NewNodeFeatureLister(indexer cache.Indexer) 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.
|
// NodeFeatures returns an object that can list and get NodeFeatures.
|
||||||
func (s *nodeFeatureLister) NodeFeatures(namespace string) NodeFeatureNamespaceLister {
|
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.
|
// NodeFeatureNamespaceLister helps list and get NodeFeatures.
|
||||||
|
@ -56,15 +56,15 @@ func (s *nodeFeatureLister) NodeFeatures(namespace string) NodeFeatureNamespaceL
|
||||||
type NodeFeatureNamespaceLister interface {
|
type NodeFeatureNamespaceLister interface {
|
||||||
// List lists all NodeFeatures in the indexer for a given namespace.
|
// List lists all NodeFeatures in the indexer for a given namespace.
|
||||||
// Objects returned here must be treated as read-only.
|
// 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.
|
// Get retrieves the NodeFeature from the indexer for a given namespace and name.
|
||||||
// Objects returned here must be treated as read-only.
|
// Objects returned here must be treated as read-only.
|
||||||
Get(name string) (*v1alpha1.NodeFeature, error)
|
Get(name string) (*nfdv1alpha1.NodeFeature, error)
|
||||||
NodeFeatureNamespaceListerExpansion
|
NodeFeatureNamespaceListerExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatureNamespaceLister implements the NodeFeatureNamespaceLister
|
// nodeFeatureNamespaceLister implements the NodeFeatureNamespaceLister
|
||||||
// interface.
|
// interface.
|
||||||
type nodeFeatureNamespaceLister struct {
|
type nodeFeatureNamespaceLister struct {
|
||||||
listers.ResourceIndexer[*v1alpha1.NodeFeature]
|
listers.ResourceIndexer[*nfdv1alpha1.NodeFeature]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/listers"
|
listers "k8s.io/client-go/listers"
|
||||||
"k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureGroupLister helps list NodeFeatureGroups.
|
// NodeFeatureGroupLister helps list NodeFeatureGroups.
|
||||||
|
@ -30,7 +30,7 @@ import (
|
||||||
type NodeFeatureGroupLister interface {
|
type NodeFeatureGroupLister interface {
|
||||||
// List lists all NodeFeatureGroups in the indexer.
|
// List lists all NodeFeatureGroups in the indexer.
|
||||||
// Objects returned here must be treated as read-only.
|
// 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 returns an object that can list and get NodeFeatureGroups.
|
||||||
NodeFeatureGroups(namespace string) NodeFeatureGroupNamespaceLister
|
NodeFeatureGroups(namespace string) NodeFeatureGroupNamespaceLister
|
||||||
NodeFeatureGroupListerExpansion
|
NodeFeatureGroupListerExpansion
|
||||||
|
@ -38,17 +38,17 @@ type NodeFeatureGroupLister interface {
|
||||||
|
|
||||||
// nodeFeatureGroupLister implements the NodeFeatureGroupLister interface.
|
// nodeFeatureGroupLister implements the NodeFeatureGroupLister interface.
|
||||||
type nodeFeatureGroupLister struct {
|
type nodeFeatureGroupLister struct {
|
||||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureGroup]
|
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureGroup]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeFeatureGroupLister returns a new NodeFeatureGroupLister.
|
// NewNodeFeatureGroupLister returns a new NodeFeatureGroupLister.
|
||||||
func NewNodeFeatureGroupLister(indexer cache.Indexer) 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.
|
// NodeFeatureGroups returns an object that can list and get NodeFeatureGroups.
|
||||||
func (s *nodeFeatureGroupLister) NodeFeatureGroups(namespace string) NodeFeatureGroupNamespaceLister {
|
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.
|
// NodeFeatureGroupNamespaceLister helps list and get NodeFeatureGroups.
|
||||||
|
@ -56,15 +56,15 @@ func (s *nodeFeatureGroupLister) NodeFeatureGroups(namespace string) NodeFeature
|
||||||
type NodeFeatureGroupNamespaceLister interface {
|
type NodeFeatureGroupNamespaceLister interface {
|
||||||
// List lists all NodeFeatureGroups in the indexer for a given namespace.
|
// List lists all NodeFeatureGroups in the indexer for a given namespace.
|
||||||
// Objects returned here must be treated as read-only.
|
// 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.
|
// Get retrieves the NodeFeatureGroup from the indexer for a given namespace and name.
|
||||||
// Objects returned here must be treated as read-only.
|
// Objects returned here must be treated as read-only.
|
||||||
Get(name string) (*v1alpha1.NodeFeatureGroup, error)
|
Get(name string) (*nfdv1alpha1.NodeFeatureGroup, error)
|
||||||
NodeFeatureGroupNamespaceListerExpansion
|
NodeFeatureGroupNamespaceListerExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatureGroupNamespaceLister implements the NodeFeatureGroupNamespaceLister
|
// nodeFeatureGroupNamespaceLister implements the NodeFeatureGroupNamespaceLister
|
||||||
// interface.
|
// interface.
|
||||||
type nodeFeatureGroupNamespaceLister struct {
|
type nodeFeatureGroupNamespaceLister struct {
|
||||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureGroup]
|
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureGroup]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/listers"
|
listers "k8s.io/client-go/listers"
|
||||||
"k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
v1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeFeatureRuleLister helps list NodeFeatureRules.
|
// NodeFeatureRuleLister helps list NodeFeatureRules.
|
||||||
|
@ -30,19 +30,19 @@ import (
|
||||||
type NodeFeatureRuleLister interface {
|
type NodeFeatureRuleLister interface {
|
||||||
// List lists all NodeFeatureRules in the indexer.
|
// List lists all NodeFeatureRules in the indexer.
|
||||||
// Objects returned here must be treated as read-only.
|
// 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.
|
// Get retrieves the NodeFeatureRule from the index for a given name.
|
||||||
// Objects returned here must be treated as read-only.
|
// Objects returned here must be treated as read-only.
|
||||||
Get(name string) (*v1alpha1.NodeFeatureRule, error)
|
Get(name string) (*nfdv1alpha1.NodeFeatureRule, error)
|
||||||
NodeFeatureRuleListerExpansion
|
NodeFeatureRuleListerExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeFeatureRuleLister implements the NodeFeatureRuleLister interface.
|
// nodeFeatureRuleLister implements the NodeFeatureRuleLister interface.
|
||||||
type nodeFeatureRuleLister struct {
|
type nodeFeatureRuleLister struct {
|
||||||
listers.ResourceIndexer[*v1alpha1.NodeFeatureRule]
|
listers.ResourceIndexer[*nfdv1alpha1.NodeFeatureRule]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeFeatureRuleLister returns a new NodeFeatureRuleLister.
|
// NewNodeFeatureRuleLister returns a new NodeFeatureRuleLister.
|
||||||
func NewNodeFeatureRuleLister(indexer cache.Indexer) 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 (
|
require (
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
k8s.io/api v0.30.7
|
k8s.io/api v0.30.8
|
||||||
k8s.io/apimachinery v0.30.7
|
k8s.io/apimachinery v0.30.8
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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.8 h1:Y+yZRF3c1WC0MTkLe0qBkiLCquRNa4I21/iDioGMCbo=
|
||||||
k8s.io/api v0.30.7/go.mod h1:bR0EwbmhYmJvUoeza7ZzBUmYCrVXccQ9JOdfv0BxhH0=
|
k8s.io/api v0.30.8/go.mod h1:89IE5MzirZ5HHxU/Hq1/KWGqXkhXClu/FHGesFhQ0A4=
|
||||||
k8s.io/apimachinery v0.30.7 h1:CoQFxvzPFKwU1eJGN/8LgM3ZJBC3hKgvwGqRrL43uIY=
|
k8s.io/apimachinery v0.30.8 h1:9jyTItYzmJc00cBDxZC5ArFNxUeKCwbw0m760iFUMKY=
|
||||||
k8s.io/apimachinery v0.30.7/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
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 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||||
|
|
|
@ -19,5 +19,3 @@ limitations under the License.
|
||||||
// +kubebuilder:object:generate=true
|
// +kubebuilder:object:generate=true
|
||||||
// +groupName=nfd.k8s-sigs.io
|
// +groupName=nfd.k8s-sigs.io
|
||||||
package v1alpha1
|
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.
|
// Features is the collection of all discovered features.
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
type Features struct {
|
type Features struct {
|
||||||
// Flags contains all the flag-type features of the node.
|
// Flags contains all the flag-type features of the node.
|
||||||
// +optional
|
// +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.
|
// Attributes contains all the attribute-type features of the node.
|
||||||
// +optional
|
// +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.
|
// Instances contains all the instance-type features of the node.
|
||||||
// +optional
|
// +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.
|
// FlagFeatureSet is a set of simple features only containing names without values.
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
type FlagFeatureSet struct {
|
type FlagFeatureSet struct {
|
||||||
// Individual features of the feature set.
|
// 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.
|
// AttributeFeatureSet is a set of features having string value.
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
type AttributeFeatureSet struct {
|
type AttributeFeatureSet struct {
|
||||||
// Individual features of the feature set.
|
// 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.
|
// InstanceFeatureSet is a set of features each of which is an instance having multiple attributes.
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
type InstanceFeatureSet struct {
|
type InstanceFeatureSet struct {
|
||||||
// Individual features of the feature set.
|
// 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.
|
// InstanceFeature represents one instance of a complex features, e.g. a device.
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
type InstanceFeature struct {
|
type InstanceFeature struct {
|
||||||
// Attributes of the instance feature.
|
// 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
|
// Nil is a dummy empty struct for protobuf compatibility.
|
||||||
//
|
// NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||||
// +protobuf=true
|
|
||||||
type Nil struct{}
|
type Nil struct{}
|
||||||
|
|
||||||
// NodeFeatureRuleList contains a list of NodeFeatureRule objects.
|
// 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:
|
properties:
|
||||||
elements:
|
elements:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
description: Nil is a dummy empty struct for protobuf
|
description: |-
|
||||||
compatibility
|
Nil is a dummy empty struct for protobuf compatibility.
|
||||||
|
NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||||
type: object
|
type: object
|
||||||
description: Individual features of the feature set.
|
description: Individual features of the feature set.
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -69,8 +69,9 @@ spec:
|
||||||
properties:
|
properties:
|
||||||
elements:
|
elements:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
description: Nil is a dummy empty struct for protobuf
|
description: |-
|
||||||
compatibility
|
Nil is a dummy empty struct for protobuf compatibility.
|
||||||
|
NOTE: protobuf definitions have been removed but this is kept for API compatibility.
|
||||||
type: object
|
type: object
|
||||||
description: Individual features of the feature set.
|
description: Individual features of the feature set.
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: "Feature Gates"
|
title: "Feature Gates"
|
||||||
layout: default
|
layout: default
|
||||||
sort: 10
|
sort: 11
|
||||||
---
|
---
|
||||||
|
|
||||||
# Feature Gates
|
# 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"
|
title: "Versions"
|
||||||
layout: default
|
layout: default
|
||||||
sort: 9
|
sort: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
# Versions and deprecation
|
# 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/go-cmp v0.6.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/jaypipes/ghw v0.13.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/noderesourcetopology-api v0.1.2
|
||||||
github.com/k8stopologyawareschedwg/podfingerprint v0.2.2
|
github.com/k8stopologyawareschedwg/podfingerprint v0.2.2
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9
|
github.com/klauspost/cpuid/v2 v2.2.9
|
||||||
github.com/onsi/ginkgo/v2 v2.22.0
|
github.com/onsi/ginkgo/v2 v2.22.0
|
||||||
github.com/onsi/gomega v1.36.1
|
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/prometheus/client_golang v1.19.1
|
||||||
github.com/smartystreets/goconvey v1.8.1
|
github.com/smartystreets/goconvey v1.8.1
|
||||||
github.com/spf13/cobra 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/net v0.32.0
|
||||||
golang.org/x/time v0.8.0
|
golang.org/x/time v0.8.0
|
||||||
google.golang.org/grpc v1.69.0
|
google.golang.org/grpc v1.69.0
|
||||||
k8s.io/api v0.31.3
|
k8s.io/api v0.32.0
|
||||||
k8s.io/apiextensions-apiserver v0.31.3
|
k8s.io/apiextensions-apiserver v0.32.0
|
||||||
k8s.io/apimachinery v0.31.3
|
k8s.io/apimachinery v0.32.0
|
||||||
k8s.io/client-go v0.31.3
|
k8s.io/client-go v0.32.0
|
||||||
k8s.io/code-generator v0.31.3
|
k8s.io/code-generator v0.32.0
|
||||||
k8s.io/component-base v0.31.3
|
k8s.io/component-base v0.32.0
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
k8s.io/kubectl v0.31.3
|
k8s.io/kubectl v0.32.0
|
||||||
k8s.io/kubelet v0.31.3
|
k8s.io/kubelet v0.32.0
|
||||||
k8s.io/kubernetes v1.31.3
|
k8s.io/kubernetes v1.32.0
|
||||||
k8s.io/pod-security-admission v0.31.3
|
k8s.io/pod-security-admission v0.32.0
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
|
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/node-feature-discovery/api/nfd v0.0.0-00010101000000-000000000000
|
||||||
sigs.k8s.io/yaml v1.4.0
|
sigs.k8s.io/yaml v1.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
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/NYTimes/gziphandler v1.1.1 // indirect
|
||||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||||
github.com/StackExchange/wmi v1.2.1 // 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/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.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-semver v0.3.1 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 // 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/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/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/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // 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/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/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // 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/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/gnostic-models v0.6.8 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // 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/gorilla/websocket v1.5.0 // indirect
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.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/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/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jaypipes/pcidb v1.0.1 // indirect
|
github.com/jaypipes/pcidb v1.0.1 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/jtolds/gls v4.20.0+incompatible // 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/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/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/moby/spdystream v0.4.0 // indirect
|
github.com/moby/spdystream v0.5.0 // indirect
|
||||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||||
github.com/moby/sys/userns v0.1.0 // 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // 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/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/runtime-spec v1.2.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/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // 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/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/smarty/assertions v1.15.1 // indirect
|
github.com/smarty/assertions v1.15.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // 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/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
|
||||||
go.etcd.io/etcd/client/v3 v3.5.14 // 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/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.31.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/otel/trace v1.31.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // 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/crypto v0.31.0 // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.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/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.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
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
howett.net/plist v1.0.0 // indirect
|
howett.net/plist v1.0.0 // indirect
|
||||||
k8s.io/apiserver v0.31.3 // indirect
|
k8s.io/apiserver v0.32.0 // indirect
|
||||||
k8s.io/cloud-provider v0.31.3 // indirect
|
k8s.io/cloud-provider v0.32.0 // indirect
|
||||||
k8s.io/component-helpers v0.31.3 // indirect
|
k8s.io/component-helpers v0.32.0 // indirect
|
||||||
k8s.io/controller-manager v0.31.3 // indirect
|
k8s.io/controller-manager v0.32.0 // indirect
|
||||||
k8s.io/cri-api v0.31.3 // indirect
|
k8s.io/cri-api v0.32.0 // indirect
|
||||||
k8s.io/cri-client v0.0.0 // indirect
|
k8s.io/cri-client v0.0.0 // indirect
|
||||||
k8s.io/csi-translation-lib v0.31.3 // indirect
|
k8s.io/csi-translation-lib v0.32.0 // indirect
|
||||||
k8s.io/dynamic-resource-allocation v0.31.3 // indirect
|
k8s.io/dynamic-resource-allocation v0.32.0 // indirect
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
|
k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 // indirect
|
||||||
k8s.io/kms v0.31.3 // indirect
|
k8s.io/kms v0.32.0 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
|
||||||
k8s.io/mount-utils v0.31.3 // indirect
|
k8s.io/kube-scheduler v0.0.0 // indirect
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
|
k8s.io/mount-utils v0.32.0 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // 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
|
// The k8s "sub-"packages do not have 'semver' compatible versions. Thus, we
|
||||||
// need to override with commits (corresponding their kubernetes-* tags)
|
// need to override with commits (corresponding their kubernetes-* tags)
|
||||||
replace (
|
replace (
|
||||||
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
|
||||||
k8s.io/api => k8s.io/api v0.31.3
|
k8s.io/api => k8s.io/api v0.32.0
|
||||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.31.3
|
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.0
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.31.3
|
k8s.io/apimachinery => k8s.io/apimachinery v0.32.0
|
||||||
k8s.io/apiserver => k8s.io/apiserver v0.31.3
|
k8s.io/apiserver => k8s.io/apiserver v0.32.0
|
||||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.31.3
|
k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.0
|
||||||
k8s.io/client-go => k8s.io/client-go v0.31.3
|
k8s.io/client-go => k8s.io/client-go v0.32.0
|
||||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.31.3
|
k8s.io/cloud-provider => k8s.io/cloud-provider v0.32.0
|
||||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.31.3
|
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.32.0
|
||||||
k8s.io/code-generator => k8s.io/code-generator v0.31.3
|
k8s.io/code-generator => k8s.io/code-generator v0.32.0
|
||||||
k8s.io/component-base => k8s.io/component-base v0.31.3
|
k8s.io/component-base => k8s.io/component-base v0.32.0
|
||||||
k8s.io/component-helpers => k8s.io/component-helpers v0.31.3
|
k8s.io/component-helpers => k8s.io/component-helpers v0.32.0
|
||||||
k8s.io/controller-manager => k8s.io/controller-manager v0.31.3
|
k8s.io/controller-manager => k8s.io/controller-manager v0.32.0
|
||||||
k8s.io/cri-api => k8s.io/cri-api v0.31.3
|
k8s.io/cri-api => k8s.io/cri-api v0.32.0
|
||||||
k8s.io/cri-client => k8s.io/cri-client v0.31.3
|
k8s.io/cri-client => k8s.io/cri-client v0.32.0
|
||||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.31.3
|
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.0
|
||||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.31.3
|
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.0
|
||||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.31.3
|
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.0
|
||||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.31.3
|
k8s.io/kube-proxy => k8s.io/kube-proxy v0.32.0
|
||||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.31.3
|
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.0
|
||||||
k8s.io/kubectl => k8s.io/kubectl v0.31.3
|
k8s.io/kubectl => k8s.io/kubectl v0.32.0
|
||||||
k8s.io/kubelet => k8s.io/kubelet v0.31.3
|
k8s.io/kubelet => k8s.io/kubelet v0.32.0
|
||||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.31.3
|
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.32.0
|
||||||
k8s.io/metrics => k8s.io/metrics v0.31.3
|
k8s.io/metrics => k8s.io/metrics v0.32.0
|
||||||
k8s.io/mount-utils => k8s.io/mount-utils v0.31.3
|
k8s.io/mount-utils => k8s.io/mount-utils v0.32.0
|
||||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.31.3
|
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.0
|
||||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.31.3
|
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.0
|
||||||
sigs.k8s.io/node-feature-discovery/api/nfd => ./api/nfd
|
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 h1:UKkYhof1njT1/xq4SEg5z+VpTgjmNeHwPGRQl7takDI=
|
||||||
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA=
|
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.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
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 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||||
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
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/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 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
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/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
|
||||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI=
|
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
|
||||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
|
||||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
|
||||||
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
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 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
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 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
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/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/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.5 h1:L81NHjquoQmcPgXcttUS9qTSR/+bXry6pbSINQGpjj4=
|
||||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
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.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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
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 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
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=
|
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.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 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
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.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 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
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.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
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 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
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=
|
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/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 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
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 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
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 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
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.51.0 h1:BspqSPdZoLKrnvuZNOvM/KiJ/A+RdixwagN20n+2H8k=
|
||||||
github.com/google/cadvisor v0.49.0/go.mod h1:s6Fqwb2KiWG6leCegVhw4KW40tf9f7m+SF1aXiE8Wsk=
|
github.com/google/cadvisor v0.51.0/go.mod h1:czGE/c/P/i0QFpVNKTFrIEzord9Y10YfpwuaSWXELc0=
|
||||||
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
|
github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g=
|
||||||
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
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 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
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=
|
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 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 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
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 h1:log8MXuB8hzTNnSktqpXMHc0c/2k/WgjOMSUtnI1RV4=
|
||||||
github.com/jaypipes/ghw v0.13.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8=
|
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 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic=
|
||||||
github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4=
|
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/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.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
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 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
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/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 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
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 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/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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
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 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
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=
|
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/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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
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 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
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=
|
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/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 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
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/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||||
github.com/opencontainers/runc v1.2.2/go.mod h1:/PXzF0h531HTMsYQnmxXkBD7YaGShm/2zcRB79dksUc=
|
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 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
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.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
|
||||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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=
|
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/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 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
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 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
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/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 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/smarty/assertions v1.15.1 h1:812oFiXI+G55vxsFf+8bIZ1ux30qtkdqzKbEFwyX3Tk=
|
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/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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
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.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
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.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.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.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 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
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.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.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.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.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.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
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/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 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
|
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 h1:lUVfiMMY/te9icPKBqOKkBIMZNxSpM90dxokDeCcfBg=
|
||||||
github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a/go.mod h1:KUxJS71XlMs+ztT+RzsLRoWUQRUpECo/+Rb0EBk8/Wc=
|
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 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
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-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
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.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/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.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0=
|
go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU=
|
go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E=
|
||||||
go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8=
|
go.etcd.io/etcd/client/v2 v2.305.16 h1:kQrn9o5czVNaukf2A2At43cE9ZtWauOtf9vRZuiKXow=
|
||||||
go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg=
|
go.etcd.io/etcd/client/v2 v2.305.16/go.mod h1:h9YxWCzcdvZENbfzBTFCnoNumr2ax3F19sKMqHFmXHE=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg=
|
go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk=
|
go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50=
|
||||||
go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M=
|
go.etcd.io/etcd/pkg/v3 v3.5.16 h1:cnavs5WSPWeK4TYwPYfmcr3Joz9BH+TZ6qoUtz6/+mc=
|
||||||
go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0=
|
go.etcd.io/etcd/pkg/v3 v3.5.16/go.mod h1:+lutCZHG5MBBFI/U4eYT5yL7sJfnexsoM20Y0t2uNuY=
|
||||||
go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
|
go.etcd.io/etcd/raft/v3 v3.5.16 h1:zBXA3ZUpYs1AwiLGPafYAKKl/CORn/uaxYDwlNwndAk=
|
||||||
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
|
go.etcd.io/etcd/raft/v3 v3.5.16/go.mod h1:P4UP14AxofMJ/54boWilabqqWoW9eLodl6I5GdGzazI=
|
||||||
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
|
go.etcd.io/etcd/server/v3 v3.5.16 h1:d0/SAdJ3vVsZvF8IFVb1k8zqMZ+heGcNfft71ul9GWE=
|
||||||
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
|
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 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/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=
|
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/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 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
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-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
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-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-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-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.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 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
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.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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
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.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
|
||||||
k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
|
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
|
||||||
k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE=
|
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
|
||||||
k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4=
|
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
|
||||||
k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
|
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
|
||||||
k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||||
k8s.io/apiserver v0.31.3 h1:+1oHTtCB+OheqFEz375D0IlzHZ5VeQKX1KGXnx+TTuY=
|
k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs=
|
||||||
k8s.io/apiserver v0.31.3/go.mod h1:PrxVbebxrxQPFhJk4powDISIROkNMKHibTg9lTRQ0Qg=
|
k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag=
|
||||||
k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4=
|
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
|
||||||
k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs=
|
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
|
||||||
k8s.io/cloud-provider v0.31.3 h1:7C3CHQUUwnv/HWWVIaibZH06iPg663RYQ6C6Zy4FnO8=
|
k8s.io/cloud-provider v0.32.0 h1:QXYJGmwME2q2rprymbmw2GroMChQYc/MWN6l/I4Kgp8=
|
||||||
k8s.io/cloud-provider v0.31.3/go.mod h1:c7csKppoVb9Ej6upJ28AvHy4B3BtlRMzXfgezsDdPKw=
|
k8s.io/cloud-provider v0.32.0/go.mod h1:cz3gVodkhgwi2ugj/JUPglIruLSdDaThxawuDyCHfr8=
|
||||||
k8s.io/code-generator v0.31.3 h1:Pj0fYOBms+ZrsulLi4DMsCEx1jG8fWKRLy44onHsLBI=
|
k8s.io/code-generator v0.32.0 h1:s0lNN8VSWny8LBz5t5iy7MCdgwdOhdg7vAGVxvS+VWU=
|
||||||
k8s.io/code-generator v0.31.3/go.mod h1:/umCIlT84g1+Yu5ZXtP1KGSRTnGiIzzX5AzUAxsNlts=
|
k8s.io/code-generator v0.32.0/go.mod h1:b7Q7KMZkvsYFy72A79QYjiv4aTz3GvW0f1T3UfhFq4s=
|
||||||
k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ=
|
k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
|
||||||
k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU=
|
k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
|
||||||
k8s.io/component-helpers v0.31.3 h1:0zGPD2PrekhFWgmz85XxlMEl7dfhlKC1tERZDe3onQc=
|
k8s.io/component-helpers v0.32.0 h1:pQEEBmRt3pDJJX98cQvZshDgJFeKRM4YtYkMmfOlczw=
|
||||||
k8s.io/component-helpers v0.31.3/go.mod h1:HZ1HZx2TKXM7xSUV2cR9L5yDoyZPhhHQNaE3BPBLPUQ=
|
k8s.io/component-helpers v0.32.0/go.mod h1:9RuClQatbClcokXOcDWSzFKQm1huIf0FzQlPRpizlMc=
|
||||||
k8s.io/controller-manager v0.31.3 h1:TyUav69iNYwLGwA96JDhusoZoGRdh1sdrLjXmWTcPgs=
|
k8s.io/controller-manager v0.32.0 h1:tpQl1rvH4huFB6Avl1nhowZHtZoCNWqn6OYdZPl7Ybc=
|
||||||
k8s.io/controller-manager v0.31.3/go.mod h1:yuhec+dbXmBz+4c32kxJxmcauB+1pjO2ttfYODWuv18=
|
k8s.io/controller-manager v0.32.0/go.mod h1:JRuYnYCkKj3NgBTy+KNQKIUm/lJRoDAvGbfdEmk9LhY=
|
||||||
k8s.io/cri-api v0.31.3 h1:dsZXzrGrCEwHjsTDlAV7rutEplpMLY8bfNRMIqrtXjo=
|
k8s.io/cri-api v0.32.0 h1:pzXJfyG7Tm4acrEt5HPqAq3r4cN5guLeapAN/NM2b70=
|
||||||
k8s.io/cri-api v0.31.3/go.mod h1:Po3TMAYH/+KrZabi7QiwQI4a692oZcUOUThd/rqwxrI=
|
k8s.io/cri-api v0.32.0/go.mod h1:DCzMuTh2padoinefWME0G678Mc3QFbLMF2vEweGzBAI=
|
||||||
k8s.io/cri-client v0.31.3 h1:9ZwddaNJomqkTBYQqSmB+Ccns3beY4HyYDwmRtWTCJM=
|
k8s.io/cri-client v0.32.0 h1:K6aTYDyS2AS8O4h79eI5r26562xstdybprtaaszjn+E=
|
||||||
k8s.io/cri-client v0.31.3/go.mod h1:klbWiYkOatOQOkXOYZMZMGSTM8q9eC/efsYGuXcgPes=
|
k8s.io/cri-client v0.32.0/go.mod h1:FB8qZNj8KrwIFfVIR2zBGb+l6KUhrp+k8YFsVp3D+kw=
|
||||||
k8s.io/csi-translation-lib v0.31.3 h1:hxcPRNdtEsk766jCXSKjgH1V8jUNx5tVqdooQ1Ars/M=
|
k8s.io/csi-translation-lib v0.32.0 h1:RAn9RGgYXHJQtDSb6qQ7zvq6QObOejzmsXDARI+f4OQ=
|
||||||
k8s.io/csi-translation-lib v0.31.3/go.mod h1:0B1gQwd868XUIDwJYy5gB2jDXWEwlcWvSsfcQEgzbRk=
|
k8s.io/csi-translation-lib v0.32.0/go.mod h1:TjCJzkTNstdOESAXNnEImrYOMIEzP14aqM7H+vkehqw=
|
||||||
k8s.io/dynamic-resource-allocation v0.31.3 h1:hiQMhyxrm7WA6tWJCLINE2P11Ii3rCVw+YzV3B6+eWo=
|
k8s.io/dynamic-resource-allocation v0.32.0 h1:0ZLSCKzlLZLVwKHxg6vafpd2U8b7jPMO3k8bbMFodis=
|
||||||
k8s.io/dynamic-resource-allocation v0.31.3/go.mod h1:l7OvYDokvnXhFAOhInQUY/z0/HezzmRuLlspld4Xfg4=
|
k8s.io/dynamic-resource-allocation v0.32.0/go.mod h1:MfoAUi0vCJtchNirAVk7c3IYfGGB3n+zbZ9GuyX4eeo=
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
|
k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 h1:si3PfKm8dDYxgfbeA6orqrtLkvvIeH8UqffFJDl0bz4=
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
|
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 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kms v0.31.3 h1:XCFmiJn5CCKs8xoOLpCmu42Ubm/KW85wNHybGFcSAYc=
|
k8s.io/kms v0.32.0 h1:jwOfunHIrcdYl5FRcA+uUKKtg6qiqoPCwmS2T3XTYL4=
|
||||||
k8s.io/kms v0.31.3/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94=
|
k8s.io/kms v0.32.0/go.mod h1:Bk2evz/Yvk0oVrvm4MvZbgq8BD34Ksxs2SRHn4/UiOM=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
|
||||||
k8s.io/kube-scheduler v0.31.3 h1:indE2jtvbwyyEYDrQMjPR2EmnoM1pd4L6cK8r2/KY0I=
|
k8s.io/kube-scheduler v0.32.0 h1:FCsF/3TPvR51ptx/gLUrqcoKqAMhQKrydYCJzPz9VGM=
|
||||||
k8s.io/kube-scheduler v0.31.3/go.mod h1:vhDtABcWycLi8139K5ScOg54WKlbEZJRgtQmLhW0Wjo=
|
k8s.io/kube-scheduler v0.32.0/go.mod h1:yof3vmyx70TWoQ6XZruYEGIUT/r0H/ELGdnWiqPF5EE=
|
||||||
k8s.io/kubectl v0.31.3 h1:3r111pCjPsvnR98oLLxDMwAeM6OPGmPty6gSKaLTQes=
|
k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw=
|
||||||
k8s.io/kubectl v0.31.3/go.mod h1:lhMECDCbJN8He12qcKqs2QfmVo9Pue30geovBVpH5fs=
|
k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE=
|
||||||
k8s.io/kubelet v0.31.3 h1:DIXRAmvVGp42mV2vpA1GCLU6oO8who0/vp3Oq6kSpbI=
|
k8s.io/kubelet v0.32.0 h1:uLyiKlz195Wo4an/K2tyge8o3QHx0ZkhVN3pevvp59A=
|
||||||
k8s.io/kubelet v0.31.3/go.mod h1:KSdbEfNy5VzqUlAHlytA/fH12s+sE1u8fb/8JY9sL/8=
|
k8s.io/kubelet v0.32.0/go.mod h1:lAwuVZT/Hm7EdLn0jW2D+WdrJoorjJL2rVSdhOFnegw=
|
||||||
k8s.io/kubernetes v1.31.3 h1:oqb7HdfnTelrGlZ6ziNugvQ/L/aJWR704114EAhUn9Q=
|
k8s.io/kubernetes v1.32.0 h1:4BDBWSolqPrv8GC3YfZw0CJvh5kA1TPnoX0FxDVd+qc=
|
||||||
k8s.io/kubernetes v1.31.3/go.mod h1:9xmT2buyTYj8TRKwRae7FcuY8k5+xlxv7VivvO0KKfs=
|
k8s.io/kubernetes v1.32.0/go.mod h1:tiIKO63GcdPRBHW2WiUFm3C0eoLczl3f7qi56Dm1W8I=
|
||||||
k8s.io/mount-utils v0.31.3 h1:CANy3prUYvvDCc2X7ZKgpjpDhAidx4gjGh/WwDrCPq8=
|
k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4=
|
||||||
k8s.io/mount-utils v0.31.3/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU=
|
k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0=
|
||||||
k8s.io/pod-security-admission v0.31.3 h1:8NzEV0HtdStX367AuSKfRMIZHn0hT4xuz8xNEf7/zO8=
|
k8s.io/pod-security-admission v0.32.0 h1:I+Og0uZIiMpIgTgPrTbW4jlwRI5RWazi8y+jrx1v10w=
|
||||||
k8s.io/pod-security-admission v0.31.3/go.mod h1:YMIcTe/7f9R9d+3ErCMMM3Wtbj9ejKo7Z9S0OxZQrRg=
|
k8s.io/pod-security-admission v0.32.0/go.mod h1:RvrcY0+5UAoCIJ7BscgDF3nbmXprgfnjTW+byCyXDvA=
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
|
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
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 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
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")
|
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)
|
tc.result(t, res)
|
||||||
assert.Equal(t, tc.output, out)
|
assert.Equal(t, tc.output, out)
|
||||||
tc.err(t, err)
|
tc.err(t, err)
|
||||||
|
@ -183,12 +183,12 @@ baz: { op: Gt, value: ["10"] }
|
||||||
t.Fatal("failed to parse data of test case")
|
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)
|
tc.result(t, res)
|
||||||
assert.Equal(t, tc.output, out)
|
assert.Equal(t, tc.output, out)
|
||||||
tc.err(t, err)
|
tc.err(t, err)
|
||||||
|
|
||||||
res, err = api.MatchValues(mes, tc.input)
|
res, _, err = api.MatchValues(mes, tc.input, true)
|
||||||
tc.result(t, res)
|
tc.result(t, res)
|
||||||
tc.err(t, err)
|
tc.err(t, err)
|
||||||
})
|
})
|
||||||
|
@ -248,12 +248,12 @@ bar: { op: Lt, value: ["10"] }
|
||||||
t.Fatal("failed to parse data of test case")
|
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)
|
assert.Equal(t, tc.output, out)
|
||||||
tc.result(t, res)
|
tc.result(t, res)
|
||||||
tc.err(t, err)
|
tc.err(t, err)
|
||||||
|
|
||||||
res, err = api.MatchInstances(mes, tc.input)
|
res, err = api.MatchInstances(mes, tc.input, true)
|
||||||
tc.result(t, res)
|
tc.result(t, res)
|
||||||
tc.err(t, err)
|
tc.err(t, err)
|
||||||
})
|
})
|
||||||
|
@ -745,7 +745,7 @@ func TestMatchMulti(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
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 {
|
if tc.expectErr {
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,6 +29,13 @@ import (
|
||||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
|
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{}{
|
var matchOps = map[nfdv1alpha1.MatchOp]struct{}{
|
||||||
nfdv1alpha1.MatchAny: {},
|
nfdv1alpha1.MatchAny: {},
|
||||||
nfdv1alpha1.MatchIn: {},
|
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 {
|
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
} else if match {
|
} else if match {
|
||||||
ret = append(ret, MatchedElement{"Name": k})
|
ret = append(ret, MatchedElement{MatchedKeyName: k})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort for reproducible output
|
// 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() {
|
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||||
mk := make([]string, len(ret))
|
mk := make([]string, len(ret))
|
||||||
for i, v := range ret {
|
for i, v := range ret {
|
||||||
mk[i] = v["Name"]
|
mk[i] = v[MatchedKeyName]
|
||||||
}
|
}
|
||||||
mkMsg := strings.Join(mk, ", ")
|
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 {
|
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
} else if match {
|
} else if match {
|
||||||
ret = append(ret, MatchedElement{"Name": k, "Value": v})
|
ret = append(ret, MatchedElement{MatchedKeyName: k, MatchedKeyValue: v})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort for reproducible output
|
// 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() {
|
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||||
mk := make([]string, len(ret))
|
mk := make([]string, len(ret))
|
||||||
for i, v := range ret {
|
for i, v := range ret {
|
||||||
mk[i] = v["Name"]
|
mk[i] = v[MatchedKeyName]
|
||||||
}
|
}
|
||||||
mkMsg := strings.Join(mk, ", ")
|
mkMsg := strings.Join(mk, ", ")
|
||||||
|
|
||||||
|
@ -278,7 +285,7 @@ func MatchInstanceAttributeNames(m *nfdv1alpha1.MatchExpression, instances []nfd
|
||||||
|
|
||||||
// MatchKeys evaluates the MatchExpressionSet against a set of keys.
|
// MatchKeys evaluates the MatchExpressionSet against a set of keys.
|
||||||
func MatchKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, error) {
|
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
|
return matched, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,56 +295,65 @@ type MatchedElement map[string]string
|
||||||
// MatchGetKeys evaluates the MatchExpressionSet against a set of keys and
|
// 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
|
// 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.
|
// MatchExpressionSet returns a match with an empty slice of matched features.
|
||||||
func MatchGetKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, []MatchedElement, error) {
|
func MatchGetKeys(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.Nil) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||||
ret := make([]MatchedElement, 0, len(*m))
|
matchedElements := make([]MatchedElement, 0, len(*m))
|
||||||
|
matchedExpressions := make(nfdv1alpha1.MatchExpressionSet)
|
||||||
|
|
||||||
for n, e := range *m {
|
for n, e := range *m {
|
||||||
match, err := evaluateMatchExpressionKeys(e, n, keys)
|
match, err := evaluateMatchExpressionKeys(e, n, keys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
}
|
}
|
||||||
if !match {
|
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 for reproducible output
|
||||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
sort.Slice(matchedElements, func(i, j int) bool { return matchedElements[i][MatchedKeyName] < matchedElements[j][MatchedKeyName] })
|
||||||
return true, ret, nil
|
return true, matchedElements, &matchedExpressions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchValues evaluates the MatchExpressionSet against a set of key-value pairs.
|
// MatchValues evaluates the MatchExpressionSet against a set of key-value pairs.
|
||||||
func MatchValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string) (bool, error) {
|
func MatchValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string, failFast bool) (bool, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||||
matched, _, err := MatchGetValues(m, values)
|
matched, _, matchedExpressions, err := MatchGetValues(m, values, failFast)
|
||||||
return matched, err
|
return matched, matchedExpressions, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchGetValues evaluates the MatchExpressionSet against a set of key-value
|
// MatchGetValues evaluates the MatchExpressionSet against a set of key-value
|
||||||
// pairs and returns all matched key-value pairs. Note that an empty
|
// pairs and returns all matched key-value pairs. Note that an empty
|
||||||
// MatchExpressionSet returns a match with an empty slice of matched features.
|
// MatchExpressionSet returns a match with an empty slice of matched features.
|
||||||
func MatchGetValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string) (bool, []MatchedElement, error) {
|
func MatchGetValues(m *nfdv1alpha1.MatchExpressionSet, values map[string]string, failFast bool) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||||
ret := make([]MatchedElement, 0, len(*m))
|
matchedElements := make([]MatchedElement, 0, len(*m))
|
||||||
|
matchedExpressions := make(nfdv1alpha1.MatchExpressionSet)
|
||||||
|
isMatch := true
|
||||||
|
|
||||||
for n, e := range *m {
|
for n, e := range *m {
|
||||||
match, err := evaluateMatchExpressionValues(e, n, values)
|
match, err := evaluateMatchExpressionValues(e, n, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
}
|
}
|
||||||
if !match {
|
if match {
|
||||||
return false, nil, nil
|
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 for reproducible output
|
||||||
sort.Slice(ret, func(i, j int) bool { return ret[i]["Name"] < ret[j]["Name"] })
|
sort.Slice(matchedElements, func(i, j int) bool { return matchedElements[i][MatchedKeyName] < matchedElements[j][MatchedKeyName] })
|
||||||
return true, ret, nil
|
return isMatch, matchedElements, &matchedExpressions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchInstances evaluates the MatchExpressionSet against a set of instance
|
// MatchInstances evaluates the MatchExpressionSet against a set of instance
|
||||||
// features, each of which is an individual set of key-value pairs
|
// features, each of which is an individual set of key-value pairs
|
||||||
// (attributes).
|
// (attributes).
|
||||||
func MatchInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature) (bool, error) {
|
func MatchInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature, failFast bool) (bool, error) {
|
||||||
isMatch, _, err := MatchGetInstances(m, instances)
|
isMatch, _, _, err := MatchGetInstances(m, instances, failFast)
|
||||||
return isMatch, err
|
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.
|
// (attributes). Returns a boolean that reports whether the expression matched.
|
||||||
// Also, returns a slice containing all matching instances. An empty (non-nil)
|
// Also, returns a slice containing all matching instances. An empty (non-nil)
|
||||||
// slice is returned if no matching instances were found.
|
// slice is returned if no matching instances were found.
|
||||||
func MatchGetInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature) (bool, []MatchedElement, error) {
|
func MatchGetInstances(m *nfdv1alpha1.MatchExpressionSet, instances []nfdv1alpha1.InstanceFeature, failFast bool) (bool, []MatchedElement, *nfdv1alpha1.MatchExpressionSet, error) {
|
||||||
ret := []MatchedElement{}
|
var (
|
||||||
|
match bool
|
||||||
|
err error
|
||||||
|
expressionSet *nfdv1alpha1.MatchExpressionSet
|
||||||
|
)
|
||||||
|
matchedElements := []MatchedElement{}
|
||||||
|
matchedExpressions := &nfdv1alpha1.MatchExpressionSet{}
|
||||||
|
|
||||||
for _, i := range instances {
|
for _, i := range instances {
|
||||||
if match, err := MatchValues(m, i.Attributes); err != nil {
|
if match, expressionSet, err = MatchValues(m, i.Attributes, failFast); err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
} else if match {
|
} 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
|
// 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.
|
// handled separately as the way of evaluating match expressions is different.
|
||||||
// This function is written to handle "multi-type" features where one feature
|
// This function is written to handle "multi-type" features where one feature
|
||||||
// (say "cpu.cpuid") contains multiple types (flag, attribute and/or instance).
|
// (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{}
|
matchedElems := []MatchedElement{}
|
||||||
|
matchedExpressions := nfdv1alpha1.MatchExpressionSet{}
|
||||||
isMatch := false
|
isMatch := false
|
||||||
|
|
||||||
// Keys and values are handled as a union, it is enough to find a match in
|
// 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 {
|
if keys != nil {
|
||||||
matchK, err = evaluateMatchExpressionKeys(e, n, keys)
|
matchK, err = evaluateMatchExpressionKeys(e, n, keys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
}
|
}
|
||||||
if matchK {
|
if matchK {
|
||||||
matchedElems = append(matchedElems, MatchedElement{"Name": n})
|
matchedElems = append(matchedElems, MatchedElement{MatchedKeyName: n})
|
||||||
|
matchedExpressions[n] = e
|
||||||
} else if e.Op == nfdv1alpha1.MatchDoesNotExist {
|
} 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).
|
// DoesNotExist is special in that both "keys" and "values" should match (i.e. the name is not found in either of them).
|
||||||
isMatch = false
|
isMatch = false
|
||||||
|
if !failFast {
|
||||||
|
continue
|
||||||
|
}
|
||||||
matchedElems = []MatchedElement{}
|
matchedElems = []MatchedElement{}
|
||||||
|
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,39 +432,53 @@ func MatchMulti(m *nfdv1alpha1.MatchExpressionSet, keys map[string]nfdv1alpha1.N
|
||||||
if values != nil {
|
if values != nil {
|
||||||
matchV, err = evaluateMatchExpressionValues(e, n, values)
|
matchV, err = evaluateMatchExpressionValues(e, n, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
}
|
}
|
||||||
if matchV {
|
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 {
|
} 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).
|
// DoesNotExist is special in that both "keys" and "values" should match (i.e. the name is not found in either of them).
|
||||||
isMatch = false
|
isMatch = false
|
||||||
|
if !failFast {
|
||||||
|
continue
|
||||||
|
}
|
||||||
matchedElems = []MatchedElement{}
|
matchedElems = []MatchedElement{}
|
||||||
|
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matchK && !matchV {
|
if !matchK && !matchV {
|
||||||
isMatch = false
|
isMatch = false
|
||||||
|
if !failFast {
|
||||||
|
continue
|
||||||
|
}
|
||||||
matchedElems = []MatchedElement{}
|
matchedElems = []MatchedElement{}
|
||||||
|
matchedExpressions = nfdv1alpha1.MatchExpressionSet{}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort for reproducible output
|
// 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
|
// Instances are handled separately as the logic is fundamentally different
|
||||||
// from keys and values and cannot be combined with them. We want to find
|
// 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
|
// instance(s) that match all match expressions. I.e. the set of all match
|
||||||
// expressions are evaluated against every instance separately.
|
// expressions are evaluated against every instance separately.
|
||||||
ma, me, err := MatchGetInstances(m, instances)
|
ma, melems, mexps, err := MatchGetInstances(m, instances, failFast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, nil, err
|
||||||
}
|
}
|
||||||
isMatch = isMatch || ma
|
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,
|
// 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).
|
// 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) {
|
func MatchNamesMulti(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1.Nil, values map[string]string, instances []nfdv1alpha1.InstanceFeature) (bool, []MatchedElement, error) {
|
||||||
ret := []MatchedElement{}
|
ret := []MatchedElement{}
|
||||||
|
|
||||||
for k := range keys {
|
for k := range keys {
|
||||||
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
} else if match {
|
} 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 {
|
if match, err := evaluateMatchExpression(m, true, k); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
} else if match {
|
} else if match {
|
||||||
ret = append(ret, MatchedElement{"Name": k, "Value": v})
|
ret = append(ret, MatchedElement{MatchedKeyName: k, MatchedKeyValue: v})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort for reproducible output
|
// 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)
|
_, me, err := MatchInstanceAttributeNames(m, instances)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -469,7 +515,7 @@ func MatchNamesMulti(m *nfdv1alpha1.MatchExpression, keys map[string]nfdv1alpha1
|
||||||
if klogV3 := klog.V(3); klogV3.Enabled() {
|
if klogV3 := klog.V(3); klogV3.Enabled() {
|
||||||
mk := make([]string, len(ret))
|
mk := make([]string, len(ret))
|
||||||
for i, v := range ret {
|
for i, v := range ret {
|
||||||
mk[i] = v["Name"]
|
mk[i] = v[MatchedKeyName]
|
||||||
}
|
}
|
||||||
mkMsg := strings.Join(mk, ", ")
|
mkMsg := strings.Join(mk, ", ")
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,31 @@ import (
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
"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.
|
// RuleOutput contains the output out rule execution.
|
||||||
// +k8s:deepcopy-gen=false
|
// +k8s:deepcopy-gen=false
|
||||||
type RuleOutput struct {
|
type RuleOutput struct {
|
||||||
|
@ -39,56 +64,69 @@ type RuleOutput struct {
|
||||||
Annotations map[string]string
|
Annotations map[string]string
|
||||||
Vars map[string]string
|
Vars map[string]string
|
||||||
Taints []corev1.Taint
|
Taints []corev1.Taint
|
||||||
|
MatchStatus *MatchStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the rule against a set of input features.
|
// 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)
|
labels := make(map[string]string)
|
||||||
vars := 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
|
// Logical OR over the matchAny matchers
|
||||||
matched := false
|
var (
|
||||||
|
featureStatus *MatchFeatureStatus
|
||||||
|
matched bool
|
||||||
|
)
|
||||||
for _, matcher := range r.MatchAny {
|
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
|
return RuleOutput{}, err
|
||||||
} else if isMatch {
|
} else if matched {
|
||||||
matched = true
|
isMatch = true
|
||||||
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches))
|
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
|
// there's no need to evaluate other matchers in MatchAny
|
||||||
// if there are no templates to be executed on them - so
|
// if there are no templates to be executed on them - so
|
||||||
// short-circuit and stop on first match here
|
// short-circuit and stop on first match here
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := executeLabelsTemplate(r, matches, labels); err != nil {
|
if err := executeLabelsTemplate(r, featureStatus.MatchedFeatures, labels); err != nil {
|
||||||
return RuleOutput{}, err
|
return RuleOutput{}, err
|
||||||
}
|
}
|
||||||
if err := executeVarsTemplate(r, matches, vars); err != nil {
|
if err := executeVarsTemplate(r, featureStatus.MatchedFeatures, vars); err != nil {
|
||||||
return RuleOutput{}, err
|
return RuleOutput{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
|
||||||
}
|
}
|
||||||
if !matched {
|
|
||||||
|
if !isMatch {
|
||||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
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 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
|
return RuleOutput{}, err
|
||||||
} else if !isMatch {
|
} else if !isMatch {
|
||||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
||||||
return RuleOutput{}, nil
|
return RuleOutput{MatchStatus: &matchStatus}, nil
|
||||||
} else {
|
} else {
|
||||||
klog.V(4).InfoS("matchFeatures matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches))
|
klog.V(4).InfoS("matchFeatures matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matchStatus.MatchedFeatures))
|
||||||
if err := executeLabelsTemplate(r, matches, labels); err != nil {
|
if err := executeLabelsTemplate(r, matchStatus.MatchedFeatures, labels); err != nil {
|
||||||
return RuleOutput{}, err
|
return RuleOutput{}, err
|
||||||
}
|
}
|
||||||
if err := executeVarsTemplate(r, matches, vars); err != nil {
|
if err := executeVarsTemplate(r, matchStatus.MatchedFeatures, vars); err != nil {
|
||||||
return RuleOutput{}, err
|
return RuleOutput{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +134,7 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, e
|
||||||
|
|
||||||
maps.Copy(labels, r.Labels)
|
maps.Copy(labels, r.Labels)
|
||||||
maps.Copy(vars, r.Vars)
|
maps.Copy(vars, r.Vars)
|
||||||
|
matchStatus.IsMatch = true
|
||||||
|
|
||||||
ret := RuleOutput{
|
ret := RuleOutput{
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
|
@ -103,6 +142,7 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features) (RuleOutput, e
|
||||||
Annotations: maps.Clone(r.Annotations),
|
Annotations: maps.Clone(r.Annotations),
|
||||||
ExtendedResources: maps.Clone(r.ExtendedResources),
|
ExtendedResources: maps.Clone(r.ExtendedResources),
|
||||||
Taints: slices.Clone(r.Taints),
|
Taints: slices.Clone(r.Taints),
|
||||||
|
MatchStatus: &matchStatus,
|
||||||
}
|
}
|
||||||
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
|
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
|
||||||
return ret, nil
|
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
|
// ExecuteGroupRule executes the GroupRule against a set of input features, and return true if the
|
||||||
// rule matches.
|
// 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
|
matched := false
|
||||||
if len(r.MatchAny) > 0 {
|
if len(r.MatchAny) > 0 {
|
||||||
// Logical OR over the matchAny matchers
|
// Logical OR over the matchAny matchers
|
||||||
for _, matcher := range r.MatchAny {
|
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
|
return false, err
|
||||||
} else if isMatch {
|
} else if isMatch {
|
||||||
matched = true
|
matched = true
|
||||||
|
@ -131,7 +171,7 @@ func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.MatchFeatures) > 0 {
|
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
|
return false, err
|
||||||
} else if !isMatch {
|
} else if !isMatch {
|
||||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
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
|
type domainMatchedFeatures map[string][]MatchedElement
|
||||||
|
|
||||||
func evaluateMatchAnyElem(e *nfdv1alpha1.MatchAnyElem, features *nfdv1alpha1.Features) (bool, matchedFeatures, error) {
|
func evaluateMatchAnyElem(e *nfdv1alpha1.MatchAnyElem, features *nfdv1alpha1.Features, failFast bool) (bool, *MatchFeatureStatus, error) {
|
||||||
return evaluateFeatureMatcher(&e.MatchFeatures, features)
|
return evaluateFeatureMatcher(&e.MatchFeatures, features, failFast)
|
||||||
}
|
}
|
||||||
|
|
||||||
func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1.Features) (bool, matchedFeatures, error) {
|
func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1.Features, failFast bool) (bool, *MatchFeatureStatus, error) {
|
||||||
matches := make(matchedFeatures, len(*m))
|
var (
|
||||||
|
isMatch = true
|
||||||
|
isTermMatch = true
|
||||||
|
)
|
||||||
|
status := &MatchFeatureStatus{
|
||||||
|
MatchedFeatures: make(matchedFeatures, len(*m)),
|
||||||
|
}
|
||||||
|
|
||||||
// Logical AND over the terms
|
// Logical AND over the terms
|
||||||
for _, term := range *m {
|
for _, term := range *m {
|
||||||
|
@ -207,14 +253,17 @@ func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1
|
||||||
|
|
||||||
dom := nameSplit[0]
|
dom := nameSplit[0]
|
||||||
nam := nameSplit[1]
|
nam := nameSplit[1]
|
||||||
if _, ok := matches[dom]; !ok {
|
if _, ok := status.MatchedFeatures[dom]; !ok {
|
||||||
matches[dom] = make(domainMatchedFeatures)
|
status.MatchedFeatures[dom] = make(domainMatchedFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMatch = true
|
|
||||||
var matchedElems []MatchedElement
|
var matchedElems []MatchedElement
|
||||||
|
var matchedExpressions *nfdv1alpha1.MatchExpressionSet
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
matchedFeatureTerm := nfdv1alpha1.FeatureMatcherTerm{
|
||||||
|
Feature: featureName,
|
||||||
|
}
|
||||||
fF, okF := features.Flags[featureName]
|
fF, okF := features.Flags[featureName]
|
||||||
fA, okA := features.Attributes[featureName]
|
fA, okA := features.Attributes[featureName]
|
||||||
fI, okI := features.Instances[featureName]
|
fI, okI := features.Instances[featureName]
|
||||||
|
@ -224,24 +273,37 @@ func evaluateFeatureMatcher(m *nfdv1alpha1.FeatureMatcher, features *nfdv1alpha1
|
||||||
}
|
}
|
||||||
|
|
||||||
if term.MatchExpressions != nil {
|
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
|
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...)
|
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 {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
} else if !isMatch {
|
} else if !isTermMatch {
|
||||||
return false, nil, nil
|
if !failFast {
|
||||||
|
isMatch = false
|
||||||
|
} else {
|
||||||
|
return false, status, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true, matches, nil
|
return isMatch, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type templateHelper struct {
|
type templateHelper struct {
|
||||||
|
|
|
@ -49,11 +49,11 @@ func TestRule(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test totally empty features
|
// Test totally empty features
|
||||||
m, err := Execute(r1, f)
|
m, err := Execute(r1, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
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.NoError(t, err, "matching against a missing feature should not have returned an error")
|
||||||
assert.Empty(t, m.Labels)
|
assert.Empty(t, m.Labels)
|
||||||
assert.Empty(t, m.Vars)
|
assert.Empty(t, m.Vars)
|
||||||
|
@ -61,12 +61,12 @@ func TestRule(t *testing.T) {
|
||||||
// Test properly initialized empty features
|
// Test properly initialized empty features
|
||||||
f = nfdv1alpha1.NewFeatures()
|
f = nfdv1alpha1.NewFeatures()
|
||||||
|
|
||||||
m, err = Execute(r1, f)
|
m, err = Execute(r1, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
||||||
assert.Empty(t, r1.Vars, "vars should be empty")
|
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.NoError(t, err, "matching against a missing feature should not have returned an error")
|
||||||
assert.Empty(t, m.Labels)
|
assert.Empty(t, m.Labels)
|
||||||
assert.Empty(t, m.Vars)
|
assert.Empty(t, m.Vars)
|
||||||
|
@ -76,11 +76,11 @@ func TestRule(t *testing.T) {
|
||||||
f.Attributes["domain-1.vf-1"] = nfdv1alpha1.NewAttributeFeatures(nil)
|
f.Attributes["domain-1.vf-1"] = nfdv1alpha1.NewAttributeFeatures(nil)
|
||||||
f.Instances["domain-1.if-1"] = nfdv1alpha1.NewInstanceFeatures()
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "unexpected match")
|
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.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"}))
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m.Labels, "empty matcher should have matched empty features")
|
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{},
|
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
m, err = Execute(r1, f)
|
m, err = Execute(r1, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m.Labels, "empty match expression set mathces anything")
|
assert.Equal(t, r1.Labels, m.Labels, "empty match expression set mathces anything")
|
||||||
|
|
||||||
// Match "key" features
|
// Match "key" features
|
||||||
m, err = Execute(r2, f)
|
m, err = Execute(r2, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "keys should not have matched")
|
assert.Nil(t, m.Labels, "keys should not have matched")
|
||||||
|
|
||||||
f.Flags["domain-1.kf-1"].Elements["key-1"] = nfdv1alpha1.Nil{}
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r2.Labels, m.Labels, "keys should have matched")
|
assert.Equal(t, r2.Labels, m.Labels, "keys should have matched")
|
||||||
assert.Equal(t, r2.Vars, m.Vars, "vars should be present")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "values should not have matched")
|
assert.Nil(t, m.Labels, "values should not have matched")
|
||||||
|
|
||||||
f.Attributes["domain-1.vf-1"].Elements["key-1"] = "val-1"
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "values should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
assert.Nil(t, m.Labels, "instances should not have matched")
|
||||||
|
|
||||||
f.Instances["domain-1.if-1"].Elements[0].Attributes["attr-1"] = "val-1"
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "key in multi-type feature should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "attribute in multi-type feature should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "attribute in multi-type feature should have matched")
|
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.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")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "features in multi-type feature should have matched instance")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
assert.Nil(t, m.Labels, "instances should not have matched")
|
||||||
|
|
||||||
(*r3.MatchFeatures[0].MatchExpressions)["key-1"] = newMatchExpression(nfdv1alpha1.MatchIn, "val-1")
|
(*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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m.Labels, "instances should not have matched")
|
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")
|
(*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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
assert.Equal(t, r3.Labels, m.Labels, "instances should have matched")
|
||||||
}
|
}
|
||||||
|
@ -437,12 +437,12 @@ var-2=
|
||||||
"kf-foo": "true",
|
"kf-foo": "true",
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := Execute(r1, f)
|
m, err := Execute(r1, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||||
assert.Equal(t, expectedVars, m.Vars, "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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||||
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
||||||
|
@ -468,7 +468,7 @@ var-2=
|
||||||
"mf-key-d": "found",
|
"mf-key-d": "found",
|
||||||
}
|
}
|
||||||
expectedVars = map[string]string{}
|
expectedVars = map[string]string{}
|
||||||
m, err = Execute(r3, f)
|
m, err = Execute(r3, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
||||||
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
|
||||||
|
@ -490,32 +490,32 @@ var-2=
|
||||||
}
|
}
|
||||||
|
|
||||||
r2.LabelsTemplate = "foo=bar"
|
r2.LabelsTemplate = "foo=bar"
|
||||||
m, err = Execute(r2, f)
|
m, err = Execute(r2, f, true)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, map[string]string{"foo": "bar"}, m.Labels, "instances should have matched")
|
assert.Equal(t, map[string]string{"foo": "bar"}, m.Labels, "instances should have matched")
|
||||||
assert.Empty(t, m.Vars)
|
assert.Empty(t, m.Vars)
|
||||||
|
|
||||||
r2.LabelsTemplate = "foo"
|
r2.LabelsTemplate = "foo"
|
||||||
_, err = Execute(r2, f)
|
_, err = Execute(r2, f, true)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
r2.LabelsTemplate = "{{"
|
r2.LabelsTemplate = "{{"
|
||||||
_, err = Execute(r2, f)
|
_, err = Execute(r2, f, true)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
r2.LabelsTemplate = ""
|
r2.LabelsTemplate = ""
|
||||||
r2.VarsTemplate = "bar=baz"
|
r2.VarsTemplate = "bar=baz"
|
||||||
m, err = Execute(r2, f)
|
m, err = Execute(r2, f, true)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Empty(t, m.Labels)
|
assert.Empty(t, m.Labels)
|
||||||
assert.Equal(t, map[string]string{"bar": "baz"}, m.Vars, "instances should have matched")
|
assert.Equal(t, map[string]string{"bar": "baz"}, m.Vars, "instances should have matched")
|
||||||
|
|
||||||
r2.VarsTemplate = "bar"
|
r2.VarsTemplate = "bar"
|
||||||
_, err = Execute(r2, f)
|
_, err = Execute(r2, f, true)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
r2.VarsTemplate = "{{"
|
r2.VarsTemplate = "{{"
|
||||||
_, err = Execute(r2, f)
|
_, err = Execute(r2, f, true)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -539,7 +539,7 @@ var-2=
|
||||||
"key-5": "",
|
"key-5": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err = Execute(r4, f)
|
m, err = Execute(r4, f, true)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
|
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.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, map[string]string(nil), m.Labels, "instances should have matched")
|
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 {
|
for _, rule := range nodeFeatureRule.Spec.Rules {
|
||||||
fmt.Println("Processing rule: ", rule.Name)
|
fmt.Println("Processing rule: ", rule.Name)
|
||||||
ruleOut, err := nodefeaturerule.Execute(&rule, &nodeFeature.Features)
|
ruleOut, err := nodefeaturerule.Execute(&rule, &nodeFeature.Features, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, fmt.Errorf("failed to process rule: %q - %w", rule.Name, err))
|
errs = append(errs, fmt.Errorf("failed to process rule: %q - %w", rule.Name, err))
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -794,7 +794,7 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
|
||||||
nodeGroupValidator := make(map[string]bool)
|
nodeGroupValidator := make(map[string]bool)
|
||||||
for _, rule := range nodeFeatureGroup.Spec.Rules {
|
for _, rule := range nodeFeatureGroup.Spec.Rules {
|
||||||
for _, feature := range nodeFeaturesList {
|
for _, feature := range nodeFeaturesList {
|
||||||
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features)
|
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
|
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
|
||||||
continue
|
continue
|
||||||
|
@ -1018,7 +1018,7 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha
|
||||||
klog.InfoS("executing NodeFeatureRule", "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
klog.InfoS("executing NodeFeatureRule", "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
||||||
}
|
}
|
||||||
for _, rule := range spec.Spec.Rules {
|
for _, rule := range spec.Spec.Rules {
|
||||||
ruleOut, err := nodefeaturerule.Execute(&rule, features)
|
ruleOut, err := nodefeaturerule.Execute(&rule, features, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "failed to process rule", "ruleName", rule.Name, "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
klog.ErrorS(err, "failed to process rule", "ruleName", rule.Name, "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName)
|
||||||
nfrProcessingErrors.Inc()
|
nfrProcessingErrors.Inc()
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) {
|
||||||
klog.V(2).InfoS("resolving custom features", "configuration", utils.DelayedDumper(allFeatureConfig))
|
klog.V(2).InfoS("resolving custom features", "configuration", utils.DelayedDumper(allFeatureConfig))
|
||||||
// Iterate over features
|
// Iterate over features
|
||||||
for _, rule := range allFeatureConfig {
|
for _, rule := range allFeatureConfig {
|
||||||
ruleOut, err := nodefeaturerule.Execute(&rule, features)
|
ruleOut, err := nodefeaturerule.Execute(&rule, features, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "failed to execute rule")
|
klog.ErrorS(err, "failed to execute rule")
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Add table
Reference in a new issue