github.com/verrazzano/verrazzano@v1.7.0/application-operator/controllers/clusters/multiclusterapplicationconfiguration/controller_test.go (about)

     1  // Copyright (c) 2021, 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 multiclusterapplicationconfiguration
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
    13  	"github.com/go-logr/logr"
    14  	"github.com/golang/mock/gomock"
    15  	asserts "github.com/stretchr/testify/assert"
    16  	clustersv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/clusters/v1alpha1"
    17  	"github.com/verrazzano/verrazzano/application-operator/constants"
    18  	"github.com/verrazzano/verrazzano/application-operator/controllers/clusters"
    19  	clusterstest "github.com/verrazzano/verrazzano/application-operator/controllers/clusters/test"
    20  	"github.com/verrazzano/verrazzano/application-operator/mocks"
    21  	vzconst "github.com/verrazzano/verrazzano/pkg/constants"
    22  	"go.uber.org/zap"
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/errors"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"k8s.io/apimachinery/pkg/runtime/schema"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  )
    31  
    32  const namespace = "unit-mcappconfig-namespace"
    33  const crName = "unit-mcappconfig"
    34  
    35  // TestAppConfigReconcilerSetupWithManager test the creation of the MultiCluster app config Reconciler.
    36  // GIVEN a controller implementation
    37  // WHEN the controller is created
    38  // THEN verify no error is returned
    39  func TestAppConfigReconcilerSetupWithManager(t *testing.T) {
    40  	assert := asserts.New(t)
    41  
    42  	var mocker *gomock.Controller
    43  	var mgr *mocks.MockManager
    44  	var cli *mocks.MockClient
    45  	var scheme *runtime.Scheme
    46  	var reconciler Reconciler
    47  	var err error
    48  
    49  	mocker = gomock.NewController(t)
    50  	mgr = mocks.NewMockManager(mocker)
    51  	cli = mocks.NewMockClient(mocker)
    52  	scheme = runtime.NewScheme()
    53  	_ = clustersv1alpha1.AddToScheme(scheme)
    54  	reconciler = Reconciler{Client: cli, Scheme: scheme}
    55  	mgr.EXPECT().GetControllerOptions().AnyTimes()
    56  	mgr.EXPECT().GetScheme().Return(scheme)
    57  	mgr.EXPECT().GetLogger().Return(logr.Discard())
    58  	mgr.EXPECT().SetFields(gomock.Any()).Return(nil).AnyTimes()
    59  	mgr.EXPECT().Add(gomock.Any()).Return(nil).AnyTimes()
    60  	err = reconciler.SetupWithManager(mgr)
    61  	mocker.Finish()
    62  	assert.NoError(err)
    63  }
    64  
    65  // TestReconcileCreateAppConfig tests the basic happy path of reconciling a
    66  // MultiClusterApplicationConfiguration. We expect to write out an OAM app config
    67  // GIVEN a MultiClusterApplicationConfiguration resource is created
    68  // WHEN the controller Reconcile function is called
    69  // THEN expect an OAM app config to be created
    70  func TestReconcileCreateAppConfig(t *testing.T) {
    71  	assert := asserts.New(t)
    72  
    73  	mocker := gomock.NewController(t)
    74  	cli := mocks.NewMockClient(mocker)
    75  	mockStatusWriter := mocks.NewMockStatusWriter(mocker)
    76  
    77  	mcAppConfigSample, err := getSampleMCAppConfig()
    78  
    79  	if err != nil {
    80  		t.Fatalf(err.Error())
    81  	}
    82  
    83  	// expect a call to fetch the MultiClusterApplicationConfiguration
    84  	doExpectGetMultiClusterAppConfig(cli, mcAppConfigSample, false)
    85  
    86  	// expect a call to fetch the MCRegistration secret
    87  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
    88  
    89  	// expect a call to fetch existing OAM app config, and return not found error, to test create case
    90  	cli.EXPECT().
    91  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: crName}, gomock.Not(gomock.Nil())).
    92  		Return(errors.NewNotFound(schema.GroupResource{Group: "core.oam.dev", Resource: "ApplicationConfiguration"}, crName))
    93  
    94  	// expect a call to create the OAM app config
    95  	cli.EXPECT().
    96  		Create(gomock.Any(), gomock.Any()).
    97  		DoAndReturn(func(ctx context.Context, c *v1alpha2.ApplicationConfiguration, opts ...client.CreateOption) error {
    98  			assertAppConfigValid(assert, c, mcAppConfigSample)
    99  			return nil
   100  		})
   101  
   102  	// expect a call to update the resource with a finalizer
   103  	cli.EXPECT().
   104  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   105  		DoAndReturn(func(ctx context.Context, appConfig *clustersv1alpha1.MultiClusterApplicationConfiguration, opts ...client.UpdateOption) error {
   106  			assert.True(len(appConfig.ObjectMeta.Finalizers) == 1, "Wrong number of finalizers")
   107  			assert.Equal(finalizerName, appConfig.ObjectMeta.Finalizers[0], "wrong finalizer")
   108  			return nil
   109  		})
   110  
   111  	// expect a call to update the status of the MultiClusterApplicationConfiguration
   112  	doExpectStatusUpdateSucceeded(cli, mockStatusWriter, assert)
   113  
   114  	// create a request and reconcile it
   115  	request := clusterstest.NewRequest(namespace, crName)
   116  	reconciler := newReconciler(cli)
   117  	result, err := reconciler.Reconcile(context.TODO(), request)
   118  
   119  	mocker.Finish()
   120  	assert.NoError(err)
   121  	assert.Equal(false, result.Requeue)
   122  }
   123  
   124  // TestReconcileUpdateAppConfig tests the path of reconciling a MultiClusterApplicationConfiguration
   125  // when the underlying OAM app config already exists i.e. update case
   126  // GIVEN a MultiClusterApplicationConfiguration resource is created
   127  // WHEN the controller Reconcile function is called
   128  // THEN expect an OAM app config to be updated
   129  func TestReconcileUpdateAppConfig(t *testing.T) {
   130  	assert := asserts.New(t)
   131  
   132  	mocker := gomock.NewController(t)
   133  	cli := mocks.NewMockClient(mocker)
   134  	mockStatusWriter := mocks.NewMockStatusWriter(mocker)
   135  
   136  	mcAppConfigSample, err := getSampleMCAppConfig()
   137  	if err != nil {
   138  		t.Fatalf(err.Error())
   139  	}
   140  
   141  	existingOAMAppConfig, err := getExistingOAMAppConfig()
   142  	if err != nil {
   143  		t.Fatalf(err.Error())
   144  	}
   145  
   146  	// expect a call to fetch the MultiClusterApplicationConfiguration
   147  	doExpectGetMultiClusterAppConfig(cli, mcAppConfigSample, true)
   148  
   149  	// expect a call to fetch the MCRegistration secret
   150  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   151  
   152  	// expect a call to fetch underlying OAM app config, and return an existing one
   153  	doExpectGetAppConfigExists(cli, mcAppConfigSample.ObjectMeta, existingOAMAppConfig.Spec)
   154  
   155  	// expect a call to update the OAM app config with the new app config data
   156  	cli.EXPECT().
   157  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   158  		DoAndReturn(func(ctx context.Context, app *v1alpha2.ApplicationConfiguration, opts ...client.CreateOption) error {
   159  			assertAppConfigValid(assert, app, mcAppConfigSample)
   160  			return nil
   161  		})
   162  
   163  	// expect a call to update the status of the multicluster app config
   164  	doExpectStatusUpdateSucceeded(cli, mockStatusWriter, assert)
   165  
   166  	// create a request and reconcile it
   167  	request := clusterstest.NewRequest(namespace, crName)
   168  	reconciler := newReconciler(cli)
   169  	result, err := reconciler.Reconcile(context.TODO(), request)
   170  
   171  	mocker.Finish()
   172  	assert.NoError(err)
   173  	assert.Equal(false, result.Requeue)
   174  }
   175  
   176  // TestReconcileCreateAppConfigFailed tests the path of reconciling a
   177  // MultiClusterApplicationConfiguration when the underlying OAM app config does not exist and
   178  // fails to be created due to some error condition
   179  // GIVEN a MultiClusterApplicationConfiguration resource is created
   180  // WHEN the controller Reconcile function is called and create underlying app config fails
   181  // THEN expect the status of the MultiClusterApplicationConfiguration to be updated with failure
   182  func TestReconcileCreateAppConfigFailed(t *testing.T) {
   183  	assert := asserts.New(t)
   184  
   185  	mocker := gomock.NewController(t)
   186  	cli := mocks.NewMockClient(mocker)
   187  	mockStatusWriter := mocks.NewMockStatusWriter(mocker)
   188  
   189  	mcAppConfigSample, err := getSampleMCAppConfig()
   190  	if err != nil {
   191  		t.Fatalf(err.Error())
   192  	}
   193  
   194  	// expect a call to fetch the MultiClusterApplicationConfiguration
   195  	doExpectGetMultiClusterAppConfig(cli, mcAppConfigSample, false)
   196  
   197  	// expect a call to fetch the MCRegistration secret
   198  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   199  
   200  	// expect a call to fetch existing OAM app config and return not found error, to simulate create case
   201  	cli.EXPECT().
   202  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: crName}, gomock.Not(gomock.Nil()), gomock.Any()).
   203  		Return(errors.NewNotFound(schema.GroupResource{Group: "core.oam.dev", Resource: "ApplicationConfiguration"}, crName))
   204  
   205  	// expect a call to create the OAM app config and fail the call
   206  	cli.EXPECT().
   207  		Create(gomock.Any(), gomock.Any()).
   208  		DoAndReturn(func(ctx context.Context, c *v1alpha2.ApplicationConfiguration, opts ...client.CreateOption) error {
   209  			return errors.NewBadRequest("will not create it")
   210  		})
   211  
   212  	// expect that the status of MultiClusterApplicationConfiguration is updated to failed because we
   213  	// failed the underlying OAM app config's creation
   214  	doExpectStatusUpdateFailed(cli, mockStatusWriter, assert)
   215  
   216  	// create a request and reconcile it
   217  	request := clusterstest.NewRequest(namespace, crName)
   218  	reconciler := newReconciler(cli)
   219  	result, err := reconciler.Reconcile(context.TODO(), request)
   220  
   221  	mocker.Finish()
   222  	assert.Nil(err)
   223  	assert.Equal(true, result.Requeue)
   224  }
   225  
   226  // TestReconcileUpdateAppConfigFailed tests the path of reconciling a
   227  // MultiClusterApplicationConfiguration when the underlying OAM app config exists and fails to be
   228  // updated due to some error condition
   229  // GIVEN a MultiClusterApplicationConfiguration resource is created
   230  // WHEN the controller Reconcile function is called and update underlying app config fails
   231  // THEN expect the status of the MultiClusterApplicationConfiguration to be updated with
   232  // failure information
   233  func TestReconcileUpdateAppConfigFailed(t *testing.T) {
   234  	assert := asserts.New(t)
   235  
   236  	mocker := gomock.NewController(t)
   237  	cli := mocks.NewMockClient(mocker)
   238  	mockStatusWriter := mocks.NewMockStatusWriter(mocker)
   239  
   240  	mcAppConfigSample, err := getSampleMCAppConfig()
   241  	if err != nil {
   242  		t.Fatalf(err.Error())
   243  	}
   244  
   245  	// expect a call to fetch the MultiClusterApplicationConfiguration
   246  	doExpectGetMultiClusterAppConfig(cli, mcAppConfigSample, true)
   247  
   248  	// expect a call to fetch the MCRegistration secret
   249  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   250  
   251  	// expect a call to fetch existing OAM app config (simulate update case)
   252  	doExpectGetAppConfigExists(cli, mcAppConfigSample.ObjectMeta, mcAppConfigSample.Spec.Template.Spec)
   253  
   254  	// expect a call to update the OAM app config and fail the call
   255  	cli.EXPECT().
   256  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   257  		DoAndReturn(func(ctx context.Context, c *v1alpha2.ApplicationConfiguration, opts ...client.CreateOption) error {
   258  			return errors.NewBadRequest("will not update it")
   259  		})
   260  
   261  	// expect that the status of MultiClusterApplicationConfiguration is updated to failed because we
   262  	// failed the underlying OAM app config's creation
   263  	doExpectStatusUpdateFailed(cli, mockStatusWriter, assert)
   264  
   265  	// create a request and reconcile it
   266  	request := clusterstest.NewRequest(namespace, crName)
   267  	reconciler := newReconciler(cli)
   268  	result, err := reconciler.Reconcile(context.TODO(), request)
   269  
   270  	mocker.Finish()
   271  	assert.Nil(err)
   272  	assert.Equal(true, result.Requeue)
   273  }
   274  
   275  // TestReconcileResourceNotFound tests the path of reconciling a
   276  // MultiClusterApplicationConfiguration resource which is non-existent when reconcile is called,
   277  // possibly because it has been deleted.
   278  // GIVEN a MultiClusterApplicationConfiguration resource has been deleted
   279  // WHEN the controller Reconcile function is called
   280  // THEN expect that no action is taken
   281  func TestReconcileResourceNotFound(t *testing.T) {
   282  	assert := asserts.New(t)
   283  
   284  	mocker := gomock.NewController(t)
   285  	cli := mocks.NewMockClient(mocker)
   286  
   287  	// expect a call to fetch the MultiClusterApplicationConfiguration
   288  	// and return a not found error
   289  	cli.EXPECT().
   290  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: crName}, gomock.Not(gomock.Nil()), gomock.Any()).
   291  		Return(errors.NewNotFound(schema.GroupResource{Group: clustersv1alpha1.SchemeGroupVersion.Group, Resource: clustersv1alpha1.MultiClusterAppConfigResource}, crName))
   292  
   293  	// expect no further action to be taken
   294  
   295  	// create a request and reconcile it
   296  	request := clusterstest.NewRequest(namespace, crName)
   297  	reconciler := newReconciler(cli)
   298  	result, err := reconciler.Reconcile(context.TODO(), request)
   299  
   300  	mocker.Finish()
   301  	assert.NoError(err)
   302  	assert.Equal(false, result.Requeue)
   303  }
   304  
   305  // TestReconcilePlacementInDifferentCluster tests the path of reconciling a
   306  // MultiClusterApplicationConfiguration which is placed on a cluster other than the current cluster.
   307  // We expect this MultiClusterApplicationConfiguration to be ignored, i.e. no OAM app config created
   308  // GIVEN a MultiClusterApplicationConfiguration resource is created with a placement in different cluster
   309  // WHEN the controller Reconcile function is called
   310  // THEN expect that no OAM app config is created
   311  func TestReconcilePlacementInDifferentCluster(t *testing.T) {
   312  	assert := asserts.New(t)
   313  
   314  	mocker := gomock.NewController(t)
   315  	cli := mocks.NewMockClient(mocker)
   316  	statusWriter := mocks.NewMockStatusWriter(mocker)
   317  
   318  	mcAppConfigSample, err := getSampleMCAppConfig()
   319  	if err != nil {
   320  		t.Fatalf(err.Error())
   321  	}
   322  
   323  	mcAppConfigSample.Spec.Placement.Clusters[0].Name = "not-my-cluster"
   324  
   325  	// expect a call to fetch the MultiClusterApplicationConfiguration
   326  	doExpectGetMultiClusterAppConfig(cli, mcAppConfigSample, true)
   327  
   328  	// expect a call to fetch the MCRegistration secret
   329  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   330  
   331  	// The effective state of the object will get updated even if it is note locally placed,
   332  	// since it would have changed
   333  	clusterstest.DoExpectUpdateState(t, cli, statusWriter, &mcAppConfigSample, clustersv1alpha1.Pending)
   334  
   335  	clusterstest.ExpectDeleteAssociatedResource(cli, &v1alpha2.Component{
   336  		ObjectMeta: metav1.ObjectMeta{
   337  			Name:      mcAppConfigSample.Name,
   338  			Namespace: mcAppConfigSample.Namespace,
   339  		},
   340  	}, types.NamespacedName{
   341  		Namespace: mcAppConfigSample.Namespace,
   342  		Name:      mcAppConfigSample.Name,
   343  	})
   344  	// Expect no further action
   345  
   346  	// expect a call to update the resource with no finalizers
   347  	cli.EXPECT().
   348  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   349  		DoAndReturn(func(ctx context.Context, mcAppConfig *clustersv1alpha1.MultiClusterApplicationConfiguration, opts ...client.UpdateOption) error {
   350  			assert.True(len(mcAppConfig.Finalizers) == 0, "Wrong number of finalizers")
   351  			return nil
   352  		})
   353  
   354  	// create a request and reconcile it
   355  	request := clusterstest.NewRequest(namespace, crName)
   356  	reconciler := newReconciler(cli)
   357  	result, err := reconciler.Reconcile(context.TODO(), request)
   358  
   359  	mocker.Finish()
   360  	assert.NoError(err)
   361  	assert.Equal(false, result.Requeue)
   362  }
   363  
   364  // doExpectGetAppConfigExists expects a call to get an OAM app config and return an "existing" one
   365  func doExpectGetAppConfigExists(cli *mocks.MockClient, metadata metav1.ObjectMeta, appConfigSpec v1alpha2.ApplicationConfigurationSpec) {
   366  	cli.EXPECT().
   367  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: crName}, gomock.Not(gomock.Nil()), gomock.Any()).
   368  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *v1alpha2.ApplicationConfiguration, opts ...client.GetOption) error {
   369  			appConfig.Spec = appConfigSpec
   370  			appConfig.ObjectMeta = metadata
   371  			return nil
   372  		})
   373  }
   374  
   375  // doExpectStatusUpdateFailed expects a call to update status of
   376  // MultiClusterApplicationConfiguration to failure
   377  func doExpectStatusUpdateFailed(cli *mocks.MockClient, mockStatusWriter *mocks.MockStatusWriter, assert *asserts.Assertions) {
   378  	// expect a call to fetch the MCRegistration secret to get the cluster name for status update
   379  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   380  
   381  	// expect a call to update the status of the MultiClusterApplicationConfiguration
   382  	cli.EXPECT().Status().Return(mockStatusWriter)
   383  
   384  	// the status update should be to failure status/conditions on the MultiClusterApplicationConfiguration
   385  	mockStatusWriter.EXPECT().
   386  		Update(gomock.Any(), gomock.AssignableToTypeOf(&clustersv1alpha1.MultiClusterApplicationConfiguration{}), gomock.Any()).
   387  		DoAndReturn(func(ctx context.Context, mcAppConfig *clustersv1alpha1.MultiClusterApplicationConfiguration, options ...client.UpdateOption) error {
   388  			clusterstest.AssertMultiClusterResourceStatus(assert, mcAppConfig.Status, clustersv1alpha1.Failed, clustersv1alpha1.DeployFailed, v1.ConditionTrue)
   389  			return nil
   390  		})
   391  }
   392  
   393  // doExpectStatusUpdateSucceeded expects a call to update status of
   394  // MultiClusterApplicationConfiguration to success
   395  func doExpectStatusUpdateSucceeded(cli *mocks.MockClient, mockStatusWriter *mocks.MockStatusWriter, assert *asserts.Assertions) {
   396  	// expect a call to fetch the MCRegistration secret to get the cluster name for status update
   397  	clusterstest.DoExpectGetMCRegistrationSecret(cli)
   398  
   399  	// expect a call to update the status of the MultiClusterApplicationConfiguration
   400  	cli.EXPECT().Status().Return(mockStatusWriter)
   401  
   402  	// the status update should be to success status/conditions on the MultiClusterApplicationConfiguration
   403  	mockStatusWriter.EXPECT().
   404  		Update(gomock.Any(), gomock.AssignableToTypeOf(&clustersv1alpha1.MultiClusterApplicationConfiguration{}), gomock.Any()).
   405  		DoAndReturn(func(ctx context.Context, mcAppConfig *clustersv1alpha1.MultiClusterApplicationConfiguration, options ...client.UpdateOption) error {
   406  			clusterstest.AssertMultiClusterResourceStatus(assert, mcAppConfig.Status, clustersv1alpha1.Succeeded, clustersv1alpha1.DeployComplete, v1.ConditionTrue)
   407  			return nil
   408  		})
   409  }
   410  
   411  // doExpectGetMultiClusterAppConfig adds an expectation to the given MockClient to expect a Get
   412  // call for a MultiClusterApplicationConfiguration, and populate it with given sample data
   413  func doExpectGetMultiClusterAppConfig(cli *mocks.MockClient, mcAppConfigSample clustersv1alpha1.MultiClusterApplicationConfiguration, addFinalizer bool) {
   414  	cli.EXPECT().
   415  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: crName}, gomock.AssignableToTypeOf(&mcAppConfigSample), gomock.Any()).
   416  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, mcAppConfig *clustersv1alpha1.MultiClusterApplicationConfiguration, opts ...client.GetOption) error {
   417  			mcAppConfig.ObjectMeta = mcAppConfigSample.ObjectMeta
   418  			mcAppConfig.TypeMeta = mcAppConfigSample.TypeMeta
   419  			mcAppConfig.Spec = mcAppConfigSample.Spec
   420  			if addFinalizer {
   421  				mcAppConfig.Finalizers = append(mcAppConfigSample.Finalizers, finalizerName)
   422  			}
   423  			return nil
   424  		})
   425  }
   426  
   427  // assertAppConfigValid asserts that the metadata and content of the created/updated OAM app config
   428  // are valid
   429  func assertAppConfigValid(assert *asserts.Assertions, app *v1alpha2.ApplicationConfiguration, mcAppConfig clustersv1alpha1.MultiClusterApplicationConfiguration) {
   430  	assert.Equal(namespace, app.ObjectMeta.Namespace)
   431  	assert.Equal(crName, app.ObjectMeta.Name)
   432  	assert.Equal(mcAppConfig.Spec.Template.Spec, app.Spec)
   433  
   434  	// assert that the app config is labeled verrazzano-managed=true since it was created by Verrazzano
   435  	assert.NotNil(app.Labels)
   436  	assert.Equal(constants.LabelVerrazzanoManagedDefault, app.Labels[vzconst.VerrazzanoManagedLabelKey])
   437  
   438  	// assert some fields on the app config spec (e.g. in the case of update, these fields should
   439  	// be different from the mock pre existing OAM app config)
   440  	assert.Equal(len(mcAppConfig.Spec.Template.Spec.Components), len(app.Spec.Components))
   441  	for i, comp := range mcAppConfig.Spec.Template.Spec.Components {
   442  		assert.Equal(comp.ComponentName, app.Spec.Components[i].ComponentName)
   443  		assert.Equal(comp.ParameterValues, app.Spec.Components[i].ParameterValues)
   444  		assert.Equal(comp.Scopes, app.Spec.Components[i].Scopes)
   445  		assert.Equal(comp.Traits, app.Spec.Components[i].Traits)
   446  	}
   447  
   448  }
   449  
   450  // getSampleMCAppConfig creates and returns a sample MultiClusterApplicationConfiguration used in tests
   451  func getSampleMCAppConfig() (clustersv1alpha1.MultiClusterApplicationConfiguration, error) {
   452  	mcAppConfig := clustersv1alpha1.MultiClusterApplicationConfiguration{}
   453  	sampleMCAppConfigFile, err := filepath.Abs("testdata/hello-multiclusterappconfig.yaml")
   454  	if err != nil {
   455  		return mcAppConfig, err
   456  	}
   457  
   458  	rawMCAppConfig, err := clusterstest.ReadYaml2Json(sampleMCAppConfigFile)
   459  	if err != nil {
   460  		return mcAppConfig, err
   461  	}
   462  
   463  	err = json.Unmarshal(rawMCAppConfig, &mcAppConfig)
   464  
   465  	return mcAppConfig, err
   466  }
   467  
   468  func getExistingOAMAppConfig() (v1alpha2.ApplicationConfiguration, error) {
   469  	oamAppConfig := v1alpha2.ApplicationConfiguration{}
   470  	existingAppConfigFile, err := filepath.Abs("testdata/hello-oam-appconfig-existing.yaml")
   471  	if err != nil {
   472  		return oamAppConfig, err
   473  	}
   474  	rawMcAppConfig, err := clusterstest.ReadYaml2Json(existingAppConfigFile)
   475  	if err != nil {
   476  		return oamAppConfig, err
   477  	}
   478  
   479  	err = json.Unmarshal(rawMcAppConfig, &oamAppConfig)
   480  	return oamAppConfig, err
   481  }
   482  
   483  // newReconciler creates a new reconciler for testing
   484  // c - The K8s client to inject into the reconciler
   485  func newReconciler(c client.Client) Reconciler {
   486  	return Reconciler{
   487  		Client: c,
   488  		Log:    zap.S().With("test"),
   489  		Scheme: clusters.NewScheme(),
   490  	}
   491  }
   492  
   493  // TestReconcileKubeSystem tests to make sure we do not reconcile
   494  // Any resource that belong to the kube-system namespace
   495  func TestReconcileKubeSystem(t *testing.T) {
   496  	assert := asserts.New(t)
   497  
   498  	var mocker = gomock.NewController(t)
   499  	var cli = mocks.NewMockClient(mocker)
   500  
   501  	// create a request and reconcile it
   502  	request := clusterstest.NewRequest(vzconst.KubeSystem, "unit-test-verrazzano-helidon-workload")
   503  	reconciler := newReconciler(cli)
   504  	result, err := reconciler.Reconcile(context.TODO(), request)
   505  
   506  	mocker.Finish()
   507  	assert.Nil(err)
   508  	assert.True(result.IsZero())
   509  }