mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	bug(quota): handle ResourcesChanged on resource quota filter
This commit is contained in:
		@@ -18,7 +18,11 @@ package install
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
						"k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
 | 
						podutil "k8s.io/kubernetes/pkg/api/v1/pod"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/quota/v1/evaluator/core"
 | 
						"k8s.io/kubernetes/pkg/quota/v1/evaluator/core"
 | 
				
			||||||
	"k8s.io/utils/clock"
 | 
						"k8s.io/utils/clock"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -30,6 +34,10 @@ func DefaultUpdateFilter() func(resource schema.GroupVersionResource, oldObj, ne
 | 
				
			|||||||
		case schema.GroupResource{Resource: "pods"}:
 | 
							case schema.GroupResource{Resource: "pods"}:
 | 
				
			||||||
			oldPod := oldObj.(*v1.Pod)
 | 
								oldPod := oldObj.(*v1.Pod)
 | 
				
			||||||
			newPod := newObj.(*v1.Pod)
 | 
								newPod := newObj.(*v1.Pod)
 | 
				
			||||||
 | 
								// when Resources changed
 | 
				
			||||||
 | 
								if feature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && hasResourcesChanged(oldPod, newPod) {
 | 
				
			||||||
 | 
									return true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return core.QuotaV1Pod(oldPod, clock.RealClock{}) && !core.QuotaV1Pod(newPod, clock.RealClock{})
 | 
								return core.QuotaV1Pod(oldPod, clock.RealClock{}) && !core.QuotaV1Pod(newPod, clock.RealClock{})
 | 
				
			||||||
		case schema.GroupResource{Resource: "services"}:
 | 
							case schema.GroupResource{Resource: "services"}:
 | 
				
			||||||
			oldService := oldObj.(*v1.Service)
 | 
								oldService := oldObj.(*v1.Service)
 | 
				
			||||||
@@ -44,3 +52,20 @@ func DefaultUpdateFilter() func(resource schema.GroupVersionResource, oldObj, ne
 | 
				
			|||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// hasResourcesChanged function to compare resources in container statuses
 | 
				
			||||||
 | 
					func hasResourcesChanged(oldPod *v1.Pod, newPod *v1.Pod) bool {
 | 
				
			||||||
 | 
						for _, oldStatus := range oldPod.Status.ContainerStatuses {
 | 
				
			||||||
 | 
							newStatus, ok := podutil.GetContainerStatus(newPod.Status.ContainerStatuses, oldStatus.Name)
 | 
				
			||||||
 | 
							if ok && !apiequality.Semantic.DeepEqual(oldStatus.Resources, newStatus.Resources) {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, oldInitContainerStatus := range oldPod.Status.InitContainerStatuses {
 | 
				
			||||||
 | 
							newInitContainerStatus, ok := podutil.GetContainerStatus(newPod.Status.InitContainerStatuses, oldInitContainerStatus.Name)
 | 
				
			||||||
 | 
							if ok && !apiequality.Semantic.DeepEqual(oldInitContainerStatus.Resources, newInitContainerStatus.Resources) {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										141
									
								
								pkg/quota/v1/install/update_filter_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								pkg/quota/v1/install/update_filter_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/api/resource"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						containerFoo = v1.Container{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Name: "foo",
 | 
				
			||||||
 | 
							Resources: v1.ResourceRequirements{
 | 
				
			||||||
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
 | 
									v1.ResourceCPU: resource.MustParse("2"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						containerFooInitialStatus = v1.ContainerStatus{
 | 
				
			||||||
 | 
							Name: "foo",
 | 
				
			||||||
 | 
							Resources: &v1.ResourceRequirements{
 | 
				
			||||||
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
 | 
									v1.ResourceCPU: resource.MustParse("2"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						containerFooChangedStatus = v1.ContainerStatus{
 | 
				
			||||||
 | 
							Name: "foo",
 | 
				
			||||||
 | 
							Resources: &v1.ResourceRequirements{
 | 
				
			||||||
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
 | 
									v1.ResourceCPU: resource.MustParse("3"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestHasResourcesChanged(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oldNotChangedPod := &v1.Pod{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{},
 | 
				
			||||||
 | 
							Spec: v1.PodSpec{
 | 
				
			||||||
 | 
								Containers: []v1.Container{
 | 
				
			||||||
 | 
									containerFoo,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Status: v1.PodStatus{
 | 
				
			||||||
 | 
								Phase: v1.PodRunning,
 | 
				
			||||||
 | 
								ContainerStatuses: []v1.ContainerStatus{
 | 
				
			||||||
 | 
									containerFooInitialStatus,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newNotChangedPod := &v1.Pod{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{},
 | 
				
			||||||
 | 
							Spec: v1.PodSpec{
 | 
				
			||||||
 | 
								Containers: []v1.Container{
 | 
				
			||||||
 | 
									containerFoo,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Status: v1.PodStatus{
 | 
				
			||||||
 | 
								Phase: v1.PodRunning,
 | 
				
			||||||
 | 
								ContainerStatuses: []v1.ContainerStatus{
 | 
				
			||||||
 | 
									containerFooInitialStatus,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oldChangedPod := &v1.Pod{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{},
 | 
				
			||||||
 | 
							Spec: v1.PodSpec{
 | 
				
			||||||
 | 
								Containers: []v1.Container{
 | 
				
			||||||
 | 
									containerFoo,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Status: v1.PodStatus{
 | 
				
			||||||
 | 
								Phase: v1.PodRunning,
 | 
				
			||||||
 | 
								ContainerStatuses: []v1.ContainerStatus{
 | 
				
			||||||
 | 
									containerFooInitialStatus,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newChangedPod := &v1.Pod{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{},
 | 
				
			||||||
 | 
							Spec: v1.PodSpec{
 | 
				
			||||||
 | 
								Containers: []v1.Container{
 | 
				
			||||||
 | 
									containerFoo,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Status: v1.PodStatus{
 | 
				
			||||||
 | 
								Phase: v1.PodRunning,
 | 
				
			||||||
 | 
								ContainerStatuses: []v1.ContainerStatus{
 | 
				
			||||||
 | 
									containerFooChangedStatus,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name     string
 | 
				
			||||||
 | 
							oldPod   *v1.Pod
 | 
				
			||||||
 | 
							newPod   *v1.Pod
 | 
				
			||||||
 | 
							expected bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "not-changed-pod",
 | 
				
			||||||
 | 
								oldPod:   oldNotChangedPod,
 | 
				
			||||||
 | 
								newPod:   newNotChangedPod,
 | 
				
			||||||
 | 
								expected: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "changed-pod",
 | 
				
			||||||
 | 
								oldPod:   oldChangedPod,
 | 
				
			||||||
 | 
								newPod:   newChangedPod,
 | 
				
			||||||
 | 
								expected: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							t.Run(test.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								if got := hasResourcesChanged(test.oldPod, test.newPod); got != test.expected {
 | 
				
			||||||
 | 
									t.Errorf("TestHasResourcesChanged = %v, expected %v", got, test.expected)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user