@@ -129,6 +129,7 @@ func TestLimitRequestAdmission(t *testing.T) {
129
129
expectedCpuLimit resource.Quantity
130
130
expectedCpuRequest resource.Quantity
131
131
namespace * kapi.Namespace
132
+ namespaceLimits []* kapi.LimitRange
132
133
}{
133
134
{
134
135
name : "ignore pods that have no memory limit specified" ,
@@ -139,6 +140,21 @@ func TestLimitRequestAdmission(t *testing.T) {
139
140
expectedCpuRequest : resource .MustParse ("0" ),
140
141
namespace : fakeNamespace (true ),
141
142
},
143
+ {
144
+ name : "with namespace limits, ignore pods that have no memory limit specified" ,
145
+ config : testConfig (100 , 50 , 50 ),
146
+ pod : testBestEffortPod (),
147
+ expectedMemRequest : resource .MustParse ("0" ),
148
+ expectedCpuLimit : resource .MustParse ("0" ),
149
+ expectedCpuRequest : resource .MustParse ("0" ),
150
+ namespace : fakeNamespace (true ),
151
+ namespaceLimits : []* kapi.LimitRange {
152
+ fakeMinCPULimitRange ("567m" ),
153
+ fakeMinCPULimitRange ("678m" ),
154
+ fakeMinMemoryLimitRange ("700Gi" ),
155
+ fakeMinMemoryLimitRange ("456Gi" ),
156
+ },
157
+ },
142
158
{
143
159
name : "test floor for memory and cpu" ,
144
160
config : testConfig (100 , 50 , 50 ),
@@ -148,6 +164,21 @@ func TestLimitRequestAdmission(t *testing.T) {
148
164
expectedCpuRequest : resource .MustParse ("1m" ),
149
165
namespace : fakeNamespace (true ),
150
166
},
167
+ {
168
+ name : "with namespace limits, test floor for memory and cpu" ,
169
+ config : testConfig (100 , 50 , 50 ),
170
+ pod : testPod ("1Mi" , "0" , "0" , "0" ),
171
+ expectedMemRequest : resource .MustParse ("456Gi" ),
172
+ expectedCpuLimit : resource .MustParse ("567m" ),
173
+ expectedCpuRequest : resource .MustParse ("567m" ),
174
+ namespace : fakeNamespace (true ),
175
+ namespaceLimits : []* kapi.LimitRange {
176
+ fakeMinCPULimitRange ("567m" ),
177
+ fakeMinCPULimitRange ("678m" ),
178
+ fakeMinMemoryLimitRange ("700Gi" ),
179
+ fakeMinMemoryLimitRange ("456Gi" ),
180
+ },
181
+ },
151
182
{
152
183
name : "nil config" ,
153
184
config : nil ,
@@ -157,6 +188,21 @@ func TestLimitRequestAdmission(t *testing.T) {
157
188
expectedCpuRequest : resource .MustParse ("1" ),
158
189
namespace : fakeNamespace (true ),
159
190
},
191
+ {
192
+ name : "with namespace limits, nil config" ,
193
+ config : nil ,
194
+ pod : testPod ("1" , "1" , "1" , "1" ),
195
+ expectedMemRequest : resource .MustParse ("1" ),
196
+ expectedCpuLimit : resource .MustParse ("1" ),
197
+ expectedCpuRequest : resource .MustParse ("1" ),
198
+ namespace : fakeNamespace (true ),
199
+ namespaceLimits : []* kapi.LimitRange {
200
+ fakeMinCPULimitRange ("567m" ),
201
+ fakeMinCPULimitRange ("678m" ),
202
+ fakeMinMemoryLimitRange ("700Gi" ),
203
+ fakeMinMemoryLimitRange ("456Gi" ),
204
+ },
205
+ },
160
206
{
161
207
name : "all values are adjusted" ,
162
208
config : testConfig (100 , 50 , 50 ),
@@ -166,6 +212,21 @@ func TestLimitRequestAdmission(t *testing.T) {
166
212
expectedCpuRequest : resource .MustParse ("500m" ),
167
213
namespace : fakeNamespace (true ),
168
214
},
215
+ {
216
+ name : "with namespace limits, all values are adjusted to floor of namespace limits" ,
217
+ config : testConfig (100 , 50 , 50 ),
218
+ pod : testPod ("1Gi" , "0" , "2000m" , "0" ),
219
+ expectedMemRequest : resource .MustParse ("456Gi" ),
220
+ expectedCpuLimit : resource .MustParse ("10567m" ),
221
+ expectedCpuRequest : resource .MustParse ("10567m" ),
222
+ namespace : fakeNamespace (true ),
223
+ namespaceLimits : []* kapi.LimitRange {
224
+ fakeMinCPULimitRange ("10567m" ),
225
+ fakeMinCPULimitRange ("20678m" ),
226
+ fakeMinMemoryLimitRange ("700Gi" ),
227
+ fakeMinMemoryLimitRange ("456Gi" ),
228
+ },
229
+ },
169
230
{
170
231
name : "just requests are adjusted" ,
171
232
config : testConfig (0 , 50 , 50 ),
@@ -175,6 +236,21 @@ func TestLimitRequestAdmission(t *testing.T) {
175
236
expectedCpuRequest : resource .MustParse ("25m" ),
176
237
namespace : fakeNamespace (true ),
177
238
},
239
+ {
240
+ name : "with namespace limits, all requests are adjusted to floor of namespace limits" ,
241
+ config : testConfig (0 , 50 , 50 ),
242
+ pod : testPod ("10Mi" , "0" , "50m" , "0" ),
243
+ expectedMemRequest : resource .MustParse ("456Gi" ),
244
+ expectedCpuLimit : resource .MustParse ("50m" ),
245
+ expectedCpuRequest : resource .MustParse ("10567m" ),
246
+ namespace : fakeNamespace (true ),
247
+ namespaceLimits : []* kapi.LimitRange {
248
+ fakeMinCPULimitRange ("10567m" ),
249
+ fakeMinCPULimitRange ("20678m" ),
250
+ fakeMinMemoryLimitRange ("700Gi" ),
251
+ fakeMinMemoryLimitRange ("456Gi" ),
252
+ },
253
+ },
178
254
{
179
255
name : "project annotation disables overrides" ,
180
256
config : testConfig (0 , 50 , 50 ),
@@ -184,6 +260,21 @@ func TestLimitRequestAdmission(t *testing.T) {
184
260
expectedCpuRequest : resource .MustParse ("0" ),
185
261
namespace : fakeNamespace (false ),
186
262
},
263
+ {
264
+ name : "with namespace limits, project annotation disables overrides" ,
265
+ config : testConfig (0 , 50 , 50 ),
266
+ pod : testPod ("10Mi" , "0" , "50m" , "0" ),
267
+ expectedMemRequest : resource .MustParse ("0" ),
268
+ expectedCpuLimit : resource .MustParse ("50m" ),
269
+ expectedCpuRequest : resource .MustParse ("0" ),
270
+ namespace : fakeNamespace (false ),
271
+ namespaceLimits : []* kapi.LimitRange {
272
+ fakeMinCPULimitRange ("10567m" ),
273
+ fakeMinCPULimitRange ("20678m" ),
274
+ fakeMinMemoryLimitRange ("700Gi" ),
275
+ fakeMinMemoryLimitRange ("456Gi" ),
276
+ },
277
+ },
187
278
{
188
279
name : "large values don't overflow" ,
189
280
config : testConfig (100 , 50 , 50 ),
@@ -211,10 +302,24 @@ func TestLimitRequestAdmission(t *testing.T) {
211
302
expectedCpuRequest : resource .MustParse ("250m" ),
212
303
namespace : fakeNamespace (true ),
213
304
},
305
+ {
306
+ name : "test only containers types are considered with namespace limits" ,
307
+ config : testConfig (100 , 50 , 50 ),
308
+ pod : testPod ("1Gi" , "0" , "2000m" , "0" ),
309
+ expectedMemRequest : resource .MustParse ("512Mi" ),
310
+ expectedCpuLimit : resource .MustParse ("1" ),
311
+ expectedCpuRequest : resource .MustParse ("500m" ),
312
+ namespace : fakeNamespace (true ),
313
+ namespaceLimits : []* kapi.LimitRange {
314
+ fakeMinStorageLimitRange ("1567Mi" ),
315
+ },
316
+ },
214
317
}
215
318
216
319
for _ , test := range tests {
217
- c , err := newClusterResourceOverride (test .config )
320
+ c , err := newClusterResourceOverride (test .config , func (a * clusterResourceOverridePlugin , attr admission.Attributes ) ([]* kapi.LimitRange , error ) {
321
+ return test .namespaceLimits , nil
322
+ })
218
323
if err != nil {
219
324
t .Errorf ("%s: config de/serialize failed: %v" , test .name , err )
220
325
continue
@@ -336,3 +441,32 @@ func testConfig(lc2mr int64, cr2lr int64, mr2lr int64) *clusterresourceoverride.
336
441
MemoryRequestToLimitPercent : mr2lr ,
337
442
}
338
443
}
444
+
445
+ func fakeMinLimitRange (limitType kapi.LimitType , resourceType kapi.ResourceName , limits ... string ) * kapi.LimitRange {
446
+ r := & kapi.LimitRange {}
447
+
448
+ for i := range limits {
449
+ rl := kapi.ResourceList {}
450
+ rl [resourceType ] = resource .MustParse (limits [i ])
451
+ r .Spec .Limits = append (r .Spec .Limits ,
452
+ kapi.LimitRangeItem {
453
+ Type : limitType ,
454
+ Min : rl ,
455
+ },
456
+ )
457
+ }
458
+
459
+ return r
460
+ }
461
+
462
+ func fakeMinMemoryLimitRange (limits ... string ) * kapi.LimitRange {
463
+ return fakeMinLimitRange (kapi .LimitTypeContainer , kapi .ResourceMemory , limits ... )
464
+ }
465
+
466
+ func fakeMinCPULimitRange (limits ... string ) * kapi.LimitRange {
467
+ return fakeMinLimitRange (kapi .LimitTypeContainer , kapi .ResourceCPU , limits ... )
468
+ }
469
+
470
+ func fakeMinStorageLimitRange (limits ... string ) * kapi.LimitRange {
471
+ return fakeMinLimitRange (kapi .LimitTypePersistentVolumeClaim , kapi .ResourceStorage , limits ... )
472
+ }
0 commit comments