Skip to content

Commit 1c2c15a

Browse files
committed
[Bugfix] Fix Resources Copy mechanism to prevent invalid pod creation
1 parent 4049362 commit 1c2c15a

File tree

3 files changed

+88
-6
lines changed

3 files changed

+88
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
44
- (Feature) Extract Scheduler API
55
- (Bugfix) Fix Image Discovery
6+
- (Bugfix) Fix Resources Copy mechanism to prevent invalid pod creation
67

78
## [1.2.38](https://github.com/arangodb/kube-arangodb/tree/1.2.38) (2024-02-22)
89
- (Feature) Extract GRPC Server

pkg/util/k8sutil/resources/resources.go

+51-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ func ApplyContainerResourceRequirements(container *core.Container, resources cor
3333
container.Resources.Requests = ApplyContainerResourceList(container.Resources.Requests, resources.Requests)
3434
}
3535

36+
// MergeContainerResource updates resources from `from` to `to` ResourceList
37+
func MergeContainerResource(to core.ResourceRequirements, from core.ResourceRequirements) core.ResourceRequirements {
38+
var r core.ResourceRequirements
39+
40+
r.Limits = MergeContainerResourceList(to.Limits, from.Limits)
41+
r.Requests = MergeContainerResourceList(to.Requests, from.Requests)
42+
43+
return r
44+
}
45+
3646
// ApplyContainerResource adds non-existing resources from `from` to `to` ResourceList
3747
func ApplyContainerResource(to core.ResourceRequirements, from core.ResourceRequirements) core.ResourceRequirements {
3848
var r core.ResourceRequirements
@@ -43,6 +53,27 @@ func ApplyContainerResource(to core.ResourceRequirements, from core.ResourceRequ
4353
return r
4454
}
4555

56+
// MergeContainerResourceList updates resources from `from` to `to` ResourceList
57+
func MergeContainerResourceList(to core.ResourceList, from core.ResourceList) core.ResourceList {
58+
if len(from) == 0 {
59+
return to
60+
}
61+
62+
if to == nil {
63+
to = core.ResourceList{}
64+
}
65+
66+
for k, v := range from {
67+
if v.IsZero() {
68+
delete(to, k)
69+
} else {
70+
to[k] = v
71+
}
72+
}
73+
74+
return to
75+
}
76+
4677
// ApplyContainerResourceList adds non-existing resources from `from` to `to` ResourceList
4778
func ApplyContainerResourceList(to core.ResourceList, from core.ResourceList) core.ResourceList {
4879
if len(from) == 0 {
@@ -69,16 +100,30 @@ func UpscaleContainerResourceRequirements(container *core.Container, resources c
69100

70101
container.Resources.Limits = UpscaleContainerResourceList(container.Resources.Limits, resources.Limits)
71102
container.Resources.Requests = UpscaleContainerResourceList(container.Resources.Requests, resources.Requests)
103+
104+
// Ensure that Limits are always higher or equals requests
105+
container.Resources.Limits = UpscaleOptionalContainerResourceList(container.Resources.Limits, container.Resources.Requests)
72106
}
73107

74-
// UpscaleContainerResource scales up resources from `from` to `to` ResourceList
75-
func UpscaleContainerResource(to core.ResourceRequirements, from core.ResourceRequirements) core.ResourceRequirements {
76-
var r core.ResourceRequirements
108+
// UpscaleOptionalContainerResourceList scales up resources from `from` to `to` ResourceList if they exists in `to`
109+
func UpscaleOptionalContainerResourceList(to core.ResourceList, from core.ResourceList) core.ResourceList {
110+
if len(from) == 0 {
111+
return to
112+
}
113+
114+
if to == nil {
115+
to = core.ResourceList{}
116+
}
77117

78-
r.Limits = UpscaleContainerResourceList(to.Limits, from.Limits)
79-
r.Requests = UpscaleContainerResourceList(to.Requests, from.Requests)
118+
for k, v := range from {
119+
if n, ok := to[k]; ok {
120+
if n.Cmp(v) < 0 {
121+
to[k] = v
122+
}
123+
}
124+
}
80125

81-
return r
126+
return to
82127
}
83128

84129
// UpscaleContainerResourceList scales up resources from `from` to `to` ResourceList

pkg/util/k8sutil/resources/resources_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ func Test_ApplyContainerResourceRequirements(t *testing.T) {
163163
}
164164

165165
func Test_UpsertContainerResourceRequirements(t *testing.T) {
166+
v0, err := resource.ParseQuantity("512Mi")
167+
require.NoError(t, err)
168+
166169
v1, err := resource.ParseQuantity("1Gi")
167170
require.NoError(t, err)
168171

@@ -174,6 +177,39 @@ func Test_UpsertContainerResourceRequirements(t *testing.T) {
174177

175178
var container core.Container
176179

180+
t.Run("Ensure limits are applied optionally", func(t *testing.T) {
181+
UpscaleContainerResourceRequirements(&container, core.ResourceRequirements{
182+
Requests: core.ResourceList{
183+
core.ResourceMemory: v1,
184+
},
185+
})
186+
187+
require.Len(t, container.Resources.Requests, 1)
188+
require.Contains(t, container.Resources.Requests, core.ResourceMemory)
189+
require.Equal(t, v1, container.Resources.Requests[core.ResourceMemory])
190+
191+
require.Len(t, container.Resources.Limits, 0)
192+
})
193+
194+
t.Run("Ensure limits are upscaled optionally", func(t *testing.T) {
195+
UpscaleContainerResourceRequirements(&container, core.ResourceRequirements{
196+
Limits: core.ResourceList{
197+
core.ResourceMemory: v0,
198+
},
199+
Requests: core.ResourceList{
200+
core.ResourceMemory: v1,
201+
},
202+
})
203+
204+
require.Len(t, container.Resources.Requests, 1)
205+
require.Contains(t, container.Resources.Requests, core.ResourceMemory)
206+
require.Equal(t, v1, container.Resources.Requests[core.ResourceMemory])
207+
208+
require.Len(t, container.Resources.Limits, 1)
209+
require.Contains(t, container.Resources.Limits, core.ResourceMemory)
210+
require.Equal(t, v1, container.Resources.Limits[core.ResourceMemory])
211+
})
212+
177213
t.Run("Ensure limits are copied", func(t *testing.T) {
178214
UpscaleContainerResourceRequirements(&container, core.ResourceRequirements{
179215
Limits: core.ResourceList{

0 commit comments

Comments
 (0)