@@ -90,6 +90,23 @@ func TestAdmit(t *testing.T) {
9090 req : req ,
9191 expectedErr : errors .NewServerTimeout (schema.GroupResource {}, "" , 2 ),
9292 },
93+ "existing namespace with the 'field.cattle.io/allow-fleetworkspace-creation-for-existing-namespace' annotation" : {
94+ m : existingNsWithAnnotationMutator ,
95+ req : req ,
96+ expectAllowed : true ,
97+ expectResultStatus : nil ,
98+ },
99+ "existing namespace with the 'field.cattle.io/allow-fleetworkspace-creation-for-existing-namespace' annotation set to false" : {
100+ m : existingNsWithAnnotationSetToFalseMutator ,
101+ req : req ,
102+ expectAllowed : false ,
103+ expectResultStatus : & metav1.Status {
104+ Status : "Failure" ,
105+ Message : "namespace 'test' already exists" ,
106+ Reason : metav1 .StatusReasonBadRequest ,
107+ Code : http .StatusBadRequest ,
108+ },
109+ },
93110 }
94111
95112 for name , test := range tests {
@@ -263,3 +280,118 @@ func newNsErrorMutator(t *testing.T) Mutator {
263280 namespaces : mockNamespaceController ,
264281 }
265282}
283+
284+ func existingNsWithAnnotationMutator (t * testing.T ) Mutator {
285+ ctrl := gomock .NewController (t )
286+
287+ mockNamespaceController := fake.NewMockNonNamespacedControllerInterface [* v1.Namespace , * v1.NamespaceList ](ctrl )
288+ mockClusterRoleCache := fake.NewMockNonNamespacedCacheInterface [* rbacv1.ClusterRole ](ctrl )
289+ mockClusterRoleController := fake.NewMockNonNamespacedControllerInterface [* rbacv1.ClusterRole , * rbacv1.ClusterRoleList ](ctrl )
290+ mockRoleBindingController := fake.NewMockControllerInterface [* rbacv1.RoleBinding , * rbacv1.RoleBindingList ](ctrl )
291+ mockClusterRoleBindingController := fake.NewMockNonNamespacedControllerInterface [* rbacv1.ClusterRoleBinding , * rbacv1.ClusterRoleBindingList ](ctrl )
292+
293+ // Namespace already exists
294+ mockNamespaceController .EXPECT ().Create (gomock .Any ()).Return (nil , errors .NewAlreadyExists (gvr .GroupResource (), nsName ))
295+ // Get returns existing namespace with the annotation
296+ mockNamespaceController .EXPECT ().Get (gomock .Any (), gomock .Any ()).Return (& v1.Namespace {
297+ ObjectMeta : metav1.ObjectMeta {
298+ Name : nsName ,
299+ Annotations : map [string ]string {"field.cattle.io/allow-fleetworkspace-creation-for-existing-namespace" : "true" },
300+ },
301+ }, nil )
302+ // Get returns the `fleetworkspace-admin` cluster role
303+ mockClusterRoleCache .EXPECT ().Get (fleetAdminRole ).Return (& rbacv1.ClusterRole {}, nil )
304+ mockClusterRoleController .EXPECT ().Cache ().Return (mockClusterRoleCache )
305+ // Create a role binding for the current user with the `fleetworkspace-admin` role
306+ roleBinding := & rbacv1.RoleBinding {
307+ ObjectMeta : metav1.ObjectMeta {
308+ Name : "fleetworkspace-admin-binding-" + nsName ,
309+ Namespace : nsName ,
310+ },
311+ Subjects : []rbacv1.Subject {
312+ {
313+ Kind : "User" ,
314+ APIGroup : "rbac.authorization.k8s.io" ,
315+ Name : user ,
316+ },
317+ },
318+ RoleRef : rbacv1.RoleRef {
319+ APIGroup : "rbac.authorization.k8s.io" ,
320+ Kind : "ClusterRole" ,
321+ Name : fleetAdminRole ,
322+ },
323+ }
324+ mockRoleBindingController .EXPECT ().Create (roleBinding )
325+ // Create a cluster role and cluster role binding
326+ clusterRole := & rbacv1.ClusterRole {
327+ ObjectMeta : metav1.ObjectMeta {
328+ Name : "fleetworkspace-own-test" ,
329+ },
330+ Rules : []rbacv1.PolicyRule {
331+ {
332+ APIGroups : []string {
333+ management .GroupName ,
334+ },
335+ Verbs : []string {
336+ "*" ,
337+ },
338+ Resources : []string {
339+ "fleetworkspaces" ,
340+ },
341+ ResourceNames : []string {
342+ nsName ,
343+ },
344+ },
345+ },
346+ }
347+
348+ clusterRoleBinding := & rbacv1.ClusterRoleBinding {
349+ ObjectMeta : metav1.ObjectMeta {
350+ Name : "fleetworkspace-own-binding-test" ,
351+ },
352+ Subjects : []rbacv1.Subject {
353+ {
354+ Kind : "User" ,
355+ APIGroup : "rbac.authorization.k8s.io" ,
356+ Name : user ,
357+ },
358+ },
359+ RoleRef : rbacv1.RoleRef {
360+ APIGroup : "rbac.authorization.k8s.io" ,
361+ Kind : "ClusterRole" ,
362+ Name : "fleetworkspace-own-test" ,
363+ },
364+ }
365+ mockClusterRoleController .EXPECT ().Create (gomock .Any ()).Return (clusterRole , nil )
366+ mockClusterRoleBindingController .EXPECT ().Create (clusterRoleBinding ).Return (clusterRoleBinding , nil )
367+
368+ resolver , _ := validation .NewTestRuleResolver (nil , nil , []* rbacv1.ClusterRole {clusterRole }, []* rbacv1.ClusterRoleBinding {clusterRoleBinding })
369+
370+ return Mutator {
371+ namespaces : mockNamespaceController ,
372+ clusterroles : mockClusterRoleController ,
373+ rolebindings : mockRoleBindingController ,
374+ clusterrolebindings : mockClusterRoleBindingController ,
375+ resolver : resolver ,
376+ }
377+ }
378+
379+ func existingNsWithAnnotationSetToFalseMutator (t * testing.T ) Mutator {
380+ ctrl := gomock .NewController (t )
381+
382+ mockNamespaceController := fake.NewMockNonNamespacedControllerInterface [* v1.Namespace , * v1.NamespaceList ](ctrl )
383+
384+ // Namespace already exists
385+ mockNamespaceController .EXPECT ().Create (gomock .Any ()).Return (nil , errors .NewAlreadyExists (gvr .GroupResource (), nsName ))
386+ // Get returns existing namespace with the annotation
387+ mockNamespaceController .EXPECT ().Get (gomock .Any (), gomock .Any ()).Return (& v1.Namespace {
388+ ObjectMeta : metav1.ObjectMeta {
389+ Name : nsName ,
390+ Annotations : map [string ]string {"field.cattle.io/allow-fleetworkspace-creation-for-existing-namespace" : "false" },
391+ },
392+ }, nil )
393+
394+ return Mutator {
395+ namespaces : mockNamespaceController ,
396+ }
397+ }
0 commit comments