Skip to content

Commit 832d7f7

Browse files
committed
apply feedback
1 parent 4c69bf2 commit 832d7f7

File tree

5 files changed

+49
-33
lines changed

5 files changed

+49
-33
lines changed

pkg/apis/core/validation/validation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5491,7 +5491,7 @@ func ValidatePodEphemeralContainersUpdate(newPod, oldPod *core.Pod, opts PodVali
54915491
func ValidatePodResize(newPod, oldPod *core.Pod, opts PodValidationOptions) field.ErrorList {
54925492
// Part 1: Validate newPod's spec and updates to metadata
54935493
fldPath := field.NewPath("metadata")
5494-
allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
5494+
allErrs := ValidateImmutableField(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
54955495
allErrs = append(allErrs, validatePodMetadataAndSpec(newPod, opts)...)
54965496
allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"), opts)...)
54975497

pkg/quota/v1/evaluator/core/pods.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,15 @@ func (p *podEvaluator) GroupResource() schema.GroupResource {
155155

156156
// Handles returns true if the evaluator should handle the specified attributes.
157157
func (p *podEvaluator) Handles(a admission.Attributes) bool {
158-
if a.GetSubresource() != "" && a.GetSubresource() != "resize" {
158+
op := a.GetOperation()
159+
switch a.GetSubresource() {
160+
case "":
161+
return op == admission.Create
162+
case "resize":
163+
return op == admission.Update
164+
default:
159165
return false
160166
}
161-
op := a.GetOperation()
162-
return op == admission.Create || (a.GetSubresource() == "resize" && op == admission.Update)
163167
}
164168

165169
// Matches returns true if the evaluator matches the specified quota with the provided input item

pkg/registry/core/pod/strategy.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -275,19 +275,31 @@ func (podEphemeralContainersStrategy) WarningsOnUpdate(ctx context.Context, obj,
275275

276276
type podResizeStrategy struct {
277277
podStrategy
278+
279+
resetFieldsFilter fieldpath.Filter
278280
}
279281

280282
// ResizeStrategy wraps and exports the used podStrategy for the storage package.
281-
var ResizeStrategy = podResizeStrategy{Strategy}
283+
var ResizeStrategy = podResizeStrategy{
284+
podStrategy: Strategy,
285+
resetFieldsFilter: fieldpath.NewIncludeMatcherFilter(
286+
fieldpath.MakePrefixMatcherOrDie("spec", "containers", fieldpath.MatchAnyPathElement(), "resources"),
287+
fieldpath.MakePrefixMatcherOrDie("spec", "containers", fieldpath.MatchAnyPathElement(), "resizePolicy"),
288+
),
289+
}
282290

283-
// dropNonPodResizeUpdates discards all changes except for pod.Spec.Containers[*].Resources,ResizePolicy and certain metadata
284-
func dropNonPodResizeUpdates(newPod, oldPod *api.Pod) *api.Pod {
291+
// dropNonResizeUpdates discards all changes except for pod.Spec.Containers[*].Resources,ResizePolicy and certain metadata
292+
func dropNonResizeUpdates(newPod, oldPod *api.Pod) *api.Pod {
285293
pod := dropPodUpdates(newPod, oldPod)
286294

295+
// Containers are not allowed to be re-ordered, but in case they were,
296+
// we don't want to corrupt them here. It will get caught in validation.
287297
oldCtrToIndex := make(map[string]int)
288298
for idx, ctr := range pod.Spec.Containers {
289299
oldCtrToIndex[ctr.Name] = idx
290300
}
301+
// TODO: Once we add in-place pod resize support for sidecars, we need to allow
302+
// modifying sidecar resources via resize subresource too.
291303
for _, ctr := range newPod.Spec.Containers {
292304
idx, ok := oldCtrToIndex[ctr.Name]
293305
if !ok {
@@ -303,7 +315,7 @@ func (podResizeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
303315
newPod := obj.(*api.Pod)
304316
oldPod := old.(*api.Pod)
305317

306-
*newPod = *dropNonPodResizeUpdates(newPod, oldPod)
318+
*newPod = *dropNonResizeUpdates(newPod, oldPod)
307319
podutil.MarkPodProposedForResize(oldPod, newPod)
308320
podutil.DropDisabledPodFields(newPod, oldPod)
309321
}
@@ -323,12 +335,9 @@ func (podResizeStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.
323335

324336
// GetResetFieldsFilter returns a set of fields filter reset by the strategy
325337
// and should not be modified by the user.
326-
func (podResizeStrategy) GetResetFieldsFilter() map[fieldpath.APIVersion]fieldpath.Filter {
338+
func (p podResizeStrategy) GetResetFieldsFilter() map[fieldpath.APIVersion]fieldpath.Filter {
327339
return map[fieldpath.APIVersion]fieldpath.Filter{
328-
"v1": fieldpath.NewIncludeMatcherFilter(
329-
fieldpath.MakePrefixMatcherOrDie("spec", "containers", fieldpath.MatchAnyPathElement(), "resources"),
330-
fieldpath.MakePrefixMatcherOrDie("spec", "containers", fieldpath.MatchAnyPathElement(), "resizePolicy"),
331-
),
340+
"v1": p.resetFieldsFilter,
332341
}
333342
}
334343

plugin/pkg/admission/limitranger/admission.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ func (d *DefaultLimitRangerActions) ValidateLimit(limitRange *corev1.LimitRange,
415415
// SupportsAttributes ignores all calls that do not deal with pod resources or storage requests (PVCs).
416416
// Also ignores any call that has a subresource defined.
417417
func (d *DefaultLimitRangerActions) SupportsAttributes(a admission.Attributes) bool {
418-
// Handle the special case for in-place pod vertical scaling
418+
// Handle in-place vertical scaling of pods, where users modify container
419+
// resources using the resize subresource.
419420
if a.GetSubresource() == "resize" && a.GetKind().GroupKind() == api.Kind("Pod") && a.GetOperation() == admission.Update {
420421
return true
421422
}

test/e2e/node/pod_resize.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ import (
4040
func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
4141
testcases := []struct {
4242
name string
43-
enableAdmissionPlugin func(ctx context.Context, f *framework.Framework)
43+
enableAdmissionPlugin func(ctx context.Context, f *framework.Framework, ns string)
4444
wantMemoryError string
4545
wantCPUError string
4646
}{
4747
{
4848
name: "pod-resize-resource-quota-test",
49-
enableAdmissionPlugin: func(ctx context.Context, f *framework.Framework) {
49+
enableAdmissionPlugin: func(ctx context.Context, f *framework.Framework, ns string) {
5050
resourceQuota := v1.ResourceQuota{
5151
ObjectMeta: metav1.ObjectMeta{
5252
Name: "resize-resource-quota",
53-
Namespace: f.Namespace.Name,
53+
Namespace: ns,
5454
},
5555
Spec: v1.ResourceQuotaSpec{
5656
Hard: v1.ResourceList{
@@ -61,19 +61,19 @@ func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
6161
}
6262

6363
ginkgo.By("Creating a ResourceQuota")
64-
_, rqErr := f.ClientSet.CoreV1().ResourceQuotas(f.Namespace.Name).Create(ctx, &resourceQuota, metav1.CreateOptions{})
64+
_, rqErr := f.ClientSet.CoreV1().ResourceQuotas(ns).Create(ctx, &resourceQuota, metav1.CreateOptions{})
6565
framework.ExpectNoError(rqErr, "failed to create resource quota")
6666
},
6767
wantMemoryError: "exceeded quota: resize-resource-quota, requested: memory=350Mi, used: memory=700Mi, limited: memory=800Mi",
6868
wantCPUError: "exceeded quota: resize-resource-quota, requested: cpu=200m, used: cpu=700m, limited: cpu=800m",
6969
},
7070
{
7171
name: "pod-resize-limit-ranger-test",
72-
enableAdmissionPlugin: func(ctx context.Context, f *framework.Framework) {
72+
enableAdmissionPlugin: func(ctx context.Context, f *framework.Framework, ns string) {
7373
lr := v1.LimitRange{
7474
ObjectMeta: metav1.ObjectMeta{
7575
Name: "resize-limit-ranger",
76-
Namespace: f.Namespace.Name,
76+
Namespace: ns,
7777
},
7878
Spec: v1.LimitRangeSpec{
7979
Limits: []v1.LimitRangeItem{
@@ -101,7 +101,7 @@ func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
101101
}
102102

103103
ginkgo.By("Creating a LimitRanger")
104-
_, lrErr := f.ClientSet.CoreV1().LimitRanges(f.Namespace.Name).Create(ctx, &lr, metav1.CreateOptions{})
104+
_, lrErr := f.ClientSet.CoreV1().LimitRanges(ns).Create(ctx, &lr, metav1.CreateOptions{})
105105
framework.ExpectNoError(lrErr, "failed to create limit ranger")
106106
},
107107
wantMemoryError: "forbidden: maximum memory usage per Container is 500Mi, but limit is 750Mi",
@@ -111,6 +111,9 @@ func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
111111

112112
for _, tc := range testcases {
113113
ginkgo.It(tc.name, func(ctx context.Context) {
114+
ns, err := f.CreateNamespace(ctx, tc.name, nil)
115+
framework.ExpectNoError(err, "failed creating Namespace")
116+
114117
containers := []e2epod.ResizableContainerInfo{
115118
{
116119
Name: "c1",
@@ -133,34 +136,33 @@ func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
133136
{"name":"c1", "resources":{"requests":{"cpu":"250m","memory":"750Mi"},"limits":{"cpu":"250m","memory":"750Mi"}}}
134137
]}}`
135138

136-
tc.enableAdmissionPlugin(ctx, f)
139+
tc.enableAdmissionPlugin(ctx, f, ns.Name)
137140

138141
tStamp := strconv.Itoa(time.Now().Nanosecond())
139142
e2epod.InitDefaultResizePolicy(containers)
140143
e2epod.InitDefaultResizePolicy(expected)
141-
testPod1 := e2epod.MakePodWithResizableContainers(f.Namespace.Name, "testpod1", tStamp, containers)
144+
testPod1 := e2epod.MakePodWithResizableContainers(ns.Name, "testpod1", tStamp, containers)
142145
testPod1 = e2epod.MustMixinRestrictedPodSecurity(testPod1)
143-
testPod2 := e2epod.MakePodWithResizableContainers(f.Namespace.Name, "testpod2", tStamp, containers)
146+
testPod2 := e2epod.MakePodWithResizableContainers(ns.Name, "testpod2", tStamp, containers)
144147
testPod2 = e2epod.MustMixinRestrictedPodSecurity(testPod2)
145148

146149
ginkgo.By("creating pods")
147150
podClient := e2epod.NewPodClient(f)
148-
newPod1 := podClient.CreateSync(ctx, testPod1)
149-
newPod2 := podClient.CreateSync(ctx, testPod2)
151+
newPods := podClient.CreateBatch(ctx, []*v1.Pod{testPod1, testPod2})
150152

151153
ginkgo.By("verifying initial pod resources, and policy are as expected")
152-
e2epod.VerifyPodResources(newPod1, containers)
154+
e2epod.VerifyPodResources(newPods[0], containers)
153155

154156
ginkgo.By("patching pod for resize within resource quota")
155-
patchedPod, pErr := f.ClientSet.CoreV1().Pods(newPod1.Namespace).Patch(ctx, newPod1.Name,
157+
patchedPod, pErr := f.ClientSet.CoreV1().Pods(newPods[0].Namespace).Patch(ctx, newPods[0].Name,
156158
types.StrategicMergePatchType, []byte(patchString), metav1.PatchOptions{}, "resize")
157159
framework.ExpectNoError(pErr, "failed to patch pod for resize")
158160

159161
ginkgo.By("verifying pod patched for resize within resource quota")
160162
e2epod.VerifyPodResources(patchedPod, expected)
161163

162164
ginkgo.By("waiting for resize to be actuated")
163-
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPod1)
165+
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPods[0])
164166
e2epod.ExpectPodResized(ctx, f, resizedPod, expected)
165167

166168
ginkgo.By("verifying pod resources after resize")
@@ -189,10 +191,10 @@ func doPodResizeAdmissionPluginsTests(f *framework.Framework) {
189191
framework.ExpectNoError(e2epod.VerifyPodStatusResources(patchedPodExceedMemory, expected))
190192

191193
ginkgo.By("deleting pods")
192-
delErr1 := e2epod.DeletePodWithWait(ctx, f.ClientSet, newPod1)
193-
framework.ExpectNoError(delErr1, "failed to delete pod %s", newPod1.Name)
194-
delErr2 := e2epod.DeletePodWithWait(ctx, f.ClientSet, newPod2)
195-
framework.ExpectNoError(delErr2, "failed to delete pod %s", newPod2.Name)
194+
delErr1 := e2epod.DeletePodWithWait(ctx, f.ClientSet, newPods[0])
195+
framework.ExpectNoError(delErr1, "failed to delete pod %s", newPods[0].Name)
196+
delErr2 := e2epod.DeletePodWithWait(ctx, f.ClientSet, newPods[1])
197+
framework.ExpectNoError(delErr2, "failed to delete pod %s", newPods[1].Name)
196198
})
197199
}
198200

0 commit comments

Comments
 (0)