diff --git a/staging/src/k8s.io/component-helpers/resource/helpers.go b/staging/src/k8s.io/component-helpers/resource/helpers.go index 4dd837cad5a..c37945f4b1e 100644 --- a/staging/src/k8s.io/component-helpers/resource/helpers.go +++ b/staging/src/k8s.io/component-helpers/resource/helpers.go @@ -430,7 +430,12 @@ func maxResourceList(list, newList v1.ResourceList) { // max returns the result of max(a, b...) for each named resource and is only used if we can't // accumulate into an existing resource list func max(a v1.ResourceList, b ...v1.ResourceList) v1.ResourceList { - result := a.DeepCopy() + var result v1.ResourceList + if a != nil { + result = a.DeepCopy() + } else { + result = v1.ResourceList{} + } for _, other := range b { maxResourceList(result, other) } diff --git a/staging/src/k8s.io/component-helpers/resource/helpers_test.go b/staging/src/k8s.io/component-helpers/resource/helpers_test.go index aa551547296..471b4a2bf6b 100644 --- a/staging/src/k8s.io/component-helpers/resource/helpers_test.go +++ b/staging/src/k8s.io/component-helpers/resource/helpers_test.go @@ -23,6 +23,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/utils/ptr" ) func TestPodRequestsAndLimits(t *testing.T) { @@ -2019,11 +2020,14 @@ func TestIsSupportedPodLevelResource(t *testing.T) { func TestAggregateContainerRequestsAndLimits(t *testing.T) { restartAlways := v1.ContainerRestartPolicyAlways cases := []struct { - containers []v1.Container - initContainers []v1.Container - name string - expectedRequests v1.ResourceList - expectedLimits v1.ResourceList + options PodResourcesOptions + containers []v1.Container + containerStatuses []v1.ContainerStatus + initContainers []v1.Container + initContainerStatuses []v1.ContainerStatus + name string + expectedRequests v1.ResourceList + expectedLimits v1.ResourceList }{ { name: "one container with limits", @@ -2187,20 +2191,74 @@ func TestAggregateContainerRequestsAndLimits(t *testing.T) { v1.ResourceName(v1.ResourceCPU): resource.MustParse("17"), }, }, + { + name: "regularcontainers with empty requests, but status with non-empty requests", + options: PodResourcesOptions{UseStatusResources: true}, + containers: []v1.Container{ + { + Name: "container-1", + Resources: v1.ResourceRequirements{}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + { + Name: "container-1", + Resources: &v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2"), + }, + }, + }, + }, + expectedRequests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2"), + }, + expectedLimits: v1.ResourceList{}, + }, + { + name: "always-restart init containers with empty requests, but status with non-empty requests", + options: PodResourcesOptions{UseStatusResources: true}, + initContainers: []v1.Container{ + { + Name: "container-1", + RestartPolicy: ptr.To[v1.ContainerRestartPolicy](v1.ContainerRestartPolicyAlways), + Resources: v1.ResourceRequirements{}, + }, + }, + initContainerStatuses: []v1.ContainerStatus{ + { + Name: "container-1", + Resources: &v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2"), + }, + }, + }, + }, + expectedRequests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2"), + }, + expectedLimits: v1.ResourceList{}, + }, } for idx, tc := range cases { - testPod := &v1.Pod{Spec: v1.PodSpec{Containers: tc.containers, InitContainers: tc.initContainers}} - resRequests := AggregateContainerRequests(testPod, PodResourcesOptions{}) - resLimits := AggregateContainerLimits(testPod, PodResourcesOptions{}) + t.Run(tc.name, func(t *testing.T) { + testPod := &v1.Pod{ + Spec: v1.PodSpec{Containers: tc.containers, InitContainers: tc.initContainers}, + Status: v1.PodStatus{ContainerStatuses: tc.containerStatuses, InitContainerStatuses: tc.initContainerStatuses}, + } + resRequests := AggregateContainerRequests(testPod, tc.options) + resLimits := AggregateContainerLimits(testPod, tc.options) - if !equality.Semantic.DeepEqual(tc.expectedRequests, resRequests) { - t.Errorf("test case failure[%d]: %v, requests:\n expected:\t%v\ngot\t\t%v", idx, tc.name, tc.expectedRequests, resRequests) - } + if !equality.Semantic.DeepEqual(tc.expectedRequests, resRequests) { + t.Errorf("test case failure[%d]: %v, requests:\n expected:\t%v\ngot\t\t%v", idx, tc.name, tc.expectedRequests, resRequests) + } - if !equality.Semantic.DeepEqual(tc.expectedLimits, resLimits) { - t.Errorf("test case failure[%d]: %v, limits:\n expected:\t%v\ngot\t\t%v", idx, tc.name, tc.expectedLimits, resLimits) - } + if !equality.Semantic.DeepEqual(tc.expectedLimits, resLimits) { + t.Errorf("test case failure[%d]: %v, limits:\n expected:\t%v\ngot\t\t%v", idx, tc.name, tc.expectedLimits, resLimits) + } + }) } }