未验证 提交 3a79df0d 编写于 作者: K KubeSphere CI Bot 提交者: GitHub

Merge pull request #3467 from RolandMa1986/feat-e2e-restclient

Refine group e2e test
...@@ -74,7 +74,7 @@ require ( ...@@ -74,7 +74,7 @@ require (
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/xanzy/ssh-agent v0.2.1 // indirect github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
golang.org/x/net v0.0.0-20200707034311-ab3426394381 golang.org/x/net v0.0.0-20201224014010-6772e930b67b
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
google.golang.org/grpc v1.30.0 google.golang.org/grpc v1.30.0
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
......
...@@ -275,6 +275,8 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg ...@@ -275,6 +275,8 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg
github.com/go-playground/universal-translator v0.0.0-20170327191703-71201497bace/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-playground/universal-translator v0.0.0-20170327191703-71201497bace/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4= github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-resty/resty/v2 v2.5.0 h1:WFb5bD49/85PO7WgAjZ+/TJQ+Ty1XOcWEfD1zIFCM1c=
github.com/go-resty/resty/v2 v2.5.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
......
...@@ -7,6 +7,7 @@ module kubesphere.io/client-go ...@@ -7,6 +7,7 @@ module kubesphere.io/client-go
go 1.13 go 1.13
require ( require (
github.com/go-resty/resty/v2 v2.5.0
k8s.io/apimachinery v0.18.6 k8s.io/apimachinery v0.18.6
k8s.io/client-go v0.18.6 k8s.io/client-go v0.18.6
sigs.k8s.io/controller-runtime v0.6.4 sigs.k8s.io/controller-runtime v0.6.4
......
...@@ -117,6 +117,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh ...@@ -117,6 +117,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-resty/resty/v2 v2.5.0 h1:WFb5bD49/85PO7WgAjZ+/TJQ+Ty1XOcWEfD1zIFCM1c=
github.com/go-resty/resty/v2 v2.5.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
...@@ -324,6 +326,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL ...@@ -324,6 +326,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
...@@ -355,6 +359,9 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w ...@@ -355,6 +359,9 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
......
/*
Copyright 2021 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package restclient
import (
rest "k8s.io/client-go/rest"
iamv1alpha2 "kubesphere.io/client-go/restclient/versioned/iam/v1alpha2"
)
// NewForConfig returns a new Client using the provided config and Options.
func NewForConfig(c *rest.Config) (*RestClient, error) {
var rc RestClient
var err error
rc.iamV1alpha2, err = iamv1alpha2.NewForConfig(c)
if err != nil {
return nil, err
}
return &rc, nil
}
// RestClient is a set of restful API clients that doesn't compatible with
// Kube API machinery.
type RestClient struct {
iamV1alpha2 *iamv1alpha2.IamV1alpha2Client
}
// IamV1alpha2 retrieves the IamV1alpha2Client
func (c *RestClient) IamV1alpha2() iamv1alpha2.IamV1alpha2Interface {
return c.iamV1alpha2
}
/*
Copyright 2021 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
import (
"context"
resty "github.com/go-resty/resty/v2"
)
type GroupsGetter interface {
Groups() GroupInterface
}
type GroupInterface interface {
CreateBinding(ctx context.Context, workspace, group, user string) (string, error)
}
type groups struct {
client *resty.Client
}
func newGroups(c *IamV1alpha2Client) *groups {
return &groups{
client: c.client,
}
}
//TODO: to be remoted once we move kubesphere.io/apis out of kubesphere package
type groupMember struct {
UserName string `json:"userName"`
GroupName string `json:"groupName"`
}
// Create takes the representation of a group and creates it. Returns the server's representation of the group, and an error, if there is any.
func (c *groups) CreateBinding(ctx context.Context, workspace, group, user string) (result string, err error) {
members := []groupMember{{
UserName: user,
GroupName: group,
}}
resp, err := c.client.R().
SetHeader("Content-Type", "application/json").
SetBody(members).
SetPathParams(map[string]string{
"workspace": workspace,
}).
Post("/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/groupbindings")
return resp.String(), err
}
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
import (
resty "github.com/go-resty/resty/v2"
rest "k8s.io/client-go/rest"
)
type IamV1alpha2Interface interface {
GroupsGetter
RoleBindingsGetter
}
type IamV1alpha2Client struct {
client *resty.Client
}
func (c *IamV1alpha2Client) Groups() GroupInterface {
return newGroups(c)
}
func (c *IamV1alpha2Client) RoleBindings() RoleBindingInterface {
return newRoleBindings(c)
}
// NewForConfig creates a new IamV1alpha2Client for the given config.
func NewForConfig(c *rest.Config) (*IamV1alpha2Client, error) {
client := resty.New()
client.SetHostURL(c.Host)
if c.BearerToken != "" {
client.SetAuthToken(c.BearerToken)
}
if c.Username != "" {
client.SetBasicAuth(c.Username, c.Password)
}
return &IamV1alpha2Client{client}, nil
}
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
import (
"context"
resty "github.com/go-resty/resty/v2"
)
type RoleBindingsGetter interface {
RoleBindings() RoleBindingInterface
}
type RoleBindingInterface interface {
CreateRoleBinding(ctx context.Context, namespace, role, group string) (string, error)
CreateWorkspaceRoleBinding(ctx context.Context, namespace, role, group string) (string, error)
}
type rolebindings struct {
client *resty.Client
}
func newRoleBindings(c *IamV1alpha2Client) *rolebindings {
return &rolebindings{
client: c.client,
}
}
// CreateRoleBinding assembling of a rolebinding object and creates it. Returns the server's response and an error, if there is any.
func (c *rolebindings) CreateRoleBinding(ctx context.Context, namespace, role, group string) (result string, err error) {
roles := []map[string]interface{}{{
"subjects": []map[string]interface{}{
{
"kind": "Group",
"apiGroup": "rbac.authorization.k8s.io",
"name": group,
},
},
"roleRef": map[string]interface{}{
"apiGroup": "rbac.authorization.k8s.io",
"kind": "Role",
"name": role,
},
}}
resp, err := c.client.R().
SetHeader("Content-Type", "application/json").
SetBody(roles).
SetPathParams(map[string]string{
"namespace": namespace,
}).
Post("/kapis/iam.kubesphere.io/v1alpha2/namespaces/{namespace}/rolebindings")
return resp.String(), err
}
// CreateWorkspaceRoleBinding assembling of a workspacerolebinding object and creates it. Returns the server's response, and an error, if there is any.
func (c *rolebindings) CreateWorkspaceRoleBinding(ctx context.Context, workspace, role, group string) (result string, err error) {
roles := []map[string]interface{}{{
"subjects": []map[string]interface{}{
{
"kind": "Group",
"apiGroup": "rbac.authorization.k8s.io",
"name": group,
},
},
"roleRef": map[string]interface{}{
"apiGroup": "iam.kubesphere.io/v1alpha2",
"kind": "WorkspaceRoleBinding",
"name": role,
},
}}
resp, err := c.client.R().
SetHeader("Content-Type", "application/json").
SetBody(roles).
SetPathParams(map[string]string{
"workspace": workspace,
}).
Post("/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/workspacerolebindings/")
return resp.String(), err
}
...@@ -14,8 +14,11 @@ See the License for the specific language governing permissions and ...@@ -14,8 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package e2e package constant
const ( const (
DefaultWorkspaceRoleAdmin = "%v-admin" DefaultWorkspaceRoleAdmin = "%v-admin"
DefaultAdminUser = "admin"
DefaultPassword = "P@88w0rd"
LocalAPIServer = "http://127.0.0.1:9090"
) )
...@@ -19,6 +19,7 @@ package framework ...@@ -19,6 +19,7 @@ package framework
import ( import (
"context" "context"
"fmt" "fmt"
"time"
"github.com/onsi/ginkgo" //nolint:stylecheck "github.com/onsi/ginkgo" //nolint:stylecheck
"github.com/onsi/gomega" "github.com/onsi/gomega"
...@@ -29,11 +30,21 @@ import ( ...@@ -29,11 +30,21 @@ import (
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"kubesphere.io/client-go/client" "kubesphere.io/client-go/client"
"kubesphere.io/client-go/client/generic" "kubesphere.io/client-go/client/generic"
"kubesphere.io/client-go/restclient"
"kubesphere.io/kubesphere/pkg/apis" "kubesphere.io/kubesphere/pkg/apis"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/test/e2e/framework/workspace" "kubesphere.io/kubesphere/test/e2e/framework/workspace"
) )
const (
// Using the same interval as integration should be fine given the
// minimal load that the apiserver is likely to be under.
PollInterval = 50 * time.Millisecond
// How long to try single API calls (like 'get' or 'list'). Used to prevent
// transient failures from failing tests.
DefaultSingleCallTimeout = 30 * time.Second
)
type Framework struct { type Framework struct {
BaseName string BaseName string
Workspace string Workspace string
...@@ -45,6 +56,7 @@ type Framework struct { ...@@ -45,6 +56,7 @@ type Framework struct {
// that the implementation can vary without affecting tests. // that the implementation can vary without affecting tests.
type KubeSphereFramework interface { type KubeSphereFramework interface {
GenericClient(userAgent string) client.Client GenericClient(userAgent string) client.Client
RestClient(userAgent string) *restclient.RestClient
KubeSphereSystemNamespace() string KubeSphereSystemNamespace() string
// Name of the workspace for the current test to target // Name of the workspace for the current test to target
...@@ -54,6 +66,8 @@ type KubeSphereFramework interface { ...@@ -54,6 +66,8 @@ type KubeSphereFramework interface {
CreateNamespace(name string) string CreateNamespace(name string) string
// Get Names of the namespaces for the current test to target // Get Names of the namespaces for the current test to target
GetNamespaceNames() []string GetNamespaceNames() []string
GetScheme() *runtime.Scheme
} }
func NewKubeSphereFramework(baseName string) KubeSphereFramework { func NewKubeSphereFramework(baseName string) KubeSphereFramework {
...@@ -65,6 +79,7 @@ func NewKubeSphereFramework(baseName string) KubeSphereFramework { ...@@ -65,6 +79,7 @@ func NewKubeSphereFramework(baseName string) KubeSphereFramework {
if err := scheme.AddToScheme(sch); err != nil { if err := scheme.AddToScheme(sch); err != nil {
Failf("unable add Kubernetes APIs to scheme: %v", err) Failf("unable add Kubernetes APIs to scheme: %v", err)
} }
f := &Framework{ f := &Framework{
BaseName: baseName, BaseName: baseName,
Scheme: sch, Scheme: sch,
...@@ -97,7 +112,7 @@ func CreateTestWorkSpace(client client.Client, baseName string) string { ...@@ -97,7 +112,7 @@ func CreateTestWorkSpace(client client.Client, baseName string) string {
wspt.GenerateName = fmt.Sprintf("e2e-tests-%v-", baseName) wspt.GenerateName = fmt.Sprintf("e2e-tests-%v-", baseName)
wspt, err := workspace.CreateWorkspace(client, wspt) wspt, err := workspace.CreateWorkspace(client, wspt)
gomega.Expect(err).NotTo(gomega.HaveOccurred()) gomega.Expect(err).NotTo(gomega.HaveOccurred())
ginkgo.By(fmt.Sprintf("Created test namespace %s", wspt.Name)) ginkgo.By(fmt.Sprintf("Created test workspace %s", wspt.Name))
return wspt.Name return wspt.Name
} }
...@@ -106,6 +121,7 @@ func (f *Framework) GetNamespaceNames() []string { ...@@ -106,6 +121,7 @@ func (f *Framework) GetNamespaceNames() []string {
} }
func (f *Framework) CreateNamespace(name string) string { func (f *Framework) CreateNamespace(name string) string {
name = fmt.Sprintf("%s-%s", f.Workspace, name)
ns := &corev1.Namespace{ ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
...@@ -133,19 +149,32 @@ func (f *Framework) KubeSphereSystemNamespace() string { ...@@ -133,19 +149,32 @@ func (f *Framework) KubeSphereSystemNamespace() string {
func (f *Framework) GenericClient(userAgent string) client.Client { func (f *Framework) GenericClient(userAgent string) client.Client {
ctx := TestContext ctx := TestContext
config := &rest.Config{ config := &rest.Config{
Host: "127.0.0.1:9090", Host: ctx.Host,
Username: "admin", Username: ctx.Username,
Password: "P@88w0rd", Password: ctx.Password,
}
if ctx.Host != "" {
config = &rest.Config{
Host: ctx.Host,
Username: ctx.Username,
Password: ctx.Password,
}
} }
rest.AddUserAgent(config, userAgent) rest.AddUserAgent(config, userAgent)
return generic.NewForConfigOrDie(config, client.Options{Scheme: f.Scheme}) return generic.NewForConfigOrDie(config, client.Options{Scheme: f.Scheme})
} }
func (f *Framework) RestClient(userAgent string) *restclient.RestClient {
ctx := TestContext
config := &rest.Config{
Host: ctx.Host,
Username: ctx.Username,
Password: ctx.Password,
}
c, err := restclient.NewForConfig(config)
if err != nil {
panic(err)
}
return c
}
func (f *Framework) GetScheme() *runtime.Scheme {
return f.Scheme
}
...@@ -41,7 +41,7 @@ func NewUser(name, globelRole string) *iamv1alpha2.User { ...@@ -41,7 +41,7 @@ func NewUser(name, globelRole string) *iamv1alpha2.User {
}, },
}, },
Spec: iamv1alpha2.UserSpec{ Spec: iamv1alpha2.UserSpec{
Email: fmt.Sprint("%v@kubesphere.io", name), Email: fmt.Sprintf("%s@kubesphere.io", name),
EncryptedPassword: "P@88w0rd", EncryptedPassword: "P@88w0rd",
}, },
} }
......
/*
Copyright 2021 KubeSphere Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package iam
import (
"context"
"fmt"
"golang.org/x/oauth2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
"kubesphere.io/client-go/client"
"kubesphere.io/client-go/client/generic"
"kubesphere.io/client-go/restclient"
"kubesphere.io/kubesphere/test/e2e/framework"
)
//NewClient creates a new client with user authencation
func NewClient(s *runtime.Scheme, user, passsword string) (client.Client, error) {
ctx := framework.TestContext
token, err := getToken(ctx.Host, user, passsword)
if err != nil {
return nil, err
}
config := &rest.Config{
Host: ctx.Host,
BearerToken: token.AccessToken,
}
return generic.New(config, client.Options{Scheme: s})
}
func NewRestClient(user, passsword string) (*restclient.RestClient, error) {
ctx := framework.TestContext
token, err := getToken(ctx.Host, user, passsword)
if err != nil {
return nil, err
}
config := &rest.Config{
Host: ctx.Host,
BearerToken: token.AccessToken,
}
return restclient.NewForConfig(config)
}
func getToken(host, user, password string) (*oauth2.Token, error) {
config := &oauth2.Config{
Endpoint: oauth2.Endpoint{
TokenURL: fmt.Sprintf("%s/oauth/token", host),
AuthStyle: oauth2.AuthStyleInParams,
},
}
return config.PasswordCredentialsToken(context.TODO(), user, password)
}
/*
Copyright 2021 KubeSphere Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"context"
v1 "k8s.io/api/core/v1"
"kubesphere.io/client-go/client"
)
// ListPods gets the Pods by namespace. If the returned error is nil, the returned PodList is valid.
func ListPods(c client.Client, namespace string) (*v1.PodList, error) {
pods := &v1.PodList{}
err := c.List(context.TODO(), pods, &client.ListOptions{Namespace: namespace})
if err != nil {
return nil, err
}
return pods, nil
}
...@@ -19,6 +19,8 @@ package framework ...@@ -19,6 +19,8 @@ package framework
import ( import (
"flag" "flag"
"os" "os"
"kubesphere.io/kubesphere/test/e2e/constant"
) )
type TestContextType struct { type TestContextType struct {
...@@ -41,7 +43,22 @@ func registerFlags(t *TestContextType) { ...@@ -41,7 +43,22 @@ func registerFlags(t *TestContextType) {
var TestContext *TestContextType = &TestContextType{} var TestContext *TestContextType = &TestContextType{}
func setDefaultValue(t *TestContextType) {
if t.Host == "" {
t.Host = constant.LocalAPIServer
}
if t.Username == "" {
t.Username = constant.DefaultAdminUser
}
if t.Password == "" {
t.Password = constant.DefaultPassword
}
}
func ParseFlags() { func ParseFlags() {
registerFlags(TestContext) registerFlags(TestContext)
flag.Parse() flag.Parse()
setDefaultValue(TestContext)
} }
...@@ -17,34 +17,115 @@ limitations under the License. ...@@ -17,34 +17,115 @@ limitations under the License.
package e2e package e2e
import ( import (
"context"
"fmt"
. "github.com/onsi/ginkgo" //nolint:stylecheck . "github.com/onsi/ginkgo" //nolint:stylecheck
. "github.com/onsi/gomega" //nolint:stylecheck . "github.com/onsi/gomega" //nolint:stylecheck
"k8s.io/apimachinery/pkg/util/wait"
"kubesphere.io/client-go/client" "kubesphere.io/client-go/client"
"kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
"kubesphere.io/kubesphere/test/e2e/constant"
"kubesphere.io/kubesphere/test/e2e/framework" "kubesphere.io/kubesphere/test/e2e/framework"
"kubesphere.io/kubesphere/test/e2e/framework/iam" "kubesphere.io/kubesphere/test/e2e/framework/iam"
"kubesphere.io/kubesphere/test/e2e/framework/resource"
apierrors "k8s.io/apimachinery/pkg/api/errors"
) )
var _ = Describe("Worksspace", func() { const (
GroupName = "test-group"
UserName = "tester"
)
var _ = Describe("Groups", func() {
f := framework.NewKubeSphereFramework("group") f := framework.NewKubeSphereFramework("group")
var wsName = "" var workspace = ""
var gclient client.Client var namespace = ""
var group = ""
var userClient client.Client
adminClient := f.GenericClient("group")
restClient := f.RestClient("group")
Context("Grant Permissions by assign user to group", func() {
It("Should create group and assign members successfully", func() {
By("Expecting to create test workspace for Group tests")
workspace = f.TestWorkSpaceName()
namespace = f.CreateNamespace("group")
g, err := iam.CreateGroup(adminClient, iam.NewGroup(GroupName, workspace), workspace)
framework.ExpectNoError(err)
group = g.Name
Eventually(func() bool {
expGroup, err := iam.GetGroup(adminClient, group, workspace)
return err == nil && expGroup.Name == group
}, timeout, interval).Should(BeTrue())
By("Create user and wait until active")
u, err := createUserWithWait(f, adminClient, UserName)
framework.ExpectNoError(err)
By("Assign user to Group")
_, err = restClient.IamV1alpha2().Groups().CreateBinding(context.TODO(), workspace, group, UserName)
framework.ExpectNoError(err)
By("Creating a new client with user authentication")
userClient, err = iam.NewClient(f.GetScheme(), u.Name, constant.DefaultPassword)
framework.ExpectNoError(err)
})
It(fmt.Sprintf("%s has no permissions to access namespace: %s", UserName, namespace), func() {
err := CheckNamespaceAccess(f, userClient, namespace)
Expect(apierrors.IsForbidden(err)).To(BeTrue())
})
It(fmt.Sprintf("%s should has full access namespace: %s", UserName, namespace), func() {
rolename := fmt.Sprintf("%s-regular", workspace)
By("Grant namespace permission by bind admin role to group")
_, err := restClient.IamV1alpha2().RoleBindings().CreateRoleBinding(context.TODO(), namespace, "admin", group)
framework.ExpectNoError(err)
_, err = restClient.IamV1alpha2().RoleBindings().CreateWorkspaceRoleBinding(context.TODO(), workspace, rolename, group)
framework.ExpectNoError(err)
err = CheckNamespaceAccess(f, userClient, namespace)
framework.ExpectNoError(err)
})
BeforeEach(func() {
gclient = f.GenericClient("group")
}) })
})
It("Should create group successfully", func() { // Todo: The can-i API should be a better option, but ks-apiserver doesn't support it yet.
// So we will try to list objects in the namespace.
func CheckNamespaceAccess(f framework.KubeSphereFramework, c client.Client, namespace string) error {
_, err := resource.ListPods(c, namespace)
return err
}
By("Expecting to create workspace thronght workspace template") // Create a user and wait until the user became active status.
wsName = f.TestWorkSpaceName() func createUserWithWait(f framework.KubeSphereFramework, c client.Client, username string) (*v1alpha2.User, error) {
u := iam.NewUser(username, "platform-regular")
if _, err := iam.CreateUser(c, u); err != nil {
return nil, err
}
group, err := iam.CreateGroup(gclient, iam.NewGroup("group1", wsName), wsName) err := wait.PollImmediate(framework.PollInterval, framework.DefaultSingleCallTimeout, func() (bool, error) {
framework.ExpectNoError(err) u, err := iam.GetUser(c, username)
Eventually(func() bool { if err != nil {
expGroup, err := iam.GetGroup(gclient, group.Name, wsName) framework.Failf("Cannot retrieve User %q: %v", username, err)
return err == nil && expGroup.Name == group.Name return false, err
}, timeout, interval).Should(BeTrue()) }
if u == nil || u.Status.State == nil {
return false, nil
}
return *u.Status.State == v1alpha2.UserActive, nil
}) })
}) if err != nil {
return nil, err
}
return u, nil
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册