[Mitigate KCM CrashLooping] Add unittests for controllers' Init function.

pull/564/head
yuwenma 2019-01-25 18:22:55 -08:00
parent c6a6c65e32
commit e6ab3cfc54
2 changed files with 52 additions and 21 deletions

View File

@ -36,6 +36,7 @@ import (
cacheddiscovery "k8s.io/client-go/discovery/cached" cacheddiscovery "k8s.io/client-go/discovery/cached"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned" csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud" cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud"
@ -331,6 +332,10 @@ func startNamespaceController(ctx ControllerContext) (http.Handler, bool, error)
nsKubeconfig.QPS *= 20 nsKubeconfig.QPS *= 20
nsKubeconfig.Burst *= 100 nsKubeconfig.Burst *= 100
namespaceKubeClient := clientset.NewForConfigOrDie(nsKubeconfig) namespaceKubeClient := clientset.NewForConfigOrDie(nsKubeconfig)
return startModifiedNamespaceController(ctx, namespaceKubeClient, nsKubeconfig)
}
func startModifiedNamespaceController(ctx ControllerContext, namespaceKubeClient clientset.Interface, nsKubeconfig *restclient.Config) (http.Handler, bool, error) {
dynamicClient, err := dynamic.NewForConfig(nsKubeconfig) dynamicClient, err := dynamic.NewForConfig(nsKubeconfig)
if err != nil { if err != nil {

View File

@ -17,6 +17,7 @@ limitations under the License.
package app package app
import ( import (
"net/http"
"testing" "testing"
"time" "time"
@ -34,8 +35,11 @@ type TestClientBuilder struct {
clientset clientset.Interface clientset clientset.Interface
} }
func (TestClientBuilder) Config(name string) (*restclient.Config, error) { return nil, nil } func (TestClientBuilder) Config(name string) (*restclient.Config, error) { return nil, nil }
func (TestClientBuilder) ConfigOrDie(name string) *restclient.Config { return nil } func (TestClientBuilder) ConfigOrDie(name string) *restclient.Config {
return &restclient.Config{}
}
func (TestClientBuilder) Client(name string) (clientset.Interface, error) { return nil, nil } func (TestClientBuilder) Client(name string) (clientset.Interface, error) { return nil, nil }
func (m TestClientBuilder) ClientOrDie(name string) clientset.Interface { func (m TestClientBuilder) ClientOrDie(name string) clientset.Interface {
return m.clientset return m.clientset
@ -62,6 +66,10 @@ func (c *FakeClientSet) Discovery() discovery.DiscoveryInterface {
return c.DiscoveryObj return c.DiscoveryObj
} }
func (c *FakeClientSet) GetPossibleResources() []*metav1.APIResourceList {
return c.DiscoveryObj.PossibleResources
}
// Create a fake Clientset with its Discovery method overridden. // Create a fake Clientset with its Discovery method overridden.
func NewFakeClientset(fakeDiscovery FakeDiscoveryWithError) *FakeClientSet { func NewFakeClientset(fakeDiscovery FakeDiscoveryWithError) *FakeClientSet {
cs := &FakeClientSet{} cs := &FakeClientSet{}
@ -69,7 +77,30 @@ func NewFakeClientset(fakeDiscovery FakeDiscoveryWithError) *FakeClientSet {
return cs return cs
} }
func TestStartResourceQuotaController_DiscoveryError(t *testing.T) { func possibleDiscoveryResource() []*metav1.APIResourceList {
return []*metav1.APIResourceList{
{
GroupVersion: "create/v1",
APIResources: []metav1.APIResource{
{
Name: "jobs",
Verbs: []string{"create", "list", "watch", "delete"},
ShortNames: []string{"jz"},
Categories: []string{"all"},
},
},
},
}
}
type controllerInitFunc func(ControllerContext) (http.Handler, bool, error)
func TestController_DiscoveryError(t *testing.T) {
controllerInitFuncMap := map[string]controllerInitFunc{
"ResourceQuotaController": startResourceQuotaController,
"GarbageCollectorController": startGarbageCollectorController,
}
tcs := map[string]struct { tcs := map[string]struct {
discoveryError error discoveryError error
expectedErr bool expectedErr bool
@ -77,25 +108,13 @@ func TestStartResourceQuotaController_DiscoveryError(t *testing.T) {
}{ }{
"No Discovery Error": { "No Discovery Error": {
discoveryError: nil, discoveryError: nil,
possibleResources: nil, possibleResources: possibleDiscoveryResource(),
expectedErr: false, expectedErr: false,
}, },
"Discovery Calls Partially Failed": { "Discovery Calls Partially Failed": {
discoveryError: new(discovery.ErrGroupDiscoveryFailed), discoveryError: new(discovery.ErrGroupDiscoveryFailed),
possibleResources: []*metav1.APIResourceList{ possibleResources: possibleDiscoveryResource(),
{ expectedErr: false,
GroupVersion: "create/v1",
APIResources: []metav1.APIResource{
{
Name: "jobs",
Verbs: []string{"create", "list", "watch", "delete"},
ShortNames: []string{"jz"},
Categories: []string{"all"},
},
},
},
},
expectedErr: false,
}, },
} }
for name, test := range tcs { for name, test := range tcs {
@ -107,9 +126,16 @@ func TestStartResourceQuotaController_DiscoveryError(t *testing.T) {
InformerFactory: informers.NewSharedInformerFactoryWithOptions(testClientset, time.Duration(1)), InformerFactory: informers.NewSharedInformerFactoryWithOptions(testClientset, time.Duration(1)),
InformersStarted: make(chan struct{}), InformersStarted: make(chan struct{}),
} }
_, _, err := startResourceQuotaController(ctx) for funcName, controllerInit := range controllerInitFuncMap {
_, _, err := controllerInit(ctx)
if test.expectedErr != (err != nil) {
t.Errorf("%v test failed for use case: %v", funcName, name)
}
}
_, _, err := startModifiedNamespaceController(
ctx, testClientset, testClientBuilder.ConfigOrDie("namespace-controller"))
if test.expectedErr != (err != nil) { if test.expectedErr != (err != nil) {
t.Errorf("test failed for use case: %v", name) t.Errorf("Namespace Controller test failed for use case: %v", name)
} }
} }
} }