github.com/verrazzano/verrazzano@v1.7.0/application-operator/controllers/clusters/test/test_utils.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 clusterstest
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"os"
    11  	"sigs.k8s.io/controller-runtime/pkg/client"
    12  	"testing"
    13  
    14  	"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
    15  	"github.com/golang/mock/gomock"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/verrazzano/verrazzano/application-operator/apis/clusters/v1alpha1"
    18  	"github.com/verrazzano/verrazzano/application-operator/constants"
    19  	"github.com/verrazzano/verrazzano/application-operator/controllers/clusters"
    20  	"github.com/verrazzano/verrazzano/application-operator/mocks"
    21  	"k8s.io/api/core/v1"
    22  	"k8s.io/apimachinery/pkg/runtime"
    23  	"k8s.io/apimachinery/pkg/types"
    24  	ctrl "sigs.k8s.io/controller-runtime"
    25  	"sigs.k8s.io/yaml"
    26  )
    27  
    28  // UnitTestClusterName - cluster name used in unit tests
    29  const UnitTestClusterName = "cluster1"
    30  
    31  // NewRequest creates a new reconciler request for testing
    32  // namespace - The namespace to use in the request
    33  // name - The name to use in the request
    34  func NewRequest(namespace string, name string) ctrl.Request {
    35  	return ctrl.Request{
    36  		NamespacedName: types.NamespacedName{
    37  			Namespace: namespace,
    38  			Name:      name,
    39  		},
    40  	}
    41  }
    42  
    43  // ReadYaml2Json reads the testdata YAML file at the given path, converts it to JSON and returns
    44  // a byte slice containing the JSON
    45  func ReadYaml2Json(filename string) ([]byte, error) {
    46  	yamlBytes, err := os.ReadFile(filename)
    47  	if err != nil {
    48  		return nil, fmt.Errorf("failed to read test data file %s: %s", filename, err.Error())
    49  	}
    50  	jsonBytes, err := yaml.YAMLToJSON(yamlBytes)
    51  	if err != nil {
    52  		return nil, fmt.Errorf("failed to unmarshall YAML to JSON in file %s: %s", filename, err.Error())
    53  	}
    54  	return jsonBytes, nil
    55  }
    56  
    57  // ReadContainerizedWorkload reads the raw workload (typically from an OAM component) into
    58  // a ContainerizedWorkload object
    59  func ReadContainerizedWorkload(rawWorkload runtime.RawExtension) (v1alpha2.ContainerizedWorkload, error) {
    60  	ctrWorkload := v1alpha2.ContainerizedWorkload{}
    61  	workloadBytes, err := rawWorkload.MarshalJSON()
    62  	if err != nil {
    63  		return ctrWorkload, err
    64  	}
    65  	err = json.Unmarshal(workloadBytes, &ctrWorkload)
    66  	return ctrWorkload, err
    67  }
    68  
    69  // DoExpectGetMCRegistrationSecret adds an expectation to the given MockClient to expect a Get
    70  // call for the managed cluster registration secret, and populate it with the cluster-name
    71  func DoExpectGetMCRegistrationSecret(cli *mocks.MockClient) {
    72  	// expect a call to fetch the MCRegistrationSecret and return a fake one with a specific cluster name
    73  	mockRegistrationSecretData := map[string][]byte{constants.ClusterNameData: []byte(UnitTestClusterName)}
    74  	cli.EXPECT().
    75  		Get(gomock.Any(), types.NamespacedName{
    76  			Namespace: clusters.MCRegistrationSecretFullName.Namespace,
    77  			Name:      clusters.MCRegistrationSecretFullName.Name},
    78  			gomock.Not(gomock.Nil()),
    79  			gomock.Any()).
    80  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, secret *v1.Secret, opts ...client.GetOption) error {
    81  			secret.Data = mockRegistrationSecretData
    82  			secret.ObjectMeta.Namespace = clusters.MCRegistrationSecretFullName.Namespace
    83  			secret.ObjectMeta.Name = clusters.MCRegistrationSecretFullName.Name
    84  			return nil
    85  		})
    86  }
    87  
    88  // AssertMultiClusterResourceStatus asserts that the status, conditions and cluster level status
    89  // on the MultiClusterResourceStatus are as expected
    90  func AssertMultiClusterResourceStatus(assert *assert.Assertions,
    91  	actualStatus v1alpha1.MultiClusterResourceStatus,
    92  	expectedState v1alpha1.StateType,
    93  	expectedConditionType v1alpha1.ConditionType,
    94  	expectedConditionStatus v1.ConditionStatus) {
    95  
    96  	assert.Equal(expectedState, actualStatus.State)
    97  	assert.Equal(1, len(actualStatus.Conditions))
    98  	assert.Equal(expectedConditionStatus, actualStatus.Conditions[0].Status)
    99  	assert.Equal(expectedConditionType, actualStatus.Conditions[0].Type)
   100  
   101  	assert.Equal(1, len(actualStatus.Clusters))
   102  	assert.Equal(UnitTestClusterName, actualStatus.Clusters[0].Name)
   103  	assert.Equal(expectedState, actualStatus.Clusters[0].State)
   104  }
   105  
   106  // DoExpectUpdateState checks that the status writer was retrieved and an update of the
   107  // resource's state to the given value was called
   108  func DoExpectUpdateState(t *testing.T, cli *mocks.MockClient, statusWriter *mocks.MockStatusWriter, mcAppConfig clusters.MultiClusterResource, expectedState v1alpha1.StateType) {
   109  	// expect a call to update the status of the MultiClusterApplicationConfiguration
   110  	cli.EXPECT().Status().Return(statusWriter)
   111  
   112  	// the status update should be to success status/conditions on the MultiClusterApplicationConfiguration
   113  	statusWriter.EXPECT().
   114  		Update(gomock.Any(), gomock.AssignableToTypeOf(mcAppConfig), gomock.Any()).
   115  		DoAndReturn(func(ctx context.Context, mcAppConfig clusters.MultiClusterResource, opts ...client.UpdateOption) error {
   116  			assert.Equal(t, v1alpha1.Pending, mcAppConfig.GetStatus().State)
   117  			return nil
   118  		})
   119  }
   120  
   121  // ExpectDeleteAssociatedResource adds an expectation to the given MockClient to expect a Get
   122  // call for the runtime resource and a subsequent request to delete it
   123  func ExpectDeleteAssociatedResource(cli *mocks.MockClient, resource runtime.Object, name types.NamespacedName) {
   124  	cli.EXPECT().
   125  		Get(gomock.Any(), types.NamespacedName{Namespace: name.Namespace, Name: name.Name}, gomock.Not(gomock.Nil()), gomock.Any()).
   126  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, obj runtime.Object, opts ...client.GetOption) error {
   127  			return nil
   128  		})
   129  
   130  	cli.EXPECT().
   131  		Delete(gomock.Any(), gomock.Any(), gomock.Any()).
   132  		DoAndReturn(func(ctx context.Context, resource runtime.Object, opts ...client.DeleteOption) error {
   133  			return nil
   134  		})
   135  
   136  }