github.com/verrazzano/verrazzano@v1.7.1/application-operator/controllers/wlsworkload/weblogicworkload_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 wlsworkload
     5  
     6  import (
     7  	"context"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/go-logr/logr"
    13  
    14  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    15  
    16  	oamrt "github.com/crossplane/crossplane-runtime/apis/common/v1"
    17  	"github.com/crossplane/oam-kubernetes-runtime/apis/core"
    18  	oamcore "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
    19  	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
    20  	"github.com/golang/mock/gomock"
    21  	asserts "github.com/stretchr/testify/assert"
    22  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
    23  	"github.com/verrazzano/verrazzano/application-operator/constants"
    24  	"github.com/verrazzano/verrazzano/application-operator/controllers/logging"
    25  	"github.com/verrazzano/verrazzano/application-operator/controllers/metricstrait"
    26  	"github.com/verrazzano/verrazzano/application-operator/mocks"
    27  	vzconst "github.com/verrazzano/verrazzano/pkg/constants"
    28  	"go.uber.org/zap"
    29  	corev1 "k8s.io/api/core/v1"
    30  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    33  	"k8s.io/apimachinery/pkg/runtime"
    34  	k8sschema "k8s.io/apimachinery/pkg/runtime/schema"
    35  	"k8s.io/apimachinery/pkg/types"
    36  	ctrl "sigs.k8s.io/controller-runtime"
    37  	"sigs.k8s.io/controller-runtime/pkg/client"
    38  	"sigs.k8s.io/yaml"
    39  )
    40  
    41  const image = "unit-test-image:existing"
    42  const clusterOne = "cluster-1"
    43  const namespace = "unit-test-namespace"
    44  const restartVersion = "new-restart"
    45  const weblogicDomainName = "unit-test-domain"
    46  const commonMetadata = `{"name":"unit-test-cluster"}`
    47  const weblogicDomain = `
    48  {
    49     "domainUID": "unit-test-domain"
    50  }
    51  `
    52  const weblogicDomainv9WithPV = `
    53  {
    54    "clusters": [
    55      {
    56        "name": "cluster-1"
    57      }
    58    ],
    59    "configuration": {
    60      "initializeDomainOnPV": {
    61        "domain": {
    62          "domainCreationImages": [
    63            {
    64              "image": "phx.ocir.io/devweblogic/sankar-ai:aimiidemov1",
    65              "sourceModelHome": "/u01/wdt/models",
    66              "sourceWDTInstallHome": "/u01/wdt/weblogic-deploy"
    67            }
    68          ],
    69          "domainType": "WLS"
    70        },
    71        "persistentVolume": {
    72          "metadata": {
    73            "name": "unit-test-domain-pv"
    74          },
    75          "spec": {
    76            "capacity": {
    77              "storage": "500Gi"
    78            },
    79            "nfs": {
    80              "path": "/shared",
    81              "readOnly": false,
    82              "server": "100.101.68.92"
    83            },
    84            "storageClassName": "oci-fss"
    85          }
    86        },
    87        "persistentVolumeClaim": {
    88          "metadata": {
    89            "name": "unit-test-domain-pvc"
    90          },
    91          "spec": {
    92            "resources": {
    93              "requests": {
    94                "storage": "100Gi"
    95              }
    96            },
    97            "storageClassName": "oci-fss",
    98            "volumeName": "unit-test-domain-pv"
    99          }
   100        }
   101      },
   102      "introspectorJobActiveDeadlineSeconds": 900
   103    },
   104    "domainHome": "/shared/domains/mymii-domain",
   105    "domainHomeSourceType": "PersistentVolume",
   106    "domainUID": "unit-test-domain",
   107    "image": "phx.ocir.io/devweblogic/test-images/weblogic:14.1.1.0-11",
   108    "imagePullPolicy": "IfNotPresent",
   109    "serverPod": {
   110      "env": [
   111        {
   112          "name": "JAVA_OPTIONS",
   113          "value": "-Dweblogic.StdoutDebugEnabled=false -Djava.security.egd=file:/dev/./urandom -Dweblogic.security.SSL.ignoreHostnameVerification=true"
   114        },
   115        {
   116          "name": "USER_MEM_ARGS",
   117          "value": "-Xms64m -Xmx256m"
   118        }
   119      ],
   120      "volumeMounts": [
   121        {
   122          "mountPath": "/shared",
   123          "name": "weblogic-domain-storage-volume"
   124        },
   125        {
   126          "mountPath": "/scratch",
   127          "name": "weblogic-domain-scratch-volume"
   128        }
   129      ],
   130      "volumes": [
   131        {
   132          "name": "weblogic-domain-storage-volume",
   133          "persistentVolumeClaim": {
   134            "claimName": "mymii-domain-pvc"
   135          }
   136        },
   137        {
   138          "name": "weblogic-domain-scratch-volume",
   139          "persistentVolumeClaim": {
   140            "claimName": "mymii-domain-pvc-scratch"
   141          }
   142        }
   143      ]
   144    }
   145  }
   146  `
   147  const weblogicDomainv9WithTwoClusters = `
   148  {
   149     "domainUID": "unit-test-domain",
   150     "clusters": [
   151     {
   152        "clusterName": "cluster-1"
   153     },
   154     {
   155        "clusterName": "cluster-2"
   156     }
   157     ]
   158  }
   159  `
   160  const weblogicDomainWithMonitoringExporter = `
   161  {
   162     "domainUID": "unit-test-domain",
   163     "monitoringExporter": {
   164        "image": "my-weblogic-monitoring-exporter:1.0.0",
   165        "imagePullPolicy": "IfNotPresent",
   166        "configuration": {
   167           "metricsNameSnakeCase": true,
   168           "domainQualifier": true,
   169           "queries": [
   170           {
   171              "JVMRuntime": {
   172                 "prefix": "wls_jvm_",
   173                 "key": "name"
   174              }
   175           }
   176           ]
   177        }
   178     }
   179  }
   180  `
   181  const weblogicDomainWithWDTConfigMap = `
   182  {
   183     "domainUID": "unit-test-domain",
   184     "configuration": {
   185        "model": {
   186           "configMap": "wdt-config-map"
   187        }
   188     }
   189  }
   190  `
   191  const weblogicDomainWithLogHome = `
   192  {
   193     "domainUID": "unit-test-domain",
   194     "logHome": "/unit_test/log_home",
   195     "serverPod": {
   196        "volumes": [
   197        {
   198           "name": "unit-test-logging-volume",
   199           "persistentVolumeClaim": {
   200              "claimName": "unit-test-pvc"
   201           }
   202        }
   203        ],
   204        "volumeMounts": [
   205        {
   206           "name": "unit-test-logging-volume",
   207           "mountPath": "/unit_test"
   208        }
   209        ]
   210     }
   211  }
   212  `
   213  const loggingTrait = `
   214  {
   215  	"apiVersion": "oam.verrazzano.io/v1alpha1",
   216  	"kind": "LoggingTrait",
   217  	"name": "my-logging-trait"
   218  }
   219  `
   220  
   221  func buildTemplate(apiVersion string, metadata string, spec string) vzapi.VerrazzanoWebLogicWorkloadTemplate {
   222  	return vzapi.VerrazzanoWebLogicWorkloadTemplate{APIVersion: apiVersion, Metadata: runtime.RawExtension{Raw: []byte(metadata)}, Spec: runtime.RawExtension{Raw: []byte(strings.ReplaceAll(strings.ReplaceAll(spec, " ", ""), "\n", ""))}}
   223  }
   224  
   225  func buildDomainV8Template(spec string) vzapi.VerrazzanoWebLogicWorkloadTemplate {
   226  	return buildTemplate(APIVersionV8, commonMetadata, spec)
   227  }
   228  
   229  func buildDomainV9Template(spec string) vzapi.VerrazzanoWebLogicWorkloadTemplate {
   230  	return buildTemplate(APIVersionV9, commonMetadata, spec)
   231  }
   232  
   233  func buildClusterTemplate(name string) vzapi.VerrazzanoWebLogicWorkloadTemplate {
   234  	return buildTemplate(APIVersionV1, `{"name":"`+name+`"}`, `{"clusterName":"`+name+`"}`)
   235  }
   236  
   237  // TestReconcilerSetupWithManager test the creation of the VerrazzanoWebLogicWorkload reconciler.
   238  // GIVEN a controller implementation
   239  // WHEN the controller is created
   240  // THEN verify no error is returned
   241  func TestReconcilerSetupWithManager(t *testing.T) {
   242  	assert := asserts.New(t)
   243  
   244  	var mocker *gomock.Controller
   245  	var mgr *mocks.MockManager
   246  	var cli *mocks.MockClient
   247  	var scheme *runtime.Scheme
   248  	var reconciler Reconciler
   249  	var err error
   250  
   251  	mocker = gomock.NewController(t)
   252  	mgr = mocks.NewMockManager(mocker)
   253  	cli = mocks.NewMockClient(mocker)
   254  	scheme = runtime.NewScheme()
   255  	_ = vzapi.AddToScheme(scheme)
   256  	reconciler = Reconciler{Client: cli, Scheme: scheme}
   257  	mgr.EXPECT().GetControllerOptions().AnyTimes()
   258  	mgr.EXPECT().GetScheme().Return(scheme)
   259  	mgr.EXPECT().GetLogger().Return(logr.Discard())
   260  	mgr.EXPECT().SetFields(gomock.Any()).Return(nil).AnyTimes()
   261  	mgr.EXPECT().Add(gomock.Any()).Return(nil).AnyTimes()
   262  	err = reconciler.SetupWithManager(mgr)
   263  	mocker.Finish()
   264  	assert.NoError(err)
   265  }
   266  
   267  // TestReconcileCreateWebLogicDomain tests the basic happy path of reconciling a VerrazzanoWebLogicWorkload. We
   268  // expect to write out a WebLogic domain CR, but we aren't adding logging or any other scopes or traits.
   269  // GIVEN a VerrazzanoWebLogicWorkload resource is created
   270  // WHEN the controller Reconcile function is called
   271  // THEN expect a WebLogic domain CR to be written
   272  func TestReconcileCreateWebLogicDomain(t *testing.T) {
   273  	assert := asserts.New(t)
   274  
   275  	var mocker = gomock.NewController(t)
   276  	var cli = mocks.NewMockClient(mocker)
   277  	mockStatus := mocks.NewMockStatusWriter(mocker)
   278  
   279  	appConfigName := "unit-test-app-config"
   280  	componentName := "unit-test-component"
   281  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   282  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   283  	svcLabels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   284  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   285  
   286  	// expect call to fetch existing WebLogic Domain
   287  	cli.EXPECT().
   288  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
   289  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   290  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   291  		})
   292  	// expect a call to fetch the VerrazzanoWebLogicWorkload
   293  	cli.EXPECT().
   294  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
   295  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
   296  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
   297  			workload.ObjectMeta.Labels = labels
   298  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
   299  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
   300  			workload.Namespace = namespace
   301  			workload.ObjectMeta.Generation = 2
   302  			workload.Status.LastGeneration = "1"
   303  			return nil
   304  		})
   305  	// expect a call to list the FLUENTD config maps
   306  	cli.EXPECT().
   307  		List(gomock.Any(), gomock.Any(), gomock.Any()).
   308  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
   309  			// return no resources
   310  			return nil
   311  		})
   312  	// no config maps found, so expect a call to create a config map with our parsing rules
   313  	cli.EXPECT().
   314  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   315  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   316  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
   317  			return nil
   318  		})
   319  	// expect call to fetch the WDT config Map
   320  	cli.EXPECT().
   321  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
   322  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
   323  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
   324  		})
   325  	// no WDT config maps found, so expect a call to create a WDT config map
   326  	cli.EXPECT().
   327  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   328  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   329  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
   330  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
   331  			assert.Equal(weblogicDomainName, configMap.ObjectMeta.Labels[webLogicDomainUIDLabel])
   332  			return nil
   333  		})
   334  	// expect a call to get the namespace for the domain
   335  	cli.EXPECT().
   336  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
   337  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
   338  			return nil
   339  		})
   340  	// expect a call to get the application configuration for the workload
   341  	cli.EXPECT().
   342  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
   343  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
   344  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
   345  			return nil
   346  		}).Times(2)
   347  	// expect a call to attempt to get the WebLogic CR - return not found
   348  	cli.EXPECT().
   349  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
   350  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
   351  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
   352  		})
   353  	// expect a call to create the WebLogic domain CR
   354  	cli.EXPECT().
   355  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   356  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   357  			assert.Equal(APIVersionV8, u.GetAPIVersion())
   358  			assert.Equal(DomainKind, u.GetKind())
   359  
   360  			// make sure the OAM component and app name labels were copied to the pod spec
   361  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   362  			assert.Equal(labels, specLabels)
   363  
   364  			// make sure the OAM component and app name labels were copied to the service spec
   365  			specServiceLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerServiceLabelsFields...)
   366  			assert.Equal(svcLabels, specServiceLabels)
   367  
   368  			// make sure configuration.istio.enabled is false
   369  			specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
   370  			assert.Equal(specIstioEnabled, false)
   371  
   372  			// make sure the restartVersion is empty
   373  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
   374  			assert.Equal("", domainRestartVersion)
   375  
   376  			// make sure monitoringExporter exists
   377  			validateDefaultMonitoringExporter(u, t)
   378  
   379  			// make sure default WDT configMap exists
   380  			validateDefaultWDTConfigMap(u, t)
   381  
   382  			return nil
   383  		})
   384  
   385  	// expect a call to status update
   386  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
   387  
   388  	// Expect a call to update the status of the Verrazzano resource to update components
   389  	mockStatus.EXPECT().
   390  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   391  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
   392  			return nil
   393  		})
   394  
   395  	// create a request and reconcile it
   396  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
   397  	reconciler := newReconciler(cli)
   398  	result, err := reconciler.Reconcile(context.TODO(), request)
   399  
   400  	mocker.Finish()
   401  	assert.NoError(err)
   402  	assert.Equal(false, result.Requeue)
   403  }
   404  
   405  // TestReconcileCreateWebLogicDomainV9WithPV tests the basic happy path of reconciling a VerrazzanoWebLogicWorkload. We
   406  // expect to write out WebLogic Domain and Cluster CR's, but we aren't adding logging or any other scopes or traits.
   407  // GIVEN a VerrazzanoWebLogicWorkload resource is created
   408  // WHEN the controller Reconcile function is called
   409  // THEN expect WebLogic Domain and Cluster CR's to be written
   410  func TestReconcileCreateWebLogicDomainV9WithPV(t *testing.T) {
   411  	assert := asserts.New(t)
   412  
   413  	var mocker = gomock.NewController(t)
   414  	var cli = mocks.NewMockClient(mocker)
   415  	mockStatus := mocks.NewMockStatusWriter(mocker)
   416  
   417  	appConfigName := "unit-test-app-config"
   418  	componentName := "unit-test-component"
   419  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   420  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   421  
   422  	// expect call to fetch existing WebLogic Domain
   423  	cli.EXPECT().
   424  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
   425  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   426  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   427  		})
   428  	// expect a call to fetch the VerrazzanoWebLogicWorkload
   429  	cli.EXPECT().
   430  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
   431  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
   432  			workload.Spec.Template = buildDomainV9Template(weblogicDomainv9WithPV)
   433  			workload.Spec.Clusters = []vzapi.VerrazzanoWebLogicWorkloadTemplate{buildClusterTemplate(clusterOne)}
   434  			workload.ObjectMeta.Labels = labels
   435  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
   436  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
   437  			workload.Namespace = namespace
   438  			workload.ObjectMeta.Generation = 2
   439  			workload.Status.LastGeneration = "1"
   440  			return nil
   441  		})
   442  	// expect a call to list the FLUENTD config maps
   443  	cli.EXPECT().
   444  		List(gomock.Any(), gomock.Any(), gomock.Any()).
   445  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
   446  			// return no resources
   447  			return nil
   448  		})
   449  	// no config maps found, so expect a call to create a config map with our parsing rules
   450  	cli.EXPECT().
   451  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   452  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   453  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
   454  			return nil
   455  		})
   456  	// expect call to fetch the WDT config Map
   457  	cli.EXPECT().
   458  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
   459  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
   460  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
   461  		})
   462  	// no WDT config maps found, so expect a call to create a WDT config map
   463  	cli.EXPECT().
   464  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   465  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   466  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
   467  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
   468  			assert.Equal(weblogicDomainName, configMap.ObjectMeta.Labels[webLogicDomainUIDLabel])
   469  			return nil
   470  		})
   471  	// expect a call to get the application configuration for the workload
   472  	cli.EXPECT().
   473  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
   474  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
   475  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
   476  			return nil
   477  		}).Times(2)
   478  	// expect call to fetch existing WebLogic Cluster cluster-1
   479  	cli.EXPECT().
   480  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: clusterOne}, gomock.Not(gomock.Nil()), gomock.Any()).
   481  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   482  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   483  		})
   484  	// expect a call to attempt to get the WebLogic CR - return not found
   485  	cli.EXPECT().
   486  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
   487  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
   488  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
   489  		})
   490  	// expect a call to create the WebLogic Cluster CR cluster-1
   491  	cli.EXPECT().
   492  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   493  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   494  			assert.Equal(APIVersionV1, u.GetAPIVersion())
   495  			assert.Equal(ClusterKind, u.GetKind())
   496  
   497  			// make sure the OAM component and app name labels were copied
   498  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   499  			assert.Equal(labels, specLabels)
   500  
   501  			return nil
   502  		})
   503  	// expect a call to create the WebLogic domain CR
   504  	cli.EXPECT().
   505  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   506  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   507  			assert.Equal(APIVersionV9, u.GetAPIVersion())
   508  			assert.Equal(DomainKind, u.GetKind())
   509  
   510  			// make sure the OAM component and app name labels were copied
   511  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   512  			assert.Equal(labels, specLabels)
   513  
   514  			// make sure the restartVersion is empty
   515  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
   516  			assert.Equal("", domainRestartVersion)
   517  
   518  			// make sure monitoringExporter exists
   519  			validateDefaultMonitoringExporter(u, t)
   520  
   521  			// make sure default WDT configMap exists
   522  			validatePVWDTConfigMap(u, t)
   523  
   524  			return nil
   525  		})
   526  
   527  	// expect a call to status update
   528  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
   529  
   530  	// Expect a call to update the status of the Verrazzano resource to update components
   531  	mockStatus.EXPECT().
   532  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   533  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
   534  			return nil
   535  		})
   536  
   537  	// create a request and reconcile it
   538  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
   539  	reconciler := newReconciler(cli)
   540  	result, err := reconciler.Reconcile(context.TODO(), request)
   541  
   542  	mocker.Finish()
   543  	assert.NoError(err)
   544  	assert.Equal(false, result.Requeue)
   545  }
   546  
   547  // TestReconcileCreateWebLogicDomainV9 tests the basic happy path of reconciling a VerrazzanoWebLogicWorkload. We
   548  // expect to write out WebLogic Domain and Cluster CR's, but we aren't adding logging or any other scopes or traits.
   549  // GIVEN a VerrazzanoWebLogicWorkload resource is created
   550  // WHEN the controller Reconcile function is called
   551  // THEN expect WebLogic Domain and Cluster CR's to be written
   552  func TestReconcileCreateWebLogicDomainV9(t *testing.T) {
   553  	assert := asserts.New(t)
   554  
   555  	var mocker = gomock.NewController(t)
   556  	var cli = mocks.NewMockClient(mocker)
   557  	mockStatus := mocks.NewMockStatusWriter(mocker)
   558  
   559  	appConfigName := "unit-test-app-config"
   560  	componentName := "unit-test-component"
   561  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   562  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   563  
   564  	// expect call to fetch existing WebLogic Domain
   565  	cli.EXPECT().
   566  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
   567  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   568  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   569  		})
   570  	// expect a call to fetch the VerrazzanoWebLogicWorkload
   571  	cli.EXPECT().
   572  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
   573  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
   574  			workload.Spec.Template = buildDomainV9Template(weblogicDomainv9WithTwoClusters)
   575  			workload.Spec.Clusters = []vzapi.VerrazzanoWebLogicWorkloadTemplate{buildClusterTemplate(clusterOne), buildClusterTemplate("cluster-2")}
   576  			workload.ObjectMeta.Labels = labels
   577  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
   578  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
   579  			workload.Namespace = namespace
   580  			workload.ObjectMeta.Generation = 2
   581  			workload.Status.LastGeneration = "1"
   582  			return nil
   583  		})
   584  	// expect a call to list the FLUENTD config maps
   585  	cli.EXPECT().
   586  		List(gomock.Any(), gomock.Any(), gomock.Any()).
   587  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
   588  			// return no resources
   589  			return nil
   590  		})
   591  	// no config maps found, so expect a call to create a config map with our parsing rules
   592  	cli.EXPECT().
   593  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   594  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   595  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
   596  			return nil
   597  		})
   598  	// expect call to fetch the WDT config Map
   599  	cli.EXPECT().
   600  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
   601  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
   602  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
   603  		})
   604  	// no WDT config maps found, so expect a call to create a WDT config map
   605  	cli.EXPECT().
   606  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   607  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   608  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
   609  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
   610  			assert.Equal(weblogicDomainName, configMap.ObjectMeta.Labels[webLogicDomainUIDLabel])
   611  			return nil
   612  		})
   613  	// expect a call to get the application configuration for the workload
   614  	cli.EXPECT().
   615  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
   616  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
   617  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
   618  			return nil
   619  		}).Times(2)
   620  	// expect call to fetch existing WebLogic Cluster cluster-1
   621  	cli.EXPECT().
   622  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: clusterOne}, gomock.Not(gomock.Nil()), gomock.Any()).
   623  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   624  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   625  		})
   626  	// expect call to fetch existing WebLogic Cluster cluster-2
   627  	cli.EXPECT().
   628  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "cluster-2"}, gomock.Not(gomock.Nil()), gomock.Any()).
   629  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   630  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   631  		})
   632  	// expect a call to attempt to get the WebLogic CR - return not found
   633  	cli.EXPECT().
   634  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
   635  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
   636  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
   637  		})
   638  	// expect a call to create the WebLogic Cluster CR cluster-1
   639  	cli.EXPECT().
   640  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   641  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   642  			assert.Equal(APIVersionV1, u.GetAPIVersion())
   643  			assert.Equal(ClusterKind, u.GetKind())
   644  
   645  			// make sure the OAM component and app name labels were copied
   646  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   647  			assert.Equal(labels, specLabels)
   648  
   649  			return nil
   650  		})
   651  	// expect a call to create the WebLogic Cluster CR cluster-2
   652  	cli.EXPECT().
   653  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   654  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   655  			assert.Equal(APIVersionV1, u.GetAPIVersion())
   656  			assert.Equal(ClusterKind, u.GetKind())
   657  
   658  			// make sure the OAM component and app name labels were copied
   659  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   660  			assert.Equal(labels, specLabels)
   661  
   662  			return nil
   663  		})
   664  	// expect a call to create the WebLogic domain CR
   665  	cli.EXPECT().
   666  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   667  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   668  			assert.Equal(APIVersionV9, u.GetAPIVersion())
   669  			assert.Equal(DomainKind, u.GetKind())
   670  
   671  			// make sure the OAM component and app name labels were copied
   672  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   673  			assert.Equal(labels, specLabels)
   674  
   675  			// make sure the restartVersion is empty
   676  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
   677  			assert.Equal("", domainRestartVersion)
   678  
   679  			// make sure monitoringExporter exists
   680  			validateDefaultMonitoringExporter(u, t)
   681  
   682  			// make sure default WDT configMap exists
   683  			validateDefaultWDTConfigMap(u, t)
   684  
   685  			return nil
   686  		})
   687  
   688  	// expect a call to status update
   689  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
   690  
   691  	// Expect a call to update the status of the Verrazzano resource to update components
   692  	mockStatus.EXPECT().
   693  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   694  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
   695  			return nil
   696  		})
   697  
   698  	// create a request and reconcile it
   699  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
   700  	reconciler := newReconciler(cli)
   701  	result, err := reconciler.Reconcile(context.TODO(), request)
   702  
   703  	mocker.Finish()
   704  	assert.NoError(err)
   705  	assert.Equal(false, result.Requeue)
   706  }
   707  
   708  // TestReconcileCreateWebLogicDomainWithMonitoringExporter tests the basic happy path of reconciling a VerrazzanoWebLogicWorkload
   709  // with monitoringExporter. We expect to write out a WebLogic domain CR with this monitoringExporter intact.
   710  // GIVEN a VerrazzanoWebLogicWorkload resource is created
   711  // WHEN the controller Reconcile function is called
   712  // THEN expect a WebLogic domain CR to be written
   713  func TestReconcileCreateWebLogicDomainWithMonitoringExporter(t *testing.T) {
   714  	assert := asserts.New(t)
   715  
   716  	var mocker = gomock.NewController(t)
   717  	var cli = mocks.NewMockClient(mocker)
   718  	mockStatus := mocks.NewMockStatusWriter(mocker)
   719  
   720  	appConfigName := "unit-test-app-config"
   721  	componentName := "unit-test-component"
   722  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   723  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   724  
   725  	// expect call to fetch existing WebLogic Domain
   726  	cli.EXPECT().
   727  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
   728  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   729  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   730  		})
   731  	// expect a call to fetch the VerrazzanoWebLogicWorkload
   732  	cli.EXPECT().
   733  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
   734  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
   735  			workload.Spec.Template = buildDomainV8Template(weblogicDomainWithMonitoringExporter)
   736  			workload.ObjectMeta.Labels = labels
   737  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
   738  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
   739  			workload.Namespace = namespace
   740  			workload.ObjectMeta.Generation = 2
   741  			workload.Status.LastGeneration = "1"
   742  			return nil
   743  		})
   744  	// expect a call to list the FLUENTD config maps
   745  	cli.EXPECT().
   746  		List(gomock.Any(), gomock.Any(), gomock.Any()).
   747  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
   748  			// return no resources
   749  			return nil
   750  		})
   751  	// no config maps found, so expect a call to create a config map with our parsing rules
   752  	cli.EXPECT().
   753  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   754  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   755  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
   756  			return nil
   757  		})
   758  	// expect call to fetch the WDT config Map
   759  	cli.EXPECT().
   760  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
   761  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
   762  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
   763  		})
   764  	// no WDT config maps found, so expect a call to create a WDT config map
   765  	cli.EXPECT().
   766  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   767  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   768  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
   769  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
   770  			return nil
   771  		})
   772  	// expect a call to get the namespace for the domain
   773  	cli.EXPECT().
   774  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
   775  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
   776  			return nil
   777  		})
   778  	// expect a call to get the application configuration for the workload
   779  	cli.EXPECT().
   780  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
   781  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
   782  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
   783  			return nil
   784  		}).Times(2)
   785  	// expect a call to attempt to get the WebLogic CR - return not found
   786  	cli.EXPECT().
   787  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
   788  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
   789  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
   790  		})
   791  	// expect a call to create the WebLogic domain CR
   792  	cli.EXPECT().
   793  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   794  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   795  			assert.Equal(APIVersionV8, u.GetAPIVersion())
   796  			assert.Equal(DomainKind, u.GetKind())
   797  
   798  			// make sure the OAM component and app name labels were copied
   799  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   800  			assert.Equal(labels, specLabels)
   801  
   802  			// make sure configuration.istio.enabled is false
   803  			specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
   804  			assert.Equal(specIstioEnabled, false)
   805  
   806  			// make sure the restartVersion is empty
   807  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
   808  			assert.Equal("", domainRestartVersion)
   809  
   810  			// make sure monitoringExporter exists
   811  			validateTestMonitoringExporter(u, t)
   812  
   813  			return nil
   814  		})
   815  
   816  	// expect a call to status update
   817  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
   818  
   819  	// Expect a call to update the status of the Verrazzano resource to update components
   820  	mockStatus.EXPECT().
   821  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   822  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
   823  			return nil
   824  		})
   825  
   826  	// create a request and reconcile it
   827  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
   828  	reconciler := newReconciler(cli)
   829  	result, err := reconciler.Reconcile(context.TODO(), request)
   830  
   831  	mocker.Finish()
   832  	assert.NoError(err)
   833  	assert.Equal(false, result.Requeue)
   834  }
   835  
   836  // TestReconcileCreateWebLogicDomainWithLogging tests the happy path of reconciling a VerrazzanoWebLogicWorkload
   837  // with an attached logging scope. We expect to write out a WebLogic domain CR with the FLUENTD sidecar and
   838  // associated volumes and mounts.
   839  // GIVEN a VerrazzanoWebLogicWorkload resource is created with a logging scope
   840  // WHEN the controller Reconcile function is called
   841  // THEN expect a WebLogic domain CR to be written with logging extras.
   842  func TestReconcileCreateWebLogicDomainWithLogging(t *testing.T) {
   843  	assert := asserts.New(t)
   844  
   845  	var mocker = gomock.NewController(t)
   846  	var cli = mocks.NewMockClient(mocker)
   847  	mockStatus := mocks.NewMockStatusWriter(mocker)
   848  
   849  	appConfigName := "unit-test-app-config"
   850  	componentName := "unit-test-component"
   851  	fluentdImage := "unit-test-image:latest"
   852  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   853  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   854  
   855  	_ = os.Setenv("WEBLOGIC_MONITORING_EXPORTER_IMAGE", "my-weblogic-monitoring-exporter:a")
   856  	defer func() { _ = os.Unsetenv("WEBLOGIC_MONITORING_EXPORTER_IMAGE") }()
   857  
   858  	// set the Fluentd image which is obtained via env then reset at end of test
   859  	initialDefaultFluentdImage := logging.DefaultFluentdImage
   860  	logging.DefaultFluentdImage = fluentdImage
   861  	defer func() { logging.DefaultFluentdImage = initialDefaultFluentdImage }()
   862  
   863  	// expect call to fetch existing WebLogic Domain
   864  	cli.EXPECT().
   865  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
   866  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
   867  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
   868  		})
   869  	// expect a call to fetch the VerrazzanoWebLogicWorkload
   870  	cli.EXPECT().
   871  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
   872  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
   873  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
   874  			workload.ObjectMeta.Labels = labels
   875  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
   876  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
   877  			workload.Namespace = namespace
   878  			workload.ObjectMeta.Generation = 2
   879  			workload.Status.LastGeneration = "1"
   880  			return nil
   881  		})
   882  	// expect a call to list the FLUENTD config maps
   883  	cli.EXPECT().
   884  		List(gomock.Any(), gomock.Any(), gomock.Any()).
   885  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
   886  			// return no resources
   887  			return nil
   888  		})
   889  	// no config maps found, so expect a call to create a config map with our parsing rules
   890  	cli.EXPECT().
   891  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   892  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   893  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
   894  			return nil
   895  		})
   896  	// expect call to fetch the WDT config Map
   897  	cli.EXPECT().
   898  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
   899  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
   900  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
   901  		})
   902  	// no WDT config maps found, so expect a call to create a WDT config map
   903  	cli.EXPECT().
   904  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   905  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
   906  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
   907  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
   908  			return nil
   909  		})
   910  	// expect a call to get the namespace for the domain
   911  	cli.EXPECT().
   912  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
   913  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
   914  			return nil
   915  		})
   916  	// expect a call to get the application configuration for the workload
   917  	cli.EXPECT().
   918  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
   919  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
   920  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
   921  			return nil
   922  		}).Times(2)
   923  	// expect a call to attempt to get the WebLogic CR - return not found
   924  	cli.EXPECT().
   925  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
   926  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
   927  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
   928  		})
   929  	// expect a call to create the WebLogic domain CR
   930  	cli.EXPECT().
   931  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   932  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
   933  			assert.Equal(APIVersionV8, u.GetAPIVersion())
   934  			assert.Equal(DomainKind, u.GetKind())
   935  
   936  			// make sure the OAM component and app name labels were copied
   937  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
   938  			assert.Equal(labels, specLabels)
   939  
   940  			// make sure configuration.istio.enabled is false
   941  			specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
   942  			assert.Equal(specIstioEnabled, false)
   943  
   944  			// make sure the FLUENTD sidecar was added
   945  			containers, _, _ := unstructured.NestedSlice(u.Object, specServerPodContainersFields...)
   946  			assert.Equal(1, len(containers))
   947  			assert.Equal(fluentdImage, containers[0].(map[string]interface{})["image"])
   948  
   949  			// make sure the restartVersion is empty
   950  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
   951  			assert.Equal("", domainRestartVersion)
   952  
   953  			// make sure monitoringExporter exists
   954  			validateDefaultMonitoringExporter(u, t)
   955  
   956  			return nil
   957  		})
   958  
   959  	// expect a call to status update
   960  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
   961  
   962  	// Expect a call to update the status of the Verrazzano resource to update components
   963  	mockStatus.EXPECT().
   964  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
   965  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
   966  			//		asserts.NotZero(len(verrazzano.Status.Components), "Status.Components len should not be zero")
   967  			return nil
   968  		})
   969  
   970  	// create a request and reconcile it
   971  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
   972  	reconciler := newReconciler(cli)
   973  	result, err := reconciler.Reconcile(context.TODO(), request)
   974  
   975  	mocker.Finish()
   976  	assert.NoError(err)
   977  	assert.Equal(false, result.Requeue)
   978  }
   979  
   980  // TestReconcileCreateWebLogicDomainWithCustomLogging tests the happy path of reconciling a VerrazzanoWebLogicWorkload
   981  // with a custom logging trait. We expect to write out a WebLogic domain CR with an extra FLUENTD sidecar,
   982  // ConfigMap, and associated volumes and mounts.
   983  // GIVEN a VerrazzanoWebLogicWorkload resource is created with a custom logging trait
   984  // WHEN the controller Reconcile function is called
   985  // THEN expect a WebLogic domain CR to be written with custom logging extras.
   986  func TestReconcileCreateWebLogicDomainWithCustomLogging(t *testing.T) {
   987  	assert := asserts.New(t)
   988  
   989  	var mocker = gomock.NewController(t)
   990  	var cli = mocks.NewMockClient(mocker)
   991  	mockStatus := mocks.NewMockStatusWriter(mocker)
   992  
   993  	appConfigName := "unit-test-app-config"
   994  	componentName := "unit-test-component"
   995  	workloadName := "unit-test-verrazzano-weblogic-workload"
   996  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
   997  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
   998  
   999  	// expect call to fetch existing WebLogic Domain
  1000  	cli.EXPECT().
  1001  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1002  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  1003  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
  1004  		})
  1005  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1006  	cli.EXPECT().
  1007  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: workloadName}, gomock.Not(gomock.Nil()), gomock.Any()).
  1008  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1009  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  1010  			workload.ObjectMeta.Labels = labels
  1011  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1012  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1013  			workload.Namespace = namespace
  1014  			workload.Name = workloadName
  1015  			workload.ObjectMeta.Generation = 2
  1016  			workload.Status.LastGeneration = "1"
  1017  			workload.OwnerReferences = []metav1.OwnerReference{
  1018  				{
  1019  					UID: namespace,
  1020  				},
  1021  			}
  1022  			return nil
  1023  		})
  1024  	// expect a call to list the logging traits
  1025  	cli.EXPECT().
  1026  		List(gomock.Any(), &vzapi.LoggingTraitList{TypeMeta: metav1.TypeMeta{Kind: "LoggingTrait", APIVersion: "oam.verrazzano.io/v1alpha1"}}, gomock.Not(gomock.Nil())).
  1027  		DoAndReturn(func(ctx context.Context, loggingTraitList *vzapi.LoggingTraitList, inNamespace client.InNamespace) error {
  1028  			loggingTraitList.Items = []vzapi.LoggingTrait{
  1029  				{
  1030  					ObjectMeta: metav1.ObjectMeta{
  1031  						OwnerReferences: []metav1.OwnerReference{
  1032  							{
  1033  								UID: namespace,
  1034  							},
  1035  						},
  1036  					},
  1037  					Spec: vzapi.LoggingTraitSpec{
  1038  						WorkloadReference: oamrt.TypedReference{
  1039  							Name: workloadName,
  1040  						},
  1041  					},
  1042  				},
  1043  			}
  1044  			return nil
  1045  		})
  1046  	// expect a call to list the FLUENTD config maps
  1047  	cli.EXPECT().
  1048  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  1049  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  1050  			// return no resources
  1051  			return nil
  1052  		})
  1053  	// Define expected ConfigMap
  1054  	data := make(map[string]string)
  1055  	data["custom.conf"] = ""
  1056  	customLoggingConfigMap := &corev1.ConfigMap{
  1057  		TypeMeta: metav1.TypeMeta{
  1058  			Kind:       "",
  1059  			APIVersion: "",
  1060  		},
  1061  		ObjectMeta: metav1.ObjectMeta{
  1062  			Name:              loggingNamePart + "-unit-test-cluster-domain",
  1063  			Namespace:         namespace,
  1064  			CreationTimestamp: metav1.Time{},
  1065  			OwnerReferences: []metav1.OwnerReference{
  1066  				{
  1067  					APIVersion:         "oam.verrazzano.io/v1alpha1",
  1068  					Kind:               vzconst.VerrazzanoWebLogicWorkloadKind,
  1069  					Name:               "unit-test-verrazzano-weblogic-workload",
  1070  					UID:                "",
  1071  					Controller:         newTrue(),
  1072  					BlockOwnerDeletion: newTrue(),
  1073  				},
  1074  			},
  1075  		},
  1076  		Data: data,
  1077  	}
  1078  	// expect a call to create the custom logging config map
  1079  	cli.EXPECT().
  1080  		Create(gomock.Any(), customLoggingConfigMap, gomock.Any()).
  1081  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1082  			return nil
  1083  		})
  1084  	// no config maps found, so expect a call to create a config map with our parsing rules
  1085  	cli.EXPECT().
  1086  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1087  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1088  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  1089  			return nil
  1090  		})
  1091  	// expect call to fetch the WDT config Map
  1092  	cli.EXPECT().
  1093  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  1094  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1095  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  1096  		})
  1097  	// no WDT config maps found, so expect a call to create a WDT config map
  1098  	cli.EXPECT().
  1099  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1100  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1101  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  1102  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  1103  			return nil
  1104  		})
  1105  	// expect a call to get the namespace for the domain
  1106  	cli.EXPECT().
  1107  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  1108  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  1109  			return nil
  1110  		})
  1111  	// expect a call to get the application configuration for the workload
  1112  	cli.EXPECT().
  1113  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  1114  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1115  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{
  1116  				{
  1117  					ComponentName: componentName,
  1118  					Traits: []oamcore.ComponentTrait{
  1119  						{
  1120  							Trait: runtime.RawExtension{
  1121  								Raw: []byte(strings.ReplaceAll(strings.ReplaceAll(loggingTrait, " ", ""), "\n", "")),
  1122  							},
  1123  						},
  1124  					},
  1125  				},
  1126  			}
  1127  			return nil
  1128  		}).Times(2)
  1129  	// expect a call to get the ConfigMap for logging - return not found
  1130  	cli.EXPECT().
  1131  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: "logging-stdout-unit-test-cluster-domain"}), gomock.Not(gomock.Nil()), gomock.Any()).
  1132  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1133  			return k8serrors.NewNotFound(k8sschema.GroupResource{
  1134  				Group:    "",
  1135  				Resource: "ConfigMap",
  1136  			},
  1137  				"logging-stdout-unit-test-cluster-domain")
  1138  		})
  1139  	// expect a call to attempt to get the WebLogic CR - return not found
  1140  	cli.EXPECT().
  1141  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
  1142  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
  1143  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  1144  		})
  1145  	// expect a call to create the WebLogic domain CR
  1146  	cli.EXPECT().
  1147  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1148  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  1149  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  1150  			assert.Equal(DomainKind, u.GetKind())
  1151  
  1152  			// make sure the OAM component and app name labels were copied
  1153  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
  1154  			assert.Equal(labels, specLabels)
  1155  
  1156  			// make sure configuration.istio.enabled is false
  1157  			specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
  1158  			assert.Equal(specIstioEnabled, false)
  1159  
  1160  			// make sure the restartVersion is empty
  1161  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
  1162  			assert.Equal("", domainRestartVersion)
  1163  
  1164  			// make sure monitoringExporter exists
  1165  			validateDefaultMonitoringExporter(u, t)
  1166  
  1167  			// make sure default WDT configMap exists
  1168  			validateDefaultWDTConfigMap(u, t)
  1169  
  1170  			return nil
  1171  		})
  1172  
  1173  	// expect a call to status update
  1174  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1175  
  1176  	// Expect a call to update the status of the Verrazzano resource to update components
  1177  	mockStatus.EXPECT().
  1178  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1179  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  1180  			//		asserts.NotZero(len(verrazzano.Status.Components), "Status.Components len should not be zero")
  1181  			return nil
  1182  		})
  1183  
  1184  	// create a request and reconcile it
  1185  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1186  	reconciler := newReconciler(cli)
  1187  	result, err := reconciler.Reconcile(context.TODO(), request)
  1188  
  1189  	mocker.Finish()
  1190  	assert.NoError(err)
  1191  	assert.Equal(false, result.Requeue)
  1192  }
  1193  
  1194  // TestReconcileCreateWebLogicDomainWithCustomLogging tests the happy path of reconciling a VerrazzanoWebLogicWorkload
  1195  // with a custom logging trait. We expect to write out a WebLogic domain CR with an extra FLUENTD sidecar
  1196  // and associated volumes and mounts. This test, we are testing the case when the ConfigMap already exists
  1197  // GIVEN a VerrazzanoWebLogicWorkload resource is created with a custom logging trait
  1198  // WHEN the controller Reconcile function is called
  1199  // THEN expect a WebLogic domain CR to be written with custom logging extras.
  1200  func TestReconcileCreateWebLogicDomainWithCustomLoggingConfigMapExists(t *testing.T) {
  1201  	assert := asserts.New(t)
  1202  
  1203  	var mocker = gomock.NewController(t)
  1204  	var cli = mocks.NewMockClient(mocker)
  1205  	mockStatus := mocks.NewMockStatusWriter(mocker)
  1206  
  1207  	appConfigName := "unit-test-app-config"
  1208  	componentName := "unit-test-component"
  1209  	workloadName := "unit-test-verrazzano-weblogic-workload"
  1210  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  1211  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  1212  
  1213  	_ = os.Setenv("WEBLOGIC_MONITORING_EXPORTER_IMAGE", "")
  1214  	defer func() { _ = os.Unsetenv("WEBLOGIC_MONITORING_EXPORTER_IMAGE") }()
  1215  
  1216  	// expect call to fetch existing WebLogic Domain
  1217  	cli.EXPECT().
  1218  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1219  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  1220  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
  1221  		})
  1222  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1223  	cli.EXPECT().
  1224  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: workloadName}, gomock.Not(gomock.Nil()), gomock.Any()).
  1225  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1226  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  1227  			workload.ObjectMeta.Labels = labels
  1228  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1229  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1230  			workload.Namespace = namespace
  1231  			workload.Name = workloadName
  1232  			workload.ObjectMeta.Generation = 2
  1233  			workload.Status.LastGeneration = "1"
  1234  			workload.OwnerReferences = []metav1.OwnerReference{
  1235  				{
  1236  					UID: namespace,
  1237  				},
  1238  			}
  1239  			return nil
  1240  		})
  1241  	// expect a call to list the logging traits
  1242  	cli.EXPECT().
  1243  		List(gomock.Any(), &vzapi.LoggingTraitList{TypeMeta: metav1.TypeMeta{Kind: "LoggingTrait", APIVersion: "oam.verrazzano.io/v1alpha1"}}, gomock.Not(gomock.Nil())).
  1244  		DoAndReturn(func(ctx context.Context, loggingTraitList *vzapi.LoggingTraitList, inNamespace client.InNamespace) error {
  1245  			loggingTraitList.Items = []vzapi.LoggingTrait{
  1246  				{
  1247  					ObjectMeta: metav1.ObjectMeta{
  1248  						OwnerReferences: []metav1.OwnerReference{
  1249  							{
  1250  								UID: namespace,
  1251  							},
  1252  						},
  1253  					},
  1254  					Spec: vzapi.LoggingTraitSpec{
  1255  						WorkloadReference: oamrt.TypedReference{
  1256  							Name: workloadName,
  1257  						},
  1258  					},
  1259  				},
  1260  			}
  1261  			return nil
  1262  		})
  1263  	// expect a call to list the FLUENTD config maps
  1264  	cli.EXPECT().
  1265  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  1266  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  1267  			// return no resources
  1268  			return nil
  1269  		})
  1270  	// no config maps found, so expect a call to create a config map with our parsing rules
  1271  	cli.EXPECT().
  1272  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1273  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1274  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  1275  			return nil
  1276  		})
  1277  	// expect call to fetch the WDT config Map
  1278  	cli.EXPECT().
  1279  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  1280  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1281  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  1282  		})
  1283  	// no WDT config maps found, so expect a call to create a WDT config map
  1284  	cli.EXPECT().
  1285  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1286  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1287  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  1288  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  1289  			return nil
  1290  		})
  1291  	// expect a call to get the namespace for the domain
  1292  	cli.EXPECT().
  1293  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  1294  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  1295  			return nil
  1296  		})
  1297  	// expect a call to get the application configuration for the workload
  1298  	cli.EXPECT().
  1299  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  1300  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1301  
  1302  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{
  1303  				{
  1304  					ComponentName: componentName,
  1305  					Traits: []oamcore.ComponentTrait{
  1306  						{
  1307  							Trait: runtime.RawExtension{
  1308  								Raw: []byte(strings.ReplaceAll(strings.ReplaceAll(loggingTrait, " ", ""), "\n", "")),
  1309  							},
  1310  						},
  1311  					},
  1312  				},
  1313  			}
  1314  			return nil
  1315  		}).Times(2)
  1316  	// expect a call to get the ConfigMap for logging
  1317  	cli.EXPECT().
  1318  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: "logging-stdout-unit-test-cluster-domain"}), gomock.Not(gomock.Nil()), gomock.Any()).
  1319  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1320  			return nil
  1321  		})
  1322  	// expect a call to attempt to get the WebLogic CR - return not found
  1323  	cli.EXPECT().
  1324  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
  1325  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
  1326  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  1327  		})
  1328  	// expect a call to create the WebLogic domain CR
  1329  	cli.EXPECT().
  1330  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1331  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  1332  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  1333  			assert.Equal(DomainKind, u.GetKind())
  1334  
  1335  			// make sure the OAM component and app name labels were copied
  1336  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
  1337  			assert.Equal(labels, specLabels)
  1338  
  1339  			// make sure configuration.istio.enabled is false
  1340  			specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
  1341  			assert.Equal(specIstioEnabled, false)
  1342  
  1343  			// make sure the restartVersion is empty
  1344  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
  1345  			assert.Equal("", domainRestartVersion)
  1346  
  1347  			// make sure monitoringExporter exists
  1348  			validateDefaultMonitoringExporter(u, t)
  1349  
  1350  			// make sure default WDT configMap exists
  1351  			validateDefaultWDTConfigMap(u, t)
  1352  
  1353  			return nil
  1354  		})
  1355  
  1356  	// expect a call to status update
  1357  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1358  
  1359  	// Expect a call to update the status of the Verrazzano resource to update components
  1360  	mockStatus.EXPECT().
  1361  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1362  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  1363  			//		asserts.NotZero(len(verrazzano.Status.Components), "Status.Components len should not be zero")
  1364  			return nil
  1365  		})
  1366  
  1367  	// create a request and reconcile it
  1368  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1369  	reconciler := newReconciler(cli)
  1370  	result, err := reconciler.Reconcile(context.TODO(), request)
  1371  
  1372  	mocker.Finish()
  1373  	assert.NoError(err)
  1374  	assert.Equal(false, result.Requeue)
  1375  }
  1376  
  1377  // TestReconcileCreateWebLogicDomainWithWDTConfigMap tests the basic happy path of reconciling a VerrazzanoWebLogicWorkload
  1378  // with WDT configMap. We expect to update this configMap with default WebLogic plugin configuration details.
  1379  // GIVEN a VerrazzanoWebLogicWorkload resource is created
  1380  // WHEN the controller Reconcile function is called
  1381  // THEN expect a WebLogic domain CR to be written with WDT configMap updated with WebLogic plugin configuration details.
  1382  func TestReconcileCreateWebLogicDomainWithWDTConfigMap(t *testing.T) {
  1383  	assert := asserts.New(t)
  1384  
  1385  	var mocker = gomock.NewController(t)
  1386  	var cli = mocks.NewMockClient(mocker)
  1387  	mockStatus := mocks.NewMockStatusWriter(mocker)
  1388  
  1389  	appConfigName := "unit-test-app-config"
  1390  	componentName := "unit-test-component"
  1391  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  1392  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  1393  
  1394  	// expect call to fetch existing WebLogic Domain
  1395  	cli.EXPECT().
  1396  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1397  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  1398  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
  1399  		})
  1400  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1401  	cli.EXPECT().
  1402  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1403  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1404  			workload.Spec.Template = buildDomainV8Template(weblogicDomainWithWDTConfigMap)
  1405  			workload.ObjectMeta.Labels = labels
  1406  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1407  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1408  			workload.Namespace = namespace
  1409  			workload.ObjectMeta.Generation = 2
  1410  			workload.Status.LastGeneration = "1"
  1411  			return nil
  1412  		})
  1413  	// expect a call to list the FLUENTD config maps
  1414  	cli.EXPECT().
  1415  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  1416  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  1417  			// return no resources
  1418  			return nil
  1419  		})
  1420  	// no config maps found, so expect a call to create a config map with our parsing rules
  1421  	cli.EXPECT().
  1422  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1423  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1424  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  1425  			return nil
  1426  		})
  1427  	// expect a call to get the namespace for the domain
  1428  	cli.EXPECT().
  1429  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  1430  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  1431  			return nil
  1432  		})
  1433  	// expect a call to get the application configuration for the workload
  1434  	cli.EXPECT().
  1435  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  1436  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1437  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  1438  			return nil
  1439  		})
  1440  
  1441  	// expect call to fetch the WDT config map
  1442  	cli.EXPECT().
  1443  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "wdt-config-map"}, gomock.Any(), gomock.Any()).
  1444  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1445  			// set up a scaled down existing scrape config entry for cluster1
  1446  			configMap.Data = map[string]string{
  1447  				"resources": "test",
  1448  			}
  1449  			return nil
  1450  		})
  1451  	// WDT config map found, so expect a call to update a WDT config map
  1452  	cli.EXPECT().
  1453  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1454  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.UpdateOption) error {
  1455  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  1456  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  1457  			return nil
  1458  		})
  1459  
  1460  	// expect a call to attempt to get the WebLogic CR - return not found
  1461  	cli.EXPECT().
  1462  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
  1463  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
  1464  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  1465  		})
  1466  	// expect a call to create the WebLogic domain CR
  1467  	cli.EXPECT().
  1468  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1469  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  1470  			validateWDTConfigMap(u, t)
  1471  			return nil
  1472  		})
  1473  
  1474  	// expect a call to status update
  1475  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1476  
  1477  	// Expect a call to update the status of the Verrazzano resource to update components
  1478  	mockStatus.EXPECT().
  1479  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1480  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  1481  			return nil
  1482  		})
  1483  
  1484  	// create a request and reconcile it
  1485  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1486  	reconciler := newReconciler(cli)
  1487  	result, err := reconciler.Reconcile(context.TODO(), request)
  1488  
  1489  	mocker.Finish()
  1490  	assert.NoError(err)
  1491  	assert.Equal(false, result.Requeue)
  1492  }
  1493  
  1494  // TestReconcileUpdateFluentdImage tests reconciling a VerrazzanoWebLogicWorkload when the Fluentd image
  1495  // in the managed server pod sidecar is old and a new image is available. This should result in the latest Fluentd
  1496  // image being pulled from the env and replaced in the sidecar
  1497  // GIVEN a VerrazzanoWebLogicWorkload resource that is using an old Fluentd image
  1498  // WHEN the controller Reconcile function is called
  1499  // THEN the Fluentd image should be replaced in the Fluentd sidecar
  1500  func TestReconcileUpdateFluentdImage(t *testing.T) {
  1501  	assert := asserts.New(t)
  1502  
  1503  	var mocker = gomock.NewController(t)
  1504  	var cli = mocks.NewMockClient(mocker)
  1505  	mockStatus := mocks.NewMockStatusWriter(mocker)
  1506  
  1507  	appConfigName := "unit-test-app-config"
  1508  	componentName := "unit-test-component"
  1509  	fluentdImage := "unit-test-image:latest"
  1510  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  1511  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  1512  
  1513  	// set the Fluentd image which is obtained via env then reset at end of test
  1514  	initialDefaultFluentdImage := logging.DefaultFluentdImage
  1515  	logging.DefaultFluentdImage = fluentdImage
  1516  	defer func() { logging.DefaultFluentdImage = initialDefaultFluentdImage }()
  1517  
  1518  	// expect call to fetch existing WebLogic Domain
  1519  	cli.EXPECT().
  1520  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1521  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  1522  			// return nil error to simulate domain existing
  1523  			return nil
  1524  		})
  1525  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1526  	cli.EXPECT().
  1527  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1528  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1529  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  1530  			workload.ObjectMeta.Labels = labels
  1531  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1532  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1533  			workload.Namespace = namespace
  1534  			workload.ObjectMeta.Generation = 2
  1535  			workload.Status.LastGeneration = "1"
  1536  			return nil
  1537  		})
  1538  	// expect a call to list the FLUENTD config maps
  1539  	cli.EXPECT().
  1540  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  1541  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  1542  			// return no resources
  1543  			return nil
  1544  		})
  1545  	// no config maps found, so expect a call to create a config map with our parsing rules
  1546  	cli.EXPECT().
  1547  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1548  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1549  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  1550  			return nil
  1551  		})
  1552  	// expect call to fetch the WDT config Map
  1553  	cli.EXPECT().
  1554  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  1555  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1556  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  1557  		})
  1558  	// no WDT config maps found, so expect a call to create a WDT config map
  1559  	cli.EXPECT().
  1560  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1561  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1562  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  1563  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  1564  			return nil
  1565  		})
  1566  	// expect a call to get the namespace for the domain
  1567  	cli.EXPECT().
  1568  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  1569  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  1570  			return nil
  1571  		})
  1572  	// expect a call to attempt to get the VerrazzanoWebLogicWorkload CR
  1573  	cli.EXPECT().
  1574  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1575  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, u *unstructured.Unstructured, opts ...client.GetOption) error {
  1576  			// set the old Fluentd image on the returned obj
  1577  			containers, _, _ := unstructured.NestedSlice(u.Object, "spec", "serverPod", "containers")
  1578  			_ = unstructured.SetNestedField(containers[0].(map[string]interface{}), image, "image")
  1579  			_ = unstructured.SetNestedSlice(u.Object, containers, "spec", "serverPod", "containers")
  1580  			// return nil error because the VerrazzanoWebLogicWorkload CR exists
  1581  			return nil
  1582  		})
  1583  	// expect a call to get the application configuration for the workload
  1584  	cli.EXPECT().
  1585  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  1586  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1587  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  1588  			return nil
  1589  		}).Times(2)
  1590  	// expect a call to create the WebLogic domain CR
  1591  	cli.EXPECT().
  1592  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1593  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  1594  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  1595  			assert.Equal(DomainKind, u.GetKind())
  1596  
  1597  			// make sure the OAM component and app name labels were copied and the WebLogic type lobel applied
  1598  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
  1599  			assert.Equal(3, len(specLabels))
  1600  			assert.Equal("unit-test-component", specLabels["app.oam.dev/component"])
  1601  			assert.Equal("unit-test-app-config", specLabels["app.oam.dev/name"])
  1602  			assert.Equal(constants.WorkloadTypeWeblogic, specLabels[constants.LabelWorkloadType])
  1603  
  1604  			// make sure the FLUENTD sidecar was added
  1605  			containers, _, _ := unstructured.NestedSlice(u.Object, specServerPodContainersFields...)
  1606  			assert.Equal(1, len(containers))
  1607  			assert.Equal(fluentdImage, containers[0].(map[string]interface{})["image"])
  1608  
  1609  			// make sure the restartVersion is empty
  1610  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
  1611  			assert.Equal("", domainRestartVersion)
  1612  
  1613  			return nil
  1614  		})
  1615  
  1616  	// expect a call to status update
  1617  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1618  	// expect a call to update the status upgrade version
  1619  	mockStatus.EXPECT().
  1620  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  1621  		DoAndReturn(func(ctx context.Context, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  1622  			return nil
  1623  		})
  1624  
  1625  	// expect a call to status update
  1626  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1627  
  1628  	// create a request and reconcile it
  1629  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1630  	reconciler := newReconciler(cli)
  1631  	result, err := reconciler.Reconcile(context.TODO(), request)
  1632  
  1633  	mocker.Finish()
  1634  	assert.NoError(err)
  1635  	assert.Equal(false, result.Requeue)
  1636  }
  1637  
  1638  // TestReconcileErrorOnCreate tests reconciling a VerrazzanoWebLogicWorkload and an
  1639  // error occurs attempting to create the WebLogic domain CR.
  1640  // GIVEN a VerrazzanoWebLogicWorkload resource is created
  1641  // WHEN the controller Reconcile function is called and there is an error creating the WebLogic domain CR
  1642  // THEN expect an error to be returned
  1643  func TestReconcileErrorOnCreate(t *testing.T) {
  1644  	assert := asserts.New(t)
  1645  
  1646  	var mocker = gomock.NewController(t)
  1647  	var cli = mocks.NewMockClient(mocker)
  1648  	mockStatus := mocks.NewMockStatusWriter(mocker)
  1649  
  1650  	appConfigName := "unit-test-app-config"
  1651  	componentName := "unit-test-component"
  1652  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  1653  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  1654  
  1655  	// expect call to fetch existing WebLogic Domain
  1656  	cli.EXPECT().
  1657  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1658  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  1659  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
  1660  		})
  1661  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1662  	cli.EXPECT().
  1663  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1664  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1665  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  1666  			workload.ObjectMeta.Labels = labels
  1667  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1668  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1669  			workload.Namespace = namespace
  1670  			workload.ObjectMeta.Generation = 2
  1671  			workload.Status.LastGeneration = "1"
  1672  			return nil
  1673  		})
  1674  	// expect a call to list the FLUENTD config maps
  1675  	cli.EXPECT().
  1676  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  1677  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  1678  			// return no resources
  1679  			return nil
  1680  		})
  1681  	// no config maps found, so expect a call to create a config map with our parsing rules
  1682  	cli.EXPECT().
  1683  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1684  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1685  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  1686  			return nil
  1687  		})
  1688  	// expect call to fetch the WDT config Map
  1689  	cli.EXPECT().
  1690  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  1691  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  1692  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  1693  		})
  1694  	// no WDT config maps found, so expect a call to create a WDT config map
  1695  	cli.EXPECT().
  1696  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1697  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  1698  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  1699  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  1700  			return nil
  1701  		})
  1702  	// expect a call to get the namespace for the domain
  1703  	cli.EXPECT().
  1704  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  1705  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  1706  			return nil
  1707  		})
  1708  	// expect a call to get the application configuration for the workload
  1709  	cli.EXPECT().
  1710  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  1711  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1712  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  1713  			return nil
  1714  		}).Times(2)
  1715  	// expect a call to attempt to get the WebLogic CR - return not found
  1716  	cli.EXPECT().
  1717  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
  1718  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
  1719  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  1720  		})
  1721  	// expect a call to create the WebLogic domain CR and return a BadRequest error
  1722  	cli.EXPECT().
  1723  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1724  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  1725  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  1726  			assert.Equal(DomainKind, u.GetKind())
  1727  
  1728  			// make sure the restartVersion is empty
  1729  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
  1730  			assert.Equal("", domainRestartVersion)
  1731  
  1732  			return k8serrors.NewBadRequest("an error has occurred")
  1733  		})
  1734  
  1735  	// expect a call to status update
  1736  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  1737  
  1738  	// create a request and reconcile it
  1739  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1740  	reconciler := newReconciler(cli)
  1741  	result, err := reconciler.Reconcile(context.TODO(), request)
  1742  
  1743  	mocker.Finish()
  1744  	assert.Nil(err)
  1745  	assert.True(result.Requeue)
  1746  }
  1747  
  1748  // TestReconcileWorkloadNotFound tests reconciling a VerrazzanoWebLogicWorkload when the workload
  1749  // cannot be fetched. This happens when the workload has been deleted by the OAM runtime.
  1750  // GIVEN a VerrazzanoWebLogicWorkload resource has been deleted
  1751  // WHEN the controller Reconcile function is called and we attempt to fetch the workload
  1752  // THEN return success from the controller as there is nothing more to do
  1753  func TestReconcileWorkloadNotFound(t *testing.T) {
  1754  	assert := asserts.New(t)
  1755  
  1756  	var mocker = gomock.NewController(t)
  1757  	var cli = mocks.NewMockClient(mocker)
  1758  
  1759  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1760  	cli.EXPECT().
  1761  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1762  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1763  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  1764  		})
  1765  
  1766  	// create a request and reconcile it
  1767  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1768  	reconciler := newReconciler(cli)
  1769  	result, err := reconciler.Reconcile(context.TODO(), request)
  1770  
  1771  	mocker.Finish()
  1772  	assert.NoError(err)
  1773  	assert.Equal(false, result.Requeue)
  1774  }
  1775  
  1776  // TestReconcileFetchWorkloadError tests reconciling a VerrazzanoWebLogicWorkload when the workload
  1777  // cannot be fetched due to an unexpected error.
  1778  // GIVEN a VerrazzanoWebLogicWorkload resource has been created
  1779  // WHEN the controller Reconcile function is called and we attempt to fetch the workload and get an error
  1780  // THEN return the error
  1781  func TestReconcileFetchWorkloadError(t *testing.T) {
  1782  	assert := asserts.New(t)
  1783  
  1784  	var mocker = gomock.NewController(t)
  1785  	var cli = mocks.NewMockClient(mocker)
  1786  
  1787  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  1788  	cli.EXPECT().
  1789  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1790  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1791  			return k8serrors.NewBadRequest("an error has occurred")
  1792  		})
  1793  
  1794  	// create a request and reconcile it
  1795  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1796  	reconciler := newReconciler(cli)
  1797  	result, err := reconciler.Reconcile(context.TODO(), request)
  1798  
  1799  	mocker.Finish()
  1800  	assert.Nil(err)
  1801  	assert.Equal(true, result.Requeue)
  1802  }
  1803  
  1804  // TestCopyLabelsFailure tests reconciling a VerrazzanoWebLogicWorkload and we are
  1805  // not able to copy labels to the WebLogic domain CR.
  1806  // GIVEN a VerrazzanoWebLogicWorkload resource
  1807  // WHEN the controller Reconcile function is called and the labels cannot be copied
  1808  // THEN expect an error to be returned
  1809  func TestCopyLabelsFailure(t *testing.T) {
  1810  	assert := asserts.New(t)
  1811  
  1812  	var mocker = gomock.NewController(t)
  1813  	var cli = mocks.NewMockClient(mocker)
  1814  	//	mockStatus := mocks.NewMockStatusWriter(mocker)
  1815  
  1816  	// expect a call to fetch the VerrazzanoWebLogicWorkload - return a malformed WebLogic resource (spec should be an object
  1817  	// so when we attempt to set the labels field inside spec it will fail) - this is a contrived example, but it's the easiest
  1818  	// way to force error on copying labels
  1819  	cli.EXPECT().
  1820  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1821  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  1822  			json := `{27}`
  1823  			workload.Spec.Template = buildDomainV8Template(json)
  1824  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  1825  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  1826  			workload.ObjectMeta.Generation = 2
  1827  			workload.Status.LastGeneration = "1"
  1828  			return nil
  1829  		})
  1830  
  1831  	// create a request and reconcile it
  1832  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  1833  	reconciler := newReconciler(cli)
  1834  	result, err := reconciler.Reconcile(context.TODO(), request)
  1835  
  1836  	mocker.Finish()
  1837  	assert.Nil(err)
  1838  	assert.Equal(true, result.Requeue)
  1839  }
  1840  
  1841  // TestCreateRuntimeEncryptionSecretCreate tests creation of a runtimeEncryptionSecret
  1842  // GIVEN the runtime encryption secret does not exist
  1843  // WHEN the controller CreateRuntimeEncryptionSecret function is called
  1844  // THEN expect no error to be returned and runtime encryption secret is created
  1845  func TestCreateRuntimeEncryptionSecretCreate(t *testing.T) {
  1846  	assert := asserts.New(t)
  1847  
  1848  	var mocker = gomock.NewController(t)
  1849  	var cli = mocks.NewMockClient(mocker)
  1850  
  1851  	// Expect a call to get a secret and return that it is not found.
  1852  	cli.EXPECT().
  1853  		Get(gomock.Any(), types.NamespacedName{Namespace: "test-namespace", Name: "test-secret"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1854  		Return(k8serrors.NewNotFound(k8sschema.GroupResource{Group: "test-space", Resource: "Secret"}, "test-space-secret"))
  1855  
  1856  	// Expect a call to get the appconfig resource to set the owner reference
  1857  	cli.EXPECT().
  1858  		Get(gomock.Any(), types.NamespacedName{Namespace: "test-namespace", Name: "test-app"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1859  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, app *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  1860  			app.TypeMeta = metav1.TypeMeta{
  1861  				APIVersion: "core.oam.dev/v1alpha2",
  1862  				Kind:       "ApplicationConfiguration",
  1863  			}
  1864  			return nil
  1865  		})
  1866  
  1867  	// Expect a call to create the secret and return success
  1868  	cli.EXPECT().
  1869  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  1870  		DoAndReturn(func(ctx context.Context, secret *corev1.Secret, opts ...client.CreateOption) error {
  1871  			assert.Equal("Secret", secret.Kind)
  1872  			assert.Equal("v1", secret.APIVersion)
  1873  			assert.Len(secret.Data, 1)
  1874  			assert.Equal(1, len(secret.OwnerReferences))
  1875  			assert.Equal("ApplicationConfiguration", secret.OwnerReferences[0].Kind)
  1876  			assert.Equal("core.oam.dev/v1alpha2", secret.OwnerReferences[0].APIVersion)
  1877  			return nil
  1878  		})
  1879  
  1880  	scheme := runtime.NewScheme()
  1881  	_ = core.AddToScheme(scheme)
  1882  	_ = vzapi.AddToScheme(scheme)
  1883  	reconciler := Reconciler{Client: cli, Scheme: scheme}
  1884  
  1885  	workloadLabels := make(map[string]string)
  1886  	workloadLabels["app.oam.dev/name"] = "test-app"
  1887  	err := reconciler.createRuntimeEncryptionSecret(context.Background(), vzlog.DefaultLogger(), "test-namespace", "test-secret", workloadLabels)
  1888  	mocker.Finish()
  1889  	assert.NoError(err)
  1890  }
  1891  
  1892  // TestCreateRuntimeEncryptionSecretNoCreate tests that a runtimeEncryptionSecret already exist
  1893  // GIVEN the runtime encryption secret exist
  1894  // WHEN the controller createRuntimeEncryptionSecret function is called
  1895  // THEN expect no error to be returned and runtime encryption secret is not created
  1896  func TestCreateRuntimeEncryptionSecretNoCreate(t *testing.T) {
  1897  	assert := asserts.New(t)
  1898  
  1899  	var mocker = gomock.NewController(t)
  1900  	var cli = mocks.NewMockClient(mocker)
  1901  
  1902  	// Expect a call to get a secret and return that it was found.
  1903  	cli.EXPECT().
  1904  		Get(gomock.Any(), types.NamespacedName{Namespace: "test-namespace", Name: "test-secret"}, gomock.Not(gomock.Nil()), gomock.Any()).
  1905  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, dr *corev1.Secret, opts ...client.GetOption) error {
  1906  			dr.TypeMeta = metav1.TypeMeta{
  1907  				APIVersion: "v1",
  1908  				Kind:       "Secret"}
  1909  			return nil
  1910  		})
  1911  
  1912  	scheme := runtime.NewScheme()
  1913  	_ = core.AddToScheme(scheme)
  1914  	_ = vzapi.AddToScheme(scheme)
  1915  	reconciler := Reconciler{Client: cli, Scheme: scheme}
  1916  
  1917  	workloadLabels := make(map[string]string)
  1918  	workloadLabels["app.oam.dev/name"] = "test-app"
  1919  	err := reconciler.createRuntimeEncryptionSecret(context.Background(), vzlog.DefaultLogger(), "test-namespace", "test-secret", workloadLabels)
  1920  	mocker.Finish()
  1921  	assert.NoError(err)
  1922  }
  1923  
  1924  // TestCreateRuntimeEncryptionSecretNoOamLabel tests creation of a runtime encryption secret with no oam label found
  1925  // GIVEN no app.oam.dev/name label specified
  1926  // WHEN the controller createRuntimeEncryptionSecret function is called
  1927  // THEN expect an error to be returned
  1928  func TestCreateRuntimeEncryptionSecretNoOamLabel(t *testing.T) {
  1929  	assert := asserts.New(t)
  1930  
  1931  	reconciler := Reconciler{}
  1932  	workloadLabels := make(map[string]string)
  1933  	err := reconciler.createRuntimeEncryptionSecret(context.Background(), vzlog.DefaultLogger(), "test-namespace", "test-secret", workloadLabels)
  1934  	assert.Equal("OAM app name label missing from metadata, unable to create owner reference to appconfig", err.Error())
  1935  }
  1936  
  1937  // TestIstioEnabled tests that domain resource spec.configuration.istio.enabled is set correctly.
  1938  // GIVEN istio-injection is enabled
  1939  // THEN the domain resource to spec.configuration.istio.enabled is set to true
  1940  func TestIstioEnabled(t *testing.T) {
  1941  	assert := asserts.New(t)
  1942  
  1943  	u := &unstructured.Unstructured{
  1944  		Object: map[string]interface{}{
  1945  			"kind": "Domain",
  1946  		},
  1947  	}
  1948  	namespaceLabels := make(map[string]string)
  1949  	namespaceLabels["istio-injection"] = "enabled"
  1950  	err := updateIstioEnabled(namespaceLabels, u)
  1951  	assert.NoError(err, "Unexpected error setting istio enabled")
  1952  	specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
  1953  	assert.Equal(specIstioEnabled, true)
  1954  }
  1955  
  1956  // TestIstioDisabled tests that domain resource spec.configuration.istio.enabled is set correctly.
  1957  // GIVEN istio-injection is disabled
  1958  // THEN the domain resource to spec.configuration.istio.enabled is set to false
  1959  func TestIstioDisabled(t *testing.T) {
  1960  	assert := asserts.New(t)
  1961  
  1962  	u := &unstructured.Unstructured{
  1963  		Object: map[string]interface{}{
  1964  			"kind": "Domain",
  1965  		},
  1966  	}
  1967  	namespaceLabels := make(map[string]string)
  1968  	namespaceLabels["istio-injection"] = "disabled"
  1969  	err := updateIstioEnabled(namespaceLabels, u)
  1970  	assert.NoError(err, "Unexpected error setting istio enabled")
  1971  	specIstioEnabled, _, _ := unstructured.NestedBool(u.Object, specConfigurationIstioEnabledFields...)
  1972  	assert.Equal(specIstioEnabled, false)
  1973  }
  1974  
  1975  // newScheme creates a new scheme that includes this package's object to use for testing
  1976  func newScheme() *runtime.Scheme {
  1977  	scheme := runtime.NewScheme()
  1978  	_ = core.AddToScheme(scheme)
  1979  	_ = vzapi.AddToScheme(scheme)
  1980  	return scheme
  1981  }
  1982  
  1983  // newReconciler creates a new reconciler for testing
  1984  // c - The K8s client to inject into the reconciler
  1985  func newReconciler(c client.Client) Reconciler {
  1986  	scheme := newScheme()
  1987  	metricsReconciler := &metricstrait.Reconciler{Client: c, Scheme: scheme, Scraper: "verrazzano-system/vmi-system-prometheus-0"}
  1988  	return Reconciler{
  1989  		Client:  c,
  1990  		Log:     zap.S().With("test"),
  1991  		Scheme:  scheme,
  1992  		Metrics: metricsReconciler,
  1993  	}
  1994  }
  1995  
  1996  // newRequest creates a new reconciler request for testing
  1997  // namespace - The namespace to use in the request
  1998  // name - The name to use in the request
  1999  func newRequest(namespace string, name string) ctrl.Request {
  2000  	return ctrl.Request{
  2001  		NamespacedName: types.NamespacedName{
  2002  			Namespace: namespace,
  2003  			Name:      name,
  2004  		},
  2005  	}
  2006  }
  2007  
  2008  // validateDefaultMonitoringExporter validates the default monitoringExporter in the WebLogic domain spec
  2009  func validateDefaultMonitoringExporter(u *unstructured.Unstructured, t *testing.T) {
  2010  	_, found, err := unstructured.NestedFieldNoCopy(u.Object, specMonitoringExporterFields...)
  2011  	asserts.Nil(t, err, "Expect no error finding monitoringExporter in WebLogic domain CR")
  2012  	asserts.True(t, found, "Found monitoringExporter in WebLogic domain CR")
  2013  	imageName, _, _ := unstructured.NestedFieldNoCopy(u.Object, append(specMonitoringExporterFields, "image")...)
  2014  	if value := os.Getenv("WEBLOGIC_MONITORING_EXPORTER_IMAGE"); len(value) > 0 {
  2015  		asserts.Equal(t, value, imageName, "monitoringExporter.image should match in WebLogic domain CR")
  2016  	} else {
  2017  		asserts.Equal(t, nil, imageName, "monitoringExporter.image should match in WebLogic domain CR")
  2018  	}
  2019  	imagePullPolicy, _, _ := unstructured.NestedFieldNoCopy(u.Object, append(specMonitoringExporterFields, "imagePullPolicy")...)
  2020  	asserts.Equal(t, "IfNotPresent", imagePullPolicy, "monitoringExporter.imagePullPolicy should be IfNotPresent in WebLogic domain CR")
  2021  	domainQualifier, _, _ := unstructured.NestedBool(u.Object, append(specMonitoringExporterFields, "configuration", "domainQualifier")...)
  2022  	asserts.True(t, domainQualifier, "monitoringExporter.configuration.domainQualifier should be TRUE")
  2023  	metricsNameSnakeCase, _, _ := unstructured.NestedBool(u.Object, append(specMonitoringExporterFields, "configuration", "metricsNameSnakeCase")...)
  2024  	asserts.True(t, metricsNameSnakeCase, "monitoringExporter.configuration.metricsNameSnakeCase should be TRUE")
  2025  	queries, _, _ := unstructured.NestedSlice(u.Object, append(specMonitoringExporterFields, "configuration", "queries")...)
  2026  	asserts.Equal(t, 9, len(queries), "there should be 9 queries")
  2027  	query, _ := runtime.DefaultUnstructuredConverter.ToUnstructured(&queries[0])
  2028  	runtimeType, _, _ := unstructured.NestedString(query, "applicationRuntimes", "componentRuntimes", "type")
  2029  	asserts.Equal(t, "WebAppComponentRuntime", runtimeType, "query runtime type should be WebAppComponentRuntime")
  2030  }
  2031  
  2032  // validateTestMonitoringExporter validates the test monitoringExporter in the WebLogic domain spec
  2033  func validateTestMonitoringExporter(u *unstructured.Unstructured, t *testing.T) {
  2034  	_, found, err := unstructured.NestedFieldNoCopy(u.Object, specMonitoringExporterFields...)
  2035  	asserts.Nil(t, err, "Expect no error finding monitoringExporter in WebLogic domain CR")
  2036  	asserts.True(t, found, "Found monitoringExporter in WebLogic domain CR")
  2037  	imageName, _, _ := unstructured.NestedFieldNoCopy(u.Object, append(specMonitoringExporterFields, "image")...)
  2038  	asserts.Equal(t, "my-weblogic-monitoring-exporter:1.0.0", imageName, "monitoringExporter.image should match in WebLogic domain CR")
  2039  	imagePullPolicy, _, _ := unstructured.NestedFieldNoCopy(u.Object, append(specMonitoringExporterFields, "imagePullPolicy")...)
  2040  	asserts.Equal(t, "IfNotPresent", imagePullPolicy, "monitoringExporter.imagePullPolicy should be IfNotPresent in WebLogic domain CR")
  2041  	domainQualifier, _, _ := unstructured.NestedBool(u.Object, append(specMonitoringExporterFields, "configuration", "domainQualifier")...)
  2042  	asserts.True(t, domainQualifier, "monitoringExporter.configuration.domainQualifier should be TRUE")
  2043  	metricsNameSnakeCase, _, _ := unstructured.NestedBool(u.Object, append(specMonitoringExporterFields, "configuration", "metricsNameSnakeCase")...)
  2044  	asserts.True(t, metricsNameSnakeCase, "monitoringExporter.configuration.metricsNameSnakeCase should be TRUE")
  2045  	queries, _, _ := unstructured.NestedSlice(u.Object, append(specMonitoringExporterFields, "configuration", "queries")...)
  2046  	asserts.Equal(t, 1, len(queries), "there should be 1 query")
  2047  	query, _ := runtime.DefaultUnstructuredConverter.ToUnstructured(&queries[0])
  2048  	jvmRuntimePrefix, _, _ := unstructured.NestedString(query, "JVMRuntime", "prefix")
  2049  	asserts.Equal(t, "wls_jvm_", jvmRuntimePrefix, "query JVMRuntime prefix should be wls_jvm_")
  2050  }
  2051  
  2052  // validateDefaultWDTConfigMap validates the default WDT config map in the WebLogic domain spec
  2053  func validateDefaultWDTConfigMap(u *unstructured.Unstructured, t *testing.T) {
  2054  	mapName, found, err := unstructured.NestedString(u.Object, specConfigurationWDTConfigMap...)
  2055  	asserts.Nil(t, err, "Expect no error finding WDTConfigMap in WebLogic domain CR")
  2056  	asserts.True(t, found, "Found WDTConfigMap in WebLogic domain CR")
  2057  	asserts.Equal(t, mapName, getWDTConfigMapName(weblogicDomainName), "mapName should be ")
  2058  }
  2059  
  2060  // validatePVWDTConfigMap validates the default WDT config map in the WebLogic domain spec
  2061  func validatePVWDTConfigMap(u *unstructured.Unstructured, t *testing.T) {
  2062  	mapName, found, err := unstructured.NestedString(u.Object, specConfigurationDomainOnPVConfigMap...)
  2063  	asserts.Nil(t, err, "Expect no error finding WDTConfigMap in WebLogic domain CR")
  2064  	asserts.True(t, found, "Found WDTConfigMap in WebLogic domain CR")
  2065  	asserts.Equal(t, mapName, getWDTConfigMapName(weblogicDomainName), "mapName should be ")
  2066  }
  2067  
  2068  // validateWDTConfigMap validates the WDT config name in the WebLogic domain spec
  2069  func validateWDTConfigMap(u *unstructured.Unstructured, t *testing.T) {
  2070  	mapName, found, err := unstructured.NestedString(u.Object, specConfigurationWDTConfigMap...)
  2071  	asserts.Nil(t, err, "Expect no error finding WDTConfigMap in WebLogic domain CR")
  2072  	asserts.True(t, found, "Found WDTConfigMap in WebLogic domain CR")
  2073  	asserts.Equal(t, mapName, "wdt-config-map", "mapName should be ")
  2074  }
  2075  
  2076  // Used for bool in struct literal
  2077  func newTrue() *bool {
  2078  	b := true
  2079  	return &b
  2080  }
  2081  
  2082  // TestGetWLSLogPath tests building the WebLogic log path
  2083  func TestGetWLSLogPath(t *testing.T) {
  2084  	assert := asserts.New(t)
  2085  
  2086  	// GIVEN a call to getWLSLogPath
  2087  	// WHEN the logHome is not set
  2088  	// THEN the returned log path uses a generated base log path
  2089  	logPath := getWLSLogPath("", "test-domain")
  2090  	assert.Equal("/scratch/logs/test-domain/$(SERVER_NAME).log,/scratch/logs/test-domain/$(SERVER_NAME)_access.log,/scratch/logs/test-domain/$(SERVER_NAME)_nodemanager.log,/scratch/logs/test-domain/$(DOMAIN_UID).log", logPath)
  2091  
  2092  	// GIVEN a call to getWLSLogPath
  2093  	// WHEN the logHome is set
  2094  	// THEN the returned log path uses the provided logHome as the base path
  2095  	logPath = getWLSLogPath("/unit_test/log_home", "test-domain")
  2096  	assert.Equal("/unit_test/log_home/$(SERVER_NAME).log,/unit_test/log_home/$(SERVER_NAME)_access.log,/unit_test/log_home/$(SERVER_NAME)_nodemanager.log,/unit_test/log_home/$(DOMAIN_UID).log", logPath)
  2097  }
  2098  
  2099  // TestReconcileRestart tests reconciling a VerrazzanoWebLogicWorkload when the WebLogic
  2100  // domain CR already exists and the restart-version specified in the annotations.
  2101  // This should result in restartVersion written to the WLS domain .
  2102  // GIVEN a VerrazzanoWebLogicWorkload resource
  2103  // WHEN the controller Reconcile function is called and the WebLogic domain CR already exists and the restart-version is specified
  2104  // THEN the WLS domain has restartVersion
  2105  func TestReconcileRestart(t *testing.T) {
  2106  	assert := asserts.New(t)
  2107  
  2108  	var mocker = gomock.NewController(t)
  2109  	var cli = mocks.NewMockClient(mocker)
  2110  
  2111  	appConfigName := "unit-test-app-config"
  2112  	componentName := "unit-test-component"
  2113  	fluentdImage := "unit-test-image:latest"
  2114  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  2115  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  2116  	annotations := map[string]string{vzconst.RestartVersionAnnotation: restartVersion}
  2117  	mockStatus := mocks.NewMockStatusWriter(mocker)
  2118  
  2119  	// set the Fluentd image which is obtained via env then reset at end of test
  2120  	initialDefaultFluentdImage := logging.DefaultFluentdImage
  2121  	logging.DefaultFluentdImage = fluentdImage
  2122  	defer func() { logging.DefaultFluentdImage = initialDefaultFluentdImage }()
  2123  
  2124  	// expect call to fetch existing WebLogic Domain
  2125  	cli.EXPECT().
  2126  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2127  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  2128  			// return nil error to simulate domain existing
  2129  			return nil
  2130  		})
  2131  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  2132  	cli.EXPECT().
  2133  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2134  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  2135  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  2136  			workload.ObjectMeta.Labels = labels
  2137  			workload.ObjectMeta.Annotations = annotations
  2138  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  2139  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  2140  			workload.Namespace = namespace
  2141  			workload.ObjectMeta.Generation = 2
  2142  			workload.Status.LastGeneration = "1"
  2143  			return nil
  2144  		})
  2145  	// expect a call to list the FLUENTD config maps
  2146  	cli.EXPECT().
  2147  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  2148  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  2149  			// return no resources
  2150  			return nil
  2151  		})
  2152  	// no config maps found, so expect a call to create a config map with our parsing rules
  2153  	cli.EXPECT().
  2154  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2155  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2156  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  2157  			return nil
  2158  		})
  2159  	// expect call to fetch the WDT config Map
  2160  	cli.EXPECT().
  2161  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  2162  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  2163  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  2164  		})
  2165  	// no WDT config maps found, so expect a call to create a WDT config map
  2166  	cli.EXPECT().
  2167  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2168  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2169  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  2170  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  2171  			return nil
  2172  		})
  2173  	// expect a call to get the namespace for the domain
  2174  	cli.EXPECT().
  2175  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  2176  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  2177  			return nil
  2178  		})
  2179  	// expect a call to attempt to get the domain CR
  2180  	cli.EXPECT().
  2181  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2182  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, u *unstructured.Unstructured, opts ...client.GetOption) error {
  2183  			// set the old Fluentd image on the returned obj
  2184  			containers, _, _ := unstructured.NestedSlice(u.Object, "spec", "serverPod", "containers")
  2185  			_ = unstructured.SetNestedField(containers[0].(map[string]interface{}), image, "image")
  2186  			_ = unstructured.SetNestedSlice(u.Object, containers, "spec", "serverPod", "containers")
  2187  			// return nil error because the VerrazzanoWebLogicWorkload CR StatefulSet exists
  2188  			return nil
  2189  		})
  2190  	// expect a call to get the application configuration for the workload
  2191  	cli.EXPECT().
  2192  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  2193  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  2194  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  2195  			return nil
  2196  		}).Times(2)
  2197  	// expect a call to create the WebLogic domain CR
  2198  	cli.EXPECT().
  2199  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2200  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.UpdateOption) error {
  2201  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  2202  			assert.Equal(DomainKind, u.GetKind())
  2203  
  2204  			// make sure the OAM component and app name labels were copied and the WebLogic type lobel applied
  2205  			specLabels, _, _ := unstructured.NestedStringMap(u.Object, specServerPodLabelsFields...)
  2206  			assert.Equal(3, len(specLabels))
  2207  			assert.Equal("unit-test-component", specLabels["app.oam.dev/component"])
  2208  			assert.Equal("unit-test-app-config", specLabels["app.oam.dev/name"])
  2209  			assert.Equal(constants.WorkloadTypeWeblogic, specLabels[constants.LabelWorkloadType])
  2210  
  2211  			// make sure the FLUENTD sidecar was added
  2212  			containers, _, _ := unstructured.NestedSlice(u.Object, specServerPodContainersFields...)
  2213  			assert.Equal(1, len(containers))
  2214  			assert.Equal(fluentdImage, containers[0].(map[string]interface{})["image"])
  2215  
  2216  			// make sure the restartVersion was added to the domain
  2217  			domainRestartVersion, _, _ := unstructured.NestedString(u.Object, specRestartVersionFields...)
  2218  			assert.Equal(restartVersion, domainRestartVersion)
  2219  
  2220  			return nil
  2221  		})
  2222  
  2223  	// expect a call to status update
  2224  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  2225  
  2226  	// Expect a call to update the status of the Verrazzano resource to update components
  2227  	mockStatus.EXPECT().
  2228  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2229  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  2230  			//		asserts.NotZero(len(verrazzano.Status.Components), "Status.Components len should not be zero")
  2231  			return nil
  2232  		})
  2233  
  2234  	// create a request and reconcile it
  2235  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  2236  	reconciler := newReconciler(cli)
  2237  	result, err := reconciler.Reconcile(context.TODO(), request)
  2238  
  2239  	mocker.Finish()
  2240  	assert.NoError(err)
  2241  	assert.Equal(false, result.Requeue)
  2242  }
  2243  
  2244  // TestReconcileStopDomain tests reconciling a VerrazzanoWebLogicWorkload when the WebLogic
  2245  // domain CR already exists and the lifecycle-action==stop is specified in the annotations.
  2246  // GIVEN a VerrazzanoWebLogicWorkload resource
  2247  // WHEN the controller Reconcile function is called and the WebLogic domain CR already exists and the restart-version is specified
  2248  // THEN the WLS domain has restartVersion
  2249  //
  2250  //	This should result in:
  2251  //	  1. NEVER written to the WLS domain serverStartPolicy
  2252  //	  2. The old serverStartPolicy saved in the domain annotation
  2253  //	  3. The WebLogic workload.Status.LastLifeCycleAction should have stop
  2254  func TestReconcileStopDomain(t *testing.T) {
  2255  	assert := asserts.New(t)
  2256  
  2257  	var mocker = gomock.NewController(t)
  2258  	var cli = mocks.NewMockClient(mocker)
  2259  
  2260  	appConfigName := "unit-test-app-config"
  2261  	componentName := "unit-test-component"
  2262  
  2263  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  2264  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  2265  	annotations := map[string]string{vzconst.LifecycleActionAnnotation: vzconst.LifecycleActionStop}
  2266  	mockStatus := mocks.NewMockStatusWriter(mocker)
  2267  
  2268  	// expect call to fetch existing WebLogic Domain
  2269  	cli.EXPECT().
  2270  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2271  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  2272  			// return nil error to simulate domain existing
  2273  			return nil
  2274  		})
  2275  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  2276  	cli.EXPECT().
  2277  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2278  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  2279  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  2280  			workload.ObjectMeta.Labels = labels
  2281  			workload.ObjectMeta.Annotations = annotations
  2282  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  2283  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  2284  			workload.Namespace = namespace
  2285  			workload.ObjectMeta.Generation = 2
  2286  			workload.Status.LastGeneration = "1"
  2287  			return nil
  2288  		})
  2289  	// expect a call to list the FLUENTD config maps
  2290  	cli.EXPECT().
  2291  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  2292  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  2293  			// return no resources
  2294  			return nil
  2295  		})
  2296  	// no config maps found, so expect a call to create a config map with our parsing rules
  2297  	cli.EXPECT().
  2298  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2299  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2300  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  2301  			return nil
  2302  		})
  2303  	// expect call to fetch the WDT config Map
  2304  	cli.EXPECT().
  2305  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  2306  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  2307  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  2308  		})
  2309  	// no WDT config maps found, so expect a call to create a WDT config map
  2310  	cli.EXPECT().
  2311  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2312  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2313  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  2314  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  2315  			return nil
  2316  		})
  2317  	// expect a call to get the namespace for the domain
  2318  	cli.EXPECT().
  2319  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  2320  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  2321  			return nil
  2322  		})
  2323  	// expect a call to attempt to get the WebLogic CR
  2324  	cli.EXPECT().
  2325  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2326  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, u *unstructured.Unstructured, opts ...client.GetOption) error {
  2327  			// set the old Fluentd image on the returned obj
  2328  			containers, _, _ := unstructured.NestedSlice(u.Object, "spec", "serverPod", "containers")
  2329  			_ = unstructured.SetNestedField(containers[0].(map[string]interface{}), image, "image")
  2330  			_ = unstructured.SetNestedSlice(u.Object, containers, "spec", "serverPod", "containers")
  2331  			// return nil error because the VerrazzanoWebLogicWorkload CR StatefulSet exists
  2332  			return nil
  2333  		})
  2334  	// expect a call to get the application configuration for the workload
  2335  	cli.EXPECT().
  2336  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  2337  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  2338  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  2339  			return nil
  2340  		}).Times(2)
  2341  	// expect a call to update the WebLogic domain CR
  2342  	cli.EXPECT().
  2343  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2344  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  2345  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  2346  			assert.Equal(DomainKind, u.GetKind())
  2347  
  2348  			// make sure the restartVersion was added to the domain
  2349  			policy, _, _ := unstructured.NestedString(u.Object, specServerStartPolicyFields...)
  2350  			assert.Equal(NeverV8, policy)
  2351  
  2352  			annos, _, _ := unstructured.NestedStringMap(u.Object, metaAnnotationFields...)
  2353  			assert.Equal(annos[lastServerStartPolicyAnnotation], IfNeededV8)
  2354  			return nil
  2355  		})
  2356  
  2357  	// expect a call to status update
  2358  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  2359  
  2360  	// Expect a call to update the status of the Verrazzano resource to update components
  2361  	mockStatus.EXPECT().
  2362  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2363  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  2364  			assert.Equal(vzconst.LifecycleActionStop, wl.Status.LastLifecycleAction)
  2365  			return nil
  2366  		})
  2367  
  2368  	// create a request and reconcile it
  2369  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  2370  	reconciler := newReconciler(cli)
  2371  	result, err := reconciler.Reconcile(context.TODO(), request)
  2372  
  2373  	mocker.Finish()
  2374  	assert.NoError(err)
  2375  	assert.Equal(false, result.Requeue)
  2376  }
  2377  
  2378  // TestReconcileStartDomain tests reconciling a VerrazzanoWebLogicWorkload when the WebLogic
  2379  // domain CR already exists and the lifecycle-action==start is specified in the annotations.
  2380  // GIVEN a VerrazzanoWebLogicWorkload resource
  2381  // WHEN the controller Reconcile function is called and the WebLogic domain CR already exists and the restart-version is specified
  2382  // THEN the WLS domain has restartVersion
  2383  //
  2384  //	This should result in:
  2385  //	  1. IF_NEEDED written to the WLS domain serverStartPolicy
  2386  //	  2. The WebLogic workload.Status.LastLifeCycleAction should have start
  2387  func TestReconcileStartDomain(t *testing.T) {
  2388  	assert := asserts.New(t)
  2389  
  2390  	var mocker = gomock.NewController(t)
  2391  	var cli = mocks.NewMockClient(mocker)
  2392  
  2393  	appConfigName := "unit-test-app-config"
  2394  	componentName := "unit-test-component"
  2395  
  2396  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  2397  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  2398  	annotations := map[string]string{vzconst.LifecycleActionAnnotation: vzconst.LifecycleActionStart}
  2399  	mockStatus := mocks.NewMockStatusWriter(mocker)
  2400  
  2401  	// expect call to fetch existing WebLogic Domain
  2402  	cli.EXPECT().
  2403  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2404  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  2405  			// return nil error to simulate domain existing
  2406  			return nil
  2407  		})
  2408  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  2409  	cli.EXPECT().
  2410  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2411  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  2412  			workload.Spec.Template = buildDomainV8Template(weblogicDomain)
  2413  			workload.ObjectMeta.Labels = labels
  2414  			workload.ObjectMeta.Annotations = annotations
  2415  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  2416  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  2417  			workload.Namespace = namespace
  2418  			workload.ObjectMeta.Generation = 2
  2419  			workload.Status.LastGeneration = "1"
  2420  			return nil
  2421  		})
  2422  	// expect a call to list the FLUENTD config maps
  2423  	cli.EXPECT().
  2424  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  2425  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  2426  			// return no resources
  2427  			return nil
  2428  		})
  2429  	// no config maps found, so expect a call to create a config map with our parsing rules
  2430  	cli.EXPECT().
  2431  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2432  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2433  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  2434  			return nil
  2435  		})
  2436  	// expect call to fetch the WDT config Map
  2437  	cli.EXPECT().
  2438  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  2439  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  2440  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  2441  		})
  2442  	// no WDT config maps found, so expect a call to create a WDT config map
  2443  	cli.EXPECT().
  2444  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2445  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2446  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  2447  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  2448  			return nil
  2449  		})
  2450  	// expect a call to get the namespace for the domain
  2451  	cli.EXPECT().
  2452  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  2453  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  2454  			return nil
  2455  		})
  2456  	// expect a call to attempt to get the WebLogic CR
  2457  	cli.EXPECT().
  2458  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2459  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, u *unstructured.Unstructured, opts ...client.GetOption) error {
  2460  			// set the old Fluentd image on the returned obj
  2461  			containers, _, _ := unstructured.NestedSlice(u.Object, "spec", "serverPod", "containers")
  2462  			_ = unstructured.SetNestedField(containers[0].(map[string]interface{}), image, "image")
  2463  			_ = unstructured.SetNestedSlice(u.Object, containers, "spec", "serverPod", "containers")
  2464  			// return nil error because the VerrazzanoWebLogicWorkload CR StatefulSet exists
  2465  			return nil
  2466  		})
  2467  	// expect a call to get the application configuration for the workload
  2468  	cli.EXPECT().
  2469  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  2470  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  2471  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  2472  			return nil
  2473  		}).Times(2)
  2474  	// expect a call to update the WebLogic domain CR
  2475  	cli.EXPECT().
  2476  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2477  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  2478  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  2479  			assert.Equal(DomainKind, u.GetKind())
  2480  
  2481  			// make sure the restartVersion was added to the domain
  2482  			policy, _, _ := unstructured.NestedString(u.Object, specServerStartPolicyFields...)
  2483  			assert.Equal(IfNeededV8, policy)
  2484  
  2485  			return nil
  2486  		})
  2487  
  2488  	// expect a call to status update
  2489  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  2490  
  2491  	// Expect a call to update the status of the Verrazzano resource to update components
  2492  	mockStatus.EXPECT().
  2493  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2494  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  2495  			assert.Equal(vzconst.LifecycleActionStart, wl.Status.LastLifecycleAction)
  2496  			return nil
  2497  		})
  2498  
  2499  	// create a request and reconcile it
  2500  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  2501  	reconciler := newReconciler(cli)
  2502  	result, err := reconciler.Reconcile(context.TODO(), request)
  2503  
  2504  	mocker.Finish()
  2505  	assert.NoError(err)
  2506  	assert.Equal(false, result.Requeue)
  2507  }
  2508  
  2509  // TestReconcileKubeSystem tests to make sure we do not reconcile
  2510  // Any resource that belong to the kube-system namespace
  2511  func TestReconcileKubeSystem(t *testing.T) {
  2512  	assert := asserts.New(t)
  2513  
  2514  	var mocker = gomock.NewController(t)
  2515  	var cli = mocks.NewMockClient(mocker)
  2516  
  2517  	// create a request and reconcile it
  2518  	request := newRequest(vzconst.KubeSystem, "unit-test-verrazzano-helidon-workload")
  2519  	reconciler := newReconciler(cli)
  2520  	result, err := reconciler.Reconcile(context.TODO(), request)
  2521  
  2522  	// Validate the results
  2523  	mocker.Finish()
  2524  	assert.Nil(err)
  2525  	assert.True(result.IsZero())
  2526  }
  2527  
  2528  // GIVEN a VerrazzanoWebLogicWorkload with a domain spec that has a logHome set
  2529  // WHEN we reconcile the workload
  2530  // THEN the Fluentd sidecar has the correct log paths, environment variable settings, volume, and volume mount
  2531  // AND we do not overwrite the logHome setting
  2532  func TestReconcileUserProvidedLogHome(t *testing.T) {
  2533  	assert := asserts.New(t)
  2534  
  2535  	var mocker = gomock.NewController(t)
  2536  	var cli = mocks.NewMockClient(mocker)
  2537  	mockStatus := mocks.NewMockStatusWriter(mocker)
  2538  
  2539  	appConfigName := "unit-test-app-config"
  2540  	componentName := "unit-test-component"
  2541  	labels := map[string]string{oam.LabelAppComponent: componentName, oam.LabelAppName: appConfigName,
  2542  		constants.LabelWorkloadType: constants.WorkloadTypeWeblogic}
  2543  
  2544  	// expect call to fetch existing WebLogic Domain
  2545  	cli.EXPECT().
  2546  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-cluster"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2547  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, domain *unstructured.Unstructured, opts ...client.GetOption) error {
  2548  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "test")
  2549  		})
  2550  	// expect a call to fetch the VerrazzanoWebLogicWorkload
  2551  	cli.EXPECT().
  2552  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: "unit-test-verrazzano-weblogic-workload"}, gomock.Not(gomock.Nil()), gomock.Any()).
  2553  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, workload *vzapi.VerrazzanoWebLogicWorkload, opts ...client.GetOption) error {
  2554  			workload.Spec.Template = buildDomainV8Template(weblogicDomainWithLogHome)
  2555  			workload.ObjectMeta.Labels = labels
  2556  			workload.APIVersion = vzapi.SchemeGroupVersion.String()
  2557  			workload.Kind = vzconst.VerrazzanoWebLogicWorkloadKind
  2558  			workload.Namespace = namespace
  2559  			workload.ObjectMeta.Generation = 2
  2560  			workload.Status.LastGeneration = "1"
  2561  			return nil
  2562  		})
  2563  	// expect a call to list the FLUENTD config maps
  2564  	cli.EXPECT().
  2565  		List(gomock.Any(), gomock.Any(), gomock.Any()).
  2566  		DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
  2567  			// return no resources
  2568  			return nil
  2569  		})
  2570  	// no config maps found, so expect a call to create a config map with our parsing rules
  2571  	cli.EXPECT().
  2572  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2573  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2574  			assert.Equal(strings.Join(strings.Split(WlsFluentdParsingRules, "{{ .CAFile}}"), ""), configMap.Data["fluentd.conf"])
  2575  			return nil
  2576  		})
  2577  	// expect call to fetch the WDT config Map
  2578  	cli.EXPECT().
  2579  		Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: getWDTConfigMapName(weblogicDomainName)}, gomock.Any(), gomock.Any()).
  2580  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, configMap *corev1.ConfigMap, opts ...client.GetOption) error {
  2581  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, getWDTConfigMapName(weblogicDomainName))
  2582  		})
  2583  	// no WDT config maps found, so expect a call to create a WDT config map
  2584  	cli.EXPECT().
  2585  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2586  		DoAndReturn(func(ctx context.Context, configMap *corev1.ConfigMap, opts ...client.CreateOption) error {
  2587  			bytes, _ := yaml.JSONToYAML([]byte(defaultWDTConfigMapData))
  2588  			assert.Equal(string(bytes), configMap.Data[webLogicPluginConfigYamlKey])
  2589  			return nil
  2590  		})
  2591  	// expect a call to get the namespace for the domain
  2592  	cli.EXPECT().
  2593  		Get(gomock.Any(), gomock.Eq(client.ObjectKey{Namespace: "", Name: namespace}), gomock.Not(gomock.Nil()), gomock.Any()).
  2594  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, namespace *corev1.Namespace, opts ...client.GetOption) error {
  2595  			return nil
  2596  		})
  2597  	// expect a call to get the application configuration for the workload
  2598  	cli.EXPECT().
  2599  		Get(gomock.Any(), gomock.Eq(types.NamespacedName{Namespace: namespace, Name: appConfigName}), gomock.Not(gomock.Nil()), gomock.Any()).
  2600  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, appConfig *oamcore.ApplicationConfiguration, opts ...client.GetOption) error {
  2601  			appConfig.Spec.Components = []oamcore.ApplicationConfigurationComponent{{ComponentName: componentName}}
  2602  			return nil
  2603  		}).Times(2)
  2604  	// expect a call to attempt to get the WebLogic CR - return not found
  2605  	cli.EXPECT().
  2606  		Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).
  2607  		DoAndReturn(func(ctx context.Context, key client.ObjectKey, u *unstructured.Unstructured, opts ...client.GetOption) error {
  2608  			return k8serrors.NewNotFound(k8sschema.GroupResource{}, "")
  2609  		})
  2610  	// expect a call to create the WebLogic domain CR
  2611  	cli.EXPECT().
  2612  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
  2613  		DoAndReturn(func(ctx context.Context, u *unstructured.Unstructured, opts ...client.CreateOption) error {
  2614  			assert.Equal(APIVersionV8, u.GetAPIVersion())
  2615  			assert.Equal(DomainKind, u.GetKind())
  2616  
  2617  			const (
  2618  				expectedLogHome         = "/unit_test/log_home"
  2619  				expectedVolumeName      = "unit-test-logging-volume"
  2620  				expectedVolumeMountPath = "/unit_test"
  2621  			)
  2622  
  2623  			// make sure the user-specified logHome is set correctly
  2624  			logHome, _, _ := unstructured.NestedString(u.Object, specLogHomeFields...)
  2625  			assert.Equal(expectedLogHome, logHome)
  2626  
  2627  			// find the Fluentd container
  2628  			foundFluentdContainer := false
  2629  			containers, _, _ := unstructured.NestedSlice(u.Object, specServerPodContainersFields...)
  2630  			for _, container := range containers {
  2631  				c := container.(map[string]interface{})
  2632  				if c["name"] == logging.FluentdStdoutSidecarName {
  2633  					foundFluentdContainer = true
  2634  
  2635  					// make sure the Fluentd container environment variables reference the correct logHome
  2636  					envs := c["env"].([]interface{})
  2637  					assertEnvValueStartsWith(t, envs, "SERVER_LOG_PATH", expectedLogHome)
  2638  					assertEnvValueStartsWith(t, envs, "ACCESS_LOG_PATH", expectedLogHome)
  2639  					assertEnvValueStartsWith(t, envs, "NODEMANAGER_LOG_PATH", expectedLogHome)
  2640  					assertEnvValueStartsWith(t, envs, "DOMAIN_LOG_PATH", expectedLogHome)
  2641  					assertPathsStartWith(t, envs, "LOG_PATH", expectedLogHome)
  2642  
  2643  					// make sure the Fluentd container has the correct volume mount
  2644  					mounts := c["volumeMounts"].([]interface{})
  2645  					assertVolumeMount(t, "Fluentd container", mounts, expectedVolumeName, expectedVolumeMountPath, expectedLogHome)
  2646  				}
  2647  			}
  2648  			assert.True(foundFluentdContainer, "Expected to find container with name %s", logging.FluentdStdoutSidecarName)
  2649  
  2650  			// make sure the serverPod volume mount is correct
  2651  			serverPod, _, _ := unstructured.NestedMap(u.Object, specServerPodFields...)
  2652  			assertVolumeMount(t, "serverPod", serverPod["volumeMounts"].([]interface{}), expectedVolumeName, expectedVolumeMountPath, expectedLogHome)
  2653  
  2654  			// make sure the serverPod volume has not been overwritten
  2655  			assertVolume(t, serverPod["volumes"].([]interface{}), expectedVolumeName, "unit-test-pvc")
  2656  
  2657  			return nil
  2658  		})
  2659  
  2660  	// expect a call to status update
  2661  	cli.EXPECT().Status().Return(mockStatus).AnyTimes()
  2662  
  2663  	// expect a call to update the status of the Verrazzano resource to update components
  2664  	mockStatus.EXPECT().
  2665  		Update(gomock.Any(), gomock.Any(), gomock.Any()).
  2666  		DoAndReturn(func(ctx context.Context, wl *vzapi.VerrazzanoWebLogicWorkload, opts ...client.UpdateOption) error {
  2667  			return nil
  2668  		})
  2669  
  2670  	// create a request and reconcile it
  2671  	request := newRequest(namespace, "unit-test-verrazzano-weblogic-workload")
  2672  	reconciler := newReconciler(cli)
  2673  	result, err := reconciler.Reconcile(context.TODO(), request)
  2674  
  2675  	mocker.Finish()
  2676  	assert.NoError(err)
  2677  	assert.Equal(false, result.Requeue)
  2678  }
  2679  
  2680  // assertEnvValueStartsWith asserts that the named environment variable value starts with the specified string
  2681  func assertEnvValueStartsWith(t *testing.T, envs []interface{}, name string, startsWith string) {
  2682  	assert := asserts.New(t)
  2683  
  2684  	for _, env := range envs {
  2685  		e := env.(map[string]interface{})
  2686  		if e["name"] == name {
  2687  			v := e["value"].(string)
  2688  			assert.True(strings.HasPrefix(v, startsWith), "Expected %s value %s to start with %s", name, v, startsWith)
  2689  			return
  2690  		}
  2691  	}
  2692  	assert.Fail("Failed", "Unable to find env var named %s", name)
  2693  }
  2694  
  2695  // assertPathsStartWith asserts that each path in the comma-delimited string value (identified by the env var name) starts
  2696  // with the specified string
  2697  func assertPathsStartWith(t *testing.T, envs []interface{}, name string, startsWith string) {
  2698  	assert := asserts.New(t)
  2699  
  2700  	for _, env := range envs {
  2701  		e := env.(map[string]interface{})
  2702  		if e["name"] == name {
  2703  			for _, path := range strings.Split(e["value"].(string), ",") {
  2704  				assert.True(strings.HasPrefix(path, startsWith), "Expected %s path %s to start with %s", name, path, startsWith)
  2705  				return
  2706  			}
  2707  		}
  2708  	}
  2709  	assert.Fail("Failed", "Unable to find env var named %s", name)
  2710  }
  2711  
  2712  // assertVolumeMount asserts that the volume mount's mount path is correct and is a prefix of the log path
  2713  func assertVolumeMount(t *testing.T, context string, mounts []interface{}, volumeName string, mountPath string, logPath string) {
  2714  	assert := asserts.New(t)
  2715  
  2716  	for _, mount := range mounts {
  2717  		m := mount.(map[string]interface{})
  2718  		if m["name"] == volumeName {
  2719  			mp := m["mountPath"].(string)
  2720  			assert.Equal(mountPath, mp)
  2721  			assert.True(strings.HasPrefix(logPath, mp), "Expected %s volume mount %s mount path %s to be a prefix of %s", context, volumeName, mp, logPath)
  2722  			return
  2723  		}
  2724  	}
  2725  	assert.Fail("Failed", "Unable to find volume mount named %s in %s", volumeName, context)
  2726  }
  2727  
  2728  // assertVolume asserts that the specified volume has the specified persistent volume claim name
  2729  func assertVolume(t *testing.T, volumes []interface{}, volumeName string, claimName string) {
  2730  	assert := asserts.New(t)
  2731  
  2732  	for _, volume := range volumes {
  2733  		v := volume.(map[string]interface{})
  2734  		if v["name"] == volumeName {
  2735  			if pvc, ok := v["persistentVolumeClaim"]; ok {
  2736  				pvcName := pvc.(map[string]interface{})["claimName"]
  2737  				assert.Equal(claimName, pvcName)
  2738  				return
  2739  			}
  2740  			assert.Fail("Failed", "Unable to find persistentVolumeClaim in volume named %s", volumeName)
  2741  			return
  2742  		}
  2743  	}
  2744  	assert.Fail("Failed", "Unable to find volume named %s", volumeName)
  2745  }