Skip to content

Commit aec2ea1

Browse files
authored
Merge pull request kubernetes#124609 from AxeZhan/refac
Move some helper functions from api/v1 to component-helpers
2 parents ed67bd7 + 2ffb568 commit aec2ea1

File tree

17 files changed

+1481
-1381
lines changed

17 files changed

+1481
-1381
lines changed

pkg/api/v1/resource/helpers.go

Lines changed: 0 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -24,242 +24,8 @@ import (
2424

2525
v1 "k8s.io/api/core/v1"
2626
"k8s.io/apimachinery/pkg/api/resource"
27-
28-
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
2927
)
3028

31-
// PodResourcesOptions controls the behavior of PodRequests and PodLimits.
32-
type PodResourcesOptions struct {
33-
// Reuse, if provided will be reused to accumulate resources and returned by the PodRequests or PodLimits
34-
// functions. All existing values in Reuse will be lost.
35-
Reuse v1.ResourceList
36-
// InPlacePodVerticalScalingEnabled indicates that the in-place pod vertical scaling feature gate is enabled.
37-
InPlacePodVerticalScalingEnabled bool
38-
// ExcludeOverhead controls if pod overhead is excluded from the calculation.
39-
ExcludeOverhead bool
40-
// ContainerFn is called with the effective resources required for each container within the pod.
41-
ContainerFn func(res v1.ResourceList, containerType podutil.ContainerType)
42-
// NonMissingContainerRequests if provided will replace any missing container level requests for the specified resources
43-
// with the given values. If the requests for those resources are explicitly set, even if zero, they will not be modified.
44-
NonMissingContainerRequests v1.ResourceList
45-
}
46-
47-
// PodRequests computes the pod requests per the PodResourcesOptions supplied. If PodResourcesOptions is nil, then
48-
// the requests are returned including pod overhead. The computation is part of the API and must be reviewed
49-
// as an API change.
50-
func PodRequests(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
51-
// attempt to reuse the maps if passed, or allocate otherwise
52-
reqs := reuseOrClearResourceList(opts.Reuse)
53-
54-
var containerStatuses map[string]*v1.ContainerStatus
55-
if opts.InPlacePodVerticalScalingEnabled {
56-
containerStatuses = make(map[string]*v1.ContainerStatus, len(pod.Status.ContainerStatuses))
57-
for i := range pod.Status.ContainerStatuses {
58-
containerStatuses[pod.Status.ContainerStatuses[i].Name] = &pod.Status.ContainerStatuses[i]
59-
}
60-
}
61-
62-
for _, container := range pod.Spec.Containers {
63-
containerReqs := container.Resources.Requests
64-
if opts.InPlacePodVerticalScalingEnabled {
65-
cs, found := containerStatuses[container.Name]
66-
if found {
67-
if pod.Status.Resize == v1.PodResizeStatusInfeasible {
68-
containerReqs = cs.AllocatedResources.DeepCopy()
69-
} else {
70-
containerReqs = max(container.Resources.Requests, cs.AllocatedResources)
71-
}
72-
}
73-
}
74-
75-
if len(opts.NonMissingContainerRequests) > 0 {
76-
containerReqs = applyNonMissing(containerReqs, opts.NonMissingContainerRequests)
77-
}
78-
79-
if opts.ContainerFn != nil {
80-
opts.ContainerFn(containerReqs, podutil.Containers)
81-
}
82-
83-
addResourceList(reqs, containerReqs)
84-
}
85-
86-
restartableInitContainerReqs := v1.ResourceList{}
87-
initContainerReqs := v1.ResourceList{}
88-
// init containers define the minimum of any resource
89-
// Note: In-place resize is not allowed for InitContainers, so no need to check for ResizeStatus value
90-
//
91-
// Let's say `InitContainerUse(i)` is the resource requirements when the i-th
92-
// init container is initializing, then
93-
// `InitContainerUse(i) = sum(Resources of restartable init containers with index < i) + Resources of i-th init container`.
94-
//
95-
// See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#exposing-pod-resource-requirements for the detail.
96-
for _, container := range pod.Spec.InitContainers {
97-
containerReqs := container.Resources.Requests
98-
if len(opts.NonMissingContainerRequests) > 0 {
99-
containerReqs = applyNonMissing(containerReqs, opts.NonMissingContainerRequests)
100-
}
101-
102-
if container.RestartPolicy != nil && *container.RestartPolicy == v1.ContainerRestartPolicyAlways {
103-
// and add them to the resulting cumulative container requests
104-
addResourceList(reqs, containerReqs)
105-
106-
// track our cumulative restartable init container resources
107-
addResourceList(restartableInitContainerReqs, containerReqs)
108-
containerReqs = restartableInitContainerReqs
109-
} else {
110-
tmp := v1.ResourceList{}
111-
addResourceList(tmp, containerReqs)
112-
addResourceList(tmp, restartableInitContainerReqs)
113-
containerReqs = tmp
114-
}
115-
116-
if opts.ContainerFn != nil {
117-
opts.ContainerFn(containerReqs, podutil.InitContainers)
118-
}
119-
maxResourceList(initContainerReqs, containerReqs)
120-
}
121-
122-
maxResourceList(reqs, initContainerReqs)
123-
124-
// Add overhead for running a pod to the sum of requests if requested:
125-
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
126-
addResourceList(reqs, pod.Spec.Overhead)
127-
}
128-
129-
return reqs
130-
}
131-
132-
// applyNonMissing will return a copy of the given resource list with any missing values replaced by the nonMissing values
133-
func applyNonMissing(reqs v1.ResourceList, nonMissing v1.ResourceList) v1.ResourceList {
134-
cp := v1.ResourceList{}
135-
for k, v := range reqs {
136-
cp[k] = v.DeepCopy()
137-
}
138-
139-
for k, v := range nonMissing {
140-
if _, found := reqs[k]; !found {
141-
rk := cp[k]
142-
rk.Add(v)
143-
cp[k] = rk
144-
}
145-
}
146-
return cp
147-
}
148-
149-
// PodLimits computes the pod limits per the PodResourcesOptions supplied. If PodResourcesOptions is nil, then
150-
// the limits are returned including pod overhead for any non-zero limits. The computation is part of the API and must be reviewed
151-
// as an API change.
152-
func PodLimits(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
153-
// attempt to reuse the maps if passed, or allocate otherwise
154-
limits := reuseOrClearResourceList(opts.Reuse)
155-
156-
for _, container := range pod.Spec.Containers {
157-
if opts.ContainerFn != nil {
158-
opts.ContainerFn(container.Resources.Limits, podutil.Containers)
159-
}
160-
addResourceList(limits, container.Resources.Limits)
161-
}
162-
163-
restartableInitContainerLimits := v1.ResourceList{}
164-
initContainerLimits := v1.ResourceList{}
165-
// init containers define the minimum of any resource
166-
//
167-
// Let's say `InitContainerUse(i)` is the resource requirements when the i-th
168-
// init container is initializing, then
169-
// `InitContainerUse(i) = sum(Resources of restartable init containers with index < i) + Resources of i-th init container`.
170-
//
171-
// See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#exposing-pod-resource-requirements for the detail.
172-
for _, container := range pod.Spec.InitContainers {
173-
containerLimits := container.Resources.Limits
174-
// Is the init container marked as a restartable init container?
175-
if container.RestartPolicy != nil && *container.RestartPolicy == v1.ContainerRestartPolicyAlways {
176-
addResourceList(limits, containerLimits)
177-
178-
// track our cumulative restartable init container resources
179-
addResourceList(restartableInitContainerLimits, containerLimits)
180-
containerLimits = restartableInitContainerLimits
181-
} else {
182-
tmp := v1.ResourceList{}
183-
addResourceList(tmp, containerLimits)
184-
addResourceList(tmp, restartableInitContainerLimits)
185-
containerLimits = tmp
186-
}
187-
188-
if opts.ContainerFn != nil {
189-
opts.ContainerFn(containerLimits, podutil.InitContainers)
190-
}
191-
maxResourceList(initContainerLimits, containerLimits)
192-
}
193-
194-
maxResourceList(limits, initContainerLimits)
195-
196-
// Add overhead to non-zero limits if requested:
197-
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
198-
for name, quantity := range pod.Spec.Overhead {
199-
if value, ok := limits[name]; ok && !value.IsZero() {
200-
value.Add(quantity)
201-
limits[name] = value
202-
}
203-
}
204-
}
205-
206-
return limits
207-
}
208-
209-
// addResourceList adds the resources in newList to list.
210-
func addResourceList(list, newList v1.ResourceList) {
211-
for name, quantity := range newList {
212-
if value, ok := list[name]; !ok {
213-
list[name] = quantity.DeepCopy()
214-
} else {
215-
value.Add(quantity)
216-
list[name] = value
217-
}
218-
}
219-
}
220-
221-
// maxResourceList sets list to the greater of list/newList for every resource in newList
222-
func maxResourceList(list, newList v1.ResourceList) {
223-
for name, quantity := range newList {
224-
if value, ok := list[name]; !ok || quantity.Cmp(value) > 0 {
225-
list[name] = quantity.DeepCopy()
226-
}
227-
}
228-
}
229-
230-
// max returns the result of max(a, b) for each named resource and is only used if we can't
231-
// accumulate into an existing resource list
232-
func max(a v1.ResourceList, b v1.ResourceList) v1.ResourceList {
233-
result := v1.ResourceList{}
234-
for key, value := range a {
235-
if other, found := b[key]; found {
236-
if value.Cmp(other) <= 0 {
237-
result[key] = other.DeepCopy()
238-
continue
239-
}
240-
}
241-
result[key] = value.DeepCopy()
242-
}
243-
for key, value := range b {
244-
if _, found := result[key]; !found {
245-
result[key] = value.DeepCopy()
246-
}
247-
}
248-
return result
249-
}
250-
251-
// reuseOrClearResourceList is a helper for avoiding excessive allocations of
252-
// resource lists within the inner loop of resource calculations.
253-
func reuseOrClearResourceList(reuse v1.ResourceList) v1.ResourceList {
254-
if reuse == nil {
255-
return make(v1.ResourceList, 4)
256-
}
257-
for k := range reuse {
258-
delete(reuse, k)
259-
}
260-
return reuse
261-
}
262-
26329
// GetResourceRequestQuantity finds and returns the request quantity for a specific resource.
26430
func GetResourceRequestQuantity(pod *v1.Pod, resourceName v1.ResourceName) resource.Quantity {
26531
requestQuantity := resource.Quantity{}

0 commit comments

Comments
 (0)