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 }