github.com/verrazzano/verrazzano@v1.7.0/platform-operator/controllers/configmaps/components/controller_test.go (about)

     1  // Copyright (c) 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package components
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/verrazzano"
    10  	"testing"
    11  
    12  	helmcli "github.com/verrazzano/verrazzano/pkg/helm"
    13  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    14  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1"
    15  	vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1"
    16  	"github.com/verrazzano/verrazzano/platform-operator/constants"
    17  	"github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/helm"
    18  	"github.com/verrazzano/verrazzano/platform-operator/internal/config"
    19  	"helm.sh/helm/v3/pkg/release"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	corev1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  	"k8s.io/apimachinery/pkg/types"
    26  	controllerruntime "sigs.k8s.io/controller-runtime"
    27  	"sigs.k8s.io/controller-runtime/pkg/client"
    28  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    29  )
    30  
    31  const (
    32  	testBomFilePath = "../../verrazzano/testdata/test_bom.json"
    33  )
    34  
    35  // TestConfigMapKindHelmReconciler tests the configMap Reconcile function for a correct and incorrect configmap
    36  func TestConfigMapKindHelmReconciler(t *testing.T) {
    37  	asserts := assert.New(t)
    38  
    39  	tests := []struct {
    40  		name        string
    41  		cm          corev1.ConfigMap
    42  		err         error
    43  		returnError bool
    44  		requeue     bool
    45  	}{
    46  		{
    47  			name: "successful installation",
    48  			cm: corev1.ConfigMap{
    49  				ObjectMeta: metav1.ObjectMeta{
    50  					Name:      "test-component",
    51  					Namespace: constants.VerrazzanoInstallNamespace,
    52  					Labels: map[string]string{
    53  						devComponentConfigMapKindLabel:       devComponentConfigMapKindHelmComponent,
    54  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
    55  					},
    56  				},
    57  				Data: map[string]string{
    58  					componentNameKey:      "test-component",
    59  					chartPathKey:          "test-component",
    60  					componentNamespaceKey: constants.VerrazzanoSystemNamespace,
    61  					overridesKey:          "overrideKey: overrideVal",
    62  				},
    63  			},
    64  			returnError: false,
    65  			requeue:     false,
    66  		},
    67  		{
    68  			name: "configmap in wrong namespace",
    69  			cm: corev1.ConfigMap{
    70  				ObjectMeta: metav1.ObjectMeta{
    71  					Name:      "test-component",
    72  					Namespace: constants.VerrazzanoSystemNamespace,
    73  					Labels: map[string]string{
    74  						devComponentConfigMapKindLabel:       devComponentConfigMapKindHelmComponent,
    75  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
    76  					},
    77  				},
    78  				Data: map[string]string{
    79  					componentNameKey:      "test-component",
    80  					chartPathKey:          "test-component",
    81  					componentNamespaceKey: constants.VerrazzanoSystemNamespace,
    82  					overridesKey:          "overrideKey: overrideVal",
    83  				},
    84  			},
    85  			returnError: true,
    86  			requeue:     false,
    87  		},
    88  		{
    89  			name: "no name",
    90  			cm: corev1.ConfigMap{
    91  				ObjectMeta: metav1.ObjectMeta{
    92  					Name:      "test-component",
    93  					Namespace: constants.VerrazzanoInstallNamespace,
    94  					Labels: map[string]string{
    95  						devComponentConfigMapKindLabel:       devComponentConfigMapKindHelmComponent,
    96  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
    97  					},
    98  				},
    99  				Data: map[string]string{
   100  					chartPathKey:          "test-component",
   101  					componentNamespaceKey: constants.VerrazzanoSystemNamespace,
   102  					overridesKey:          "overrideKey: overrideVal",
   103  				},
   104  			},
   105  			returnError: true,
   106  			requeue:     false,
   107  		},
   108  		{
   109  			name: "no chart path",
   110  			cm: corev1.ConfigMap{
   111  				ObjectMeta: metav1.ObjectMeta{
   112  					Name:      "test-component",
   113  					Namespace: constants.VerrazzanoInstallNamespace,
   114  					Labels: map[string]string{
   115  						devComponentConfigMapKindLabel:       devComponentConfigMapKindHelmComponent,
   116  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   117  					},
   118  				},
   119  				Data: map[string]string{
   120  					componentNameKey:      "test-component",
   121  					componentNamespaceKey: constants.VerrazzanoSystemNamespace,
   122  					overridesKey:          "overrideKey: overrideVal",
   123  				},
   124  			},
   125  			returnError: true,
   126  			requeue:     false,
   127  		},
   128  		{
   129  			name: "no namespace",
   130  			cm: corev1.ConfigMap{
   131  				ObjectMeta: metav1.ObjectMeta{
   132  					Name:      "test-component",
   133  					Namespace: constants.VerrazzanoInstallNamespace,
   134  					Labels: map[string]string{
   135  						devComponentConfigMapKindLabel:       devComponentConfigMapKindHelmComponent,
   136  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   137  					},
   138  				},
   139  				Data: map[string]string{
   140  					componentNameKey: "test-component",
   141  					chartPathKey:     "test-component",
   142  					overridesKey:     "overrideKey: overrideVal",
   143  				},
   144  			},
   145  			returnError: true,
   146  			requeue:     false,
   147  		},
   148  	}
   149  
   150  	for _, tt := range tests {
   151  		t.Run(tt.name, func(t *testing.T) {
   152  			config.SetDefaultBomFilePath(testBomFilePath)
   153  			helm.SetUpgradeFunc(fakeUpgrade)
   154  			defer helm.SetDefaultUpgradeFunc()
   155  			config.TestProfilesDir = "../../../manifests/profiles"
   156  			defer func() { config.TestProfilesDir = "" }()
   157  
   158  			cli := buildFakeClient(tt.cm)
   159  
   160  			req := newRequest(tt.cm.Namespace, tt.cm.Name)
   161  			reconciler := newConfigMapReconciler(cli)
   162  			res, err := reconciler.Reconcile(context.TODO(), req)
   163  
   164  			if tt.returnError {
   165  				assert.Error(t, err)
   166  			} else {
   167  				assert.Nil(t, err)
   168  			}
   169  
   170  			asserts.Equal(tt.requeue, res.Requeue)
   171  
   172  		})
   173  	}
   174  }
   175  
   176  // TestConfigMapKindShimReconciler tests the configMap Reconcile function for a correct and incorrect configmap
   177  func TestConfigMapKindShimReconciler(t *testing.T) {
   178  	asserts := assert.New(t)
   179  
   180  	tests := []struct {
   181  		name        string
   182  		cm          corev1.ConfigMap
   183  		err         error
   184  		returnError bool
   185  		requeue     bool
   186  		init        bool
   187  	}{
   188  		{
   189  			name: "successful installation",
   190  			cm: corev1.ConfigMap{
   191  				ObjectMeta: metav1.ObjectMeta{
   192  					Name:      "test-component",
   193  					Namespace: constants.VerrazzanoInstallNamespace,
   194  					Labels: map[string]string{
   195  						devComponentConfigMapKindLabel:       devComponentConfigMapKindShimComponent,
   196  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   197  					},
   198  				},
   199  				Data: map[string]string{
   200  					componentNameKey: "verrazzano",
   201  				},
   202  			},
   203  			init:        true,
   204  			returnError: false,
   205  			requeue:     false,
   206  		},
   207  		{
   208  			name: "component not found",
   209  			cm: corev1.ConfigMap{
   210  				ObjectMeta: metav1.ObjectMeta{
   211  					Name:      "test-component",
   212  					Namespace: constants.VerrazzanoInstallNamespace,
   213  					Labels: map[string]string{
   214  						devComponentConfigMapKindLabel:       devComponentConfigMapKindShimComponent,
   215  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   216  					},
   217  				},
   218  				Data: map[string]string{
   219  					componentNameKey: "test-component",
   220  				},
   221  			},
   222  			init:        false,
   223  			returnError: true,
   224  			requeue:     false,
   225  		},
   226  		{
   227  			name: "configmap in wrong namespace",
   228  			cm: corev1.ConfigMap{
   229  				ObjectMeta: metav1.ObjectMeta{
   230  					Name:      "test-component",
   231  					Namespace: constants.VerrazzanoSystemNamespace,
   232  					Labels: map[string]string{
   233  						devComponentConfigMapKindLabel:       devComponentConfigMapKindShimComponent,
   234  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   235  					},
   236  				},
   237  				Data: map[string]string{
   238  					componentNameKey: "test-component",
   239  				},
   240  			},
   241  			init:        false,
   242  			returnError: true,
   243  			requeue:     false,
   244  		},
   245  		{
   246  			name: "no name",
   247  			cm: corev1.ConfigMap{
   248  				ObjectMeta: metav1.ObjectMeta{
   249  					Name:      "test-component",
   250  					Namespace: constants.VerrazzanoInstallNamespace,
   251  					Labels: map[string]string{
   252  						devComponentConfigMapKindLabel:       devComponentConfigMapKindShimComponent,
   253  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   254  					},
   255  				},
   256  				Data: map[string]string{},
   257  			},
   258  			init:        false,
   259  			returnError: true,
   260  			requeue:     false,
   261  		},
   262  		{
   263  			name: "invalid map kind",
   264  			cm: corev1.ConfigMap{
   265  				ObjectMeta: metav1.ObjectMeta{
   266  					Name:      "test-component",
   267  					Namespace: constants.VerrazzanoInstallNamespace,
   268  					Labels: map[string]string{
   269  						devComponentConfigMapKindLabel:       "invalid-kind",
   270  						devComponentConfigMapAPIVersionLabel: devComponentConfigMapAPIVersionv1beta2,
   271  					},
   272  				},
   273  				Data: map[string]string{
   274  					componentNameKey: "test-component",
   275  				},
   276  			},
   277  			init:        false,
   278  			returnError: true,
   279  			requeue:     false,
   280  		},
   281  	}
   282  
   283  	for _, tt := range tests {
   284  		t.Run(tt.name, func(t *testing.T) {
   285  			config.SetDefaultBomFilePath(testBomFilePath)
   286  			helm.SetUpgradeFunc(fakeUpgrade)
   287  			defer helm.SetDefaultUpgradeFunc()
   288  			config.TestProfilesDir = "../../../manifests/profiles"
   289  			defer func() { config.TestProfilesDir = "" }()
   290  
   291  			cli := buildFakeClient(tt.cm)
   292  
   293  			if tt.init {
   294  				shimComponents[verrazzano.ComponentName] = verrazzano.NewComponent()
   295  			}
   296  			req := newRequest(tt.cm.Namespace, tt.cm.Name)
   297  			reconciler := newConfigMapReconciler(cli)
   298  			res, err := reconciler.Reconcile(context.TODO(), req)
   299  
   300  			if tt.returnError {
   301  				assert.Error(t, err)
   302  			} else {
   303  				assert.Nil(t, err)
   304  			}
   305  
   306  			asserts.Equal(tt.requeue, res.Requeue)
   307  
   308  		})
   309  	}
   310  }
   311  
   312  // newScheme creates a new scheme that includes this package's object to use for testing
   313  func newScheme() *runtime.Scheme {
   314  	scheme := runtime.NewScheme()
   315  	_ = corev1.AddToScheme(scheme)
   316  	_ = v1alpha1.AddToScheme(scheme)
   317  	_ = vzapi.AddToScheme(scheme)
   318  	return scheme
   319  }
   320  
   321  // newRequest creates a new reconciler request for testing
   322  // namespace - The namespace to use in the request
   323  // name - The name to use in the request
   324  func newRequest(namespace string, name string) controllerruntime.Request {
   325  	return controllerruntime.Request{
   326  		NamespacedName: types.NamespacedName{
   327  			Namespace: namespace,
   328  			Name:      name}}
   329  }
   330  
   331  // newConfigMapReconciler creates a new reconciler for testing
   332  func newConfigMapReconciler(c client.Client) ComponentConfigMapReconciler {
   333  	scheme := newScheme()
   334  	reconciler := ComponentConfigMapReconciler{
   335  		Client: c,
   336  		Scheme: scheme,
   337  	}
   338  	return reconciler
   339  }
   340  
   341  func buildFakeClient(cm corev1.ConfigMap) client.Client {
   342  	vz := &v1alpha1.Verrazzano{
   343  		ObjectMeta: metav1.ObjectMeta{
   344  			Name:      "test-vz",
   345  			Namespace: constants.VerrazzanoInstallNamespace,
   346  		},
   347  	}
   348  	secret := &corev1.Secret{
   349  		ObjectMeta: metav1.ObjectMeta{
   350  			Name:      constants.GlobalImagePullSecName,
   351  			Namespace: "default",
   352  		},
   353  	}
   354  	return fake.NewClientBuilder().WithObjects(vz, &cm, secret).WithScheme(newScheme()).Build()
   355  }
   356  
   357  // fakeUpgrade verifies that the correct parameter values are passed to upgrade
   358  func fakeUpgrade(_ vzlog.VerrazzanoLogger, releaseName string, namespace string, chartDir string, _ bool, _ bool, overrides []helmcli.HelmOverrides) (*release.Release, error) {
   359  	if releaseName != "test-component" {
   360  		return nil, fmt.Errorf("Incorrect  releaseName, expecting test-component, got %s", releaseName)
   361  	}
   362  	if chartDir != "/verrazzano/platform-operator/thirdparty/charts/test-component" {
   363  		return nil, fmt.Errorf("Incorrect  releaseName, expecting test-component, got %s", chartDir)
   364  	}
   365  	if namespace != constants.VerrazzanoSystemNamespace {
   366  		return nil, fmt.Errorf("Incorrect release namespace, expecting verrazzano-system, got %s", namespace)
   367  	}
   368  	if len(overrides) != 2 {
   369  		return nil, fmt.Errorf("Incorrect number of overrides, expecting 2, got %d", len(overrides))
   370  	}
   371  	return nil, nil
   372  }