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

Merge pull request #2011 from wansir/dev

migrate legacy API
apiVersion: admissionregistration.k8s.io/v1beta1 apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration kind: ValidatingWebhookConfiguration
metadata: metadata:
name: kubesphere-iam-validator name: kubesphere-iam-validator
webhooks: webhooks:
......
...@@ -152,7 +152,6 @@ const ( ...@@ -152,7 +152,6 @@ const (
ClusterScope Scope = "Cluster" ClusterScope Scope = "Cluster"
WorkspaceScope Scope = "Workspace" WorkspaceScope Scope = "Workspace"
NamespaceScope Scope = "Namespace" NamespaceScope Scope = "Namespace"
TargetAll = "*"
UserKind = "User" UserKind = "User"
PolicyRuleKind = "PolicyRule" PolicyRuleKind = "PolicyRule"
RoleKind = "Role" RoleKind = "Role"
......
...@@ -37,6 +37,7 @@ import ( ...@@ -37,6 +37,7 @@ import (
resourcesv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2" resourcesv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3" resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2" terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/iam/am" "kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im" "kubesphere.io/kubesphere/pkg/models/iam/im"
...@@ -141,6 +142,7 @@ func (s *APIServer) installKubeSphereAPIs() { ...@@ -141,6 +142,7 @@ func (s *APIServer) installKubeSphereAPIs() {
urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient)) urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes())) urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory)) urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory))
urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.InformerFactory))
urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config())) urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
urlruntime.Must(iamv1alpha2.AddToContainer(s.container, im.NewOperator(s.KubernetesClient.KubeSphere(), urlruntime.Must(iamv1alpha2.AddToContainer(s.container, im.NewOperator(s.KubernetesClient.KubeSphere(),
s.InformerFactory.KubeSphereSharedInformerFactory()), s.InformerFactory.KubeSphereSharedInformerFactory()),
...@@ -285,7 +287,6 @@ func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error { ...@@ -285,7 +287,6 @@ func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "roles"}, {Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "roles"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "rolebindings"}, {Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "rolebindings"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "policyrules"}, {Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "policyrules"},
{Group: "tower.kubesphere.io", Version: "v1alpha1", Resource: "agents"},
} }
devopsGVRs := []schema.GroupVersionResource{ devopsGVRs := []schema.GroupVersionResource{
......
...@@ -51,7 +51,7 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author ...@@ -51,7 +51,7 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
return authorizer.DecisionDeny, "", err return authorizer.DecisionDeny, "", err
} }
// check platform role policy rules // check global role policy rules
if authorized, reason, err = o.makeDecision(globalRole, attr); authorized == authorizer.DecisionAllow { if authorized, reason, err = o.makeDecision(globalRole, attr); authorized == authorizer.DecisionAllow {
return authorized, reason, nil return authorized, reason, nil
} }
......
...@@ -48,11 +48,12 @@ func newPagination(limit int, offset int) *Pagination { ...@@ -48,11 +48,12 @@ func newPagination(limit int, offset int) *Pagination {
} }
func (p *Pagination) GetValidPagination(total int) (startIndex, endIndex int) { func (p *Pagination) GetValidPagination(total int) (startIndex, endIndex int) {
if p.Limit == NoPagination.Limit { if p.Limit == NoPagination.Limit {
return 0, total return 0, total
} }
if p.Limit < 0 || p.Offset < 0 { if p.Limit < 0 || p.Offset < 0 || total == 0 {
return 0, 0 return 0, 0
} }
......
...@@ -36,7 +36,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response ...@@ -36,7 +36,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
limit, offset := params.ParsePaging(request) limit, offset := params.ParsePaging(request)
namespace := request.PathParameter("namespace") namespace := request.PathParameter("namespace")
orderBy := params.GetStringValueWithDefault(request, params.OrderByParam, openpitrix.CreateTime) orderBy := params.GetStringValueWithDefault(request, params.OrderByParam, openpitrix.CreateTime)
reverse := params.GetBoolValueWithDefault(request, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(request, params.ReverseParam, false)
conditions, err := params.ParseConditions(request) conditions, err := params.ParseConditions(request)
if err != nil { if err != nil {
...@@ -301,7 +301,7 @@ func (h *openpitrixHandler) GetAppVersionFiles(req *restful.Request, resp *restf ...@@ -301,7 +301,7 @@ func (h *openpitrixHandler) GetAppVersionFiles(req *restful.Request, resp *restf
func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
appId := req.PathParameter("app") appId := req.PathParameter("app")
versionId := req.PathParameter("version") versionId := req.PathParameter("version")
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
...@@ -331,7 +331,7 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res ...@@ -331,7 +331,7 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res
func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
if err != nil { if err != nil {
...@@ -354,7 +354,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp ...@@ -354,7 +354,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
appId := req.PathParameter("app") appId := req.PathParameter("app")
statistics := params.GetBoolValueWithDefault(req, "statistics", false) statistics := params.GetBoolValueWithDefault(req, "statistics", false)
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
...@@ -394,7 +394,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful. ...@@ -394,7 +394,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
statistics := params.GetBoolValueWithDefault(req, "statistics", false) statistics := params.GetBoolValueWithDefault(req, "statistics", false)
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
...@@ -697,7 +697,7 @@ func (h *openpitrixHandler) DescribeCategory(req *restful.Request, resp *restful ...@@ -697,7 +697,7 @@ func (h *openpitrixHandler) DescribeCategory(req *restful.Request, resp *restful
func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
statistics := params.GetBoolValueWithDefault(req, "statistics", false) statistics := params.GetBoolValueWithDefault(req, "statistics", false)
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
...@@ -836,7 +836,7 @@ func (h *openpitrixHandler) DescribeRepo(req *restful.Request, resp *restful.Res ...@@ -836,7 +836,7 @@ func (h *openpitrixHandler) DescribeRepo(req *restful.Request, resp *restful.Res
func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Response) { func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req) limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime) orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true) reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
conditions, err := params.ParseConditions(req) conditions, err := params.ParseConditions(req)
if err != nil { if err != nil {
......
...@@ -66,18 +66,20 @@ func (r *resourceHandler) handleListNamespaceResources(request *restful.Request, ...@@ -66,18 +66,20 @@ func (r *resourceHandler) handleListNamespaceResources(request *restful.Request,
conditions, err := params.ParseConditions(request) conditions, err := params.ParseConditions(request)
if err != nil { if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, err) klog.Error(err)
api.HandleBadRequest(response, request, err)
return return
} }
result, err := r.resourcesGetter.ListResources(namespace, resource, conditions, orderBy, reverse, limit, offset) result, err := r.resourcesGetter.ListResources(namespace, resource, conditions, orderBy, reverse, limit, offset)
if err != nil { if err != nil {
klog.Error(err)
api.HandleInternalError(response, nil, err) api.HandleInternalError(response, nil, err)
return return
} }
response.WriteAsJson(result) response.WriteEntity(result)
} }
func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, response *restful.Response) { func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, response *restful.Response) {
......
...@@ -2,34 +2,56 @@ package v1alpha3 ...@@ -2,34 +2,56 @@ package v1alpha3
import ( import (
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query" "kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/components" "kubesphere.io/kubesphere/pkg/models/components"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"net/http" resourcev1alpha2 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
"kubesphere.io/kubesphere/pkg/server/params"
"strings"
) )
type Handler struct { type Handler struct {
namespacedResourceGetter *resource.ResourceGetter resourceGetterV1alpha3 *resourcev1alpha3.ResourceGetter
componentsGetter components.ComponentsGetter resourcesGetterV1alpha2 *resourcev1alpha2.ResourceGetter
componentsGetter components.ComponentsGetter
} }
func New(factory informers.InformerFactory) *Handler { func New(factory informers.InformerFactory) *Handler {
return &Handler{ return &Handler{
namespacedResourceGetter: resource.New(factory), resourceGetterV1alpha3: resourcev1alpha3.NewResourceGetter(factory),
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()), resourcesGetterV1alpha2: resourcev1alpha2.NewResourceGetter(factory),
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
} }
} }
// handleListResources retrieves resources // handleListResources retrieves resources
func (h Handler) handleListResources(request *restful.Request, response *restful.Response) { func (h *Handler) handleListResources(request *restful.Request, response *restful.Response) {
query := query.ParseQueryParameter(request) query := query.ParseQueryParameter(request)
resource := request.PathParameter("resources") resourceType := request.PathParameter("resources")
namespace := request.PathParameter("namespace") namespace := request.PathParameter("namespace")
result, err := h.namespacedResourceGetter.List(resource, namespace, query) result, err := h.resourceGetterV1alpha3.List(resourceType, namespace, query)
if err == nil {
response.WriteEntity(result)
return
}
if err != resourcev1alpha3.ErrResourceNotSupported {
klog.Error(err)
api.HandleInternalError(response, nil, err)
return
}
// fallback to v1alpha2
result, err = h.fallback(resourceType, namespace, query)
if err != nil { if err != nil {
klog.Error(err)
api.HandleInternalError(response, nil, err) api.HandleInternalError(response, nil, err)
return return
} }
...@@ -37,38 +59,96 @@ func (h Handler) handleListResources(request *restful.Request, response *restful ...@@ -37,38 +59,96 @@ func (h Handler) handleListResources(request *restful.Request, response *restful
response.WriteEntity(result) response.WriteEntity(result)
} }
func (h Handler) handleGetComponentStatus(request *restful.Request, response *restful.Response) { func (h *Handler) fallback(resourceType string, namespace string, q *query.Query) (*api.ListResult, error) {
orderBy := string(q.SortBy)
limit, offset := q.Pagination.Limit, q.Pagination.Offset
reverse := !q.Ascending
conditions := &params.Conditions{}
for _, filter := range q.Filters {
switch filter.Field {
case query.FieldName:
conditions.Match[v1alpha2.Name] = string(filter.Value)
break
case query.FieldCreationTimeStamp:
conditions.Match[v1alpha2.CreateTime] = string(filter.Value)
break
case query.FieldLastUpdateTimestamp:
conditions.Match[v1alpha2.UpdateTime] = string(filter.Value)
break
case query.FieldLabel:
values := strings.SplitN(string(filter.Value), ":", 2)
if len(values) == 2 {
conditions.Match[values[0]] = values[1]
} else {
conditions.Match[v1alpha2.Label] = values[0]
}
break
case query.FieldAnnotation:
values := strings.SplitN(string(filter.Value), ":", 2)
if len(values) == 2 {
conditions.Match[v1alpha2.Annotation] = values[1]
} else {
conditions.Match[v1alpha2.Annotation] = values[0]
}
break
case query.FieldStatus:
conditions.Match[v1alpha2.Status] = string(filter.Value)
break
case query.FieldOwnerReference:
conditions.Match[v1alpha2.Owner] = string(filter.Value)
break
}
}
result, err := h.resourcesGetterV1alpha2.ListResources(namespace, resourceType, conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Error(err)
return nil, err
}
return &api.ListResult{
Items: result.Items,
TotalItems: result.TotalCount,
}, nil
}
func (h *Handler) handleGetComponentStatus(request *restful.Request, response *restful.Response) {
component := request.PathParameter("component") component := request.PathParameter("component")
result, err := h.componentsGetter.GetComponentStatus(component) result, err := h.componentsGetter.GetComponentStatus(component)
if err != nil { if err != nil {
klog.Error(err)
api.HandleInternalError(response, nil, err) api.HandleInternalError(response, nil, err)
return return
} }
response.WriteHeaderAndEntity(http.StatusOK, result) response.WriteEntity(result)
} }
func (h Handler) handleGetSystemHealthStatus(request *restful.Request, response *restful.Response) { func (h *Handler) handleGetSystemHealthStatus(request *restful.Request, response *restful.Response) {
result, err := h.componentsGetter.GetSystemHealthStatus() result, err := h.componentsGetter.GetSystemHealthStatus()
if err != nil { if err != nil {
klog.Error(err)
api.HandleInternalError(response, nil, err) api.HandleInternalError(response, nil, err)
return return
} }
response.WriteHeaderAndEntity(http.StatusOK, result) response.WriteEntity(result)
} }
// get all componentsHandler // get all componentsHandler
func (h Handler) handleGetComponents(request *restful.Request, response *restful.Response) { func (h *Handler) handleGetComponents(request *restful.Request, response *restful.Response) {
result, err := h.componentsGetter.GetAllComponentsStatus() result, err := h.componentsGetter.GetAllComponentsStatus()
if err != nil { if err != nil {
klog.Error(err)
api.HandleInternalError(response, nil, err) api.HandleInternalError(response, nil, err)
return return
} }
response.WriteHeaderAndEntity(http.StatusOK, result) response.WriteEntity(result)
} }
package v1alpha3 package v1alpha3
import "testing" import (
"github.com/google/go-cmp/cmp"
fakeapp "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned/fake"
fakeistio "istio.io/client-go/pkg/clientset/versioned/fake"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakek8s "k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/informers"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
"testing"
)
func TestComponentHandler(t *testing.T) { func TestResourceV1alpha2Fallback(t *testing.T) {
tests := []struct {
description string
namespace string
resource string
query *query.Query
expectedError error
expected *api.ListResult
}{
{
description: "list namespaces",
namespace: "default",
resource: "namespaces",
query: &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: "name",
Ascending: false,
Filters: nil,
},
expectedError: nil,
expected: &api.ListResult{
Items: []interface{}{kubesphereNamespace, defaultNamespace},
TotalItems: 2,
},
},
{
description: "list secrets fallback",
namespace: "default",
resource: "secrets",
query: &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: "name",
Ascending: false,
Filters: nil,
},
expectedError: nil,
expected: &api.ListResult{
Items: []interface{}{secretFoo2, secretFoo1},
TotalItems: 2,
},
},
}
factory, err := prepare()
if err != nil {
t.Fatal(err)
}
handler := New(factory)
for _, test := range tests {
got, err := listResources(test.namespace, test.resource, test.query, handler)
if err != test.expectedError {
t.Fatalf("expected error: %s, got: %s", test.expectedError, err)
}
if diff := cmp.Diff(got, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
func listResources(namespace, resourceType string, query *query.Query, h *Handler) (*api.ListResult, error) {
result, err := h.resourceGetterV1alpha3.List(resourceType, namespace, query)
if err == nil {
return result, nil
}
if err != resourcev1alpha3.ErrResourceNotSupported {
return nil, err
}
// fallback to v1alpha2
return h.fallback(resourceType, namespace, query)
}
var (
defaultNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
kubesphereNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kubesphere-system",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
secretFoo1 = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "default",
},
}
secretFoo2 = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "default",
},
}
replicas = int32(1)
nginxDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "nginx",
Namespace: "default",
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 1,
},
}
redisDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "redis",
Namespace: "default",
Labels: map[string]string{"kubesphere.io/creator": "admin"},
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 0,
},
}
deployments = []interface{}{redisDeployment, nginxDeployment}
namespaces = []interface{}{defaultNamespace, kubesphereNamespace}
secrets = []interface{}{secretFoo1, secretFoo2}
)
func prepare() (informers.InformerFactory, error) {
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient)
k8sInformerFactory := fakeInformerFactory.KubernetesSharedInformerFactory()
for _, namespace := range namespaces {
err := k8sInformerFactory.Core().V1().Namespaces().Informer().GetIndexer().Add(namespace)
if err != nil {
return nil, err
}
}
for _, deployment := range deployments {
err := k8sInformerFactory.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment)
if err != nil {
return nil, err
}
}
for _, secret := range secrets {
err := k8sInformerFactory.Core().V1().Secrets().Informer().GetIndexer().Add(secret)
if err != nil {
return nil, err
}
}
return fakeInformerFactory, nil
} }
...@@ -32,7 +32,7 @@ func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Respo ...@@ -32,7 +32,7 @@ func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Respo
return return
} }
result, err := h.tenant.ListWorkspaces(user.GetName()) result, err := h.tenant.ListWorkspaces(user)
if err != nil { if err != nil {
api.HandleInternalError(resp, nil, err) api.HandleInternalError(resp, nil, err)
...@@ -52,9 +52,9 @@ func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Respo ...@@ -52,9 +52,9 @@ func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Respo
return return
} }
worksapceName := req.PathParameter("workspace") workspace := req.PathParameter("workspace")
result, err := h.tenant.ListNamespaces(worksapceName, user.GetName()) result, err := h.tenant.ListNamespaces(user, workspace)
if err != nil { if err != nil {
api.HandleInternalError(resp, nil, err) api.HandleInternalError(resp, nil, err)
......
...@@ -113,8 +113,7 @@ func (am *amOperator) GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target ...@@ -113,8 +113,7 @@ func (am *amOperator) GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target
return nil, err return nil, err
} }
for _, role := range roles { for _, role := range roles {
if role.Target.Name == iamv1alpha2.TargetAll || if role.Target.Name == target {
role.Target.Name == target {
return &role, nil return &role, nil
} }
} }
......
...@@ -22,18 +22,9 @@ import ( ...@@ -22,18 +22,9 @@ import (
"github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1" "github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
"github.com/kubernetes-sigs/application/pkg/client/informers/externalversions" "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
)
const (
app = "app"
chart = "chart"
release = "release"
) )
type appSearcher struct { type appSearcher struct {
...@@ -48,70 +39,24 @@ func (s *appSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -48,70 +39,24 @@ func (s *appSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name) return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
} }
// exactly Match
func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool { func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace func (s *appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything()) apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
...@@ -134,7 +79,7 @@ func (s *appSearcher) Search(namespace string, conditions *params.Conditions, or ...@@ -134,7 +79,7 @@ func (s *appSearcher) Search(namespace string, conditions *params.Conditions, or
if reverse { if reverse {
i, j = j, i i, j = j, i
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -18,17 +18,14 @@ ...@@ -18,17 +18,14 @@
package clusterrole package clusterrole
import ( import (
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
) )
type clusterRoleSearcher struct { type clusterRoleSearcher struct {
...@@ -43,7 +40,6 @@ func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,7 +40,6 @@ func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name) return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name)
} }
// exactly Match
func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool { func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
...@@ -55,15 +51,6 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol ...@@ -55,15 +51,6 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) { if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
return false return false
} }
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case v1alpha2.UserFacing: case v1alpha2.UserFacing:
if v == "true" { if v == "true" {
if !isUserFacingClusterRole(item) { if !isUserFacingClusterRole(item) {
...@@ -71,8 +58,7 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol ...@@ -71,8 +58,7 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
} }
} }
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -80,43 +66,15 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol ...@@ -80,43 +66,15 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
return true return true
} }
// Fuzzy searchInNamespace func (s *clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything()) clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything())
...@@ -137,11 +95,9 @@ func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Condit ...@@ -137,11 +95,9 @@ func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Condit
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -18,16 +18,12 @@ ...@@ -18,16 +18,12 @@
package configmap package configmap
import ( import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
) )
type configMapSearcher struct { type configMapSearcher struct {
...@@ -42,70 +38,24 @@ func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -42,70 +38,24 @@ func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name) return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
} }
// exactly Match func (s *configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace func (s *configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything()) configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
...@@ -128,7 +78,7 @@ func (s *configMapSearcher) Search(namespace string, conditions *params.Conditio ...@@ -128,7 +78,7 @@ func (s *configMapSearcher) Search(namespace string, conditions *params.Conditio
if reverse { if reverse {
i, j = j, i i, j = j, i
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -18,15 +18,11 @@ ...@@ -18,15 +18,11 @@
package cronjob package cronjob
import ( import (
"k8s.io/api/batch/v1beta1"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/api/batch/v1beta1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
...@@ -50,26 +46,15 @@ func cronJobStatus(item *v1beta1.CronJob) string { ...@@ -50,26 +46,15 @@ func cronJobStatus(item *v1beta1.CronJob) string {
return v1alpha2.StatusRunning return v1alpha2.StatusRunning
} }
// Exactly Match
func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool { func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Status: case v1alpha2.Status:
if cronJobStatus(item) != v { if cronJobStatus(item) != v {
return false return false
} }
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -80,50 +65,26 @@ func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bo ...@@ -80,50 +65,26 @@ func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bo
func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bool { func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool { func (*cronJobSearcher) compare(left, right *v1beta1.CronJob, orderBy string) bool {
switch orderBy { switch orderBy {
case v1alpha2.LastScheduleTime: case v1alpha2.LastScheduleTime:
if a.Status.LastScheduleTime == nil { if left.Status.LastScheduleTime == nil {
return true return true
} }
if b.Status.LastScheduleTime == nil { if right.Status.LastScheduleTime == nil {
return false return false
} }
return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime) return left.Status.LastScheduleTime.Before(right.Status.LastScheduleTime)
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
default: default:
fallthrough return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
case v1alpha2.Name:
return strings.Compare(a.Name, b.Name) <= 0
} }
} }
...@@ -146,10 +107,7 @@ func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions ...@@ -146,10 +107,7 @@ func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions
} }
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { return c.compare(result[i], result[j], orderBy) && !reverse
i, j = j, i
}
return c.compare(result[i], result[j], orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -18,16 +18,12 @@ ...@@ -18,16 +18,12 @@
package daemonset package daemonset
import ( import (
"k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels"
) )
type daemonSetSearcher struct { type daemonSetSearcher struct {
...@@ -52,7 +48,6 @@ func daemonSetStatus(item *v1.DaemonSet) string { ...@@ -52,7 +48,6 @@ func daemonSetStatus(item *v1.DaemonSet) string {
} }
} }
// Exactly Match
func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool { func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
...@@ -60,18 +55,8 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo ...@@ -60,18 +55,8 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo
if daemonSetStatus(item) != v { if daemonSetStatus(item) != v {
return false return false
} }
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -79,48 +64,15 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo ...@@ -79,48 +64,15 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo
return true return true
} }
func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) bool { func (*daemonSetSearcher) fuzzy(kv map[string]string, item *v1.DaemonSet) bool {
for k, v := range kv {
for k, v := range fuzzy { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
switch k {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*daemonSetSearcher) compare(a, b *v1.DaemonSet, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
daemonSets, err := c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything()) daemonSets, err := c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything())
...@@ -143,7 +95,7 @@ func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditio ...@@ -143,7 +95,7 @@ func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditio
if reverse { if reverse {
i, j = j, i i, j = j, i
} }
return c.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
/*
*
* 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.
* /
*/
/*
Copyright 2019 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 deployment
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
"strings"
"time"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/api/apps/v1"
)
type deploymentSearcher struct {
informer informers.SharedInformerFactory
}
func NewDeploymentSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &deploymentSearcher{informer: informers}
}
func (s *deploymentSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
}
func deploymentStatus(item *v1.Deployment) string {
if item.Spec.Replicas != nil {
if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 {
return v1alpha2.StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return v1alpha2.StatusRunning
} else {
return v1alpha2.StatusUpdating
}
}
return v1alpha2.StatusStopped
}
func (*deploymentSearcher) match(kv map[string]string, item *v1.Deployment) bool {
for k, v := range kv {
switch k {
case v1alpha2.Status:
if deploymentStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*deploymentSearcher) fuzzy(kv map[string]string, item *v1.Deployment) bool {
for k, v := range kv {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
switch orderBy {
case v1alpha2.UpdateTime:
aLastUpdateTime := s.lastUpdateTime(a)
bLastUpdateTime := s.lastUpdateTime(b)
if aLastUpdateTime.Equal(bLastUpdateTime) {
return strings.Compare(a.Name, b.Name) <= 0
}
return aLastUpdateTime.Before(bLastUpdateTime)
default:
return v1alpha2.ObjectMetaCompare(a.ObjectMeta, b.ObjectMeta, orderBy)
}
}
func (s *deploymentSearcher) lastUpdateTime(deployment *v1.Deployment) time.Time {
lastUpdateTime := deployment.CreationTimestamp.Time
for _, condition := range deployment.Status.Conditions {
if condition.LastUpdateTime.After(lastUpdateTime) {
lastUpdateTime = condition.LastUpdateTime.Time
}
}
return lastUpdateTime
}
func (s *deploymentSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
deployments, err := s.informer.Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Deployment, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = deployments
} else {
for _, item := range deployments {
if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) {
result = append(result, item)
}
}
}
sort.Slice(result, func(i, j int) bool {
if reverse {
i, j = j, i
}
return s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}
...@@ -19,15 +19,11 @@ package hpa ...@@ -19,15 +19,11 @@ package hpa
import ( import (
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/apimachinery/pkg/labels"
) )
type hpaSearcher struct { type hpaSearcher struct {
...@@ -58,17 +54,8 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori ...@@ -58,17 +54,8 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
if !hpaTargetMatch(item, kind, name) { if !hpaTargetMatch(item, kind, name) {
return false return false
} }
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
if item.Labels[k] != v { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false return false
} }
} }
...@@ -76,47 +63,15 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori ...@@ -76,47 +63,15 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
return true return true
} }
// Fuzzy searchInNamespace
func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool { func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) && !v1alpha2.SearchFuzzy(item.Annotations, k, v) {
return false
}
} }
} }
return true return true
} }
func (*hpaSearcher) compare(a, b *autoscalingv2beta2.HorizontalPodAutoscaler, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
horizontalPodAutoscalers, err := s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything()) horizontalPodAutoscalers, err := s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything())
...@@ -138,11 +93,9 @@ func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, or ...@@ -138,11 +93,9 @@ func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, or
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -18,15 +18,11 @@ ...@@ -18,15 +18,11 @@
package ingress package ingress
import ( import (
"k8s.io/api/extensions/v1beta1"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
...@@ -43,70 +39,24 @@ func (s *ingressSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,70 +39,24 @@ func (s *ingressSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name) return s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name)
} }
// exactly Match
func (*ingressSearcher) match(match map[string]string, item *v1beta1.Ingress) bool { func (*ingressSearcher) match(match map[string]string, item *v1beta1.Ingress) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Ingress) bool { func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Ingress) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*ingressSearcher) compare(a, b *v1beta1.Ingress, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
ingresses, err := s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything()) ingresses, err := s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything())
...@@ -127,11 +77,9 @@ func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions ...@@ -127,11 +77,9 @@ func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
package v1alpha2 package v1alpha2
import ( import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"strings" "strings"
) )
...@@ -24,6 +27,7 @@ const ( ...@@ -24,6 +27,7 @@ const (
Keyword = "keyword" Keyword = "keyword"
UserFacing = "userfacing" UserFacing = "userfacing"
Status = "status" Status = "status"
Owner = "owner"
StatusRunning = "running" StatusRunning = "running"
StatusPaused = "paused" StatusPaused = "paused"
...@@ -66,7 +70,61 @@ type Interface interface { ...@@ -66,7 +70,61 @@ type Interface interface {
Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error)
} }
func SearchFuzzy(m map[string]string, key, value string) bool { func ObjectMetaExactlyMath(key, value string, item metav1.ObjectMeta) bool {
switch key {
case Name:
names := strings.Split(value, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, value) && !FuzzyMatch(item.Labels, "", value) && !FuzzyMatch(item.Annotations, "", value) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[key]; !ok || val != value {
return false
}
}
return true
}
func ObjectMetaFuzzyMath(key, value string, item metav1.ObjectMeta) bool {
switch key {
case Name:
if !strings.Contains(item.Name, value) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], value) {
return false
}
case Label:
if !FuzzyMatch(item.Labels, "", value) {
return false
}
case Annotation:
if !FuzzyMatch(item.Annotations, "", value) {
return false
}
return false
case App:
if !strings.Contains(item.Labels[Chart], value) && !strings.Contains(item.Labels[Release], value) {
return false
}
case Owner:
for _, ownerReference := range item.OwnerReferences {
if strings.Compare(string(ownerReference.UID), value) == 0 {
return true
}
}
return false
default:
if !FuzzyMatch(item.Labels, key, value) {
return false
}
}
return true
}
func FuzzyMatch(m map[string]string, key, value string) bool {
val, exist := m[key] val, exist := m[key]
...@@ -78,3 +136,17 @@ func SearchFuzzy(m map[string]string, key, value string) bool { ...@@ -78,3 +136,17 @@ func SearchFuzzy(m map[string]string, key, value string) bool {
return false return false
} }
func ObjectMetaCompare(left, right metav1.ObjectMeta, compareField string) bool {
switch compareField {
case CreateTime:
if left.CreationTimestamp.Equal(&right.CreationTimestamp) {
return strings.Compare(left.Name, right.Name) <= 0
}
return left.CreationTimestamp.Time.Before(right.CreationTimestamp.Time)
case Name:
fallthrough
default:
return strings.Compare(left.Name, right.Name) <= 0
}
}
...@@ -19,14 +19,11 @@ package job ...@@ -19,14 +19,11 @@ package job
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"time" "time"
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
...@@ -64,7 +61,6 @@ func jobStatus(item *batchv1.Job) string { ...@@ -64,7 +61,6 @@ func jobStatus(item *batchv1.Job) string {
return status return status
} }
// Exactly Match
func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool { func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
...@@ -80,18 +76,8 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool { ...@@ -80,18 +76,8 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") { if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") {
return false return false
} }
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -100,33 +86,11 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool { ...@@ -100,33 +86,11 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
} }
func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool { func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
...@@ -143,16 +107,12 @@ func jobUpdateTime(item *batchv1.Job) time.Time { ...@@ -143,16 +107,12 @@ func jobUpdateTime(item *batchv1.Job) time.Time {
return updateTime return updateTime
} }
func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool { func (*jobSearcher) compare(left, right *batchv1.Job, orderBy string) bool {
switch orderBy { switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.UpdateTime: case v1alpha2.UpdateTime:
return jobUpdateTime(a).Before(jobUpdateTime(b)) return jobUpdateTime(left).Before(jobUpdateTime(right))
case v1alpha2.Name:
fallthrough
default: default:
return strings.Compare(a.Name, b.Name) <= 0 return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
} }
} }
...@@ -176,9 +136,7 @@ func (s *jobSearcher) Search(namespace string, conditions *params.Conditions, or ...@@ -176,9 +136,7 @@ func (s *jobSearcher) Search(namespace string, conditions *params.Conditions, or
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return s.compare(result[i], result[j], orderBy)
}) })
......
...@@ -19,16 +19,12 @@ package namespace ...@@ -19,16 +19,12 @@ package namespace
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type namespaceSearcher struct { type namespaceSearcher struct {
...@@ -43,66 +39,24 @@ func (s *namespaceSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,66 +39,24 @@ func (s *namespaceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Namespaces().Lister().Get(name) return s.informers.Core().V1().Namespaces().Lister().Get(name)
} }
// exactly Match
func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool { func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool { func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
namespaces, err := s.informers.Core().V1().Namespaces().Lister().List(labels.Everything()) namespaces, err := s.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
...@@ -123,11 +77,9 @@ func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditio ...@@ -123,11 +77,9 @@ func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditio
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -20,16 +20,12 @@ package node ...@@ -20,16 +20,12 @@ package node
import ( import (
"fmt" "fmt"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
const ( const (
...@@ -80,15 +76,9 @@ func isUnhealthyStatus(condition v1.NodeCondition) bool { ...@@ -80,15 +76,9 @@ func isUnhealthyStatus(condition v1.NodeCondition) bool {
return false return false
} }
// exactly Match
func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool { func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Role: case v1alpha2.Role:
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v) labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
if _, ok := item.Labels[labelKey]; !ok { if _, ok := item.Labels[labelKey]; !ok {
...@@ -98,13 +88,8 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool { ...@@ -98,13 +88,8 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
if getNodeStatus(item) != v { if getNodeStatus(item) != v {
return false return false
} }
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -112,43 +97,15 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool { ...@@ -112,43 +97,15 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
return true return true
} }
// Fuzzy searchInNamespace
func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool { func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*nodeSearcher) compare(a, b *v1.Node, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
nodes, err := s.informers.Core().V1().Nodes().Lister().List(labels.Everything()) nodes, err := s.informers.Core().V1().Nodes().Lister().List(labels.Everything())
...@@ -169,11 +126,9 @@ func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, o ...@@ -169,11 +126,9 @@ func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, o
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -19,7 +19,6 @@ package persistentvolumeclaim ...@@ -19,7 +19,6 @@ package persistentvolumeclaim
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"strconv" "strconv"
...@@ -60,15 +59,9 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string { ...@@ -60,15 +59,9 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string {
return status return status
} }
// exactly Match
func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool { func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Status: case v1alpha2.Status:
statuses := strings.Split(v, "|") statuses := strings.Split(v, "|")
if !sliceutil.HasString(statuses, pvcStatus(item)) { if !sliceutil.HasString(statuses, pvcStatus(item)) {
...@@ -78,13 +71,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe ...@@ -78,13 +71,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v { if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v {
return false return false
} }
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -92,47 +80,15 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe ...@@ -92,47 +80,15 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
return true return true
} }
// Fuzzy searchInNamespace
func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool { func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*persistentVolumeClaimSearcher) compare(a, b *v1.PersistentVolumeClaim, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
persistentVolumeClaims, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything()) persistentVolumeClaims, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything())
...@@ -153,11 +109,9 @@ func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *par ...@@ -153,11 +109,9 @@ func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *par
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -20,16 +20,12 @@ package pod ...@@ -20,16 +20,12 @@ package pod
import ( import (
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type podSearcher struct { type podSearcher struct {
...@@ -153,7 +149,6 @@ func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool ...@@ -153,7 +149,6 @@ func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool
return true return true
} }
// exactly Match
func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool { func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
...@@ -177,18 +172,8 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool { ...@@ -177,18 +172,8 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
if !s.podBelongToService(item, v) { if !s.podBelongToService(item, v) {
return false return false
} }
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -196,52 +181,27 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool { ...@@ -196,52 +181,27 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
return true return true
} }
// Fuzzy searchInNamespace
func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool { func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool { func (*podSearcher) compare(left, right *v1.Pod, orderBy string) bool {
switch orderBy { switch orderBy {
case v1alpha2.StartTime: case v1alpha2.StartTime:
if a.Status.StartTime == nil { if left.Status.StartTime == nil {
return false return false
} }
if b.Status.StartTime == nil { if right.Status.StartTime == nil {
return true return true
} }
return a.Status.StartTime.Before(b.Status.StartTime) return left.Status.StartTime.Before(right.Status.StartTime)
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default: default:
return strings.Compare(a.Name, b.Name) <= 0 return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
} }
} }
...@@ -266,9 +226,7 @@ func (s *podSearcher) Search(namespace string, conditions *params.Conditions, or ...@@ -266,9 +226,7 @@ func (s *podSearcher) Search(namespace string, conditions *params.Conditions, or
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return s.compare(result[i], result[j], orderBy)
}) })
......
/*
*
* 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 resource
import (
"github.com/google/go-cmp/cmp"
fakeapp "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned/fake"
fakeistio "istio.io/client-go/pkg/clientset/versioned/fake"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakek8s "k8s.io/client-go/kubernetes/fake"
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"testing"
)
func TestConditions(t *testing.T) {
factory, err := prepare()
if err != nil {
t.Fatal(err)
}
resource := NewResourceGetter(factory)
tests := []struct {
Name string
Namespace string
Resource string
Conditions *params.Conditions
OrderBy string
Reverse bool
Limit int
Offset int
ExpectResponse *models.PageableResponse
ExpectError error
}{{
Name: "list namespace order by name asc",
Namespace: "",
Resource: "namespaces",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: false,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{defaultNamespace, kubesphereNamespace},
TotalCount: 2,
},
ExpectError: nil,
}, {
Name: "list namespace order by name desc",
Namespace: "",
Resource: "namespaces",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{kubesphereNamespace, defaultNamespace},
TotalCount: 2,
},
ExpectError: nil,
},
{
Name: "list deployment",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: false,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment, redisDeployment},
TotalCount: 2,
},
ExpectError: nil,
},
{
Name: "filter deployment by keyword",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{v1alpha2.Keyword: "ngin"},
Fuzzy: nil,
},
OrderBy: "name",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment},
TotalCount: 1,
},
ExpectError: nil,
},
{
Name: "filter deployment by label",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{"kubesphere.io/creator": "admin"},
Fuzzy: nil,
},
OrderBy: "",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{redisDeployment},
TotalCount: 1,
},
ExpectError: nil,
}, {
Name: "filter deployment by status",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{v1alpha2.Status: v1alpha2.StatusRunning},
Fuzzy: nil,
},
OrderBy: "",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment},
TotalCount: 1,
},
ExpectError: nil,
},
}
for _, test := range tests {
response, err := resource.ListResources(test.Namespace, test.Resource, test.Conditions, test.OrderBy, test.Reverse, test.Limit, test.Offset)
if err != test.ExpectError {
t.Fatalf("expected error: %s, got: %s", test.ExpectError, err)
}
if diff := cmp.Diff(test.ExpectResponse, response); diff != "" {
t.Errorf(diff)
}
}
}
var (
defaultNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
kubesphereNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kubesphere-system",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
replicas = int32(1)
nginxDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "nginx",
Namespace: "default",
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 1,
},
}
redisDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "redis",
Namespace: "default",
Labels: map[string]string{"kubesphere.io/creator": "admin"},
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 0,
},
}
)
func prepare() (informers.InformerFactory, error) {
namespaces := []interface{}{defaultNamespace, kubesphereNamespace}
deployments := []interface{}{nginxDeployment, redisDeployment}
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient)
k8sInformerFactory := fakeInformerFactory.KubernetesSharedInformerFactory()
for _, namespace := range namespaces {
err := k8sInformerFactory.Core().V1().Namespaces().Informer().GetIndexer().Add(namespace)
if err != nil {
return nil, err
}
}
for _, deployment := range deployments {
err := k8sInformerFactory.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment)
if err != nil {
return nil, err
}
}
return fakeInformerFactory, nil
}
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/daemonset" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/daemonset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/deployment"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/hpa" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/hpa"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/ingress" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/ingress"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job"
...@@ -62,11 +63,10 @@ func (r ResourceGetter) Add(resource string, getter v1alpha2.Interface) { ...@@ -62,11 +63,10 @@ func (r ResourceGetter) Add(resource string, getter v1alpha2.Interface) {
func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter { func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
resourceGetters := make(map[string]v1alpha2.Interface) resourceGetters := make(map[string]v1alpha2.Interface)
//resourceGetters[v1alpha2.Deployments] = deployments
resourceGetters[v1alpha2.ConfigMaps] = configmap.NewConfigmapSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.ConfigMaps] = configmap.NewConfigmapSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.CronJobs] = cronjob.NewCronJobSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.CronJobs] = cronjob.NewCronJobSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.DaemonSets] = daemonset.NewDaemonSetSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.DaemonSets] = daemonset.NewDaemonSetSearcher(factory.KubernetesSharedInformerFactory())
// resourceGetters[Deployments] = resourceGetters[v1alpha2.Deployments] = deployment.NewDeploymentSetSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Ingresses] = ingress.NewIngressSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Ingresses] = ingress.NewIngressSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory())
...@@ -75,18 +75,16 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter { ...@@ -75,18 +75,16 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
resourceGetters[v1alpha2.StatefulSets] = statefulset.NewStatefulSetSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.StatefulSets] = statefulset.NewStatefulSetSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Pods] = pod.NewPodSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Pods] = pod.NewPodSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Roles] = role.NewRoleSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Roles] = role.NewRoleSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Nodes] = node.NewNodeSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Nodes] = node.NewNodeSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Namespaces] = namespace.NewNamespaceSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.Namespaces] = namespace.NewNamespaceSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.ClusterRoles] = clusterrole.NewClusterRoleSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.ClusterRoles] = clusterrole.NewClusterRoleSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory()) resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.KubeSphereSharedInformerFactory()) resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory()) resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory()) resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory()) resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(factory.ApplicationSharedInformerFactory()) resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(factory.ApplicationSharedInformerFactory())
return &ResourceGetter{resourcesGetters: resourceGetters} return &ResourceGetter{resourcesGetters: resourceGetters}
......
...@@ -22,13 +22,10 @@ import ( ...@@ -22,13 +22,10 @@ import (
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
rbac "k8s.io/api/rbac/v1" rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type roleSearcher struct { type roleSearcher struct {
...@@ -43,19 +40,9 @@ func (s *roleSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,19 +40,9 @@ func (s *roleSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Rbac().V1().Roles().Lister().Roles(namespace).Get(name) return s.informers.Rbac().V1().Roles().Lister().Roles(namespace).Get(name)
} }
// exactly Match
func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool { func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case v1alpha2.UserFacing: case v1alpha2.UserFacing:
if v == "true" { if v == "true" {
if !isUserFacingRole(item) { if !isUserFacingRole(item) {
...@@ -63,8 +50,7 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool { ...@@ -63,8 +50,7 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
} }
} }
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -72,43 +58,15 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool { ...@@ -72,43 +58,15 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
return true return true
} }
// Fuzzy searchInNamespace
func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool { func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*roleSearcher) compare(a, b *rbac.Role, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
roles, err := s.informers.Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything()) roles, err := s.informers.Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything())
...@@ -129,11 +87,9 @@ func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, o ...@@ -129,11 +87,9 @@ func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, o
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -20,15 +20,11 @@ package s2buildertemplate ...@@ -20,15 +20,11 @@ package s2buildertemplate
import ( import (
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/apimachinery/pkg/labels"
) )
type s2iBuilderTemplateSearcher struct { type s2iBuilderTemplateSearcher struct {
...@@ -43,66 +39,24 @@ func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, e ...@@ -43,66 +39,24 @@ func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, e
return s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name) return s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name)
} }
// exactly Match
func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool { func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool { func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*s2iBuilderTemplateSearcher) compare(a, b *v1alpha1.S2iBuilderTemplate, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
builderTemplates, err := s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything()) builderTemplates, err := s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything())
...@@ -123,11 +77,9 @@ func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params ...@@ -123,11 +77,9 @@ func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -22,13 +22,10 @@ import ( ...@@ -22,13 +22,10 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
) )
type s2iBuilderSearcher struct { type s2iBuilderSearcher struct {
...@@ -43,66 +40,24 @@ func (s *s2iBuilderSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,66 +40,24 @@ func (s *s2iBuilderSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name) return s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name)
} }
// exactly Match
func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool { func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool { func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*s2iBuilderSearcher) compare(a, b *v1alpha1.S2iBuilder, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
s2iBuilders, err := s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything()) s2iBuilders, err := s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything())
...@@ -123,11 +78,9 @@ func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditi ...@@ -123,11 +78,9 @@ func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditi
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -22,12 +22,9 @@ import ( ...@@ -22,12 +22,9 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
) )
type s2iRunSearcher struct { type s2iRunSearcher struct {
...@@ -42,26 +39,15 @@ func (s *s2iRunSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -42,26 +39,15 @@ func (s *s2iRunSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name) return s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name)
} }
// exactly Match
func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool { func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Status: case v1alpha2.Status:
if string(item.Status.RunState) != v { if string(item.Status.RunState) != v {
return false return false
} }
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -69,43 +55,15 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo ...@@ -69,43 +55,15 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo
return true return true
} }
// Fuzzy searchInNamespace
func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool { func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*s2iRunSearcher) compare(a, b *v1alpha1.S2iRun, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
s2iRuns, err := s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything()) s2iRuns, err := s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything())
...@@ -126,11 +84,9 @@ func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions, ...@@ -126,11 +84,9 @@ func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions,
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -19,16 +19,12 @@ package secret ...@@ -19,16 +19,12 @@ package secret
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type secretSearcher struct { type secretSearcher struct {
...@@ -43,26 +39,15 @@ func (s *secretSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,26 +39,15 @@ func (s *secretSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name) return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name)
} }
// exactly Match
func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool { func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case "type": case "type":
if string(item.Type) != v { if string(item.Type) != v {
return false return false
} }
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -70,47 +55,15 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool { ...@@ -70,47 +55,15 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
return true return true
} }
// Fuzzy searchInNamespace
func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool { func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*secretSearcher) compare(a, b *v1.Secret, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *secretSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *secretSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
secrets, err := s.informers.Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything()) secrets, err := s.informers.Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything())
...@@ -131,11 +84,9 @@ func (s *secretSearcher) Search(namespace string, conditions *params.Conditions, ...@@ -131,11 +84,9 @@ func (s *secretSearcher) Search(namespace string, conditions *params.Conditions,
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -19,16 +19,12 @@ package service ...@@ -19,16 +19,12 @@ package service
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type serviceSearcher struct { type serviceSearcher struct {
...@@ -43,70 +39,24 @@ func (s *serviceSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,70 +39,24 @@ func (s *serviceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Services().Lister().Services(namespace).Get(name) return s.informers.Core().V1().Services().Lister().Services(namespace).Get(name)
} }
// exactly Match
func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool { func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool { func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*serviceSearcher) compare(a, b *v1.Service, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
services, err := s.informers.Core().V1().Services().Lister().Services(namespace).List(labels.Everything()) services, err := s.informers.Core().V1().Services().Lister().Services(namespace).List(labels.Everything())
...@@ -127,11 +77,9 @@ func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions ...@@ -127,11 +77,9 @@ func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -19,16 +19,12 @@ package statefulset ...@@ -19,16 +19,12 @@ package statefulset
import ( import (
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/apps/v1" "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
"sort"
) )
type statefulSetSearcher struct { type statefulSetSearcher struct {
...@@ -56,26 +52,15 @@ func statefulSetStatus(item *v1.StatefulSet) string { ...@@ -56,26 +52,15 @@ func statefulSetStatus(item *v1.StatefulSet) string {
return v1alpha2.StatusStopped return v1alpha2.StatusStopped
} }
// Exactly Match
func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool { func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case v1alpha2.Status: case v1alpha2.Status:
if statefulSetStatus(item) != v { if statefulSetStatus(item) != v {
return false return false
} }
default: default:
// label not exist or value not equal if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
if val, ok := item.Labels[k]; !ok || val != v {
return false return false
} }
} }
...@@ -84,47 +69,14 @@ func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) ...@@ -84,47 +69,14 @@ func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet)
} }
func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) bool { func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*statefulSetSearcher) compare(a, b *v1.StatefulSet, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *statefulSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *statefulSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
statefulSets, err := s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything()) statefulSets, err := s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything())
...@@ -145,11 +97,9 @@ func (s *statefulSetSearcher) Search(namespace string, conditions *params.Condit ...@@ -145,11 +97,9 @@ func (s *statefulSetSearcher) Search(namespace string, conditions *params.Condit
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -19,16 +19,12 @@ package storageclass ...@@ -19,16 +19,12 @@ package storageclass
import ( import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
) )
type storageClassesSearcher struct { type storageClassesSearcher struct {
...@@ -43,66 +39,24 @@ func (s *storageClassesSearcher) Get(namespace, name string) (interface{}, error ...@@ -43,66 +39,24 @@ func (s *storageClassesSearcher) Get(namespace, name string) (interface{}, error
return s.informers.Storage().V1().StorageClasses().Lister().Get(name) return s.informers.Storage().V1().StorageClasses().Lister().Get(name)
} }
// exactly Match
func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool { func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool { func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*storageClassesSearcher) compare(a, b *v1.StorageClass, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *storageClassesSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *storageClassesSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
storageClasses, err := s.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything()) storageClasses, err := s.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything())
...@@ -125,7 +79,7 @@ func (s *storageClassesSearcher) Search(namespace string, conditions *params.Con ...@@ -125,7 +79,7 @@ func (s *storageClassesSearcher) Search(namespace string, conditions *params.Con
if reverse { if reverse {
i, j = j, i i, j = j, i
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
...@@ -20,15 +20,11 @@ package workspace ...@@ -20,15 +20,11 @@ package workspace
import ( import (
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings"
"k8s.io/apimachinery/pkg/labels"
) )
type workspaceSearcher struct { type workspaceSearcher struct {
...@@ -43,66 +39,24 @@ func (s *workspaceSearcher) Get(namespace, name string) (interface{}, error) { ...@@ -43,66 +39,24 @@ func (s *workspaceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Tenant().V1alpha1().Workspaces().Lister().Get(name) return s.informers.Tenant().V1alpha1().Workspaces().Lister().Get(name)
} }
// exactly Match
func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool { func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool {
for k, v := range match { for k, v := range match {
switch k { if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name: return false
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
} }
} }
return true return true
} }
// Fuzzy searchInNamespace
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool { func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false return false
default:
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
} }
} }
return true return true
} }
func (*workspaceSearcher) compare(a, b *tenantv1alpha1.Workspace, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything()) workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
...@@ -124,11 +78,9 @@ func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditio ...@@ -124,11 +78,9 @@ func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditio
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
}) })
r := make([]interface{}, 0) r := make([]interface{}, 0)
......
/*
Copyright 2019 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 application
import (
appv1beta1 "github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
"github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type applicationsGetter struct {
informer externalversions.SharedInformerFactory
}
func New(sharedInformers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &applicationsGetter{informer: sharedInformers}
}
func (d *applicationsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
}
func (d *applicationsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
all, err := d.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, app := range all {
result = append(result, app)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *applicationsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftApplication, ok := left.(*appv1beta1.Application)
if !ok {
return false
}
rightApplication, ok := right.(*appv1beta1.Application)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftApplication.ObjectMeta, rightApplication.ObjectMeta, field)
}
func (d *applicationsGetter) filter(object runtime.Object, filter query.Filter) bool {
application, ok := object.(*appv1beta1.Application)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(application.ObjectMeta, filter)
}
package application
import (
"github.com/google/go-cmp/cmp"
appv1beta1 "github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
"github.com/kubernetes-sigs/application/pkg/client/clientset/versioned/fake"
"github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"testing"
)
func applicationsToRuntimeObjects(applications ...*appv1beta1.Application) []runtime.Object {
var objs []runtime.Object
for _, app := range applications {
objs = append(objs, app)
}
return objs
}
func TestListApplications(t *testing.T) {
tests := []struct {
description string
namespace string
deployments []*appv1beta1.Application
query *query.Query
expected api.ListResult
expectedErr error
}{
{
"test name filter",
"bar2",
[]*appv1beta1.Application{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-1",
Namespace: "bar",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-2",
Namespace: "bar",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar-2",
Namespace: "bar2",
},
},
},
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: []query.Filter{
{
Field: query.FieldNamespace,
Value: query.Value("bar2"),
},
},
},
api.ListResult{
Items: []interface{}{
&appv1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "bar-2",
Namespace: "bar2",
},
},
},
TotalItems: 2,
},
nil,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
objs := applicationsToRuntimeObjects(test.deployments...)
client := fake.NewSimpleClientset(objs...)
informer := externalversions.NewSharedInformerFactory(client, 0)
for _, deployment := range test.deployments {
informer.App().V1beta1().Applications().Informer().GetIndexer().Add(deployment)
}
getter := New(informer)
got, err := getter.List(test.namespace, test.query)
if test.expectedErr != nil && err != test.expectedErr {
t.Errorf("expected error, got nothing")
} else if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(got.Items, test.expected.Items); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
/*
Copyright 2019 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 configmap
import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type configmapsGetter struct {
informer informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &configmapsGetter{informer: sharedInformers}
}
func (d *configmapsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
}
func (d *configmapsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
all, err := d.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, app := range all {
result = append(result, app)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *configmapsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftConfigMap, ok := left.(*corev1.ConfigMap)
if !ok {
return false
}
rightConfigMap, ok := right.(*corev1.ConfigMap)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftConfigMap.ObjectMeta, rightConfigMap.ObjectMeta, field)
}
func (d *configmapsGetter) filter(object runtime.Object, filter query.Filter) bool {
configMap, ok := object.(*corev1.ConfigMap)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(configMap.ObjectMeta, filter)
}
package configmap
import (
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"testing"
)
func TestListConfigMaps(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: []query.Filter{
{
Field: query.FieldNamespace,
Value: query.Value("default"),
},
},
},
&api.ListResult{
Items: []interface{}{foo3, foo2, foo1},
TotalItems: len(configmaps),
},
nil,
},
}
getter := prepare()
for _, test := range tests {
got, err := getter.List(test.namespace, test.query)
if test.expectedErr != nil && err != test.expectedErr {
t.Errorf("expected error, got nothing")
} else if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(got, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
var (
foo1 = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "default",
},
}
foo2 = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "default",
},
}
foo3 = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "foo3",
Namespace: "default",
},
}
configmaps = []interface{}{foo1, foo2, foo3}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, configmap := range configmaps {
informer.Core().V1().ConfigMaps().Informer().GetIndexer().Add(configmap)
}
return New(informer)
}
package deployment package deployment
import ( import (
"fmt"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
v1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query" "kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"testing" "testing"
"time"
) )
func newDeployments(total int, name, namespace, application string) []*v1.Deployment {
var deployments []*v1.Deployment
for i := 0; i < total; i++ {
deploy := &v1.Deployment{
TypeMeta: metaV1.TypeMeta{
Kind: "Deployment",
APIVersion: "v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", name, i),
Namespace: namespace,
Labels: map[string]string{
"seq": fmt.Sprintf("seq-%d", i),
},
Annotations: map[string]string{},
CreationTimestamp: metaV1.Time{Time: time.Now().Add(time.Duration(i*5) * time.Second)},
},
Status: v1.DeploymentStatus{
ReadyReplicas: int32(i + 1),
Replicas: int32(i + 1),
AvailableReplicas: int32(i + 1),
Conditions: []v1.DeploymentCondition{
{
Type: v1.DeploymentAvailable,
LastUpdateTime: metaV1.Time{Time: time.Now().Add(time.Duration(i*5) * time.Second)},
},
},
},
}
deployments = append(deployments, deploy)
}
return deployments
}
func deploymentsToRuntimeObjects(deployments ...*v1.Deployment) []runtime.Object {
var objs []runtime.Object
for _, deploy := range deployments {
objs = append(objs, deploy)
}
return objs
}
func TestListDeployments(t *testing.T) { func TestListDeployments(t *testing.T) {
tests := []struct { tests := []struct {
description string description string
namespace string namespace string
deployments []*v1.Deployment
query *query.Query query *query.Query
expected api.ListResult expected *api.ListResult
expectedErr error expectedErr error
}{ }{
{ {
"test name filter", "test name filter",
"bar", "bar",
[]*v1.Deployment{
{
ObjectMeta: metaV1.ObjectMeta{
Name: "foo-1",
Namespace: "bar",
},
},
{
ObjectMeta: metaV1.ObjectMeta{
Name: "foo-2",
Namespace: "bar",
},
},
{
ObjectMeta: metaV1.ObjectMeta{
Name: "bar-1",
Namespace: "bar",
},
},
},
&query.Query{ &query.Query{
Pagination: &query.Pagination{ Pagination: &query.Pagination{
Limit: 1, Limit: 1,
Offset: 1, Offset: 0,
}, },
SortBy: query.FieldName, SortBy: query.FieldName,
Ascending: false, Ascending: false,
Filters: []query.Filter{ Filters: []query.Filter{
{ {
Field: query.FieldName, Field: query.FieldName,
Value: query.Value("foo"), Value: query.Value("foo2"),
}, },
}, },
}, },
api.ListResult{ &api.ListResult{
Items: []interface{}{ Items: []interface{}{
&v1.Deployment{ foo2,
ObjectMeta: metaV1.ObjectMeta{
Name: "foo-2",
Namespace: "bar",
},
},
}, },
TotalItems: 2, TotalItems: 1,
}, },
nil, nil,
}, },
} }
getter := prepare()
for _, test := range tests { for _, test := range tests {
t.Run(test.description, func(t *testing.T) { t.Run(test.description, func(t *testing.T) {
objs := deploymentsToRuntimeObjects(test.deployments...)
client := fake.NewSimpleClientset(objs...)
informer := informers.NewSharedInformerFactory(client, 0)
for _, deployment := range test.deployments {
informer.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment)
}
getter := New(informer)
got, err := getter.List(test.namespace, test.query) got, err := getter.List(test.namespace, test.query)
if test.expectedErr != nil && err != test.expectedErr { if test.expectedErr != nil && err != test.expectedErr {
t.Errorf("expected error, got nothing") t.Errorf("expected error, got nothing")
} else if err != nil { } else if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if diff := cmp.Diff(got.Items, test.expected.Items); diff != "" { if diff := cmp.Diff(got, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff) t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
} }
}) })
} }
} }
var (
foo1 = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "bar",
},
}
foo2 = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "bar",
},
}
bar1 = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
Namespace: "bar",
},
}
deployments = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, deployment := range deployments {
informer.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment)
}
return New(informer)
}
...@@ -17,6 +17,7 @@ type Interface interface { ...@@ -17,6 +17,7 @@ type Interface interface {
List(namespace string, query *query.Query) (*api.ListResult, error) List(namespace string, query *query.Query) (*api.ListResult, error)
} }
// CompareFunc return true is left great than right
type CompareFunc func(runtime.Object, runtime.Object, query.Field) bool type CompareFunc func(runtime.Object, runtime.Object, query.Field) bool
type FilterFunc func(runtime.Object, query.Filter) bool type FilterFunc func(runtime.Object, query.Filter) bool
...@@ -41,9 +42,9 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa ...@@ -41,9 +42,9 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa
// sort by sortBy field // sort by sortBy field
sort.Slice(filtered, func(i, j int) bool { sort.Slice(filtered, func(i, j int) bool {
if !query.Ascending { if !query.Ascending {
return !compareFunc(filtered[i], filtered[j], query.SortBy) return compareFunc(filtered[i], filtered[j], query.SortBy)
} }
return compareFunc(filtered[i], filtered[j], query.SortBy) return !compareFunc(filtered[i], filtered[j], query.SortBy)
}) })
total := len(filtered) total := len(filtered)
...@@ -55,6 +56,7 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa ...@@ -55,6 +56,7 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa
} }
} }
// DefaultObjectMetaCompare return true is left great than right
func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field) bool { func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field) bool {
switch sortBy { switch sortBy {
// ?sortBy=name // ?sortBy=name
...@@ -62,6 +64,10 @@ func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field) ...@@ -62,6 +64,10 @@ func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field)
return strings.Compare(left.Name, right.Name) > 0 return strings.Compare(left.Name, right.Name) > 0
// ?sortBy=creationTimestamp // ?sortBy=creationTimestamp
case query.FieldCreationTimeStamp: case query.FieldCreationTimeStamp:
// compare by name if creation timestamp is equal
if left.CreationTimestamp.Equal(&right.CreationTimestamp) {
return strings.Compare(left.Name, right.Name) > 0
}
return left.CreationTimestamp.After(right.CreationTimestamp.Time) return left.CreationTimestamp.After(right.CreationTimestamp.Time)
default: default:
return false return false
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"kubesphere.io/kubesphere/pkg/apiserver/query" "kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/application"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/deployment" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/deployment"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/namespace" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/namespace"
) )
...@@ -17,11 +18,12 @@ type ResourceGetter struct { ...@@ -17,11 +18,12 @@ type ResourceGetter struct {
getters map[schema.GroupVersionResource]v1alpha3.Interface getters map[schema.GroupVersionResource]v1alpha3.Interface
} }
func New(factory informers.InformerFactory) *ResourceGetter { func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
getters := make(map[schema.GroupVersionResource]v1alpha3.Interface) getters := make(map[schema.GroupVersionResource]v1alpha3.Interface)
getters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(factory.KubernetesSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}] = namespace.New(factory.KubernetesSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}] = namespace.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(factory.ApplicationSharedInformerFactory())
return &ResourceGetter{ return &ResourceGetter{
getters: getters, getters: getters,
......
...@@ -22,8 +22,8 @@ import ( ...@@ -22,8 +22,8 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
fakeapp "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned/fake" fakeapp "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned/fake"
fakeistio "istio.io/client-go/pkg/clientset/versioned/fake" fakeistio "istio.io/client-go/pkg/clientset/versioned/fake"
v1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
corev1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakek8s "k8s.io/client-go/kubernetes/fake" fakek8s "k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query" "kubesphere.io/kubesphere/pkg/apiserver/query"
...@@ -34,37 +34,7 @@ import ( ...@@ -34,37 +34,7 @@ import (
func TestResourceGetter(t *testing.T) { func TestResourceGetter(t *testing.T) {
namespaces := make([]interface{}, 0) resource := prepare()
defaultNamespace := &v1.Namespace{
ObjectMeta: corev1.ObjectMeta{
Name: "default",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
kubesphereNamespace := &v1.Namespace{
ObjectMeta: corev1.ObjectMeta{
Name: "kubesphere-system",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
namespaces = append(namespaces, defaultNamespace, kubesphereNamespace)
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset(defaultNamespace, kubesphereNamespace)
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient)
k8sInformerFactory := fakeInformerFactory.KubernetesSharedInformerFactory()
for _, namespace := range namespaces {
err := k8sInformerFactory.Core().V1().Namespaces().Informer().GetIndexer().Add(namespace)
if err != nil {
t.Fatal(err)
}
}
resource := New(fakeInformerFactory)
tests := []struct { tests := []struct {
Name string Name string
...@@ -89,8 +59,8 @@ func TestResourceGetter(t *testing.T) { ...@@ -89,8 +59,8 @@ func TestResourceGetter(t *testing.T) {
}, },
ExpectError: nil, ExpectError: nil,
ExpectResponse: &api.ListResult{ ExpectResponse: &api.ListResult{
Items: namespaces, Items: []interface{}{foo2, foo1, bar1},
TotalItems: 2, TotalItems: 3,
}, },
}, },
} }
...@@ -99,7 +69,6 @@ func TestResourceGetter(t *testing.T) { ...@@ -99,7 +69,6 @@ func TestResourceGetter(t *testing.T) {
result, err := resource.List(test.Resource, test.Namespace, test.Query) result, err := resource.List(test.Resource, test.Namespace, test.Query)
t.Logf("%+v", result)
if err != test.ExpectError { if err != test.ExpectError {
t.Errorf("expected error: %s, got: %s", test.ExpectError, err) t.Errorf("expected error: %s, got: %s", test.ExpectError, err)
} }
...@@ -107,5 +76,44 @@ func TestResourceGetter(t *testing.T) { ...@@ -107,5 +76,44 @@ func TestResourceGetter(t *testing.T) {
t.Errorf(diff) t.Errorf(diff)
} }
} }
}
var (
foo1 = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "bar",
},
}
foo2 = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "bar",
},
}
bar1 = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
Namespace: "bar",
},
}
namespaces = []interface{}{foo1, foo2, bar1}
)
func prepare() *ResourceGetter {
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient)
for _, namespace := range namespaces {
fakeInformerFactory.KubernetesSharedInformerFactory().Core().V1().
Namespaces().Informer().GetIndexer().Add(namespace)
}
return NewResourceGetter(fakeInformerFactory)
} }
...@@ -21,63 +21,91 @@ import ( ...@@ -21,63 +21,91 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizerfactory"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam/am" "kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/simple/client/k8s"
) )
type Interface interface { type Interface interface {
ListWorkspaces(username string) (*api.ListResult, error) ListWorkspaces(user user.Info) (*api.ListResult, error)
ListNamespaces(username, workspace string) (*api.ListResult, error) ListNamespaces(user user.Info, workspace string) (*api.ListResult, error)
} }
type tenantOperator struct { type tenantOperator struct {
informers informers.InformerFactory informers informers.InformerFactory
am am.AccessManagementInterface am am.AccessManagementInterface
authorizer authorizer.Authorizer
} }
func New(k8sClient k8s.Client, informers informers.InformerFactory) Interface { func New(k8sClient k8s.Client, informers informers.InformerFactory) Interface {
amOperator := am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory())
opaAuthorizer := authorizerfactory.NewOPAAuthorizer(amOperator)
return &tenantOperator{ return &tenantOperator{
informers: informers, informers: informers,
am: am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory()), am: amOperator,
authorizer: opaAuthorizer,
} }
} }
func (t *tenantOperator) ListWorkspaces(username string) (*api.ListResult, error) { func (t *tenantOperator) ListWorkspaces(user user.Info) (*api.ListResult, error) {
workspaces := make([]*tenantv1alpha1.Workspace, 0)
listWS := authorizer.AttributesRecord{
User: user,
Verb: "list",
APIGroup: "tenant.kubesphere.io",
APIVersion: "v1alpha2",
Resource: "workspaces",
}
decision, _, err := t.authorizer.Authorize(listWS)
workspaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, username)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
workspaces := make([]*tenantv1alpha1.Workspace, 0) if decision == authorizer.DecisionAllow {
workspaces, err = t.informers.KubeSphereSharedInformerFactory().
for _, role := range workspaceRoles { Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
// all workspaces are allowed
if role.Target.Name == iamv1alpha2.TargetAll {
workspaces, err = t.informers.KubeSphereSharedInformerFactory().
Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
break
}
workspace, err := t.informers.KubeSphereSharedInformerFactory().
Tenant().V1alpha1().Workspaces().Lister().Get(role.Target.Name)
if errors.IsNotFound(err) { if err != nil {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target) klog.Error(err)
continue return nil, err
} }
} else {
workspaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, user.GetName())
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
if !containsWorkspace(workspaces, workspace) {
workspaces = append(workspaces, workspace) for _, role := range workspaceRoles {
workspace, err := t.informers.KubeSphereSharedInformerFactory().
Tenant().V1alpha1().Workspaces().Lister().Get(role.Target.Name)
if errors.IsNotFound(err) {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
continue
}
if err != nil {
klog.Error(err)
return nil, err
}
if !containsWorkspace(workspaces, workspace) {
workspaces = append(workspaces, workspace)
}
} }
} }
...@@ -87,39 +115,59 @@ func (t *tenantOperator) ListWorkspaces(username string) (*api.ListResult, error ...@@ -87,39 +115,59 @@ func (t *tenantOperator) ListWorkspaces(username string) (*api.ListResult, error
}, nil }, nil
} }
func (t *tenantOperator) ListNamespaces(username, workspace string) (*api.ListResult, error) { func (t *tenantOperator) ListNamespaces(user user.Info, workspace string) (*api.ListResult, error) {
namespaces := make([]*corev1.Namespace, 0)
listNSInWS := authorizer.AttributesRecord{
User: user,
Verb: "list",
APIGroup: "",
APIVersion: "v1",
Workspace: workspace,
Resource: "namespaces",
}
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, username) decision, _, err := t.authorizer.Authorize(listNSInWS)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
namespaces := make([]*corev1.Namespace, 0) if decision == authorizer.DecisionAllow {
namespaces, err = t.informers.KubernetesSharedInformerFactory().
for _, role := range namespaceRoles { Core().V1().Namespaces().Lister().List(labels.Everything())
// all workspaces are allowed if err != nil {
if role.Target.Name == iamv1alpha2.TargetAll { klog.Error(err)
namespaces, err = t.informers.KubernetesSharedInformerFactory(). return nil, err
Core().V1().Namespaces().Lister().List(labels.Everything())
break
} }
} else {
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, workspace)
namespace, err := t.informers.KubernetesSharedInformerFactory().
Core().V1().Namespaces().Lister().Get(role.Target.Name)
if errors.IsNotFound(err) {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
continue
}
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
if !containsNamespace(namespaces, namespace) {
namespaces = append(namespaces, namespace) for _, role := range namespaceRoles {
namespace, err := t.informers.KubernetesSharedInformerFactory().
Core().V1().Namespaces().Lister().Get(role.Target.Name)
if errors.IsNotFound(err) {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
continue
}
if err != nil {
klog.Error(err)
return nil, err
}
if !containsNamespace(namespaces, namespace) {
namespaces = append(namespaces, namespace)
}
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册