github.com/verrazzano/verrazzano@v1.7.0/platform-operator/internal/k8s/namespace/namespace_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  package namespace
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/verrazzano/verrazzano/platform-operator/constants"
    11  
    12  	"github.com/golang/mock/gomock"
    13  	"github.com/stretchr/testify/assert"
    14  	globalconst "github.com/verrazzano/verrazzano/pkg/constants"
    15  	"github.com/verrazzano/verrazzano/platform-operator/mocks"
    16  	corev1 "k8s.io/api/core/v1"
    17  	"k8s.io/apimachinery/pkg/api/errors"
    18  	"k8s.io/apimachinery/pkg/runtime"
    19  	"k8s.io/apimachinery/pkg/runtime/schema"
    20  	"k8s.io/apimachinery/pkg/types"
    21  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    22  	"sigs.k8s.io/controller-runtime/pkg/client"
    23  )
    24  
    25  var (
    26  	testScheme = runtime.NewScheme()
    27  
    28  	istioLabels = map[string]string{
    29  		globalconst.LabelIstioInjection: "enabled",
    30  	}
    31  )
    32  
    33  // createVZAndIstioLabels - create an expected map with both the VZ and Istio labels
    34  func createVZAndIstioLabels(ns string) map[string]string {
    35  	return map[string]string{
    36  		globalconst.LabelVerrazzanoNamespace: ns,
    37  		globalconst.LabelIstioInjection:      "enabled",
    38  	}
    39  }
    40  
    41  // createVzLabels - create a map with only the VZ-managed label
    42  func createVzLabels(ns string) map[string]string {
    43  	return map[string]string{
    44  		globalconst.LabelVerrazzanoNamespace: ns,
    45  	}
    46  }
    47  
    48  func init() {
    49  	_ = clientgoscheme.AddToScheme(testScheme)
    50  	// +kubebuilder:scaffold:testScheme
    51  }
    52  
    53  // TestCreateAndLabelNamespace tests the CreateAndLabelNamespace method for the following use case
    54  // GIVEN a call to CreateAndLabelNamespace
    55  // WHEN both the Verrazzano-managed and Istio injection label is specified
    56  // THEN no error is returned and the labels are added to the namepace
    57  func TestCreateAndLabelNamespace(t *testing.T) {
    58  	asserts := assert.New(t)
    59  	mocker := gomock.NewController(t)
    60  	mock := mocks.NewMockClient(mocker)
    61  
    62  	mock.EXPECT().
    63  		Get(gomock.Any(), types.NamespacedName{Name: "testns"}, gomock.Not(gomock.Nil()), gomock.Any()).
    64  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
    65  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), "testns")
    66  		})
    67  
    68  	mock.EXPECT().
    69  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
    70  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
    71  			asserts.Equal("testns", ns.Name)
    72  			asserts.Equal(createVZAndIstioLabels("testns"), ns.Labels)
    73  			return nil
    74  		})
    75  
    76  	asserts.NoError(CreateAndLabelNamespace(mock, "testns", true, true))
    77  }
    78  
    79  // TestCreateAndLabelNamespace tests the CreateAndLabelNamespace method for the following use case
    80  // GIVEN a call to CreateAndLabelNamespace
    81  // WHEN only the Verrazzano-managed injection label is specified
    82  // THEN no error is returned and only the requested the labels are added to the namepace
    83  func TestCreateAndLabelNamespaceIstioInjection(t *testing.T) {
    84  	asserts := assert.New(t)
    85  	mocker := gomock.NewController(t)
    86  	mock := mocks.NewMockClient(mocker)
    87  
    88  	mock.EXPECT().
    89  		Get(gomock.Any(), types.NamespacedName{Name: "testns"}, gomock.Not(gomock.Nil()), gomock.Any()).
    90  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
    91  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), "testns")
    92  		})
    93  
    94  	mock.EXPECT().
    95  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
    96  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
    97  			asserts.Equal("testns", ns.Name)
    98  			asserts.Equal(istioLabels, ns.Labels)
    99  			return nil
   100  		})
   101  
   102  	asserts.NoError(CreateAndLabelNamespace(mock, "testns", false, true))
   103  }
   104  
   105  // TestCreateAndLabelNamespace tests the CreateAndLabelNamespace method for the following use case
   106  // GIVEN a call to CreateAndLabelNamespace
   107  // WHEN only the Istio injection labels are specified
   108  // THEN no error is returned and only the requested the labels are added to the namepace
   109  func TestCreateAndLabelNamespaceVzManaged(t *testing.T) {
   110  	asserts := assert.New(t)
   111  	mocker := gomock.NewController(t)
   112  	mock := mocks.NewMockClient(mocker)
   113  
   114  	mock.EXPECT().
   115  		Get(gomock.Any(), types.NamespacedName{Name: "testns"}, gomock.Not(gomock.Nil()), gomock.Any()).
   116  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
   117  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), "testns")
   118  		})
   119  
   120  	mock.EXPECT().
   121  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   122  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
   123  			asserts.Equal("testns", ns.Name)
   124  			asserts.Equal(createVzLabels("testns"), ns.Labels)
   125  			return nil
   126  		})
   127  
   128  	asserts.NoError(CreateAndLabelNamespace(mock, "testns", true, false))
   129  }
   130  
   131  // TestCreateAndLabelNamespace tests the CreateAndLabelNamespace method for the following use case
   132  // GIVEN a call to CreateAndLabelNamespace
   133  // WHEN an unexpected error occurs during the Create call
   134  // THEN an error is returned
   135  func TestCreateAndLabelNamespaceReturnsError(t *testing.T) {
   136  	asserts := assert.New(t)
   137  	mocker := gomock.NewController(t)
   138  	mock := mocks.NewMockClient(mocker)
   139  
   140  	mock.EXPECT().
   141  		Get(gomock.Any(), types.NamespacedName{Name: "testns"}, gomock.Not(gomock.Nil()), gomock.Any()).
   142  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
   143  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), "testns")
   144  		})
   145  
   146  	mock.EXPECT().
   147  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   148  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
   149  			return fmt.Errorf("UnexpectedError")
   150  		})
   151  
   152  	asserts.Error(CreateAndLabelNamespace(mock, "testns", true, true))
   153  }
   154  
   155  // TestCreateVerrazzanoSystemNamespace tests the CreateVerrazzanoSystemNamespace function
   156  // GIVEN a call to CreateVerrazzanoSystemNamespace
   157  // WHEN no error occurs
   158  // THEN no error is returned, the namespace is created, and the proper labels have been added
   159  func TestCreateVerrazzanoSystemNamespace(t *testing.T) {
   160  	runNamespaceTestWithIstioFlag(t, globalconst.VerrazzanoSystemNamespace,
   161  		createVZAndIstioLabels(globalconst.VerrazzanoSystemNamespace),
   162  		CreateVerrazzanoSystemNamespace)
   163  }
   164  
   165  // TestCreateKeycloakNamespace tests the CreateKeycloakNamespace function
   166  // GIVEN a call to CreateKeycloakNamespace
   167  // WHEN no error occurs
   168  // THEN no error is returned, the namespace is created, and the proper labels have been added
   169  func TestCreateKeycloakNamespace(t *testing.T) {
   170  	runNamespaceTestWithIstioFlag(t, globalconst.KeycloakNamespace,
   171  		createVZAndIstioLabels(globalconst.KeycloakNamespace),
   172  		CreateKeycloakNamespace)
   173  }
   174  
   175  // TestCreateRancherNamespace tests the CreateRancherNamespace function
   176  // GIVEN a call to CreateRancherNamespace
   177  // WHEN no error occurs
   178  // THEN no error is returned, the namespace is created, and the proper labels have been added
   179  func TestCreateRancherNamespace(t *testing.T) {
   180  	runNamespaceTest(t, globalconst.RancherSystemNamespace,
   181  		createVzLabels(globalconst.RancherSystemNamespace),
   182  		CreateRancherNamespace)
   183  }
   184  
   185  // TestCreateArgoCDNamespace tests the CreateArgoCDNamespace function
   186  // GIVEN a call to CreateArgoCDNamespace
   187  // WHEN no error occurs
   188  // THEN no error is returned, the namespace is created, and the proper labels have been added
   189  func TestCreateArgoCDNamespace(t *testing.T) {
   190  	runNamespaceTestWithIstioFlag(t, constants.ArgoCDNamespace,
   191  		createVZAndIstioLabels(constants.ArgoCDNamespace),
   192  		CreateArgoCDNamespace)
   193  }
   194  
   195  // TestCreateVerrazzanoMultiClusterNamespace tests the CreateVerrazzanoMultiClusterNamespace function
   196  // GIVEN a call to CreateVerrazzanoMultiClusterNamespace
   197  // WHEN no error occurs
   198  // THEN no error is returned, the namespace is created, and the proper labels have been added
   199  func TestCreateVerrazzanoMultiClusterNamespace(t *testing.T) {
   200  	runNamespaceTest(t, globalconst.VerrazzanoMultiClusterNamespace,
   201  		map[string]string{globalconst.LabelVerrazzanoNamespace: globalconst.VerrazzanoMultiClusterNamespace},
   202  		CreateVerrazzanoMultiClusterNamespace)
   203  }
   204  
   205  // TestCreateDexNamespace tests the CreateDexNamespace function
   206  // GIVEN a call to CreateDexNamespace
   207  // WHEN no error occurs
   208  // THEN no error is returned, the namespace is created, and the proper labels have been added
   209  func TestCreateDexNamespace(t *testing.T) {
   210  	runNamespaceTestWithIstioFlag(t, constants.DexNamespace,
   211  		createVZAndIstioLabels(constants.DexNamespace),
   212  		CreateDexNamespace)
   213  }
   214  
   215  func runNamespaceTest(t *testing.T, namespace string, expectedLabels map[string]string, namespaceFunc func(client client.Client) error) {
   216  	asserts := assert.New(t)
   217  	mocker := gomock.NewController(t)
   218  	mock := mocks.NewMockClient(mocker)
   219  
   220  	mock.EXPECT().
   221  		Get(gomock.Any(), types.NamespacedName{Name: namespace}, gomock.Not(gomock.Nil()), gomock.Any()).
   222  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
   223  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), namespace)
   224  		})
   225  
   226  	mock.EXPECT().
   227  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   228  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
   229  			asserts.Equal(namespace, ns.Name)
   230  			asserts.Equal(expectedLabels, ns.Labels)
   231  			return nil
   232  		})
   233  
   234  	asserts.NoError(namespaceFunc(mock))
   235  }
   236  
   237  func runNamespaceTestWithIstioFlag(t *testing.T, namespace string, expectedLabels map[string]string, namespaceFunc func(client client.Client, istioInjectionEnabled bool) error) {
   238  	asserts := assert.New(t)
   239  	mocker := gomock.NewController(t)
   240  	mock := mocks.NewMockClient(mocker)
   241  
   242  	mock.EXPECT().
   243  		Get(gomock.Any(), types.NamespacedName{Name: namespace}, gomock.Not(gomock.Nil()), gomock.Any()).
   244  		DoAndReturn(func(ctx context.Context, name types.NamespacedName, ns *corev1.Namespace, opts ...client.GetOption) error {
   245  			return errors.NewNotFound(schema.ParseGroupResource("Namespace"), namespace)
   246  		})
   247  
   248  	mock.EXPECT().
   249  		Create(gomock.Any(), gomock.Any(), gomock.Any()).
   250  		DoAndReturn(func(ctx context.Context, ns *corev1.Namespace, opts ...client.CreateOption) error {
   251  			asserts.Equal(namespace, ns.Name)
   252  			asserts.Equal(expectedLabels, ns.Labels)
   253  			return nil
   254  		})
   255  
   256  	asserts.NoError(namespaceFunc(mock, true))
   257  }