Add WithReinvocationTesting utility for ensuring that admission plugin reinvocation is idempotent

k3s-v1.15.3
Joe Betz 2019-05-23 22:24:20 -07:00
parent a6e1db97f0
commit cc2e3616f0
32 changed files with 196 additions and 61 deletions

View File

@ -24,6 +24,7 @@ go_test(
"//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
],
)

View File

@ -21,12 +21,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core"
)
func TestAdmissionNonNilAttribute(t *testing.T) {
handler := NewAlwaysAdmit()
err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
handler := admissiontesting.WithReinvocationTesting(t, NewAlwaysAdmit().(*alwaysAdmit))
err := handler.Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("Unexpected error returned from admission handler")
}

View File

@ -27,6 +27,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
],
)

View File

@ -22,6 +22,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core"
)
@ -29,7 +30,7 @@ import (
// set to Always
func TestAdmission(t *testing.T) {
namespace := "test"
handler := &AlwaysPullImages{}
handler := admissiontesting.WithReinvocationTesting(t, &AlwaysPullImages{})
pod := api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: namespace},
Spec: api.PodSpec{
@ -137,7 +138,7 @@ func TestOtherResources(t *testing.T) {
}
for _, tc := range tests {
handler := &AlwaysPullImages{}
handler := admissiontesting.WithReinvocationTesting(t, &AlwaysPullImages{})
err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, &metav1.CreateOptions{}, false, nil), nil)

View File

@ -15,6 +15,7 @@ go_test(
"//pkg/apis/core/helper:go_default_library",
"//pkg/scheduler/api:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
],
)

View File

@ -20,6 +20,7 @@ import (
"testing"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
@ -32,7 +33,7 @@ func TestForgivenessAdmission(t *testing.T) {
return &s
}
handler := NewDefaultTolerationSeconds()
handler := admissiontesting.WithReinvocationTesting(t, NewDefaultTolerationSeconds())
// NOTE: for anyone who want to modify this test, the order of tolerations matters!
tests := []struct {
description string

View File

@ -24,6 +24,7 @@ go_test(
"//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
],
)

View File

@ -21,12 +21,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core"
)
func TestAdmission(t *testing.T) {
handler := NewAlwaysDeny()
err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
handler := admissiontesting.WithReinvocationTesting(t, NewAlwaysDeny().(*alwaysDeny))
err := handler.Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err == nil {
t.Error("Expected error returned from admission handler")
}

View File

@ -23,6 +23,7 @@ go_test(
"//pkg/apis/core/helper:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
],
)

View File

@ -21,13 +21,14 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
)
func TestAdmit(t *testing.T) {
plugin := newExtendedResourceToleration()
plugin := admissiontesting.WithReinvocationTesting(t, newExtendedResourceToleration())
containerRequestingCPU := core.Container{
Resources: core.ResourceRequirements{

View File

@ -46,6 +46,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",

View File

@ -30,6 +30,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
@ -705,7 +706,7 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{})
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Fatal(err)
}
@ -735,7 +736,7 @@ func TestLimitRangerAdmitPod(t *testing.T) {
informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{})
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Fatal(err)
}

View File

@ -36,6 +36,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
@ -99,7 +100,7 @@ func TestAdmission(t *testing.T) {
informerFactory.Start(wait.NeverStop)
pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}
@ -119,7 +120,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
informerFactory.Start(wait.NeverStop)
pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}
@ -139,7 +140,7 @@ func TestAdmissionDryRun(t *testing.T) {
informerFactory.Start(wait.NeverStop)
pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, true, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, true, nil), nil)
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}
@ -157,10 +158,10 @@ func TestIgnoreAdmission(t *testing.T) {
t.Errorf("unexpected error initializing handler: %v", err)
}
informerFactory.Start(wait.NeverStop)
chainHandler := admission.NewChainHandler(handler)
chainHandler := admissiontesting.WithReinvocationTesting(t, admission.NewChainHandler(handler))
pod := newPod(namespace)
err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, chainHandler).Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}
@ -182,7 +183,7 @@ func TestAdmissionWithLatentCache(t *testing.T) {
informerFactory.Start(wait.NeverStop)
pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}

View File

@ -19,6 +19,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
kadmission "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
@ -447,7 +448,7 @@ func TestAdmitConflictWithDifferentNamespaceShouldDoNothing(t *testing.T) {
},
}
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -493,7 +494,7 @@ func TestAdmitConflictWithNonMatchingLabelsShouldNotError(t *testing.T) {
},
}
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -540,7 +541,7 @@ func TestAdmitConflictShouldNotModifyPod(t *testing.T) {
},
}
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -603,7 +604,7 @@ func TestAdmit(t *testing.T) {
},
}
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -663,7 +664,7 @@ func TestAdmitMirrorPod(t *testing.T) {
},
}
if err := admitPod(mirrorPod, pip); err != nil {
if err := admitPod(t, mirrorPod, pip); err != nil {
t.Fatal(err)
}
@ -733,7 +734,7 @@ func TestExclusionNoAdmit(t *testing.T) {
},
}
originalPod := pod.DeepCopy()
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -797,7 +798,7 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
},
}
originalPod := pod.DeepCopy()
err := admitPod(pod, pip)
err := admitPod(t, pod, pip)
if err != nil {
t.Fatal(err)
}
@ -808,11 +809,11 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
}
}
func admitPod(pod *api.Pod, pip *settingsv1alpha1.PodPreset) error {
func admitPod(t *testing.T, pod *api.Pod, pip *settingsv1alpha1.PodPreset) error {
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
store := informerFactory.Settings().V1alpha1().PodPresets().Informer().GetStore()
store.Add(pip)
plugin := NewTestAdmission(informerFactory.Settings().V1alpha1().PodPresets().Lister())
plugin := admissiontesting.WithReinvocationTesting(t, NewTestAdmission(informerFactory.Settings().V1alpha1().PodPresets().Lister()))
attrs := kadmission.NewAttributesRecord(
pod,
nil,

View File

@ -21,6 +21,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",

View File

@ -26,6 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
@ -265,8 +266,7 @@ func TestPodAdmission(t *testing.T) {
handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist}
pod := test.pod
pod.Spec.Tolerations = test.podTolerations
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
@ -343,7 +343,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
}
// if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations.
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.CreateOptions{}, false, nil), nil)
err = admissiontesting.WithReinvocationTesting(t, handler).Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.CreateOptions{}, false, nil), nil)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}

View File

@ -19,6 +19,7 @@ go_test(
"//staging/src/k8s.io/api/scheduling/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",

View File

@ -24,6 +24,7 @@ import (
schedulingv1 "k8s.io/api/scheduling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/user"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
@ -605,7 +606,7 @@ func TestPodAdmission(t *testing.T) {
false,
nil,
)
err := ctrl.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, ctrl).Admit(attrs, nil)
klog.Infof("Got %v", err)
if !test.expectError {
if err != nil {

View File

@ -51,6 +51,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",

View File

@ -30,6 +30,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
kadmission "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
@ -1779,7 +1780,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*
attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, nil, false, userInfo)
annotations := make(map[string]string)
attrs = &fakeAttributes{attrs, annotations}
err := plugin.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, plugin).Admit(attrs, nil)
if shouldPassAdmit && err != nil {
t.Errorf("%s: expected no errors on Admit but received %v", testCaseName, err)

View File

@ -49,6 +49,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",

View File

@ -22,12 +22,12 @@ import (
"testing"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
corev1listers "k8s.io/client-go/listers/core/v1"
@ -65,7 +65,8 @@ func TestIgnoresNonCreate(t *testing.T) {
func TestIgnoresNonPodResource(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("CustomResource").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
handler := admissiontesting.WithReinvocationTesting(t, NewServiceAccount())
err := handler.Admit(attrs, nil)
if err != nil {
t.Errorf("Expected non-pod resource allowed, got err: %v", err)
}
@ -73,7 +74,8 @@ func TestIgnoresNonPodResource(t *testing.T) {
func TestIgnoresNilObject(t *testing.T) {
attrs := admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
handler := admissiontesting.WithReinvocationTesting(t, NewServiceAccount())
err := handler.Admit(attrs, nil)
if err != nil {
t.Errorf("Expected nil object allowed allowed, got err: %v", err)
}
@ -82,7 +84,8 @@ func TestIgnoresNilObject(t *testing.T) {
func TestIgnoresNonPodObject(t *testing.T) {
obj := &api.Namespace{}
attrs := admission.NewAttributesRecord(obj, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
handler := admissiontesting.WithReinvocationTesting(t, NewServiceAccount())
err := handler.Admit(attrs, nil)
if err != nil {
t.Errorf("Expected non pod object allowed, got err: %v", err)
}
@ -102,7 +105,7 @@ func TestIgnoresMirrorPod(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, NewServiceAccount()).Admit(attrs, nil)
if err != nil {
t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err)
}
@ -120,7 +123,7 @@ func TestRejectsMirrorPodWithServiceAccount(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, NewServiceAccount()).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a service account")
}
@ -140,7 +143,7 @@ func TestRejectsMirrorPodWithSecretVolumes(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, NewServiceAccount()).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume")
}
@ -165,7 +168,7 @@ func TestRejectsMirrorPodWithServiceAccountTokenVolumeProjections(t *testing.T)
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := NewServiceAccount().Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, NewServiceAccount()).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection")
}
@ -190,7 +193,7 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -218,7 +221,7 @@ func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err == nil || !errors.IsServerTimeout(err) {
t.Errorf("Expected server timeout error for missing API token: %v", err)
}
@ -243,7 +246,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -265,7 +268,7 @@ func TestDeniesInvalidServiceAccount(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected error for missing service account, got none")
}
@ -331,7 +334,7 @@ func TestAutomountsAPIToken(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -360,7 +363,7 @@ func TestAutomountsAPIToken(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if pod.Spec.ServiceAccountName != DefaultServiceAccountName {
@ -442,7 +445,7 @@ func TestRespectsExistingMount(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -472,7 +475,7 @@ func TestRespectsExistingMount(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if pod.Spec.ServiceAccountName != DefaultServiceAccountName {
@ -518,7 +521,7 @@ func TestAllowsReferencedSecret(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -542,7 +545,7 @@ func TestAllowsReferencedSecret(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -566,7 +569,7 @@ func TestAllowsReferencedSecret(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Errorf("Unexpected error: %v", err)
}
}
@ -596,7 +599,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err == nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference")
}
@ -620,7 +623,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
t.Errorf("Unexpected error: %v", err)
}
@ -644,7 +647,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
},
}
attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
t.Errorf("Unexpected error: %v", err)
}
}
@ -675,7 +678,7 @@ func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference")
}
@ -707,7 +710,7 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -736,7 +739,7 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference")
}
@ -769,7 +772,7 @@ func TestDoNotAddImagePullSecrets(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -803,7 +806,7 @@ func TestAddImagePullSecrets(t *testing.T) {
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -884,7 +887,7 @@ func TestMultipleReferencedSecrets(t *testing.T) {
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
if err := admit.Admit(attrs, nil); err != nil {
if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil); err != nil {
t.Fatal(err)
}
@ -1038,7 +1041,7 @@ func TestAutomountIsBackwardsCompatible(t *testing.T) {
},
}
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
err := admit.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, admit).Admit(attrs, nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

View File

@ -37,6 +37,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library",
],
)

View File

@ -28,6 +28,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
cloudprovider "k8s.io/cloud-provider"
api "k8s.io/kubernetes/pkg/apis/core"
)
@ -754,7 +755,7 @@ func Test_PVLAdmission(t *testing.T) {
for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
setPVLabeler(testcase.handler, testcase.pvlabeler)
handler := admission.NewChainHandler(testcase.handler)
handler := admissiontesting.WithReinvocationTesting(t, admission.NewChainHandler(testcase.handler))
err := handler.Admit(admission.NewAttributesRecord(testcase.preAdmissionPV, nil, api.Kind("PersistentVolume").WithVersion("version"), testcase.preAdmissionPV.Namespace, testcase.preAdmissionPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
if !reflect.DeepEqual(err, testcase.err) {

View File

@ -36,6 +36,7 @@ go_test(
"//staging/src/k8s.io/api/storage/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],

View File

@ -24,6 +24,7 @@ import (
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers"
api "k8s.io/kubernetes/pkg/apis/core"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
@ -212,7 +213,7 @@ func TestAdmission(t *testing.T) {
false, // dryRun
nil, // userInfo
)
err := ctrl.Admit(attrs, nil)
err := admissiontesting.WithReinvocationTesting(t, ctrl).Admit(attrs, nil)
klog.Infof("Got %v", err)
if err != nil && !test.expectError {
t.Errorf("Test %q: unexpected error received: %v", test.name, err)

View File

@ -92,6 +92,7 @@ filegroup(
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -0,0 +1,29 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/admission/testing",
importpath = "k8s.io/apiserver/pkg/admission/testing",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,75 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"reflect"
"testing"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apiserver/pkg/admission"
)
// WithReinvocationTesting wraps a mutating admission handler and reinvokes it each time Admit is
// called. It checks the admission output object and reports a test error if the admission handler
// performs non-idempotent mutatations to the object.
func WithReinvocationTesting(t *testing.T, admission admission.MutationInterface) admission.MutationInterface {
return &reinvoker{t, admission}
}
type reinvoker struct {
t *testing.T
admission admission.MutationInterface
}
// Admit reinvokes the admission handler and reports a test error if the admission handler performs
// non-idempotent mutatations to the admission object.
func (r *reinvoker) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
r.t.Helper()
outputs := []runtime.Object{}
for i := 0; i < 2; i++ {
err := r.admission.Admit(a, o)
if err != nil {
return err
}
if a.GetObject() != nil {
// keep a copy of the output for subsequent idempotency checking
outputs = append(outputs, a.GetObject().DeepCopyObject())
// replace a.GetObject() with a copy of itself to make sure admission is safe to reinvoke with a round-tripped copy (no pointer comparisons are done)
if deepCopyInto, ok := reflect.TypeOf(a.GetObject()).MethodByName("DeepCopyInto"); ok {
deepCopyInto.Func.Call([]reflect.Value{
reflect.ValueOf(a.GetObject().DeepCopyObject()),
reflect.ValueOf(a.GetObject()),
})
}
}
}
for i := 1; i < len(outputs); i++ {
if !apiequality.Semantic.DeepEqual(outputs[0], outputs[i]) {
r.t.Errorf("expected mutating admission plugin to be idempontent, but got different results on reinvocation, diff:\n%s", diff.ObjectReflectDiff(outputs[0], outputs[i]))
}
}
return nil
}
// Handles will return true if any of the admission andler handlers handle the given operation.
func (r *reinvoker) Handles(operation admission.Operation) bool {
r.t.Helper()
return r.admission.Handles(operation)
}

1
vendor/modules.txt vendored
View File

@ -1195,6 +1195,7 @@ k8s.io/apiserver/pkg/admission/plugin/webhook/request
k8s.io/apiserver/pkg/admission/plugin/webhook/rules
k8s.io/apiserver/pkg/admission/plugin/webhook/util
k8s.io/apiserver/pkg/admission/plugin/webhook/validating
k8s.io/apiserver/pkg/admission/testing
k8s.io/apiserver/pkg/apis/apiserver
k8s.io/apiserver/pkg/apis/apiserver/install
k8s.io/apiserver/pkg/apis/apiserver/v1alpha1