...

Source file src/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission_test.go

Documentation: k8s.io/kubernetes/plugin/pkg/admission/namespace/exists

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    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  // newHandlerForTest returns the admission controller configured for testing.
    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  // newMockClientForTest creates a mock client that returns a client configured for the specified list of namespaces.
    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  // newPod returns a new pod for the specified namespace
    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  // TestAdmissionNamespaceExists verifies pod is admitted only if namespace exists.
    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  // TestAdmissionNamespaceDoesNotExist verifies pod is not admitted if namespace does not exist.
    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