Remove deprecated PodRequestsAndLimits from kubectl/pkg/util/resource (#137442)

* Remove deprecated PodRequestsAndLimits from kubectl/pkg/util/resource

The PodRequestsAndLimits function was deprecated in favor of
k8s.io/component-helpers/resource.PodRequests and PodLimits,
which also support pod-level resources. There are no remaining
consumers in kubectl.

This removal includes the unexported helpers: podRequests,
podLimits, determineContainerReqs, max, addResourceList, and
maxResourceList.

* Remove test for deleted max helper function

Kubernetes-commit: e026a9482a167bec567f16f87efe9df4c09dbb06
This commit is contained in:
Nikhil 2026-03-09 19:53:31 +05:30 committed by Kubernetes Publisher
parent 8ff045b4dc
commit ad4e7654ea
2 changed files with 0 additions and 247 deletions

View file

@ -25,176 +25,8 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets"
helpers "k8s.io/component-helpers/resource"
)
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod. If pod overhead is non-nil, the pod overhead is added to the
// total container resource requests and to the total container limits which have a
// non-zero quantity.
//
// Deprecated: Use k8s.io/component-helpers/resource.PodRequests and
// k8s.io/component-helpers/resource.PodLimits instead, which also support
// pod-level resources.
func PodRequestsAndLimits(pod *corev1.Pod) (reqs, limits corev1.ResourceList) {
return podRequests(pod), podLimits(pod)
}
// podRequests is a simplified form of PodRequests from k8s.io/kubernetes/pkg/api/v1/resource that doesn't check
// feature gate enablement and avoids adding a dependency on k8s.io/kubernetes/pkg/apis/core/v1 for kubectl.
func podRequests(pod *corev1.Pod) corev1.ResourceList {
// attempt to reuse the maps if passed, or allocate otherwise
reqs := corev1.ResourceList{}
containerStatuses := map[string]*corev1.ContainerStatus{}
for i := range pod.Status.ContainerStatuses {
containerStatuses[pod.Status.ContainerStatuses[i].Name] = &pod.Status.ContainerStatuses[i]
}
for i := range pod.Status.InitContainerStatuses {
containerStatuses[pod.Status.InitContainerStatuses[i].Name] = &pod.Status.InitContainerStatuses[i]
}
for _, container := range pod.Spec.Containers {
containerReqs := container.Resources.Requests
cs, found := containerStatuses[container.Name]
if found && cs.Resources != nil {
containerReqs = determineContainerReqs(pod, &container, cs)
}
addResourceList(reqs, containerReqs)
}
restartableInitContainerReqs := corev1.ResourceList{}
initContainerReqs := corev1.ResourceList{}
for _, container := range pod.Spec.InitContainers {
containerReqs := container.Resources.Requests
if container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways {
cs, found := containerStatuses[container.Name]
if found && cs.Resources != nil {
containerReqs = determineContainerReqs(pod, &container, cs)
}
// and add them to the resulting cumulative container requests
addResourceList(reqs, containerReqs)
// track our cumulative restartable init container resources
addResourceList(restartableInitContainerReqs, containerReqs)
containerReqs = restartableInitContainerReqs
} else {
tmp := corev1.ResourceList{}
addResourceList(tmp, containerReqs)
addResourceList(tmp, restartableInitContainerReqs)
containerReqs = tmp
}
maxResourceList(initContainerReqs, containerReqs)
}
maxResourceList(reqs, initContainerReqs)
// Add overhead for running a pod to the sum of requests if requested:
if pod.Spec.Overhead != nil {
addResourceList(reqs, pod.Spec.Overhead)
}
return reqs
}
// podLimits is a simplified form of PodLimits from k8s.io/kubernetes/pkg/api/v1/resource that doesn't check
// feature gate enablement and avoids adding a dependency on k8s.io/kubernetes/pkg/apis/core/v1 for kubectl.
func podLimits(pod *corev1.Pod) corev1.ResourceList {
limits := corev1.ResourceList{}
for _, container := range pod.Spec.Containers {
addResourceList(limits, container.Resources.Limits)
}
restartableInitContainerLimits := corev1.ResourceList{}
initContainerLimits := corev1.ResourceList{}
for _, container := range pod.Spec.InitContainers {
containerLimits := container.Resources.Limits
// Is the init container marked as a restartable init container?
if container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways {
addResourceList(limits, containerLimits)
// track our cumulative restartable init container resources
addResourceList(restartableInitContainerLimits, containerLimits)
containerLimits = restartableInitContainerLimits
} else {
tmp := corev1.ResourceList{}
addResourceList(tmp, containerLimits)
addResourceList(tmp, restartableInitContainerLimits)
containerLimits = tmp
}
maxResourceList(initContainerLimits, containerLimits)
}
maxResourceList(limits, initContainerLimits)
// Add overhead to non-zero limits if requested:
if pod.Spec.Overhead != nil {
for name, quantity := range pod.Spec.Overhead {
if value, ok := limits[name]; ok && !value.IsZero() {
value.Add(quantity)
limits[name] = value
}
}
}
return limits
}
// determineContainerReqs will return a copy of the container requests based on if resizing is feasible or not.
func determineContainerReqs(pod *corev1.Pod, container *corev1.Container, cs *corev1.ContainerStatus) corev1.ResourceList {
if helpers.IsPodResizeInfeasible(pod) {
return max(cs.Resources.Requests, cs.AllocatedResources)
}
return max(container.Resources.Requests, cs.Resources.Requests, cs.AllocatedResources)
}
// 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 corev1.ResourceList, b ...corev1.ResourceList) corev1.ResourceList {
var result corev1.ResourceList
if a != nil {
result = a.DeepCopy()
} else {
result = corev1.ResourceList{}
}
for _, other := range b {
maxResourceList(result, other)
}
return result
}
// addResourceList adds the resources in newList to list
func addResourceList(list, new corev1.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = quantity.DeepCopy()
} else {
value.Add(quantity)
list[name] = value
}
}
}
// maxResourceList sets list to the greater of list/newList for every resource
// either list
func maxResourceList(list, new corev1.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = quantity.DeepCopy()
continue
} else {
if quantity.Cmp(value) > 0 {
list[name] = quantity.DeepCopy()
}
}
}
}
// ExtractContainerResourceValue extracts the value of a resource
// in an already known container
func ExtractContainerResourceValue(fs *corev1.ResourceFieldSelector, container *corev1.Container) (string, error) {

View file

@ -15,82 +15,3 @@ limitations under the License.
*/
package resource
import (
"testing"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)
func TestMaxWithNilResourceList(t *testing.T) {
tests := []struct {
name string
a corev1.ResourceList
b []corev1.ResourceList
want corev1.ResourceList
}{
{
name: "nil first argument with non-nil second",
a: nil,
b: []corev1.ResourceList{{corev1.ResourceCPU: resource.MustParse("100m")}},
want: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")},
},
{
name: "nil first argument with nil second",
a: nil,
b: []corev1.ResourceList{nil},
want: corev1.ResourceList{},
},
{
name: "nil first argument with empty second",
a: nil,
b: []corev1.ResourceList{{}},
want: corev1.ResourceList{},
},
{
name: "nil first argument with no second arguments",
a: nil,
b: nil,
want: corev1.ResourceList{},
},
{
name: "empty first argument with non-nil second",
a: corev1.ResourceList{},
b: []corev1.ResourceList{{corev1.ResourceCPU: resource.MustParse("100m")}},
want: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")},
},
{
name: "non-nil first argument takes max",
a: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")},
b: []corev1.ResourceList{{corev1.ResourceCPU: resource.MustParse("100m")}},
want: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")},
},
{
name: "second argument larger takes max",
a: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")},
b: []corev1.ResourceList{{corev1.ResourceCPU: resource.MustParse("200m")}},
want: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := max(tt.a, tt.b...)
if len(got) != len(tt.want) {
t.Errorf("case %q, expected %d resources but got %d", tt.name, len(tt.want), len(got))
return
}
for name, wantQty := range tt.want {
gotQty, ok := got[name]
if !ok {
t.Errorf("case %q, expected resource %s but it was missing", tt.name, name)
continue
}
if gotQty.Cmp(wantQty) != 0 {
t.Errorf("case %q, expected resource %s to be %s but got %s", tt.name, name, wantQty.String(), gotQty.String())
}
}
})
}
}