Skip to content

Commit 9729ac8

Browse files
authored
Merge pull request kubernetes#128637 from jpbetz/fix-mutating-admission-defaulting
Bug fix: MutatingAdmissionPolicy should default builtin types after each mutation
2 parents 4391d09 + a6e0a7b commit 9729ac8

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/mutating/dispatcher.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
k8serrors "k8s.io/apimachinery/pkg/api/errors"
2828
"k8s.io/apimachinery/pkg/api/meta"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3031
"k8s.io/apimachinery/pkg/runtime/schema"
3132
"k8s.io/apimachinery/pkg/types"
3233
"k8s.io/apiserver/pkg/admission"
@@ -249,9 +250,20 @@ func (d *dispatcher) dispatchOne(
249250
return err
250251
}
251252

253+
switch versionedAttributes.VersionedObject.(type) {
254+
case *unstructured.Unstructured:
255+
// No conversion needed before defaulting for the patch object if the admitted object is unstructured.
256+
default:
257+
// Before defaulting, if the admitted object is a typed object, convert unstructured patch result back to a typed object.
258+
newVersionedObject, err = o.GetObjectConvertor().ConvertToVersion(newVersionedObject, versionedAttributes.GetKind().GroupVersion())
259+
if err != nil {
260+
return err
261+
}
262+
}
263+
o.GetObjectDefaulter().Default(newVersionedObject)
264+
252265
versionedAttributes.Dirty = true
253266
versionedAttributes.VersionedObject = newVersionedObject
254-
o.GetObjectDefaulter().Default(newVersionedObject)
255267
return nil
256268
}
257269

staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/mutating/dispatcher_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ func TestDispatcher(t *testing.T) {
122122
Volumes: []corev1.Volume{{Name: "x"}},
123123
},
124124
},
125+
Strategy: appsv1.DeploymentStrategy{
126+
Type: appsv1.RollingUpdateDeploymentStrategyType,
127+
},
125128
}},
126129
},
127130
{
@@ -144,6 +147,9 @@ func TestDispatcher(t *testing.T) {
144147
Volumes: []corev1.Volume{{Name: "x"}},
145148
},
146149
},
150+
Strategy: appsv1.DeploymentStrategy{
151+
Type: appsv1.RollingUpdateDeploymentStrategyType,
152+
},
147153
}},
148154
params: []runtime.Object{
149155
&corev1.ConfigMap{
@@ -212,6 +218,9 @@ func TestDispatcher(t *testing.T) {
212218
Volumes: []corev1.Volume{{Name: "x"}},
213219
},
214220
},
221+
Strategy: appsv1.DeploymentStrategy{
222+
Type: appsv1.RollingUpdateDeploymentStrategyType,
223+
},
215224
}},
216225
},
217226
{
@@ -233,6 +242,9 @@ func TestDispatcher(t *testing.T) {
233242
Volumes: []corev1.Volume{{Name: "x"}},
234243
},
235244
},
245+
Strategy: appsv1.DeploymentStrategy{
246+
Type: appsv1.RollingUpdateDeploymentStrategyType,
247+
},
236248
}},
237249
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
238250
{
@@ -317,6 +329,9 @@ func TestDispatcher(t *testing.T) {
317329
Volumes: []corev1.Volume{{Name: "x"}},
318330
},
319331
},
332+
Strategy: appsv1.DeploymentStrategy{
333+
Type: appsv1.RollingUpdateDeploymentStrategyType,
334+
},
320335
}},
321336
},
322337
{
@@ -338,6 +353,9 @@ func TestDispatcher(t *testing.T) {
338353
Volumes: []corev1.Volume{{Name: "x"}},
339354
},
340355
},
356+
Strategy: appsv1.DeploymentStrategy{
357+
Type: appsv1.RollingUpdateDeploymentStrategyType,
358+
},
341359
}},
342360
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
343361
{
@@ -444,6 +462,9 @@ func TestDispatcher(t *testing.T) {
444462
Volumes: []corev1.Volume{{Name: "x"}},
445463
},
446464
},
465+
Strategy: appsv1.DeploymentStrategy{
466+
Type: appsv1.RollingUpdateDeploymentStrategyType,
467+
},
447468
}},
448469
},
449470
{
@@ -466,6 +487,9 @@ func TestDispatcher(t *testing.T) {
466487
Volumes: []corev1.Volume{{Name: "x"}},
467488
},
468489
},
490+
Strategy: appsv1.DeploymentStrategy{
491+
Type: appsv1.RollingUpdateDeploymentStrategyType,
492+
},
469493
}},
470494
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
471495
{
@@ -571,6 +595,9 @@ func TestDispatcher(t *testing.T) {
571595
Volumes: []corev1.Volume{{Name: "x"}},
572596
},
573597
},
598+
Strategy: appsv1.DeploymentStrategy{
599+
Type: appsv1.RollingUpdateDeploymentStrategyType,
600+
},
574601
}},
575602
},
576603
}
@@ -597,6 +624,11 @@ func TestDispatcher(t *testing.T) {
597624
t.Fatal(err)
598625
}
599626

627+
// Register a fake defaulter since registering the full defaulter adds noise
628+
// and creates dep cycles.
629+
scheme.AddTypeDefaultingFunc(&appsv1.Deployment{},
630+
func(obj interface{}) { fakeSetDefaultForDeployment(obj.(*appsv1.Deployment)) })
631+
600632
objectInterfaces := admission.NewObjectInterfacesFromScheme(scheme)
601633

602634
for _, tc := range testCases {
@@ -673,3 +705,11 @@ func (t testParamScope) Name() meta.RESTScopeName {
673705
}
674706

675707
var _ meta.RESTScope = testParamScope{}
708+
709+
func fakeSetDefaultForDeployment(obj *appsv1.Deployment) {
710+
// Just default strategy type so the tests have a defaulted field to observe
711+
strategy := &obj.Spec.Strategy
712+
if strategy.Type == "" {
713+
strategy.Type = appsv1.RollingUpdateDeploymentStrategyType
714+
}
715+
}

0 commit comments

Comments
 (0)