github.com/verrazzano/verrazzano@v1.7.0/application-operator/controllers/webhooks/metrics_trait_defaulter_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 webhooks
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"sigs.k8s.io/controller-runtime/pkg/client"
    10  	"testing"
    11  
    12  	oamv1 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
    16  	"github.com/verrazzano/verrazzano/application-operator/mocks"
    17  	"go.uber.org/zap"
    18  	"k8s.io/apimachinery/pkg/runtime"
    19  	"k8s.io/apimachinery/pkg/types"
    20  	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
    21  )
    22  
    23  // TestMetricsTraitDefaulter_Default tests adding a default MetricsTrait to an appconfig
    24  // GIVEN a AppConfigDefaulter and an appconfig
    25  // WHEN Default is called with an appconfig
    26  // THEN Default should add a default MetricsTrait to the appconfig if supported
    27  func TestMetricsTraitDefaulter_Default(t *testing.T) {
    28  	testDefaulter(t, "hello-comp.yaml", "hello-conf.yaml", "hello-workload.yaml", true,
    29  		0, 1)
    30  	testDefaulter(t, "hello-comp.yaml", "hello-conf_withTrait.yaml", "hello-workload.yaml", true,
    31  		1, 2)
    32  	testDefaulter(t, "hello-comp.yaml", "hello-conf_withMetricsTrait.yaml", "hello-workload.yaml", true,
    33  		2, 2)
    34  	testDefaulter(t, "bobs-component-no-metrics.yaml", "bobs-conf-no-metrics.yaml", "", false,
    35  		0, 0)
    36  }
    37  
    38  // TestMetricsTraitDefaulter_Cleanup tests cleaning up the default MetricsTrait on an appconfig
    39  // GIVEN a AppConfigDefaulter and an appconfig
    40  // WHEN Cleanup is called with an appconfig
    41  // THEN Cleanup should run without error
    42  func TestMetricsTraitDefaulter_Cleanup(t *testing.T) {
    43  	testMetricsTraitDefaulterCleanup(t, "hello-conf.yaml", false)
    44  	testMetricsTraitDefaulterCleanup(t, "hello-conf.yaml", true)
    45  	testMetricsTraitDefaulterCleanup(t, "bobs-conf-no-metrics.yaml", false)
    46  	testMetricsTraitDefaulterCleanup(t, "bobs-conf-no-metrics.yaml", true)
    47  }
    48  
    49  func testDefaulter(t *testing.T, componentPath, configPath, workloadPath string, workloadSupported bool, initTraitsSize, expectedTraitsSize int) {
    50  	mocker := gomock.NewController(t)
    51  	mock := mocks.NewMockClient(mocker)
    52  	req := admission.Request{}
    53  
    54  	req.Object = runtime.RawExtension{Raw: readYaml2Json(t, configPath)}
    55  	decoder := decoder()
    56  	appConfig := &oamv1.ApplicationConfiguration{}
    57  	err := decoder.Decode(req, appConfig)
    58  	if err != nil {
    59  		t.Fatalf("Error in decoder.Decode %v", err)
    60  	}
    61  	assert.Equal(t, 1, len(appConfig.Spec.Components))
    62  	assert.Equal(t, initTraitsSize, len(appConfig.Spec.Components[0].Traits))
    63  	defaulter := &MetricsTraitDefaulter{Client: mock}
    64  
    65  	// Expect a call to get the component.
    66  	mock.EXPECT().
    67  		Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
    68  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, component *oamv1.Component, opt ...client.GetOption) error {
    69  			err = json.Unmarshal(readYaml2Json(t, componentPath), component)
    70  			if err != nil {
    71  				t.Fatalf("Error in unmarshalling component %v", err)
    72  			}
    73  			return nil
    74  		}).AnyTimes()
    75  
    76  	err = defaulter.Default(appConfig, false, zap.S())
    77  	if err != nil {
    78  		t.Fatalf("Error in defaulter.Default %v", err)
    79  	}
    80  	assert.Equal(t, expectedTraitsSize, len(appConfig.Spec.Components[0].Traits))
    81  	foundMetricsTrait := false
    82  	for _, trait := range appConfig.Spec.Components[0].Traits {
    83  		var rawTrait map[string]interface{}
    84  		_ = json.Unmarshal(trait.Trait.Raw, &rawTrait)
    85  		if rawTrait["apiVersion"] == apiVersion && rawTrait["kind"] == v1alpha1.MetricsTraitKind {
    86  			foundMetricsTrait = true
    87  		}
    88  	}
    89  	assert.Equal(t, foundMetricsTrait, workloadSupported)
    90  }
    91  
    92  func testMetricsTraitDefaulterCleanup(t *testing.T, configPath string, dryRun bool) {
    93  	req := admission.Request{}
    94  	req.Object = runtime.RawExtension{Raw: readYaml2Json(t, configPath)}
    95  	decoder := decoder()
    96  	appConfig := &oamv1.ApplicationConfiguration{}
    97  	err := decoder.Decode(req, appConfig)
    98  	if err != nil {
    99  		t.Fatalf("Error in decoder.Decode %v", err)
   100  	}
   101  	assert.Equal(t, 1, len(appConfig.Spec.Components))
   102  	defaulter := &MetricsTraitDefaulter{}
   103  	err = defaulter.Cleanup(appConfig, dryRun, zap.S())
   104  	if err != nil {
   105  		t.Fatalf("Error in defaulter.Default %v", err)
   106  	}
   107  }