Merge pull request #3467 from RolandMa1986/feat-e2e-restclient
Refine group e2e test
This commit is contained in:
2
go.mod
2
go.mod
@@ -74,7 +74,7 @@ require (
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||
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
|
||||
google.golang.org/grpc v1.30.0
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -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-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-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/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
|
||||
@@ -7,6 +7,7 @@ module kubesphere.io/client-go
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/go-resty/resty/v2 v2.5.0
|
||||
k8s.io/apimachinery v0.18.6
|
||||
k8s.io/client-go v0.18.6
|
||||
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
|
||||
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.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/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
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
|
||||
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/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
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
|
||||
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/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.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
44
staging/src/kubesphere.io/client-go/restclient/restclient.go
Normal file
44
staging/src/kubesphere.io/client-go/restclient/restclient.go
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
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
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2e
|
||||
package constant
|
||||
|
||||
const (
|
||||
DefaultWorkspaceRoleAdmin = "%v-admin"
|
||||
DefaultAdminUser = "admin"
|
||||
DefaultPassword = "P@88w0rd"
|
||||
LocalAPIServer = "http://127.0.0.1:9090"
|
||||
)
|
||||
@@ -19,6 +19,7 @@ package framework
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo" //nolint:stylecheck
|
||||
"github.com/onsi/gomega"
|
||||
@@ -29,11 +30,21 @@ import (
|
||||
"k8s.io/client-go/rest"
|
||||
"kubesphere.io/client-go/client"
|
||||
"kubesphere.io/client-go/client/generic"
|
||||
"kubesphere.io/client-go/restclient"
|
||||
"kubesphere.io/kubesphere/pkg/apis"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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 {
|
||||
BaseName string
|
||||
Workspace string
|
||||
@@ -45,6 +56,7 @@ type Framework struct {
|
||||
// that the implementation can vary without affecting tests.
|
||||
type KubeSphereFramework interface {
|
||||
GenericClient(userAgent string) client.Client
|
||||
RestClient(userAgent string) *restclient.RestClient
|
||||
KubeSphereSystemNamespace() string
|
||||
|
||||
// Name of the workspace for the current test to target
|
||||
@@ -54,6 +66,8 @@ type KubeSphereFramework interface {
|
||||
CreateNamespace(name string) string
|
||||
// Get Names of the namespaces for the current test to target
|
||||
GetNamespaceNames() []string
|
||||
|
||||
GetScheme() *runtime.Scheme
|
||||
}
|
||||
|
||||
func NewKubeSphereFramework(baseName string) KubeSphereFramework {
|
||||
@@ -65,6 +79,7 @@ func NewKubeSphereFramework(baseName string) KubeSphereFramework {
|
||||
if err := scheme.AddToScheme(sch); err != nil {
|
||||
Failf("unable add Kubernetes APIs to scheme: %v", err)
|
||||
}
|
||||
|
||||
f := &Framework{
|
||||
BaseName: baseName,
|
||||
Scheme: sch,
|
||||
@@ -97,7 +112,7 @@ func CreateTestWorkSpace(client client.Client, baseName string) string {
|
||||
wspt.GenerateName = fmt.Sprintf("e2e-tests-%v-", baseName)
|
||||
wspt, err := workspace.CreateWorkspace(client, wspt)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -106,6 +121,7 @@ func (f *Framework) GetNamespaceNames() []string {
|
||||
}
|
||||
|
||||
func (f *Framework) CreateNamespace(name string) string {
|
||||
name = fmt.Sprintf("%s-%s", f.Workspace, name)
|
||||
ns := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
@@ -133,19 +149,32 @@ func (f *Framework) KubeSphereSystemNamespace() string {
|
||||
func (f *Framework) GenericClient(userAgent string) client.Client {
|
||||
|
||||
ctx := TestContext
|
||||
|
||||
config := &rest.Config{
|
||||
Host: "127.0.0.1:9090",
|
||||
Username: "admin",
|
||||
Password: "P@88w0rd",
|
||||
}
|
||||
if ctx.Host != "" {
|
||||
config = &rest.Config{
|
||||
Host: ctx.Host,
|
||||
Username: ctx.Username,
|
||||
Password: ctx.Password,
|
||||
}
|
||||
Host: ctx.Host,
|
||||
Username: ctx.Username,
|
||||
Password: ctx.Password,
|
||||
}
|
||||
|
||||
rest.AddUserAgent(config, userAgent)
|
||||
|
||||
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 {
|
||||
},
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{
|
||||
Email: fmt.Sprint("%v@kubesphere.io", name),
|
||||
Email: fmt.Sprintf("%s@kubesphere.io", name),
|
||||
EncryptedPassword: "P@88w0rd",
|
||||
},
|
||||
}
|
||||
|
||||
70
test/e2e/framework/iam/utils.go
Normal file
70
test/e2e/framework/iam/utils.go
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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)
|
||||
}
|
||||
35
test/e2e/framework/resource/fixtures.go
Normal file
35
test/e2e/framework/resource/fixtures.go
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"kubesphere.io/kubesphere/test/e2e/constant"
|
||||
)
|
||||
|
||||
type TestContextType struct {
|
||||
@@ -41,7 +43,22 @@ func registerFlags(t *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() {
|
||||
registerFlags(TestContext)
|
||||
flag.Parse()
|
||||
setDefaultValue(TestContext)
|
||||
}
|
||||
|
||||
@@ -17,34 +17,115 @@ limitations under the License.
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
. "github.com/onsi/ginkgo" //nolint:stylecheck
|
||||
. "github.com/onsi/gomega" //nolint:stylecheck
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"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/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")
|
||||
|
||||
var wsName = ""
|
||||
var gclient client.Client
|
||||
var workspace = ""
|
||||
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() {
|
||||
|
||||
By("Expecting to create workspace thronght workspace template")
|
||||
wsName = f.TestWorkSpaceName()
|
||||
|
||||
group, err := iam.CreateGroup(gclient, iam.NewGroup("group1", wsName), wsName)
|
||||
framework.ExpectNoError(err)
|
||||
Eventually(func() bool {
|
||||
expGroup, err := iam.GetGroup(gclient, group.Name, wsName)
|
||||
return err == nil && expGroup.Name == group.Name
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Create a user and wait until the user became active status.
|
||||
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
|
||||
}
|
||||
|
||||
err := wait.PollImmediate(framework.PollInterval, framework.DefaultSingleCallTimeout, func() (bool, error) {
|
||||
u, err := iam.GetUser(c, username)
|
||||
if err != nil {
|
||||
framework.Failf("Cannot retrieve User %q: %v", username, err)
|
||||
return false, err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user