1
16
17 package exists
18
19 import (
20 "context"
21 "fmt"
22 "testing"
23 "time"
24
25 corev1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/util/wait"
29 "k8s.io/apiserver/pkg/admission"
30 genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
31 informers "k8s.io/client-go/informers"
32 "k8s.io/client-go/kubernetes"
33 "k8s.io/client-go/kubernetes/fake"
34 core "k8s.io/client-go/testing"
35 api "k8s.io/kubernetes/pkg/apis/core"
36 )
37
38
39 func newHandlerForTest(c kubernetes.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
40 f := informers.NewSharedInformerFactory(c, 5*time.Minute)
41 handler := NewExists()
42 pluginInitializer := genericadmissioninitializer.New(c, nil, f, nil, nil, nil, nil)
43 pluginInitializer.Initialize(handler)
44 err := admission.ValidateInitialization(handler)
45 return handler, f, err
46 }
47
48
49 func newMockClientForTest(namespaces []string) *fake.Clientset {
50 mockClient := &fake.Clientset{}
51 mockClient.AddReactor("list", "namespaces", func(action core.Action) (bool, runtime.Object, error) {
52 namespaceList := &corev1.NamespaceList{
53 ListMeta: metav1.ListMeta{
54 ResourceVersion: fmt.Sprintf("%d", len(namespaces)),
55 },
56 }
57 for i, ns := range namespaces {
58 namespaceList.Items = append(namespaceList.Items, corev1.Namespace{
59 ObjectMeta: metav1.ObjectMeta{
60 Name: ns,
61 ResourceVersion: fmt.Sprintf("%d", i),
62 },
63 })
64 }
65 return true, namespaceList, nil
66 })
67 return mockClient
68 }
69
70
71 func newPod(namespace string) api.Pod {
72 return api.Pod{
73 ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: namespace},
74 Spec: api.PodSpec{
75 Volumes: []api.Volume{{Name: "vol"}},
76 Containers: []api.Container{{Name: "ctr", Image: "image"}},
77 },
78 }
79 }
80
81
82 func TestAdmissionNamespaceExists(t *testing.T) {
83 namespace := "test"
84 mockClient := newMockClientForTest([]string{namespace})
85 handler, informerFactory, err := newHandlerForTest(mockClient)
86 if err != nil {
87 t.Errorf("unexpected error initializing handler: %v", err)
88 }
89 informerFactory.Start(wait.NeverStop)
90
91 pod := newPod(namespace)
92 err = handler.Validate(context.TODO(), 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)
93 if err != nil {
94 t.Errorf("unexpected error returned from admission handler")
95 }
96 }
97
98
99 func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
100 namespace := "test"
101 mockClient := newMockClientForTest([]string{})
102 mockClient.AddReactor("get", "namespaces", func(action core.Action) (bool, runtime.Object, error) {
103 return true, nil, fmt.Errorf("nope, out of luck")
104 })
105 handler, informerFactory, err := newHandlerForTest(mockClient)
106 if err != nil {
107 t.Errorf("unexpected error initializing handler: %v", err)
108 }
109 informerFactory.Start(wait.NeverStop)
110
111 pod := newPod(namespace)
112 err = handler.Validate(context.TODO(), 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)
113 if err == nil {
114 actions := ""
115 for _, action := range mockClient.Actions() {
116 actions = actions + action.GetVerb() + ":" + action.GetResource().Resource + ":" + action.GetSubresource() + ", "
117 }
118 t.Errorf("expected error returned from admission handler: %v", actions)
119 }
120 }
121
View as plain text