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

     1  // Copyright (c) 2020, 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 metricstrait
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/Jeffail/gabs/v2"
    10  	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
    11  	asserts "github.com/stretchr/testify/assert"
    12  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
    13  	"github.com/verrazzano/verrazzano/application-operator/constants"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  )
    16  
    17  // Test_updateStringMap tests metrics trait utility function updateStringMap
    18  func Test_updateStringMap(t *testing.T) {
    19  	assert := asserts.New(t)
    20  	var input map[string]string
    21  	var output map[string]string
    22  
    23  	// GIVEN a nil input map
    24  	// WHEN a new name value pair are added
    25  	// THEN verify a map is returned containing the new name value pair.
    26  	input = nil
    27  	output = updateStringMap(input, "test-name-1", "test-value-1")
    28  	assert.Len(output, 1)
    29  	assert.Equal("test-value-1", output["test-name-1"])
    30  
    31  	// GIVEN an empty input map
    32  	// WHEN a new name value pair are added
    33  	// THEN verify a map is returned containing the new name value pair.
    34  	input = map[string]string{}
    35  	output = updateStringMap(input, "test-name-1", "test-value-1")
    36  	assert.Len(output, 1)
    37  	assert.Equal("test-value-1", output["test-name-1"])
    38  
    39  	// GIVEN an map with an existing name/value pair
    40  	// WHEN a new value is set for an existing name
    41  	// THEN verify a map contains the new value
    42  	input = map[string]string{"test-name-1": "test-value-1"}
    43  	output = updateStringMap(input, "test-name-1", "test-value-2")
    44  	assert.Len(output, 1)
    45  	assert.Equal("test-value-2", output["test-name-1"])
    46  
    47  	// GIVEN an map with an existing name/value pair
    48  	// WHEN a new name and value is set
    49  	// THEN verify a map contains both the old and the new pairs
    50  	input = map[string]string{"test-name-1": "test-value-1"}
    51  	output = updateStringMap(input, "test-name-2", "test-value-2")
    52  	assert.Len(output, 2)
    53  	assert.Equal("test-value-1", output["test-name-1"])
    54  	assert.Equal("test-value-2", output["test-name-2"])
    55  }
    56  
    57  // Test_copyStringMapEntries tests metrics trait utility function copyStringMapEntries
    58  func Test_copyStringMapEntries(t *testing.T) {
    59  	assert := asserts.New(t)
    60  	var source map[string]string
    61  	var target map[string]string
    62  	var output map[string]string
    63  
    64  	// GIVEN nil source and target maps
    65  	// WHEN a key name is copied from source to target
    66  	// THEN verify the target map is empty
    67  	source = nil
    68  	target = nil
    69  	output = copyStringMapEntries(target, source, "test-name-1")
    70  	assert.NotNil(output)
    71  	assert.Len(output, 0)
    72  
    73  	// GIVEN empty source and target maps
    74  	// WHEN a key name is copied from source to target
    75  	// THEN verify the target map is empty
    76  	source = map[string]string{}
    77  	target = map[string]string{}
    78  	output = copyStringMapEntries(target, source, "test-name-1")
    79  	assert.NotNil(output)
    80  	assert.Len(output, 0)
    81  
    82  	// GIVEN empty source and target maps
    83  	// WHEN a key name is copied from source to target
    84  	// THEN verify the output and target map have two entries
    85  	source = map[string]string{"test-name-1": "test-value-1"}
    86  	target = map[string]string{"test-name-2": "test-value-2"}
    87  	output = copyStringMapEntries(target, source, "test-name-1")
    88  	assert.NotNil(output)
    89  	assert.Equal("test-value-1", output["test-name-1"])
    90  	assert.Equal("test-value-2", output["test-name-2"])
    91  	assert.Len(output, 2)
    92  	assert.Len(source, 1)
    93  	assert.Len(target, 2)
    94  }
    95  
    96  // Test_getNamespaceFromObjectMetaOrDefault tests metrics trait utility function getNamespaceFromObjectMetaOrDefault
    97  func Test_getNamespaceFromObjectMetaOrDefault(t *testing.T) {
    98  	assert := asserts.New(t)
    99  	var meta metav1.ObjectMeta
   100  	var name string
   101  
   102  	// GIVEN metadata with a blank namespace name
   103  	// WHEN the namespace name is retrieved
   104  	// THEN verify the "default" namespace name is returned
   105  	name = getNamespaceFromObjectMetaOrDefault(meta)
   106  	assert.Equal("default", name)
   107  
   108  	// GIVEN metadata with a non-blank namespace name
   109  	// WHEN the namespace name is retrieved
   110  	// THEN verify the correct namespace name is returned
   111  	meta = metav1.ObjectMeta{Namespace: "test-namespace-1"}
   112  	name = getNamespaceFromObjectMetaOrDefault(meta)
   113  	assert.Equal("test-namespace-1", name)
   114  }
   115  
   116  // Test_parseYAMLString tests metrics trait utility function parseYAMLString
   117  // func parseYAMLString(s string) (*gabs.Container, error) {
   118  func Test_parseYAMLString(t *testing.T) {
   119  	assert := asserts.New(t)
   120  	var cont *gabs.Container
   121  	var str string
   122  	var err error
   123  
   124  	// GIVEN an empty yaml string
   125  	// WHEN the yaml string is parsed
   126  	// THEN verify that the unstructured objects are empty
   127  	str = ""
   128  	cont, err = parseYAMLString(str)
   129  	assert.NoError(err)
   130  	assert.Equal(nil, cont.Data())
   131  
   132  	// GIVEN an invalid yaml string
   133  	// WHEN the yaml string is parsed
   134  	// THEN verify that an error is returned
   135  	str = ":"
   136  	cont, err = parseYAMLString(str)
   137  	assert.Error(err)
   138  
   139  	// GIVEN an simple yaml string
   140  	// WHEN the yaml string is parsed
   141  	// THEN verify that the unstructured objects contain the correct data
   142  	str = "test-name-1: test-value-1"
   143  	cont, err = parseYAMLString(str)
   144  	assert.NoError(err)
   145  	assert.Equal("test-value-1", cont.Path("test-name-1").Data().(string))
   146  }
   147  
   148  // Test_writeYAMLString tests metrics trait utility function writeYAMLString
   149  func Test_writeYAMLString(t *testing.T) {
   150  	assert := asserts.New(t)
   151  	var str string
   152  	var err error
   153  
   154  	// GIVEN an simple yaml container
   155  	// WHEN the yaml container is written to a string
   156  	// THEN verify that the string is correct
   157  	var cont = gabs.New()
   158  	cont.Set("test-value-1", "test-name-1")
   159  	str, err = writeYAMLString(cont)
   160  	assert.NoError(err)
   161  	assert.Equal("test-name-1: test-value-1\n", str)
   162  }
   163  
   164  // Test_mergeTemplateWithContext tests metrics trait utility function mergeTemplateWithContext
   165  func Test_mergeTemplateWithContext(t *testing.T) {
   166  	assert := asserts.New(t)
   167  	var input string
   168  	var output string
   169  	var context map[string]string
   170  
   171  	// GIVEN an empty template and nil context
   172  	// WHEN the template and context are merged
   173  	// THEN verify that the result is an empty string
   174  	input = ""
   175  	context = nil
   176  	output = mergeTemplateWithContext(input, context)
   177  	assert.Equal("", output)
   178  
   179  	// GIVEN an template with no placeholders and nil context
   180  	// WHEN the template and context are merged
   181  	// THEN verify that the result is the same as the input
   182  	input = "no-place-holders"
   183  	context = nil
   184  	output = mergeTemplateWithContext(input, context)
   185  	assert.Equal("no-place-holders", output)
   186  
   187  	// GIVEN an template with duplicate placeholder and a newline
   188  	// WHEN the context contains a value for the placeholder
   189  	// THEN verify that the output has the value twice with a newline separating them
   190  	input = "{{template-name-1}}\n{{template-name-1}}"
   191  	context = map[string]string{"{{template-name-1}}": "template-value-2"}
   192  	output = mergeTemplateWithContext(input, context)
   193  	assert.Equal("template-value-2\ntemplate-value-2", output)
   194  }
   195  
   196  // TestGetSupportedWorkloadType tests metrics trait utility function GetSupportedWorkloadType
   197  func TestGetSupportedWorkloadType(t *testing.T) {
   198  	assert := asserts.New(t)
   199  	var apiVerKind string
   200  	var workloadType string
   201  
   202  	// GIVEN an api version weblogic.oracle/v8 and Kind Domain
   203  	// WHEN supported workloadtype is retrieved
   204  	// THEN verify that the workloadtype is weblogic
   205  	apiVerKind = "weblogic.oracle/v8.Domain"
   206  	workloadType = GetSupportedWorkloadType(apiVerKind)
   207  	assert.Equal(constants.WorkloadTypeWeblogic, workloadType)
   208  
   209  	// GIVEN an api version coherence.oracle.com/v1 and Kind Coherence
   210  	// WHEN supported workloadtype is retrieved
   211  	// THEN verify that the workloadType is coherence
   212  	apiVerKind = "coherence.oracle.com/v1.Coherence"
   213  	workloadType = GetSupportedWorkloadType(apiVerKind)
   214  	assert.Equal(constants.WorkloadTypeCoherence, workloadType)
   215  
   216  	// GIVEN an api version oam.verrazzano.io/v1alpha1 and Kind VerrazzanoHelidonWorkload
   217  	// WHEN supported workloadtype is retrieved
   218  	// THEN verify that the workloadType is generic
   219  	apiVerKind = "oam.verrazzano.io/v1alpha1.VerrazzanoHelidonWorkload"
   220  	workloadType = GetSupportedWorkloadType(apiVerKind)
   221  	assert.Equal(constants.WorkloadTypeGeneric, workloadType)
   222  
   223  	// GIVEN an api version core.oam.dev/v1alpha2 and Kind ContainerizedWorkload
   224  	// WHEN supported workloadtype is retrieved
   225  	// THEN verify that the workloadType is generic
   226  	apiVerKind = "core.oam.dev/v1alpha2.ContainerizedWorkload"
   227  	workloadType = GetSupportedWorkloadType(apiVerKind)
   228  	assert.Equal(constants.WorkloadTypeGeneric, workloadType)
   229  
   230  	// GIVEN an api version apps/v1 and Kind Deployment
   231  	// WHEN supported workloadtype is retrieved
   232  	// THEN verify that the workloadType is generic
   233  	apiVerKind = "apps/v1.Deployment"
   234  	workloadType = GetSupportedWorkloadType(apiVerKind)
   235  	assert.Equal(constants.WorkloadTypeGeneric, workloadType)
   236  
   237  	// GIVEN an api version vi and Kind ConfigMap
   238  	// WHEN supported workloadtype is retrieved
   239  	// THEN verify that the workloadType is empty because ConfigMap is not a supported type.
   240  	apiVerKind = "v1.ConfigMap"
   241  	workloadType = GetSupportedWorkloadType(apiVerKind)
   242  	assert.Empty(workloadType)
   243  }
   244  
   245  // TestCreateServiceMonitorName test the creation of a service monitor name from relevant resources,
   246  // as well as the creation of a legacy prometheus configmap job name
   247  func TestCreateServiceMonitorName(t *testing.T) {
   248  	tests := []struct {
   249  		name                       string
   250  		trait                      *vzapi.MetricsTrait
   251  		portNum                    int
   252  		expectedServiceMonitorName string
   253  		expectedLegacyJobName      string
   254  		expectError                bool
   255  	}{
   256  		{
   257  			name:                       "test empty trait",
   258  			trait:                      &vzapi.MetricsTrait{},
   259  			portNum:                    0,
   260  			expectedServiceMonitorName: "",
   261  			expectError:                true,
   262  		},
   263  		{
   264  			name: "test empty trait",
   265  			trait: &vzapi.MetricsTrait{
   266  				ObjectMeta: metav1.ObjectMeta{
   267  					Name:      "test-name",
   268  					Namespace: "test-namespace",
   269  					Labels: map[string]string{
   270  						oam.LabelAppName:      "test-app",
   271  						oam.LabelAppComponent: "test-comp",
   272  					},
   273  				},
   274  			},
   275  			portNum:                    0,
   276  			expectedServiceMonitorName: "test-app-test-namespace-test-comp",
   277  			expectedLegacyJobName:      "test-app_test-namespace_test-comp",
   278  			expectError:                false,
   279  		},
   280  		{
   281  			name: "test name too long",
   282  			trait: &vzapi.MetricsTrait{
   283  				ObjectMeta: metav1.ObjectMeta{
   284  					Name:      "test-name",
   285  					Namespace: "test-namespace",
   286  					Labels: map[string]string{
   287  						oam.LabelAppName:      "test-app-really-long-label",
   288  						oam.LabelAppComponent: "test-comp-extra-long-label",
   289  					},
   290  				},
   291  			},
   292  			portNum:                    1,
   293  			expectedServiceMonitorName: "test-app-really-long-label-test-namespace-1",
   294  			expectedLegacyJobName:      "test-app-really-long-label_test-namespace_1",
   295  			expectError:                false,
   296  		},
   297  	}
   298  	assert := asserts.New(t)
   299  	for _, tt := range tests {
   300  		smName, err1 := createServiceMonitorName(tt.trait, tt.portNum)
   301  		jobName, err2 := createPrometheusScrapeConfigMapJobName(tt.trait, tt.portNum)
   302  		if tt.expectError {
   303  			assert.Error(err1)
   304  			assert.Error(err2)
   305  		} else {
   306  			assert.NoError(err1)
   307  			assert.NoError(err2)
   308  
   309  		}
   310  		asserts.Equal(t, tt.expectedServiceMonitorName, smName)
   311  		asserts.Equal(t, tt.expectedLegacyJobName, jobName)
   312  	}
   313  }