Files
open-cluster-management/pkg/registration/spoke/addon/registration_controller_test.go
Jian Qiu e810520961 🌱 Refactor code to fix lint warning (#218)
* Refactor code to fix lint warning

Signed-off-by: Jian Qiu <jqiu@redhat.com>

* enable lint for testing files

Signed-off-by: Jian Qiu <jqiu@redhat.com>

---------

Signed-off-by: Jian Qiu <jqiu@redhat.com>
2023-07-25 07:12:34 +02:00

464 lines
15 KiB
Go

package addon
import (
"context"
"testing"
"time"
"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
certificates "k8s.io/api/certificates/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kubefake "k8s.io/client-go/kubernetes/fake"
clienttesting "k8s.io/client-go/testing"
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
addonfake "open-cluster-management.io/api/client/addon/clientset/versioned/fake"
addoninformers "open-cluster-management.io/api/client/addon/informers/externalversions"
clusterv1 "open-cluster-management.io/api/cluster/v1"
testingcommon "open-cluster-management.io/ocm/pkg/common/testing"
)
func TestFilterCSREvents(t *testing.T) {
clusterName := "cluster1"
signerName := "signer1"
cases := []struct {
name string
csr *certificates.CertificateSigningRequest
expected bool
}{
{
name: "csr not from the managed cluster",
csr: &certificates.CertificateSigningRequest{},
},
{
name: "csr not for the addon",
csr: &certificates.CertificateSigningRequest{},
},
{
name: "csr with different signer name",
csr: &certificates.CertificateSigningRequest{},
},
{
name: "valid csr",
csr: &certificates.CertificateSigningRequest{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
// the labels are only hints. Anyone could set/modify them.
clusterv1.ClusterNameLabelKey: clusterName,
addonv1alpha1.AddonLabelKey: addOnName,
},
},
Spec: certificates.CertificateSigningRequestSpec{
SignerName: signerName,
},
},
expected: true,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
filterFunc := createCSREventFilterFunc(clusterName, addOnName, signerName)
actual := filterFunc(c.csr)
if actual != c.expected {
t.Errorf("Expected %v but got %v", c.expected, actual)
}
})
}
}
func TestRegistrationSync(t *testing.T) {
clusterName := "cluster1"
signerName := "signer1"
config1 := addonv1alpha1.RegistrationConfig{
SignerName: signerName,
}
config2 := addonv1alpha1.RegistrationConfig{
SignerName: signerName,
Subject: addonv1alpha1.Subject{
User: addOnName,
},
}
cases := []struct {
name string
queueKey string
addOn *addonv1alpha1.ManagedClusterAddOn
addOnRegistrationConfigs map[string]map[string]registrationConfig
addonAgentOutsideManagedCluster bool
expectedAddOnRegistrationConfigHashs map[string][]string
validateActions func(t *testing.T, actions, managementActions []clienttesting.Action)
}{
{
name: "addon registration not enabled",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName, nil, false),
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
if len(managementActions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
},
},
{
name: "addon registration enabled",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config1}, false),
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config1, "", false)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
},
},
{
name: "addon registration updated",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config2}, false),
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config1, "", false): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config2, "", false)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 1 {
t.Errorf("expect 1 actions but got %d", len(actions))
}
testingcommon.AssertActions(t, actions, "delete")
},
},
{
name: "addon install namespace updated",
queueKey: addOnName,
addOn: setAddonInstallNamespace(newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config2}, false), "ns1"),
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config2, "", false): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config2, "ns1", false)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 1 {
t.Errorf("expect 1 actions but got %d", len(actions))
}
testingcommon.AssertActions(t, actions, "delete")
},
},
{
name: "addon is deleted",
queueKey: addOnName,
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config1, "", false): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
},
},
},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 1 {
t.Errorf("expect 1 actions but got %d", len(actions))
}
testingcommon.AssertActions(t, actions, "delete")
},
},
{
name: "hosted addon registration enabled",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName, []addonv1alpha1.RegistrationConfig{config1}, true),
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config1, "", true)},
},
addonAgentOutsideManagedCluster: true,
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
if len(managementActions) != 0 {
t.Errorf("expect 0 management actions but got %d", len(managementActions))
}
},
},
{
name: "hosted addon registration updated",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config2}, true),
addonAgentOutsideManagedCluster: true,
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config1, "", true): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
AgentRunningOutsideManagedCluster: true,
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config2, "", true)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
if len(managementActions) != 1 {
t.Errorf("expect 1 management actions but got %d", len(managementActions))
}
testingcommon.AssertActions(t, managementActions, "delete")
},
},
{
name: "deploy mode changes from hosted to default",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config2}, false),
addonAgentOutsideManagedCluster: false,
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config2, "", true): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
AgentRunningOutsideManagedCluster: true,
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config2, "", false)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 0 {
t.Errorf("expect 0 actions but got %d", len(actions))
}
if len(managementActions) != 1 {
t.Errorf("expect 1 management actions but got %d", len(managementActions))
}
testingcommon.AssertActions(t, managementActions, "delete")
},
},
{
name: "deploy mode changes from default to hosted",
queueKey: addOnName,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config2}, true),
addonAgentOutsideManagedCluster: true,
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config2, "", false): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
AgentRunningOutsideManagedCluster: false,
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config2, "", true)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(managementActions) != 0 {
t.Errorf("expect 0 actions but got %d", len(managementActions))
}
if len(actions) != 1 {
t.Errorf("expect 1 management actions but got %d", len(actions))
}
testingcommon.AssertActions(t, actions, "delete")
},
},
{
name: "hosted addon is deleted",
queueKey: addOnName,
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config1, "", true): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
AgentRunningOutsideManagedCluster: true,
},
},
},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(managementActions) != 1 {
t.Errorf("expect 1 actions but got %d", len(managementActions))
}
testingcommon.AssertActions(t, managementActions, "delete")
},
},
{
name: "resync",
queueKey: factory.DefaultQueueKey,
addOn: newManagedClusterAddOn(clusterName, addOnName,
[]addonv1alpha1.RegistrationConfig{config1}, false),
addOnRegistrationConfigs: map[string]map[string]registrationConfig{
addOnName: {
hash(config1, "", false): {
secretName: "secret1",
addonInstallOption: addonInstallOption{
InstallationNamespace: addOnName,
},
},
},
"addon2": {
hash(config1, "", false): {
secretName: "secret2",
addonInstallOption: addonInstallOption{
InstallationNamespace: "addon2",
},
},
},
},
expectedAddOnRegistrationConfigHashs: map[string][]string{
addOnName: {hash(config1, "", false)},
},
validateActions: func(t *testing.T, actions, managementActions []clienttesting.Action) {
if len(actions) != 1 {
t.Errorf("expect 1 actions but got %d", len(actions))
}
testingcommon.AssertActions(t, actions, "delete")
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
kubeClient := kubefake.NewSimpleClientset()
managementClient := kubefake.NewSimpleClientset()
var addons []runtime.Object
if c.addOn != nil {
addons = append(addons, c.addOn)
}
addonClient := addonfake.NewSimpleClientset(addons...)
addonInformerFactory := addoninformers.NewSharedInformerFactory(addonClient, time.Minute*10)
addonStore := addonInformerFactory.Addon().V1alpha1().ManagedClusterAddOns().Informer().GetStore()
if c.addOn != nil {
if err := addonStore.Add(c.addOn); err != nil {
t.Fatal(err)
}
}
if c.addOnRegistrationConfigs == nil {
c.addOnRegistrationConfigs = map[string]map[string]registrationConfig{}
}
controller := addOnRegistrationController{
clusterName: clusterName,
managementKubeClient: managementClient,
spokeKubeClient: kubeClient,
hubAddOnLister: addonInformerFactory.Addon().V1alpha1().ManagedClusterAddOns().Lister(),
recorder: eventstesting.NewTestingEventRecorder(t),
startRegistrationFunc: func(ctx context.Context, config registrationConfig) context.CancelFunc {
_, cancel := context.WithCancel(context.Background())
return cancel
},
addOnRegistrationConfigs: c.addOnRegistrationConfigs,
}
err := controller.sync(context.Background(), testingcommon.NewFakeSyncContext(t, c.queueKey))
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(c.expectedAddOnRegistrationConfigHashs) != len(controller.addOnRegistrationConfigs) {
t.Errorf("expected %d addOns, but got %d",
len(c.expectedAddOnRegistrationConfigHashs), len(controller.addOnRegistrationConfigs))
}
for addOnName, hashs := range c.expectedAddOnRegistrationConfigHashs {
addonRegistrationConfigs := controller.addOnRegistrationConfigs[addOnName]
if len(addonRegistrationConfigs) != len(hashs) {
t.Errorf("expected %d config items for addOn %q, but got %d",
len(hashs), addOnName, len(addonRegistrationConfigs))
}
for _, hash := range hashs {
config, ok := addonRegistrationConfigs[hash]
if !ok {
t.Errorf("registration config with hash %q is not found for addOn %q", hash, addOnName)
}
if config.AgentRunningOutsideManagedCluster != c.addonAgentOutsideManagedCluster {
t.Errorf("expect addon agent running outside managed cluster: %v, but got: %v",
c.addonAgentOutsideManagedCluster, config.AgentRunningOutsideManagedCluster)
}
}
}
if c.validateActions != nil {
c.validateActions(t, kubeClient.Actions(), managementClient.Actions())
}
})
}
}
func newManagedClusterAddOn(namespace, name string, registrations []addonv1alpha1.RegistrationConfig,
hostedMode bool) *addonv1alpha1.ManagedClusterAddOn {
addon := &addonv1alpha1.ManagedClusterAddOn{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
},
Status: addonv1alpha1.ManagedClusterAddOnStatus{
Registrations: registrations,
},
}
if hostedMode {
addon.SetAnnotations(map[string]string{hostingClusterNameAnnotation: "test"})
}
return addon
}
func setAddonInstallNamespace(
addon *addonv1alpha1.ManagedClusterAddOn,
namespace string) *addonv1alpha1.ManagedClusterAddOn {
addon.Spec.InstallNamespace = namespace
return addon
}
func hash(registration addonv1alpha1.RegistrationConfig, installNamespace string,
addOnAgentRunningOutsideManagedCluster bool) string {
if len(installNamespace) == 0 {
installNamespace = defaultAddOnInstallationNamespace
}
h, _ := getConfigHash(registration, addonInstallOption{
InstallationNamespace: installNamespace,
AgentRunningOutsideManagedCluster: addOnAgentRunningOutsideManagedCluster,
})
return h
}