/
limitquerier.go
103 lines (82 loc) · 2.52 KB
/
limitquerier.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package clusterresourceoverride
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
corev1listers "k8s.io/client-go/listers/core/v1"
)
type namespaceLimitQuerier struct {
limitRangesLister corev1listers.LimitRangeLister
}
func (l *namespaceLimitQuerier) QueryFloorAndCeiling(namespace string) (floor *CPUMemory, ceiling *CPUMemory, err error) {
limitRanges, listErr := l.limitRangesLister.LimitRanges(namespace).List(labels.Everything())
if listErr != nil {
err = fmt.Errorf("failed to query limitrange - %v", listErr)
return
}
nsCPUMinimum, nsCPUMaximum := GetMinMax(limitRanges, corev1.ResourceCPU)
nsMemMinimum, nsMemMaximum := GetMinMax(limitRanges, corev1.ResourceMemory)
floor = &CPUMemory{
CPU: nsCPUMinimum,
Memory: nsMemMinimum,
}
ceiling = &CPUMemory{
CPU: nsCPUMaximum,
Memory: nsMemMaximum,
}
return
}
// GetMinMax finds the Minimum and Maximum limit for respectively for the specified resource.
// Nil is returned if limitRanges is empty or limits contains no resourceName limits.
func GetMinMax(limitRanges []*corev1.LimitRange, resourceName corev1.ResourceName) (minimum *resource.Quantity, maximum *resource.Quantity) {
minList, maxList := findMinMaxLimits(limitRanges, resourceName)
minimum = minQuantity(minList)
maximum = maxQuantity(maxList)
return
}
func findMinMaxLimits(limitRanges []*corev1.LimitRange, resourceName corev1.ResourceName) (minimum []*resource.Quantity, maximum []*resource.Quantity) {
minimum = []*resource.Quantity{}
maximum = []*resource.Quantity{}
for _, limitRange := range limitRanges {
for _, limits := range limitRange.Spec.Limits {
if limits.Type == corev1.LimitTypeContainer {
if min, found := limits.Min[resourceName]; found {
clone := min.DeepCopy()
minimum = append(minimum, &clone)
}
if max, found := limits.Max[resourceName]; found {
clone := max.DeepCopy()
maximum = append(maximum, &clone)
}
}
}
}
return
}
func minQuantity(quantities []*resource.Quantity) *resource.Quantity {
if len(quantities) == 0 {
return nil
}
min := *quantities[0]
for i := range quantities {
if quantities[i].Cmp(min) < 0 {
min = *quantities[i]
}
}
copy := min.DeepCopy()
return ©
}
func maxQuantity(quantities []*resource.Quantity) *resource.Quantity {
if len(quantities) == 0 {
return nil
}
max := *quantities[0]
for i := range quantities {
if quantities[i].Cmp(max) > 0 {
max = *quantities[i]
}
}
copy := max.DeepCopy()
return ©
}