From b1d996f4a77562f30ee58bc0271792cd1df9c67c Mon Sep 17 00:00:00 2001 From: hongming Date: Thu, 11 Jun 2020 11:55:11 +0800 Subject: [PATCH] add test case Signed-off-by: hongming --- pkg/kapis/iam/v1alpha2/handler.go | 24 +- pkg/kapis/iam/v1alpha2/register.go | 42 +-- pkg/models/iam/am/am.go | 52 +--- pkg/models/tenant/tenant.go | 2 +- pkg/models/tenant/tenent_test.go | 432 +++++++++++++++++++++-------- 5 files changed, 362 insertions(+), 190 deletions(-) diff --git a/pkg/kapis/iam/v1alpha2/handler.go b/pkg/kapis/iam/v1alpha2/handler.go index 3238aa4cd..77f971163 100644 --- a/pkg/kapis/iam/v1alpha2/handler.go +++ b/pkg/kapis/iam/v1alpha2/handler.go @@ -61,9 +61,10 @@ func (h *iamHandler) DescribeUser(request *restful.Request, response *restful.Re } func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, response *restful.Response) { - username := request.PathParameter("user") if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralGlobalRole) { + username := request.PathParameter("user") + globalRole, err := h.am.GetGlobalRoleOfUser(username) if err != nil { @@ -93,8 +94,8 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo } if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralClusterRole) { + username := request.PathParameter("clustermember") clusterRole, err := h.am.GetClusterRoleOfUser(username) - if err != nil { // if role binding not exist return empty list if errors.IsNotFound(err) { @@ -111,7 +112,6 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo Ascending: false, Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(clusterRole.Name)}, }) - if err != nil { api.HandleInternalError(response, request, err) return @@ -123,9 +123,8 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralWorkspaceRole) { workspace := request.PathParameter("workspace") - + username := request.PathParameter("workspacemember") workspaceRole, err := h.am.GetWorkspaceRoleOfUser(username, workspace) - if err != nil { // if role binding not exist return empty list if errors.IsNotFound(err) { @@ -142,7 +141,6 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo Ascending: false, Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(workspaceRole.Name)}, }) - if err != nil { api.HandleInternalError(response, request, err) return @@ -154,7 +152,7 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralRole) { namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops")) - + username := request.PathParameter("member") if err != nil { api.HandleInternalError(response, request, err) return @@ -280,7 +278,7 @@ func (h *iamHandler) ListNamespaceMembers(request *restful.Request, response *re } func (h *iamHandler) DescribeNamespaceMember(request *restful.Request, response *restful.Response) { - username := request.PathParameter("user") + username := request.PathParameter("member") namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops")) if err != nil { @@ -347,7 +345,7 @@ func (h *iamHandler) ListWorkspaceMembers(request *restful.Request, response *re func (h *iamHandler) DescribeWorkspaceMember(request *restful.Request, response *restful.Response) { workspace := request.PathParameter("workspace") - username := request.PathParameter("user") + username := request.PathParameter("workspacemember") queryParam := query.New() queryParam.Filters[query.FieldName] = query.Value(username) @@ -828,7 +826,7 @@ func (h *iamHandler) CreateWorkspaceMembers(request *restful.Request, response * func (h *iamHandler) RemoveWorkspaceMember(request *restful.Request, response *restful.Response) { workspace := request.PathParameter("workspace") - username := request.PathParameter("user") + username := request.PathParameter("workspacemember") err := h.am.RemoveUserFromWorkspace(username, workspace) @@ -843,7 +841,7 @@ func (h *iamHandler) RemoveWorkspaceMember(request *restful.Request, response *r func (h *iamHandler) UpdateWorkspaceMember(request *restful.Request, response *restful.Response) { workspace := request.PathParameter("workspace") - username := request.PathParameter("user") + username := request.PathParameter("workspacemember") var member Member @@ -905,7 +903,7 @@ func (h *iamHandler) CreateNamespaceMembers(request *restful.Request, response * } func (h *iamHandler) UpdateNamespaceMember(request *restful.Request, response *restful.Response) { - username := request.PathParameter("user") + username := request.PathParameter("member") namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops")) if err != nil { @@ -942,7 +940,7 @@ func (h *iamHandler) UpdateNamespaceMember(request *restful.Request, response *r } func (h *iamHandler) RemoveNamespaceMember(request *restful.Request, response *restful.Response) { - username := request.PathParameter("user") + username := request.PathParameter("member") namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops")) if err != nil { diff --git a/pkg/kapis/iam/v1alpha2/register.go b/pkg/kapis/iam/v1alpha2/register.go index 995a3395f..dda7e371d 100644 --- a/pkg/kapis/iam/v1alpha2/register.go +++ b/pkg/kapis/iam/v1alpha2/register.go @@ -103,25 +103,25 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/workspaces/{workspace}/users"). + ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers"). To(handler.ListWorkspaceMembers). Doc("List all members in the specified workspace."). Param(ws.PathParameter("workspace", "workspace name")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/workspaces/{workspace}/users/{user}"). + ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}"). To(handler.DescribeWorkspaceMember). Doc("Retrieve workspace member details."). Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.POST("/workspaces/{workspace}/users"). + ws.Route(ws.POST("/workspaces/{workspace}/workspacemembers"). To(handler.CreateWorkspaceMembers). Doc("Batch add workspace members."). Reads([]Member{}). Returns(http.StatusOK, api.StatusOK, errors.None). Param(ws.PathParameter("workspace", "workspace name")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.PUT("/workspaces/{workspace}/users/{user}"). + ws.Route(ws.PUT("/workspaces/{workspace}/workspacemembers/{workspacemember}"). To(handler.UpdateWorkspaceMember). Doc("Update member in workspace."). Reads(Member{}). @@ -129,32 +129,32 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.DELETE("/workspaces/{workspace}/users/{user}"). + ws.Route(ws.DELETE("/workspaces/{workspace}/workspacemembers/{workspacemember}"). To(handler.RemoveWorkspaceMember). Doc("Remove member in workspace."). Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/namespaces/{namespace}/users"). + ws.Route(ws.GET("/namespaces/{namespace}/members"). To(handler.ListNamespaceMembers). Doc("List all members in the specified namespace."). Param(ws.PathParameter("namespace", "namespace")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/namespaces/{namespace}/users/{user}"). + ws.Route(ws.GET("/namespaces/{namespace}/members/{member}"). To(handler.DescribeNamespaceMember). Doc("Retrieve namespace member details."). Param(ws.PathParameter("namespace", "namespace")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.POST("/namespaces/{namespace}/users"). + ws.Route(ws.POST("/namespaces/{namespace}/members"). To(handler.CreateNamespaceMembers). Doc("Batch add namespace members."). Reads([]Member{}). Returns(http.StatusOK, api.StatusOK, errors.None). Param(ws.PathParameter("namespace", "namespace")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.PUT("/namespaces/{namespace}/users/{user}"). + ws.Route(ws.PUT("/namespaces/{namespace}/members/{member}"). To(handler.UpdateNamespaceMember). Doc("Update member in namespace."). Reads(Member{}). @@ -162,44 +162,44 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf Param(ws.PathParameter("namespace", "namespace")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.DELETE("/namespaces/{namespace}/users/{user}"). + ws.Route(ws.DELETE("/namespaces/{namespace}/members/{member}"). To(handler.RemoveNamespaceMember). Doc("Remove member in namespace."). Param(ws.PathParameter("namespace", "namespace")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/devops/{devops}/users"). + ws.Route(ws.GET("/devops/{devops}/members"). To(handler.ListNamespaceMembers). Doc("List all members in the specified namespace."). Param(ws.PathParameter("namespace", "namespace")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/devops/{devops}/users/{user}"). + ws.Route(ws.GET("/devops/{devops}/members/{member}"). To(handler.DescribeNamespaceMember). Doc("Retrieve namespace member details."). Param(ws.PathParameter("namespace", "namespace")). Param(ws.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.POST("/devops/{devops}/users"). + ws.Route(ws.POST("/devops/{devops}/members"). To(handler.CreateNamespaceMembers). Doc("Batch add namespace members."). Reads([]Member{}). Returns(http.StatusOK, api.StatusOK, errors.None). Param(ws.PathParameter("namespace", "namespace")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.PUT("/devops/{devops}/users/{user}"). + ws.Route(ws.PUT("/devops/{devops}/members/{member}"). To(handler.UpdateNamespaceMember). Doc("Update member in namespace."). Reads(Member{}). Returns(http.StatusOK, api.StatusOK, errors.None). Param(ws.PathParameter("namespace", "namespace")). - Param(ws.PathParameter("user", "username")). + Param(ws.PathParameter("member", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.DELETE("/devops/{devops}/users/{user}"). + ws.Route(ws.DELETE("/devops/{devops}/members/{member}"). To(handler.RemoveNamespaceMember). Doc("Remove member in namespace."). Param(ws.PathParameter("namespace", "namespace")). - Param(ws.PathParameter("user", "username")). + Param(ws.PathParameter("member", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) // globalroles @@ -375,27 +375,27 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf Param(ws.PathParameter("user", "username")). Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/users/{user}/clusterroles"). + ws.Route(ws.GET("/clustermembers/{clustermember}/clusterroles"). To(handler.RetrieveMemberRoleTemplates). Doc("Retrieve user's role templates in cluster."). Param(ws.PathParameter("user", "username")). Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/workspaces/{workspace}/users/{user}/workspaceroles"). + ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}/workspaceroles"). To(handler.RetrieveMemberRoleTemplates). Doc("Retrieve member's role templates in workspace."). Param(ws.PathParameter("workspace", "workspace")). Param(ws.PathParameter("user", "username")). Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/namespaces/{namespace}/users/{user}/roles"). + ws.Route(ws.GET("/namespaces/{namespace}/members/{member}/roles"). To(handler.RetrieveMemberRoleTemplates). Doc("Retrieve member's role templates in namespace."). Param(ws.PathParameter("namespace", "namespace")). Param(ws.PathParameter("user", "username")). Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag})) - ws.Route(ws.GET("/devops/{devops}/users/{user}/roles"). + ws.Route(ws.GET("/devops/{devops}/members/{member}/roles"). To(handler.RetrieveMemberRoleTemplates). Doc("Retrieve member's role templates in devops project."). Param(ws.PathParameter("namespace", "namespace")). diff --git a/pkg/models/iam/am/am.go b/pkg/models/iam/am/am.go index 517b2806a..85e0e5aea 100644 --- a/pkg/models/iam/am/am.go +++ b/pkg/models/iam/am/am.go @@ -32,7 +32,6 @@ import ( kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned" "kubesphere.io/kubesphere/pkg/informers" resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource" - "net/http" ) type AccessManagementInterface interface { @@ -114,17 +113,8 @@ func (am *amOperator) GetGlobalRoleOfUser(username string) (*iamv1alpha2.GlobalR return out, nil } - err = &errors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Code: http.StatusNotFound, - Reason: metav1.StatusReasonNotFound, - Details: &metav1.StatusDetails{ - Group: iamv1alpha2.SchemeGroupVersion.Group, - Kind: iamv1alpha2.ResourceKindGlobalRoleBinding, - }, - Message: fmt.Sprintf("global role binding not found for %s", username), - }} - + err = errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularGlobalRoleBinding), username) + klog.Error(err) return nil, err } @@ -157,17 +147,8 @@ func (am *amOperator) GetWorkspaceRoleOfUser(username, workspace string) (*iamv1 return out, nil } - err = &errors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Code: http.StatusNotFound, - Reason: metav1.StatusReasonNotFound, - Details: &metav1.StatusDetails{ - Group: iamv1alpha2.SchemeGroupVersion.Group, - Kind: iamv1alpha2.ResourceKindWorkspaceRoleBinding, - }, - Message: fmt.Sprintf("workspace role binding not found for %s", username), - }} - + err = errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularWorkspaceRoleBinding), username) + klog.Error(err) return nil, err } @@ -197,17 +178,8 @@ func (am *amOperator) GetNamespaceRoleOfUser(username, namespace string) (*rbacv return out, nil } - err = &errors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Code: http.StatusNotFound, - Reason: metav1.StatusReasonNotFound, - Details: &metav1.StatusDetails{ - Group: rbacv1.SchemeGroupVersion.Group, - Kind: iamv1alpha2.ResourceKindRoleBinding, - }, - Message: fmt.Sprintf("role binding not found for %s in %s", username, namespace), - }} - + err = errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularRoleBinding), username) + klog.Error(err) return nil, err } @@ -237,17 +209,9 @@ func (am *amOperator) GetClusterRoleOfUser(username string) (*rbacv1.ClusterRole out.Annotations[iamv1alpha2.ClusterRoleAnnotation] = role.Name return out, nil } - err = &errors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Code: http.StatusNotFound, - Reason: metav1.StatusReasonNotFound, - Details: &metav1.StatusDetails{ - Group: rbacv1.SchemeGroupVersion.Group, - Kind: "ClusterRoleBinding", - }, - Message: fmt.Sprintf("cluster role binding not found for %s", username), - }} + err = errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularClusterRoleBinding), username) + klog.Error(err) return nil, err } diff --git a/pkg/models/tenant/tenant.go b/pkg/models/tenant/tenant.go index 324b01e30..d56fec2d6 100644 --- a/pkg/models/tenant/tenant.go +++ b/pkg/models/tenant/tenant.go @@ -283,7 +283,7 @@ func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error { } func (t *tenantOperator) UpdateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error) { - _, err := t.DescribeNamespace(workspace, namespace.Namespace) + _, err := t.DescribeNamespace(workspace, namespace.Name) if err != nil { return nil, err } diff --git a/pkg/models/tenant/tenent_test.go b/pkg/models/tenant/tenent_test.go index 4018ed14e..7ced87b5f 100644 --- a/pkg/models/tenant/tenent_test.go +++ b/pkg/models/tenant/tenent_test.go @@ -22,7 +22,9 @@ import ( fakeistio "istio.io/client-go/pkg/clientset/versioned/fake" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authentication/user" fakek8s "k8s.io/client-go/kubernetes/fake" "kubesphere.io/kubesphere/pkg/api" @@ -32,41 +34,130 @@ import ( "kubesphere.io/kubesphere/pkg/apiserver/query" fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" "kubesphere.io/kubesphere/pkg/informers" + "reflect" "testing" ) func TestTenantOperator_ListWorkspaces(t *testing.T) { tenantOperator := prepare() tests := []struct { - name string result *api.ListResult username string expectError error }{ { - name: "list workspace", - username: "admin", + username: admin.Name, result: &api.ListResult{ - Items: workspaces, - TotalItems: len(workspaces), + Items: workspaceTemplates, + TotalItems: len(workspaceTemplates), }, }, { - name: "list workspaces", - username: "regular", + username: tester2.Name, result: &api.ListResult{ - Items: []interface{}{workspaceBar}, + Items: []interface{}{systemWorkspaceTmpl}, TotalItems: 1, }, }, } - for _, test := range tests { + for i, test := range tests { result, err := tenantOperator.ListWorkspaces(&user.DefaultInfo{Name: test.username}, query.New()) if err != nil { - if test.expectError != err { - t.Error(err) + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("got %#v, expected %#v", err, test.expectError) + } + continue + } + + if diff := cmp.Diff(result, test.result); diff != "" { + t.Errorf("case %d,%s", i, diff) + } + } +} + +func TestTenantOperator_ListNamespaces(t *testing.T) { + tenantOperator := prepare() + tests := []struct { + result *api.ListResult + username string + workspace string + expectError error + }{ + { + workspace: systemWorkspace.Name, + username: admin.Name, + result: &api.ListResult{ + Items: []interface{}{kubesphereSystem, defaultNamespace}, + TotalItems: 2, + }, + }, + { + workspace: systemWorkspace.Name, + username: tester1.Name, + result: &api.ListResult{ + Items: []interface{}{}, + TotalItems: 0, + }, + }, + { + workspace: testWorkspace.Name, + username: tester2.Name, + result: &api.ListResult{ + Items: []interface{}{testNamespace}, + TotalItems: 1, + }, + }, + } + + for i, test := range tests { + result, err := tenantOperator.ListNamespaces(&user.DefaultInfo{Name: test.username}, test.workspace, query.New()) + + if err != nil { + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("got %#v, expected %#v", err, test.expectError) + } + continue + } + + if diff := cmp.Diff(result, test.result); diff != "" { + t.Errorf("case %d, %s", i, diff) + } + } +} + +func TestTenantOperator_DescribeNamespace(t *testing.T) { + tenantOperator := prepare() + tests := []struct { + result *corev1.Namespace + username string + workspace string + namespace string + expectError error + }{ + { + result: testNamespace, + username: tester2.Name, + workspace: testWorkspace.Name, + namespace: testNamespace.Name, + expectError: nil, + }, + { + result: testNamespace, + username: tester2.Name, + workspace: systemWorkspace.Name, + namespace: testNamespace.Name, + expectError: errors.NewNotFound(corev1.Resource("namespace"), testNamespace.Name), + }, + } + + for _, test := range tests { + result, err := tenantOperator.DescribeNamespace(test.workspace, test.namespace) + + if err != nil { + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("got %#v, expected %#v", err, test.expectError) } continue } @@ -77,50 +168,157 @@ func TestTenantOperator_ListWorkspaces(t *testing.T) { } } -func TestTenantOperator_ListNamespaces(t *testing.T) { +func TestTenantOperator_CreateNamespace(t *testing.T) { tenantOperator := prepare() tests := []struct { - name string - result *api.ListResult - username string + result *corev1.Namespace workspace string + namespace *corev1.Namespace expectError error }{ { - name: "list namespaces", - workspace: "foo", - username: "admin", - result: &api.ListResult{ - Items: []interface{}{foo2, foo1}, - TotalItems: 2, + result: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: testWorkspace.Name}, + }, }, - }, - { - name: "list namespaces", - workspace: "foo", - username: "regular", - result: &api.ListResult{ - Items: []interface{}{}, - TotalItems: 0, - }, - }, - { - name: "list namespaces", - workspace: "bar", - username: "regular", - result: &api.ListResult{ - Items: []interface{}{bar1}, - TotalItems: 1, + workspace: testWorkspace.Name, + namespace: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, }, + expectError: nil, }, } - for _, test := range tests { - result, err := tenantOperator.ListNamespaces(&user.DefaultInfo{Name: test.username}, test.workspace, query.New()) + for i, test := range tests { + result, err := tenantOperator.CreateNamespace(test.workspace, test.namespace) if err != nil { - if test.expectError != err { - t.Error(err) + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError) + } + continue + } + + if diff := cmp.Diff(result, test.result); diff != "" { + t.Error(diff) + } + } +} + +func TestTenantOperator_DeleteNamespace(t *testing.T) { + tenantOperator := prepare() + tests := []struct { + workspace string + namespace string + expectError error + }{ + { + workspace: testWorkspace.Name, + namespace: kubesphereSystem.Name, + expectError: errors.NewNotFound(corev1.Resource("namespace"), kubesphereSystem.Name), + }, + { + workspace: testWorkspace.Name, + namespace: testNamespace.Name, + expectError: nil, + }, + } + + for i, test := range tests { + err := tenantOperator.DeleteNamespace(test.workspace, test.namespace) + if err != nil { + if test.expectError != nil && test.expectError.Error() == err.Error() { + continue + } else { + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError) + } + } + } + } +} + +func TestTenantOperator_UpdateNamespace(t *testing.T) { + tenantOperator := prepare() + tests := []struct { + result *corev1.Namespace + workspace string + namespace *corev1.Namespace + expectError error + }{ + { + result: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-namespace", + Annotations: map[string]string{"test": "test"}, + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: testWorkspace.Name}, + }, + }, + workspace: testWorkspace.Name, + namespace: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-namespace", + Annotations: map[string]string{"test": "test"}, + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: testWorkspace.Name}, + }, + }, + expectError: nil, + }, + } + + for i, test := range tests { + result, err := tenantOperator.UpdateNamespace(test.workspace, test.namespace) + + if err != nil { + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError) + } + continue + } + + if diff := cmp.Diff(result, test.result); diff != "" { + t.Error(diff) + } + } +} + +func TestTenantOperator_PatchNamespace(t *testing.T) { + tenantOperator := prepare() + tests := []struct { + result *corev1.Namespace + workspace string + patch *corev1.Namespace + expectError error + }{ + { + result: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-namespace", + Annotations: map[string]string{"test": "test2"}, + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: testWorkspace.Name}, + }, + }, + workspace: testWorkspace.Name, + patch: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-namespace", + Annotations: map[string]string{"test": "test2"}, + }, + }, + expectError: nil, + }, + } + + for i, test := range tests { + result, err := tenantOperator.PatchNamespace(test.workspace, test.patch) + + if err != nil { + if !reflect.DeepEqual(err, test.expectError) { + t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError) } continue } @@ -132,28 +330,56 @@ func TestTenantOperator_ListNamespaces(t *testing.T) { } var ( - foo1 = &corev1.Namespace{ + admin = user.DefaultInfo{ + Name: "admin", + } + tester1 = user.DefaultInfo{ + Name: "tester1", + } + tester2 = user.DefaultInfo{ + Name: "tester2", + } + systemWorkspaceTmpl = &tenantv1alpha2.WorkspaceTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo1", - Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: "foo"}, + Name: "system-workspace", }, } - - foo2 = &corev1.Namespace{ + testWorkspaceTmpl = &tenantv1alpha2.WorkspaceTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo2", - Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: "foo"}, + Name: "test-workspace", }, } - bar1 = &corev1.Namespace{ + systemWorkspace = &tenantv1alpha1.Workspace{ ObjectMeta: metav1.ObjectMeta{ - Name: "bar1", - Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: "bar"}, + Name: "system-workspace", }, } - adminGlobalRole = &iamv1alpha2.GlobalRole{ + testWorkspace = &tenantv1alpha1.Workspace{ ObjectMeta: metav1.ObjectMeta{ - Name: "global-admin", + Name: "test-workspace", + }, + } + kubesphereSystem = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubesphere-system", + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: systemWorkspace.Name}, + }, + } + defaultNamespace = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: systemWorkspace.Name}, + }, + } + testNamespace = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-namespace", + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: testWorkspace.Name}, + }, + } + platformAdmin = &iamv1alpha2.GlobalRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: "platform-admin", }, Rules: []rbacv1.PolicyRule{ { @@ -163,79 +389,67 @@ var ( }, }, } - regularGlobalRole = &iamv1alpha2.GlobalRole{ + platformRegular = &iamv1alpha2.GlobalRole{ ObjectMeta: metav1.ObjectMeta{ - Name: "regular", - }, - Rules: []rbacv1.PolicyRule{ - { - Verbs: []string{}, - APIGroups: []string{}, - Resources: []string{}, - }, + Name: "platform-regular", }, + Rules: []rbacv1.PolicyRule{}, } - reguarWorksapceRole = &iamv1alpha2.WorkspaceRole{ + systemWorkspaceRegular = &iamv1alpha2.WorkspaceRole{ ObjectMeta: metav1.ObjectMeta{ - Name: "workspace-regular", - Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: "bar"}, - }, - Rules: []rbacv1.PolicyRule{ - { - Verbs: []string{}, - APIGroups: []string{}, - Resources: []string{}, - }, + Name: "system-workspace-regular", + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: systemWorkspace.Name}, }, + Rules: []rbacv1.PolicyRule{}, } adminGlobalRoleBinding = &iamv1alpha2.GlobalRoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: "global-admin", + Name: admin.Name + "-" + platformAdmin.Name, }, Subjects: []rbacv1.Subject{{ Kind: "User", - Name: "admin", + Name: admin.Name, }}, RoleRef: rbacv1.RoleRef{ APIGroup: iamv1alpha2.SchemeGroupVersion.String(), Kind: iamv1alpha2.ResourceKindGlobalRole, - Name: "global-admin", + Name: platformAdmin.Name, }, } regularGlobalRoleBinding = &iamv1alpha2.GlobalRoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: "regular", + Name: tester1.Name + "-" + platformRegular.Name, }, Subjects: []rbacv1.Subject{{ Kind: "User", - Name: "regular", + Name: tester1.Name, }}, RoleRef: rbacv1.RoleRef{ APIGroup: iamv1alpha2.SchemeGroupVersion.String(), Kind: iamv1alpha2.ResourceKindGlobalRole, - Name: "regular", + Name: platformRegular.Name, }, } - regularWorkspaceRoleBinding = &iamv1alpha2.WorkspaceRoleBinding{ + systemWorkspaceRegularRoleBinding = &iamv1alpha2.WorkspaceRoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: "workspace-regular", - Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: "bar"}, + Name: tester2.Name + "-" + systemWorkspaceRegular.Name, + Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: systemWorkspace.Name}, }, Subjects: []rbacv1.Subject{{ Kind: "User", - Name: "regular", + Name: tester2.Name, }}, RoleRef: rbacv1.RoleRef{ APIGroup: iamv1alpha2.SchemeGroupVersion.String(), Kind: iamv1alpha2.ResourceKindGlobalRole, - Name: "workspace-regular", + Name: systemWorkspaceRegular.Name, }, } - bar1NamespaceRole = &rbacv1.Role{ + testNamespaceAdmin = &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: "admin", - Namespace: "bar1", + Namespace: testNamespace.Name, }, Rules: []rbacv1.PolicyRule{ { @@ -245,52 +459,48 @@ var ( }, }, } - bar1NamespaceRoleBinding = &rbacv1.RoleBinding{ + testNamespaceAdminRoleBinding = &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "admin", - Namespace: "bar1", + Namespace: testNamespace.Name, }, Subjects: []rbacv1.Subject{{ Kind: "User", - Name: "regular", + Name: tester2.Name, }}, RoleRef: rbacv1.RoleRef{ APIGroup: rbacv1.SchemeGroupVersion.String(), Kind: "Role", - Name: "admin", - }, - } - workspaceFoo = &tenantv1alpha2.WorkspaceTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - } - workspaceBar = &tenantv1alpha2.WorkspaceTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Name: "bar", + Name: testNamespaceAdmin.Name, }, } - workspaces = []interface{}{workspaceFoo, workspaceBar} - namespaces = []interface{}{foo1, foo2, bar1} - globalRoles = []interface{}{adminGlobalRole, regularGlobalRole} + workspaces = []interface{}{systemWorkspace, testWorkspace} + workspaceTemplates = []interface{}{testWorkspaceTmpl, systemWorkspaceTmpl} + namespaces = []interface{}{kubesphereSystem, defaultNamespace, testNamespace} + globalRoles = []interface{}{platformAdmin, platformRegular} globalRoleBindings = []interface{}{adminGlobalRoleBinding, regularGlobalRoleBinding} - workspaceRoles = []interface{}{regularGlobalRole} - workspaceRoleBindings = []interface{}{regularWorkspaceRoleBinding} - namespaceRoles = []interface{}{bar1NamespaceRole} - namespaceRoleBindings = []interface{}{bar1NamespaceRoleBinding} + workspaceRoles = []interface{}{systemWorkspaceRegular} + workspaceRoleBindings = []interface{}{systemWorkspaceRegularRoleBinding} + namespaceRoles = []interface{}{testNamespaceAdmin} + namespaceRoleBindings = []interface{}{testNamespaceAdminRoleBinding} ) func prepare() Interface { - ksClient := fakeks.NewSimpleClientset() - k8sClient := fakek8s.NewSimpleClientset() + ksClient := fakeks.NewSimpleClientset([]runtime.Object{testWorkspace, systemWorkspace}...) + k8sClient := fakek8s.NewSimpleClientset([]runtime.Object{testNamespace, kubesphereSystem}...) istioClient := fakeistio.NewSimpleClientset() appClient := fakeapp.NewSimpleClientset() fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient, nil, nil) for _, workspace := range workspaces { + fakeInformerFactory.KubeSphereSharedInformerFactory().Tenant().V1alpha1(). + Workspaces().Informer().GetIndexer().Add(workspace) + } + + for _, workspaceTmpl := range workspaceTemplates { fakeInformerFactory.KubeSphereSharedInformerFactory().Tenant().V1alpha2(). - WorkspaceTemplates().Informer().GetIndexer().Add(workspace) + WorkspaceTemplates().Informer().GetIndexer().Add(workspaceTmpl) } for _, namespace := range namespaces { @@ -328,5 +538,5 @@ func prepare() Interface { RoleBindings().Informer().GetIndexer().Add(roleBinding) } - return New(fakeInformerFactory, nil, nil, nil, nil, nil) + return New(fakeInformerFactory, k8sClient, ksClient, nil, nil, nil) }