github.com/verrazzano/verrazzano@v1.7.1/application-operator/controllers/metricsbinding/metricsbinding_controller_test.go (about)

     1  // Copyright (c) 2021, 2022, 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 metricsbinding
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"testing"
    10  	"time"
    11  
    12  	promoperapi "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
    13  	asserts "github.com/stretchr/testify/assert"
    14  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/app/v1alpha1"
    15  	"github.com/verrazzano/verrazzano/application-operator/constants"
    16  	vzconst "github.com/verrazzano/verrazzano/pkg/constants"
    17  	k8sapps "k8s.io/api/apps/v1"
    18  	k8score "k8s.io/api/core/v1"
    19  	k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1"
    20  	"k8s.io/apimachinery/pkg/runtime"
    21  	"k8s.io/apimachinery/pkg/types"
    22  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    23  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    24  )
    25  
    26  var metricsTemplate = &vzapi.MetricsTemplate{
    27  	TypeMeta: k8smeta.TypeMeta{
    28  		Kind:       vzconst.MetricsTemplateKind,
    29  		APIVersion: vzconst.MetricsTemplateAPIVersion,
    30  	},
    31  	ObjectMeta: k8smeta.ObjectMeta{
    32  		Namespace: testMetricsTemplateNamespace,
    33  		Name:      testMetricsTemplateName,
    34  	},
    35  }
    36  
    37  var trueValue = true
    38  var metricsBinding = &vzapi.MetricsBinding{
    39  	ObjectMeta: k8smeta.ObjectMeta{
    40  		Namespace: testMetricsBindingNamespace,
    41  		Name:      testMetricsBindingName,
    42  		OwnerReferences: []k8smeta.OwnerReference{
    43  			{
    44  				APIVersion:         fmt.Sprintf("%s/%s", deploymentGroup, deploymentVersion),
    45  				BlockOwnerDeletion: &trueValue,
    46  				Controller:         &trueValue,
    47  				Kind:               deploymentKind,
    48  				Name:               testDeploymentName,
    49  			},
    50  		},
    51  	},
    52  	Spec: vzapi.MetricsBindingSpec{
    53  		MetricsTemplate: vzapi.NamespaceName{
    54  			Namespace: testMetricsTemplateNamespace,
    55  			Name:      testMetricsTemplateName,
    56  		},
    57  		PrometheusConfigMap: vzapi.NamespaceName{
    58  			Namespace: constants.VerrazzanoSystemNamespace,
    59  			Name:      testConfigMapName,
    60  		},
    61  		Workload: vzapi.Workload{
    62  			Name: testDeploymentName,
    63  			TypeMeta: k8smeta.TypeMeta{
    64  				Kind:       vzconst.DeploymentWorkloadKind,
    65  				APIVersion: deploymentGroup + "/" + deploymentVersion,
    66  			},
    67  		},
    68  	},
    69  }
    70  
    71  var plainWorkload = &k8sapps.Deployment{
    72  	ObjectMeta: k8smeta.ObjectMeta{
    73  		Namespace: testMetricsBindingNamespace,
    74  		Name:      testDeploymentName,
    75  		UID:       types.UID(testDeploymentUID),
    76  	},
    77  }
    78  
    79  // The namespace has to contain labels for the template
    80  var plainNs = &k8score.Namespace{
    81  	ObjectMeta: k8smeta.ObjectMeta{
    82  		Name: testMetricsBindingNamespace,
    83  		Labels: map[string]string{
    84  			"test": "test",
    85  		},
    86  	},
    87  }
    88  
    89  // TestReconcile tests the reconcile process of the Metrics Binding
    90  // GIVEN a metrics binding
    91  // WHEN the function receives the binding
    92  // THEN the reconcile process occurs for updating or deleting the Metrics Binding
    93  func TestReconcile(t *testing.T) {
    94  	assert := asserts.New(t)
    95  
    96  	scheme := runtime.NewScheme()
    97  	_ = vzapi.AddToScheme(scheme)
    98  	_ = k8score.AddToScheme(scheme)
    99  	_ = k8sapps.AddToScheme(scheme)
   100  	_ = promoperapi.AddToScheme(scheme)
   101  
   102  	labeledNs := plainNs.DeepCopy()
   103  	labeledNs.Labels = map[string]string{constants.LabelIstioInjection: "enabled"}
   104  
   105  	labeledWorkload := plainWorkload.DeepCopy()
   106  	labeledWorkload.Labels = map[string]string{constants.MetricsWorkloadLabel: testDeploymentName}
   107  
   108  	populatedTemplate, err := getTemplateTestFile()
   109  	assert.NoError(err)
   110  	testFileCM, err := getConfigMapFromTestFile(true)
   111  	assert.NoError(err)
   112  	testFileSec, err := getSecretFromTestFile(true)
   113  	assert.NoError(err)
   114  
   115  	CMMetricsBinding := metricsBinding.DeepCopy()
   116  	secMetricsBinding := metricsBinding.DeepCopy()
   117  	secMetricsBinding.Spec.PrometheusConfigMap = vzapi.NamespaceName{}
   118  	secMetricsBinding.Spec.PrometheusConfigSecret = vzapi.SecretKey{
   119  		Namespace: vzconst.PrometheusOperatorNamespace,
   120  		Name:      vzconst.PromAdditionalScrapeConfigsSecretName,
   121  		Key:       prometheusConfigKey,
   122  	}
   123  	legacyBinding := metricsBinding.DeepCopy()
   124  	legacyBinding.Spec.MetricsTemplate.Namespace = constants.LegacyDefaultMetricsTemplateNamespace
   125  	legacyBinding.Spec.MetricsTemplate.Name = constants.LegacyDefaultMetricsTemplateName
   126  	legacyBinding.Spec.PrometheusConfigMap.Namespace = vzconst.VerrazzanoSystemNamespace
   127  	legacyBinding.Spec.PrometheusConfigMap.Name = vzconst.VmiPromConfigName
   128  	deleteBinding := metricsBinding.DeepCopy()
   129  	deleteBinding.DeletionTimestamp = &k8smeta.Time{Time: time.Now()}
   130  
   131  	tests := []struct {
   132  		name           string
   133  		metricsBinding *vzapi.MetricsBinding
   134  		workload       *k8sapps.Deployment
   135  		namespace      *k8score.Namespace
   136  		configMap      *k8score.ConfigMap
   137  		secret         *k8score.Secret
   138  		request        *reconcile.Request
   139  		requeue        bool
   140  		expectError    bool
   141  	}{
   142  		{
   143  			name:           "test kube-system request",
   144  			metricsBinding: CMMetricsBinding,
   145  			workload:       labeledWorkload,
   146  			namespace:      labeledNs,
   147  			request:        &reconcile.Request{NamespacedName: types.NamespacedName{Namespace: vzconst.KubeSystem}},
   148  			requeue:        false,
   149  		},
   150  		{
   151  			name:           "test configmap",
   152  			metricsBinding: CMMetricsBinding,
   153  			workload:       labeledWorkload,
   154  			namespace:      labeledNs,
   155  			configMap:      testFileCM,
   156  			requeue:        true,
   157  			expectError:    false,
   158  		},
   159  		{
   160  			name:           "test secret",
   161  			metricsBinding: secMetricsBinding,
   162  			workload:       labeledWorkload,
   163  			namespace:      labeledNs,
   164  			secret:         testFileSec,
   165  			requeue:        true,
   166  			expectError:    false,
   167  		},
   168  		{
   169  			name:           "test delete",
   170  			metricsBinding: deleteBinding,
   171  			workload:       labeledWorkload,
   172  			namespace:      labeledNs,
   173  			configMap:      testFileCM,
   174  			requeue:        false,
   175  			expectError:    false,
   176  		},
   177  	}
   178  	for _, tt := range tests {
   179  		t.Run(tt.name, func(t *testing.T) {
   180  			c := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects([]runtime.Object{
   181  				populatedTemplate,
   182  				tt.workload,
   183  				tt.namespace,
   184  				tt.metricsBinding,
   185  			}...)
   186  
   187  			if tt.configMap != nil {
   188  				c = c.WithRuntimeObjects(tt.configMap)
   189  			}
   190  			if tt.secret != nil {
   191  				c = c.WithRuntimeObjects(tt.secret)
   192  			}
   193  
   194  			client := c.Build()
   195  			r := newReconciler(client)
   196  			if tt.request == nil {
   197  				tt.request = &reconcile.Request{NamespacedName: types.NamespacedName{Namespace: tt.metricsBinding.Namespace, Name: tt.metricsBinding.Name}}
   198  			}
   199  			result, err := r.Reconcile(context.TODO(), *tt.request)
   200  			if tt.expectError {
   201  				assert.Error(err, "Expected error Reconciling the Metrics Binding")
   202  				return
   203  			}
   204  			assert.NoError(err, "Expected no error Reconciling the Metrics Binding")
   205  			assert.Equal(tt.requeue, result.Requeue)
   206  		})
   207  	}
   208  }