Skip to content

Commit

Permalink
Merge pull request #212 from openshift-kni/resync-20240624
Browse files Browse the repository at this point in the history
[KNI] resync 20240624
  • Loading branch information
openshift-merge-bot[bot] authored Jun 24, 2024
2 parents 115d656 + 74a4760 commit 6833e49
Show file tree
Hide file tree
Showing 21 changed files with 1,035 additions and 289 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ update-vendor:

.PHONY: unit-test
unit-test: install-envtest
hack/unit-test.sh
hack/unit-test.sh $(ARGS)

.PHONY: install-envtest
install-envtest:
Expand Down
1 change: 1 addition & 0 deletions RESYNC.log.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
| Resync Date | Merge With Upstream Tag/Commit | Author |
|-------------|------------------------------------------------------------------------------------------------------|-------------|
| 2024.06.24 | https://github.com/kubernetes-sigs/scheduler-plugins/commit/2c1c0cfe6134c5d55a23dae1726264664a943f4b | ffromani |
| 2024.05.29 | https://github.com/kubernetes-sigs/scheduler-plugins/commit/0834feb92676712cebe8290615ce1c47537fe078 | ffromani |
| 2024.05.07 | https://github.com/kubernetes-sigs/scheduler-plugins/commit/70981813a19f16c4202f6f74a2525bf917b63685 | ffromani |
| 2024.01.29 | https://github.com/kubernetes-sigs/scheduler-plugins/commit/93c518b7350fdba82238daa559cb0c11a9353e87 | ffromani |
Expand Down
14 changes: 14 additions & 0 deletions apis/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ const (
CacheInformerDedicated CacheInformerMode = "Dedicated"
)

// CacheResyncScope is a "string" type
type CacheResyncScope string

const (
CacheResyncScopeAll CacheResyncScope = "All"
CacheResyncScopeOnlyResources CacheResyncScope = "OnlyResources"
)

// NodeResourceTopologyCache define configuration details for the NodeResourceTopology cache.
type NodeResourceTopologyCache struct {
// ForeignPodsDetect sets how foreign pods should be handled.
Expand All @@ -205,6 +213,12 @@ type NodeResourceTopologyCache struct {
// guaranteed to best suit the cache needs, at cost of one extra connection.
// If unspecified, default is "Dedicated"
InformerMode *CacheInformerMode
// ResyncScope controls which changes the resync logic monitors to trigger an update.
// "All" consider both Attributes (metadata, node config details) and per-NUMA resources,
// while "OnlyResources" consider only per-NUMA resource values. The default is
// "All" to make the code react to node config changes avoiding reboots.
// Use "OnlyResources" to restore the previous behavior.
ResyncScope *CacheResyncScope
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
14 changes: 14 additions & 0 deletions apis/config/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ const (
CacheInformerDedicated CacheInformerMode = "Dedicated"
)

// CacheResyncScope is a "string" type
type CacheResyncScope string

const (
CacheResyncScopeAll CacheResyncScope = "All"
CacheResyncScopeOnlyResources CacheResyncScope = "OnlyResources"
)

// NodeResourceTopologyCache define configuration details for the NodeResourceTopology cache.
type NodeResourceTopologyCache struct {
// ForeignPodsDetect sets how foreign pods should be handled.
Expand All @@ -203,6 +211,12 @@ type NodeResourceTopologyCache struct {
// guaranteed to best suit the cache needs, at cost of one extra connection.
// If unspecified, default is "Dedicated"
InformerMode *CacheInformerMode `json:"informerMode,omitempty"`
// ResyncScope controls which changes the resync logic monitors to trigger an update.
// "All" consider both Attributes (metadata, node config details) and per-NUMA resources,
// while "OnlyResources" consider only per-NUMA resource values. The default is
// "All" to make the code react to node config changes avoiding reboots.
// Use "OnlyResources" to restore the previous behavior.
ResyncScope *CacheResyncScope `json:"resyncScope,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
6 changes: 4 additions & 2 deletions hack/unit-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ kube::log::status "Configuring envtest"
TEMP_DIR=${TMPDIR-/tmp}
source "${TEMP_DIR}/setup-envtest"

# TODO: make args customizable.
go test -mod=vendor \
# get the args to pass to go test
ARGS=("$@")

go test "${ARGS[@]}" -mod=vendor \
sigs.k8s.io/scheduler-plugins/cmd/... \
sigs.k8s.io/scheduler-plugins/pkg/... \
sigs.k8s.io/scheduler-plugins/apis/...
30 changes: 14 additions & 16 deletions hack/update-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,20 @@ GOBIN=${TOOLS_BIN_DIR} ${GO_INSTALL} sigs.k8s.io/controller-tools/cmd/controller

CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}

bash "${CODEGEN_PKG}"/generate-internal-groups.sh \
"deepcopy,conversion,defaulter" \
sigs.k8s.io/scheduler-plugins/pkg/generated \
sigs.k8s.io/scheduler-plugins/apis \
sigs.k8s.io/scheduler-plugins/apis \
"config:v1" \
--trim-path-prefix sigs.k8s.io/scheduler-plugins \
--output-base "./" \
--go-header-file "${SCRIPT_ROOT}"/hack/boilerplate/boilerplate.generatego.txt

bash "${CODEGEN_PKG}"/generate-groups.sh \
all \
sigs.k8s.io/scheduler-plugins/pkg/generated \
sigs.k8s.io/scheduler-plugins/apis \
"scheduling:v1alpha1" \
--go-header-file "${SCRIPT_ROOT}"/hack/boilerplate/boilerplate.generatego.txt
source "${CODEGEN_PKG}/kube_codegen.sh"

kube::codegen::gen_helpers \
--input-pkg-root sigs.k8s.io/scheduler-plugins/apis \
--output-base "../../" \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate/boilerplate.generatego.txt"

kube::codegen::gen_client \
--with-watch \
--with-applyconfig \
--input-pkg-root sigs.k8s.io/scheduler-plugins/apis \
--output-base "../../" \
--output-pkg-root sigs.k8s.io/scheduler-plugins/pkg/generated \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate/boilerplate.generatego.txt"

${CONTROLLER_GEN} object:headerFile="hack/boilerplate/boilerplate.generatego.txt" \
paths="./apis/scheduling/..."
Expand Down
99 changes: 99 additions & 0 deletions pkg/noderesourcetopology/cache/attr_watch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
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 cache

import (
"context"

"github.com/go-logr/logr"

"k8s.io/apimachinery/pkg/watch"

ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"

topologyv1alpha2 "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha2"

"sigs.k8s.io/scheduler-plugins/pkg/noderesourcetopology/logging"
"sigs.k8s.io/scheduler-plugins/pkg/noderesourcetopology/nodeconfig"
)

type Watcher struct {
lh logr.Logger
nrts *nrtStore
nodes counter
}

func (wt Watcher) NodeResourceTopologies(ctx context.Context, client ctrlclient.WithWatch) {
done := false
for !done {
wt.lh.Info("start watching NRT objects")

nrtObjs := topologyv1alpha2.NodeResourceTopologyList{}
wa, err := client.Watch(ctx, &nrtObjs)
if err != nil {
wt.lh.Error(err, "cannot watch NRT objects")
return
}

for !done {
select {
case ev := <-wa.ResultChan():
wt.ProcessEvent(ev)

case <-ctx.Done():
wt.lh.Info("stop watching NRT objects")
wa.Stop()
done = true
}
}

wt.lh.Info("done watching NRT objects")
}
}

func (wt Watcher) ProcessEvent(ev watch.Event) bool {
if ev.Type != watch.Modified {
return false
}

nrtObj, ok := ev.Object.(*topologyv1alpha2.NodeResourceTopology)
if !ok {
wt.lh.Info("unexpected object %T", ev.Object)
return false
}

nrtCur := wt.nrts.GetNRTCopyByNodeName(nrtObj.Name)
if nrtCur == nil {
wt.lh.Info("modified non-existent NRT", logging.KeyNode, nrtObj.Name)
return false
}

if !areAttrsChanged(nrtCur, nrtObj) {
return false
}

wt.lh.V(4).Info("attribute change", logging.KeyNode, nrtObj.Name)
wt.nodes.Incr(nrtObj.Name)
return true
}

func areAttrsChanged(oldNrt, newNrt *topologyv1alpha2.NodeResourceTopology) bool {
lh := logr.Discard() // avoid spam in the logs
oldConf := nodeconfig.TopologyManagerFromNodeResourceTopology(lh, oldNrt)
newConf := nodeconfig.TopologyManagerFromNodeResourceTopology(lh, newNrt)
return !oldConf.Equal(newConf)
}
153 changes: 153 additions & 0 deletions pkg/noderesourcetopology/cache/attr_watch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
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 cache

import (
"reflect"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"

"k8s.io/klog/v2"

topologyv1alpha2 "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha2"
)

func TestWatcherProcessEvent(t *testing.T) {
nrts := []topologyv1alpha2.NodeResourceTopology{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node-0",
},
Attributes: []topologyv1alpha2.AttributeInfo{
{
Name: "topologyManagerScope",
Value: "pod",
},
{
Name: "topologyManagerPolicy",
Value: "restricted",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "node-1",
},
Attributes: []topologyv1alpha2.AttributeInfo{
{
Name: "topologyManagerScope",
Value: "container",
},
{
Name: "topologyManagerPolicy",
Value: "single-numa-node",
},
},
},
}

tcases := []struct {
description string
ev watch.Event
expected []string
}{
{
description: "irrelevant object",
ev: watch.Event{
Type: watch.Added,
Object: &topologyv1alpha2.NodeResourceTopology{
ObjectMeta: metav1.ObjectMeta{
Name: "node-7",
},
Attributes: []topologyv1alpha2.AttributeInfo{
{
Name: "topologyManagerScope",
Value: "container",
},
{
Name: "topologyManagerPolicy",
Value: "single-numa-node",
},
},
},
},
expected: []string{},
},
{
description: "scope change",
ev: watch.Event{
Type: watch.Modified,
Object: &topologyv1alpha2.NodeResourceTopology{
ObjectMeta: metav1.ObjectMeta{
Name: "node-0",
},
Attributes: []topologyv1alpha2.AttributeInfo{
{
Name: "topologyManagerScope",
Value: "container",
},
{
Name: "topologyManagerPolicy",
Value: "restricted",
},
},
},
},
expected: []string{"node-0"},
},
{
description: "all attr change",
ev: watch.Event{
Type: watch.Modified,
Object: &topologyv1alpha2.NodeResourceTopology{
ObjectMeta: metav1.ObjectMeta{
Name: "node-0",
},
Attributes: []topologyv1alpha2.AttributeInfo{
{
Name: "topologyManagerScope",
Value: "container",
},
{
Name: "topologyManagerPolicy",
Value: "single-numa-node",
},
},
},
},
expected: []string{"node-0"},
},
}

wt := Watcher{
lh: klog.Background(),
nrts: newNrtStore(klog.Background(), nrts),
nodes: newCounter(),
}

for _, tcase := range tcases {
t.Run(tcase.description, func(t *testing.T) {
wt.ProcessEvent(tcase.ev)
got := wt.nodes.Keys()
if !reflect.DeepEqual(got, tcase.expected) {
t.Errorf("got=%+v expected=%+v", got, tcase.expected)
}
})
}
}
2 changes: 1 addition & 1 deletion pkg/noderesourcetopology/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type testCaseGetCachedNRTCopy struct {
expectedOK bool
}

func checkGetCachedNRTCopy(t *testing.T, makeCache func(client ctrlclient.Client, podLister podlisterv1.PodLister) (Interface, error), extraCases ...testCaseGetCachedNRTCopy) {
func checkGetCachedNRTCopy(t *testing.T, makeCache func(client ctrlclient.WithWatch, podLister podlisterv1.PodLister) (Interface, error), extraCases ...testCaseGetCachedNRTCopy) {
t.Helper()

testNodeName := "worker-node-1"
Expand Down
2 changes: 1 addition & 1 deletion pkg/noderesourcetopology/cache/discardreserved_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestDiscardReservedNodesGetCachedNRTCopy(t *testing.T) {

checkGetCachedNRTCopy(
t,
func(client ctrlclient.Client, _ podlisterv1.PodLister) (Interface, error) {
func(client ctrlclient.WithWatch, _ podlisterv1.PodLister) (Interface, error) {
return NewDiscardReserved(klog.Background(), client), nil
},
testCases...,
Expand Down
Loading

0 comments on commit 6833e49

Please sign in to comment.