...

Source file src/k8s.io/kubernetes/cmd/kube-controller-manager/app/core_test.go

Documentation: k8s.io/kubernetes/cmd/kube-controller-manager/app

     1  /*
     2  Copyright 2019 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 app
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  	"time"
    23  
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/client-go/discovery"
    26  	fakediscovery "k8s.io/client-go/discovery/fake"
    27  	"k8s.io/client-go/informers"
    28  	clientset "k8s.io/client-go/kubernetes"
    29  	fakeclientset "k8s.io/client-go/kubernetes/fake"
    30  	restclient "k8s.io/client-go/rest"
    31  )
    32  
    33  // TestClientBuilder inherits ClientBuilder and can accept a given fake clientset.
    34  type TestClientBuilder struct {
    35  	clientset clientset.Interface
    36  }
    37  
    38  func (TestClientBuilder) Config(name string) (*restclient.Config, error) { return nil, nil }
    39  func (TestClientBuilder) ConfigOrDie(name string) *restclient.Config {
    40  	return &restclient.Config{}
    41  }
    42  
    43  func (TestClientBuilder) Client(name string) (clientset.Interface, error) { return nil, nil }
    44  func (m TestClientBuilder) ClientOrDie(name string) clientset.Interface {
    45  	return m.clientset
    46  }
    47  
    48  func (m TestClientBuilder) DiscoveryClient(name string) (discovery.DiscoveryInterface, error) {
    49  	return m.clientset.Discovery(), nil
    50  }
    51  func (m TestClientBuilder) DiscoveryClientOrDie(name string) discovery.DiscoveryInterface {
    52  	ret, err := m.DiscoveryClient(name)
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  	return ret
    57  }
    58  
    59  // FakeDiscoveryWithError inherits DiscoveryInterface(via FakeDiscovery) with some methods accepting testing data.
    60  type FakeDiscoveryWithError struct {
    61  	fakediscovery.FakeDiscovery
    62  	PossibleResources []*metav1.APIResourceList
    63  	Err               error
    64  }
    65  
    66  func (d FakeDiscoveryWithError) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
    67  	return d.PossibleResources, d.Err
    68  }
    69  
    70  // FakeDiscoveryWithError inherits Clientset(via FakeClientset) with overridden Discovery method.
    71  type FakeClientSet struct {
    72  	fakeclientset.Clientset
    73  	DiscoveryObj *FakeDiscoveryWithError
    74  }
    75  
    76  func (c *FakeClientSet) Discovery() discovery.DiscoveryInterface {
    77  	return c.DiscoveryObj
    78  }
    79  
    80  func (c *FakeClientSet) GetPossibleResources() []*metav1.APIResourceList {
    81  	return c.DiscoveryObj.PossibleResources
    82  }
    83  
    84  // Create a fake Clientset with its Discovery method overridden.
    85  func NewFakeClientset(fakeDiscovery FakeDiscoveryWithError) *FakeClientSet {
    86  	cs := &FakeClientSet{}
    87  	cs.DiscoveryObj = &fakeDiscovery
    88  	return cs
    89  }
    90  
    91  func possibleDiscoveryResource() []*metav1.APIResourceList {
    92  	return []*metav1.APIResourceList{
    93  		{
    94  			GroupVersion: "create/v1",
    95  			APIResources: []metav1.APIResource{
    96  				{
    97  					Name:       "jobs",
    98  					Verbs:      []string{"create", "list", "watch", "delete"},
    99  					ShortNames: []string{"jz"},
   100  					Categories: []string{"all"},
   101  				},
   102  			},
   103  		},
   104  	}
   105  }
   106  
   107  func TestController_DiscoveryError(t *testing.T) {
   108  	controllerDescriptorMap := map[string]*ControllerDescriptor{
   109  		"ResourceQuotaController":          newResourceQuotaControllerDescriptor(),
   110  		"GarbageCollectorController":       newGarbageCollectorControllerDescriptor(),
   111  		"EndpointSliceController":          newEndpointSliceControllerDescriptor(),
   112  		"EndpointSliceMirroringController": newEndpointSliceMirroringControllerDescriptor(),
   113  		"PodDisruptionBudgetController":    newDisruptionControllerDescriptor(),
   114  	}
   115  
   116  	tcs := map[string]struct {
   117  		discoveryError    error
   118  		expectedErr       bool
   119  		possibleResources []*metav1.APIResourceList
   120  	}{
   121  		"No Discovery Error": {
   122  			discoveryError:    nil,
   123  			possibleResources: possibleDiscoveryResource(),
   124  			expectedErr:       false,
   125  		},
   126  		"Discovery Calls Partially Failed": {
   127  			discoveryError:    new(discovery.ErrGroupDiscoveryFailed),
   128  			possibleResources: possibleDiscoveryResource(),
   129  			expectedErr:       false,
   130  		},
   131  	}
   132  	for name, test := range tcs {
   133  		testDiscovery := FakeDiscoveryWithError{Err: test.discoveryError, PossibleResources: test.possibleResources}
   134  		testClientset := NewFakeClientset(testDiscovery)
   135  		testClientBuilder := TestClientBuilder{clientset: testClientset}
   136  		testInformerFactory := informers.NewSharedInformerFactoryWithOptions(testClientset, time.Duration(1))
   137  		ctx := ControllerContext{
   138  			ClientBuilder:                   testClientBuilder,
   139  			InformerFactory:                 testInformerFactory,
   140  			ObjectOrMetadataInformerFactory: testInformerFactory,
   141  			InformersStarted:                make(chan struct{}),
   142  		}
   143  		for controllerName, controllerDesc := range controllerDescriptorMap {
   144  			_, _, err := controllerDesc.GetInitFunc()(context.TODO(), ctx, controllerName)
   145  			if test.expectedErr != (err != nil) {
   146  				t.Errorf("%v test failed for use case: %v", controllerName, name)
   147  			}
   148  		}
   149  		_, _, err := startModifiedNamespaceController(
   150  			context.TODO(), ctx, testClientset, testClientBuilder.ConfigOrDie("namespace-controller"))
   151  		if test.expectedErr != (err != nil) {
   152  			t.Errorf("Namespace Controller test failed for use case: %v", name)
   153  		}
   154  	}
   155  }
   156  

View as plain text