Add WithReinvocationTesting utility for ensuring that admission plugin reinvocation is idempotent

This commit is contained in:
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", "//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/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: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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
) )
func TestAdmissionNonNilAttribute(t *testing.T) { func TestAdmissionNonNilAttribute(t *testing.T) {
handler := NewAlwaysAdmit() handler := admissiontesting.WithReinvocationTesting(t, NewAlwaysAdmit().(*alwaysAdmit))
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) 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 { if err != nil {
t.Errorf("Unexpected error returned from admission handler") 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/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime: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: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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
) )
@ -29,7 +30,7 @@ import (
// set to Always // set to Always
func TestAdmission(t *testing.T) { func TestAdmission(t *testing.T) {
namespace := "test" namespace := "test"
handler := &AlwaysPullImages{} handler := admissiontesting.WithReinvocationTesting(t, &AlwaysPullImages{})
pod := api.Pod{ pod := api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: namespace}, ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: namespace},
Spec: api.PodSpec{ Spec: api.PodSpec{
@ -137,7 +138,7 @@ func TestOtherResources(t *testing.T) {
} }
for _, tc := range tests { 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) 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/apis/core/helper:go_default_library",
"//pkg/scheduler/api: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:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
], ],
) )

View File

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

View File

@ -24,6 +24,7 @@ go_test(
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/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: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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
) )
func TestAdmission(t *testing.T) { func TestAdmission(t *testing.T) {
handler := NewAlwaysDeny() handler := admissiontesting.WithReinvocationTesting(t, NewAlwaysDeny().(*alwaysDeny))
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) 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 { if err == nil {
t.Error("Expected error returned from admission handler") t.Error("Expected error returned from admission handler")
} }

View File

@ -23,6 +23,7 @@ go_test(
"//pkg/apis/core/helper:go_default_library", "//pkg/apis/core/helper:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource: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: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/apimachinery/pkg/api/resource"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/core/helper"
) )
func TestAdmit(t *testing.T) { func TestAdmit(t *testing.T) {
plugin := newExtendedResourceToleration() plugin := admissiontesting.WithReinvocationTesting(t, newExtendedResourceToleration())
containerRequestingCPU := core.Container{ containerRequestingCPU := core.Container{
Resources: core.ResourceRequirements{ 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/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission: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/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/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake: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/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer" genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
@ -705,7 +706,7 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{}) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -735,7 +736,7 @@ func TestLimitRangerAdmitPod(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{}) 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 { if err != nil {
t.Fatal(err) 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/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission: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/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/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake: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/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer" genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
@ -99,7 +100,7 @@ func TestAdmission(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) 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 { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
@ -119,7 +120,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) 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 { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
@ -139,7 +140,7 @@ func TestAdmissionDryRun(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) 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 { if err != nil {
t.Errorf("unexpected error returned from admission handler") 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) t.Errorf("unexpected error initializing handler: %v", err)
} }
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
chainHandler := admission.NewChainHandler(handler) chainHandler := admissiontesting.WithReinvocationTesting(t, admission.NewChainHandler(handler))
pod := newPod(namespace) 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 { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
@ -182,7 +183,7 @@ func TestAdmissionWithLatentCache(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) 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 { if err != nil {
t.Errorf("unexpected error returned from admission handler") 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/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff: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: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/authentication/user:go_default_library",
"//staging/src/k8s.io/client-go/informers: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/kubernetes/fake:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
kadmission "k8s.io/apiserver/pkg/admission" kadmission "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake" "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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -493,7 +494,7 @@ func TestAdmitConflictWithNonMatchingLabelsShouldNotError(t *testing.T) {
}, },
} }
err := admitPod(pod, pip) err := admitPod(t, pod, pip)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -540,7 +541,7 @@ func TestAdmitConflictShouldNotModifyPod(t *testing.T) {
}, },
} }
err := admitPod(pod, pip) err := admitPod(t, pod, pip)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -603,7 +604,7 @@ func TestAdmit(t *testing.T) {
}, },
} }
err := admitPod(pod, pip) err := admitPod(t, pod, pip)
if err != nil { if err != nil {
t.Fatal(err) 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) t.Fatal(err)
} }
@ -733,7 +734,7 @@ func TestExclusionNoAdmit(t *testing.T) {
}, },
} }
originalPod := pod.DeepCopy() originalPod := pod.DeepCopy()
err := admitPod(pod, pip) err := admitPod(t, pod, pip)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -797,7 +798,7 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
}, },
} }
originalPod := pod.DeepCopy() originalPod := pod.DeepCopy()
err := admitPod(pod, pip) err := admitPod(t, pod, pip)
if err != nil { if err != nil {
t.Fatal(err) 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()) informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
store := informerFactory.Settings().V1alpha1().PodPresets().Informer().GetStore() store := informerFactory.Settings().V1alpha1().PodPresets().Informer().GetStore()
store.Add(pip) store.Add(pip)
plugin := NewTestAdmission(informerFactory.Settings().V1alpha1().PodPresets().Lister()) plugin := admissiontesting.WithReinvocationTesting(t, NewTestAdmission(informerFactory.Settings().V1alpha1().PodPresets().Lister()))
attrs := kadmission.NewAttributesRecord( attrs := kadmission.NewAttributesRecord(
pod, pod,
nil, 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/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:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer: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/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers: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:go_default_library",

View File

@ -26,6 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer" genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
@ -265,8 +266,7 @@ func TestPodAdmission(t *testing.T) {
handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist} handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist}
pod := test.pod pod := test.pod
pod.Spec.Tolerations = test.podTolerations pod.Spec.Tolerations = test.podTolerations
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)
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)
if test.admit && err != nil { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } 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. // 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 { if err != nil {
t.Errorf("expected no error, got: %v", err) 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/api/scheduling/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/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: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/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature: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/informers:go_default_library",

View File

@ -24,6 +24,7 @@ import (
schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1 "k8s.io/api/scheduling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
@ -605,7 +606,7 @@ func TestPodAdmission(t *testing.T) {
false, false,
nil, nil,
) )
err := ctrl.Admit(attrs, nil) err := admissiontesting.WithReinvocationTesting(t, ctrl).Admit(attrs, nil)
klog.Infof("Got %v", err) klog.Infof("Got %v", err)
if !test.expectError { if !test.expectError {
if err != nil { 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/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff: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: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/serviceaccount:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user: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", "//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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
kadmission "k8s.io/apiserver/pkg/admission" kadmission "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer" "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) 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) annotations := make(map[string]string)
attrs = &fakeAttributes{attrs, annotations} attrs = &fakeAttributes{attrs, annotations}
err := plugin.Admit(attrs, nil) err := admissiontesting.WithReinvocationTesting(t, plugin).Admit(attrs, nil)
if shouldPassAdmit && err != nil { if shouldPassAdmit && err != nil {
t.Errorf("%s: expected no errors on Admit but received %v", testCaseName, err) 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/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types: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: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/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake: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", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",

View File

@ -22,12 +22,12 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
corev1listers "k8s.io/client-go/listers/core/v1" corev1listers "k8s.io/client-go/listers/core/v1"
@ -65,7 +65,8 @@ func TestIgnoresNonCreate(t *testing.T) {
func TestIgnoresNonPodResource(t *testing.T) { func TestIgnoresNonPodResource(t *testing.T) {
pod := &api.Pod{} 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) 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 { if err != nil {
t.Errorf("Expected non-pod resource allowed, got err: %v", err) 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) { 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) 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 { if err != nil {
t.Errorf("Expected nil object allowed allowed, got err: %v", err) 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) { func TestIgnoresNonPodObject(t *testing.T) {
obj := &api.Namespace{} 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) 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 { if err != nil {
t.Errorf("Expected non pod object allowed, got err: %v", err) 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) 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 { if err != nil {
t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err) 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) 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 { if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a service account") 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) 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 { if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume") 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) 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 { if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection") 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{} 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -218,7 +221,7 @@ func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) {
pod := &api.Pod{} 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) 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) { if err == nil || !errors.IsServerTimeout(err) {
t.Errorf("Expected server timeout error for missing API token: %v", 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{} 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -265,7 +268,7 @@ func TestDeniesInvalidServiceAccount(t *testing.T) {
pod := &api.Pod{} 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) 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 { if err == nil {
t.Errorf("Expected error for missing service account, got none") 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) 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) 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) t.Errorf("Unexpected error: %v", err)
} }
if pod.Spec.ServiceAccountName != DefaultServiceAccountName { 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) 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) 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) t.Errorf("Unexpected error: %v", err)
} }
if pod.Spec.ServiceAccountName != DefaultServiceAccountName { 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) 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) 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) 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) 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) 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) 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) 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") 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) 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) 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) 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) 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) 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 { if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference") 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) 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) 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 { if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference") 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -803,7 +806,7 @@ func TestAddImagePullSecrets(t *testing.T) {
pod := &api.Pod{} 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) 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) 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) 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) 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 { if err != nil {
t.Errorf("Unexpected error: %v", err) 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/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema: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:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:go_default_library",
"//staging/src/k8s.io/cloud-provider: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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
) )
@ -754,7 +755,7 @@ func Test_PVLAdmission(t *testing.T) {
for _, testcase := range testcases { for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) { t.Run(testcase.name, func(t *testing.T) {
setPVLabeler(testcase.handler, testcase.pvlabeler) 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) 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) { 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/api/storage/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/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: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/informers:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],

View File

@ -24,6 +24,7 @@ import (
storagev1 "k8s.io/api/storage/v1" storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
admissiontesting "k8s.io/apiserver/pkg/admission/testing"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util" storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
@ -212,7 +213,7 @@ func TestAdmission(t *testing.T) {
false, // dryRun false, // dryRun
nil, // userInfo nil, // userInfo
) )
err := ctrl.Admit(attrs, nil) err := admissiontesting.WithReinvocationTesting(t, ctrl).Admit(attrs, nil)
klog.Infof("Got %v", err) klog.Infof("Got %v", err)
if err != nil && !test.expectError { if err != nil && !test.expectError {
t.Errorf("Test %q: unexpected error received: %v", test.name, err) 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/testing:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util: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/plugin/webhook/validating:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:all-srcs",
], ],
tags = ["automanaged"], 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/rules
k8s.io/apiserver/pkg/admission/plugin/webhook/util k8s.io/apiserver/pkg/admission/plugin/webhook/util
k8s.io/apiserver/pkg/admission/plugin/webhook/validating 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
k8s.io/apiserver/pkg/apis/apiserver/install k8s.io/apiserver/pkg/apis/apiserver/install
k8s.io/apiserver/pkg/apis/apiserver/v1alpha1 k8s.io/apiserver/pkg/apis/apiserver/v1alpha1