Files
open-cluster-management/pkg/addon/controllers/addontemplate/controller_test.go
2023-07-05 10:25:55 -04:00

269 lines
9.1 KiB
Go

package addontemplate
import (
"context"
"sync"
"testing"
"time"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/dynamic/dynamicinformer"
dynamicfake "k8s.io/client-go/dynamic/fake"
fakekube "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
"open-cluster-management.io/addon-framework/pkg/addonmanager/addontesting"
"open-cluster-management.io/addon-framework/pkg/utils"
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
fakeaddon "open-cluster-management.io/api/client/addon/clientset/versioned/fake"
addoninformers "open-cluster-management.io/api/client/addon/informers/externalversions"
fakecluster "open-cluster-management.io/api/client/cluster/clientset/versioned/fake"
clusterv1informers "open-cluster-management.io/api/client/cluster/informers/externalversions"
fakework "open-cluster-management.io/api/client/work/clientset/versioned/fake"
workinformers "open-cluster-management.io/api/client/work/informers/externalversions"
testingcommon "open-cluster-management.io/ocm/pkg/common/testing"
)
func TestReconcile(t *testing.T) {
cases := []struct {
name string
syncKeys []string
managedClusteraddon []runtime.Object
clusterManagementAddon []runtime.Object
expectedCount int
expectedTimeout bool
}{
{
name: "no clustermanagementaddon",
syncKeys: []string{"test"},
managedClusteraddon: []runtime.Object{},
clusterManagementAddon: []runtime.Object{},
expectedCount: 0,
expectedTimeout: true,
},
{
name: "not template type clustermanagementaddon",
syncKeys: []string{"test"},
managedClusteraddon: []runtime.Object{},
clusterManagementAddon: []runtime.Object{
addontesting.NewClusterManagementAddon("test", "", "").Build()},
expectedCount: 0,
expectedTimeout: true,
},
{
name: "one template type clustermanagementaddon",
syncKeys: []string{"test"},
managedClusteraddon: []runtime.Object{},
clusterManagementAddon: []runtime.Object{
addontesting.NewClusterManagementAddon("test", "", "").WithSupportedConfigs(
addonv1alpha1.ConfigMeta{
ConfigGroupResource: addonv1alpha1.ConfigGroupResource{
Group: utils.AddOnTemplateGVR.Group,
Resource: utils.AddOnTemplateGVR.Resource,
},
DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test"},
}).Build()},
expectedCount: 1,
expectedTimeout: false,
},
{
name: "two template type clustermanagementaddon",
syncKeys: []string{"test", "test1"},
managedClusteraddon: []runtime.Object{},
clusterManagementAddon: []runtime.Object{
addontesting.NewClusterManagementAddon("test", "", "").WithSupportedConfigs(
addonv1alpha1.ConfigMeta{
ConfigGroupResource: addonv1alpha1.ConfigGroupResource{
Group: utils.AddOnTemplateGVR.Group,
Resource: utils.AddOnTemplateGVR.Resource,
},
DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test"},
}).Build(),
addontesting.NewClusterManagementAddon("test1", "", "").WithSupportedConfigs(
addonv1alpha1.ConfigMeta{
ConfigGroupResource: addonv1alpha1.ConfigGroupResource{
Group: utils.AddOnTemplateGVR.Group,
Resource: utils.AddOnTemplateGVR.Resource,
},
DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test"},
}).Build(),
},
expectedCount: 2,
expectedTimeout: false,
},
{
name: "two template type and one not template type clustermanagementaddon",
syncKeys: []string{"test", "test1", "test2"},
managedClusteraddon: []runtime.Object{},
clusterManagementAddon: []runtime.Object{
addontesting.NewClusterManagementAddon("test", "", "").WithSupportedConfigs(
addonv1alpha1.ConfigMeta{
ConfigGroupResource: addonv1alpha1.ConfigGroupResource{
Group: utils.AddOnTemplateGVR.Group,
Resource: utils.AddOnTemplateGVR.Resource,
},
DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test"},
}).Build(),
addontesting.NewClusterManagementAddon("test1", "", "").WithSupportedConfigs(
addonv1alpha1.ConfigMeta{
ConfigGroupResource: addonv1alpha1.ConfigGroupResource{
Group: utils.AddOnTemplateGVR.Group,
Resource: utils.AddOnTemplateGVR.Resource,
},
DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test"},
}).Build(),
addontesting.NewClusterManagementAddon("test2", "", "").Build(),
},
expectedCount: 2,
expectedTimeout: true,
},
}
for _, c := range cases {
count := 0
var wg sync.WaitGroup
lock := &sync.Mutex{}
rederCount := func() int {
lock.Lock()
defer lock.Unlock()
return count
}
increaseCount := func() {
lock.Lock()
defer lock.Unlock()
count = count + 1
}
for range c.syncKeys {
wg.Add(1)
}
runController := func(ctx context.Context, addonName string) error {
defer wg.Done()
increaseCount()
return nil
}
obj := append(c.clusterManagementAddon, c.managedClusteraddon...)
fakeAddonClient := fakeaddon.NewSimpleClientset(obj...)
addonInformers := addoninformers.NewSharedInformerFactory(fakeAddonClient, 10*time.Minute)
for _, obj := range c.managedClusteraddon {
if err := addonInformers.Addon().V1alpha1().ManagedClusterAddOns().Informer().GetStore().Add(obj); err != nil {
t.Fatal(err)
}
}
for _, obj := range c.clusterManagementAddon {
if err := addonInformers.Addon().V1alpha1().ClusterManagementAddOns().Informer().GetStore().Add(obj); err != nil {
t.Fatal(err)
}
}
fakeDynamicClient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(fakeDynamicClient, 0)
fakeClusterClient := fakecluster.NewSimpleClientset()
clusterInformers := clusterv1informers.NewSharedInformerFactory(fakeClusterClient, 10*time.Minute)
fakeWorkClient := fakework.NewSimpleClientset()
workInformers := workinformers.NewSharedInformerFactory(fakeWorkClient, 10*time.Minute)
hubKubeClient := fakekube.NewSimpleClientset()
controller := NewAddonTemplateController(
nil,
hubKubeClient,
fakeAddonClient,
addonInformers,
clusterInformers,
dynamicInformerFactory,
workInformers,
eventstesting.NewTestingEventRecorder(t),
runController,
)
ctx := context.TODO()
for _, syncKey := range c.syncKeys {
syncContext := testingcommon.NewFakeSyncContext(t, syncKey)
err := controller.Sync(ctx, syncContext)
if err != nil {
t.Errorf("expected no error when sync: %v", err)
}
}
ch := make(chan struct{})
go func() {
defer close(ch)
wg.Wait()
}()
select {
case <-ch:
actualCount := rederCount()
if actualCount != c.expectedCount {
t.Errorf("name : %s, expected runControllerFunc to be called %d, but was called %d times",
c.name, c.expectedCount, actualCount)
}
case <-time.After(1 * time.Second):
if !c.expectedTimeout {
t.Errorf("name : %s, expected not timeout, but timeout", c.name)
}
actualCount := rederCount()
if actualCount != c.expectedCount {
t.Errorf("name : %s, expected runControllerFunc to be called %d, but was called %d times",
c.name, c.expectedCount, actualCount)
}
}
}
}
func TestRunController(t *testing.T) {
cases := []struct {
name string
addonName string
expectedErr string
}{
{
name: "addon name empty",
addonName: "",
expectedErr: "addon name should be set",
},
{
name: "fake kubeconfig",
addonName: "test",
expectedErr: `Get "http://localhost/api": dial tcp [::1]:80: connect: connection refused`,
},
}
for _, c := range cases {
fakeAddonClient := fakeaddon.NewSimpleClientset()
addonInformers := addoninformers.NewSharedInformerFactory(fakeAddonClient, 10*time.Minute)
fakeDynamicClient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(fakeDynamicClient, 0)
fakeClusterClient := fakecluster.NewSimpleClientset()
clusterInformers := clusterv1informers.NewSharedInformerFactory(fakeClusterClient, 10*time.Minute)
fakeWorkClient := fakework.NewSimpleClientset()
workInformers := workinformers.NewSharedInformerFactory(fakeWorkClient, 10*time.Minute)
hubKubeClient := fakekube.NewSimpleClientset()
controller := &addonTemplateController{
kubeConfig: &rest.Config{},
kubeClient: hubKubeClient,
addonClient: fakeAddonClient,
cmaLister: addonInformers.Addon().V1alpha1().ClusterManagementAddOns().Lister(),
addonManagers: make(map[string]context.CancelFunc),
addonInformers: addonInformers,
clusterInformers: clusterInformers,
dynamicInformers: dynamicInformerFactory,
workInformers: workInformers,
}
ctx := context.TODO()
err := controller.runController(ctx, c.addonName)
if len(c.expectedErr) == 0 {
assert.NoError(t, err)
}
assert.EqualErrorf(t, err, c.expectedErr, "name : %s, expected error %v, but got %v", c.name, c.expectedErr, err)
}
}