From 719a49cc13fb8c69fef158b985f7059ec6a59ec8 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Tue, 25 Jun 2024 14:35:12 +0200 Subject: [PATCH] scheduler: fix klog.KObjSlice when applied to []*NodeInfo The DRA plugin does that. It didn't actually work and only printed an error message about NodeInfo not implementing klog.KMetata. That's not a compile-time check due to limitations with Go generics and had been missed earlier. --- pkg/scheduler/framework/types.go | 15 +++++++++++++++ pkg/scheduler/framework/types_test.go | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/scheduler/framework/types.go b/pkg/scheduler/framework/types.go index 24ee01868b9..d066059276f 100644 --- a/pkg/scheduler/framework/types.go +++ b/pkg/scheduler/framework/types.go @@ -591,6 +591,21 @@ type NodeInfo struct { Generation int64 } +// NodeInfo implements KMetadata, so for example klog.KObjSlice(nodes) works +// when nodes is a []*NodeInfo. +var _ klog.KMetadata = &NodeInfo{} + +func (n *NodeInfo) GetName() string { + if n == nil { + return "" + } + if n.node == nil { + return "" + } + return n.node.Name +} +func (n *NodeInfo) GetNamespace() string { return "" } + // nextGeneration: Let's make sure history never forgets the name... // Increments the generation number monotonically ensuring that generation numbers never collide. // Collision of the generation numbers would be particularly problematic if a node was deleted and diff --git a/pkg/scheduler/framework/types_test.go b/pkg/scheduler/framework/types_test.go index 55e2f3e1ed1..b0dcae7fc2c 100644 --- a/pkg/scheduler/framework/types_test.go +++ b/pkg/scheduler/framework/types_test.go @@ -19,6 +19,7 @@ package framework import ( "fmt" "reflect" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -29,9 +30,11 @@ import ( "k8s.io/apimachinery/pkg/util/sets" utilfeature "k8s.io/apiserver/pkg/util/feature" featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/features" st "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/test/utils/ktesting" + "k8s.io/kubernetes/test/utils/ktesting/initoption" ) func TestNewResource(t *testing.T) { @@ -1657,3 +1660,17 @@ func TestCloudEvent_Match(t *testing.T) { }) } } + +func TestNodeInfoKMetadata(t *testing.T) { + tCtx := ktesting.Init(t, initoption.BufferLogs(true)) + logger := tCtx.Logger() + logger.Info("Some NodeInfo slice", "nodes", klog.KObjSlice([]*NodeInfo{nil, {}, {node: &v1.Node{}}, {node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "worker"}}}})) + + output := logger.GetSink().(ktesting.Underlier).GetBuffer().String() + + // The initial nil entry gets turned into empty ObjectRef by klog, + // which becomes an empty string during output formatting. + if !strings.Contains(output, `Some NodeInfo slice nodes=["","","","worker"]`) { + tCtx.Fatalf("unexpected output:\n%s", output) + } +}