@@ -1,5 +1,5 @@
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: MutatingWebhookConfiguration
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: kubesphere-iam-validator
|
||||
webhooks:
|
||||
|
||||
@@ -152,7 +152,6 @@ const (
|
||||
ClusterScope Scope = "Cluster"
|
||||
WorkspaceScope Scope = "Workspace"
|
||||
NamespaceScope Scope = "Namespace"
|
||||
TargetAll = "*"
|
||||
UserKind = "User"
|
||||
PolicyRuleKind = "PolicyRule"
|
||||
RoleKind = "Role"
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
resourcesv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2"
|
||||
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
|
||||
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"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||
@@ -141,6 +142,7 @@ func (s *APIServer) installKubeSphereAPIs() {
|
||||
urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
|
||||
urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
|
||||
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(iamv1alpha2.AddToContainer(s.container, im.NewOperator(s.KubernetesClient.KubeSphere(),
|
||||
s.InformerFactory.KubeSphereSharedInformerFactory()),
|
||||
@@ -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: "rolebindings"},
|
||||
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "policyrules"},
|
||||
{Group: "tower.kubesphere.io", Version: "v1alpha1", Resource: "agents"},
|
||||
}
|
||||
|
||||
devopsGVRs := []schema.GroupVersionResource{
|
||||
|
||||
@@ -51,7 +51,7 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
|
||||
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 {
|
||||
return authorized, reason, nil
|
||||
}
|
||||
|
||||
@@ -48,11 +48,12 @@ func newPagination(limit int, offset int) *Pagination {
|
||||
}
|
||||
|
||||
func (p *Pagination) GetValidPagination(total int) (startIndex, endIndex int) {
|
||||
|
||||
if p.Limit == NoPagination.Limit {
|
||||
return 0, total
|
||||
}
|
||||
|
||||
if p.Limit < 0 || p.Offset < 0 {
|
||||
if p.Limit < 0 || p.Offset < 0 || total == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
|
||||
limit, offset := params.ParsePaging(request)
|
||||
namespace := request.PathParameter("namespace")
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
@@ -301,7 +301,7 @@ func (h *openpitrixHandler) GetAppVersionFiles(req *restful.Request, resp *restf
|
||||
func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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")
|
||||
versionId := req.PathParameter("version")
|
||||
conditions, err := params.ParseConditions(req)
|
||||
@@ -331,7 +331,7 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res
|
||||
func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
@@ -354,7 +354,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
|
||||
func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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")
|
||||
statistics := params.GetBoolValueWithDefault(req, "statistics", false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
@@ -394,7 +394,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
|
||||
func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
@@ -697,7 +697,7 @@ func (h *openpitrixHandler) DescribeCategory(req *restful.Request, resp *restful
|
||||
func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
@@ -836,7 +836,7 @@ func (h *openpitrixHandler) DescribeRepo(req *restful.Request, resp *restful.Res
|
||||
func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req)
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -66,18 +66,20 @@ func (r *resourceHandler) handleListNamespaceResources(request *restful.Request,
|
||||
conditions, err := params.ParseConditions(request)
|
||||
|
||||
if err != nil {
|
||||
response.WriteHeaderAndEntity(http.StatusBadRequest, err)
|
||||
klog.Error(err)
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := r.resourcesGetter.ListResources(namespace, resource, conditions, orderBy, reverse, limit, offset)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
api.HandleInternalError(response, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, response *restful.Response) {
|
||||
|
||||
@@ -2,34 +2,56 @@ package v1alpha3
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/components"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||
"net/http"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
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 {
|
||||
namespacedResourceGetter *resource.ResourceGetter
|
||||
componentsGetter components.ComponentsGetter
|
||||
resourceGetterV1alpha3 *resourcev1alpha3.ResourceGetter
|
||||
resourcesGetterV1alpha2 *resourcev1alpha2.ResourceGetter
|
||||
componentsGetter components.ComponentsGetter
|
||||
}
|
||||
|
||||
func New(factory informers.InformerFactory) *Handler {
|
||||
return &Handler{
|
||||
namespacedResourceGetter: resource.New(factory),
|
||||
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
|
||||
resourceGetterV1alpha3: resourcev1alpha3.NewResourceGetter(factory),
|
||||
resourcesGetterV1alpha2: resourcev1alpha2.NewResourceGetter(factory),
|
||||
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
resource := request.PathParameter("resources")
|
||||
resourceType := request.PathParameter("resources")
|
||||
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 {
|
||||
klog.Error(err)
|
||||
api.HandleInternalError(response, nil, err)
|
||||
return
|
||||
}
|
||||
@@ -37,38 +59,96 @@ func (h Handler) handleListResources(request *restful.Request, response *restful
|
||||
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 := ¶ms.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")
|
||||
result, err := h.componentsGetter.GetComponentStatus(component)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
api.HandleInternalError(response, nil, err)
|
||||
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()
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
api.HandleInternalError(response, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeaderAndEntity(http.StatusOK, result)
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
api.HandleInternalError(response, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeaderAndEntity(http.StatusOK, result)
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,191 @@
|
||||
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
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.tenant.ListWorkspaces(user.GetName())
|
||||
result, err := h.tenant.ListWorkspaces(user)
|
||||
|
||||
if err != nil {
|
||||
api.HandleInternalError(resp, nil, err)
|
||||
@@ -52,9 +52,9 @@ func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Respo
|
||||
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 {
|
||||
api.HandleInternalError(resp, nil, err)
|
||||
|
||||
@@ -113,8 +113,7 @@ func (am *amOperator) GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target
|
||||
return nil, err
|
||||
}
|
||||
for _, role := range roles {
|
||||
if role.Target.Name == iamv1alpha2.TargetAll ||
|
||||
role.Target.Name == target {
|
||||
if role.Target.Name == target {
|
||||
return &role, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,18 +22,9 @@ import (
|
||||
"github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
|
||||
"github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
app = "app"
|
||||
chart = "chart"
|
||||
release = "release"
|
||||
)
|
||||
|
||||
type appSearcher struct {
|
||||
@@ -48,68 +39,22 @@ func (s *appSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
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 {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range fuzzy {
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
@@ -134,7 +79,7 @@ func (s *appSearcher) Search(namespace string, conditions *params.Conditions, or
|
||||
if reverse {
|
||||
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)
|
||||
|
||||
@@ -18,17 +18,14 @@
|
||||
package clusterrole
|
||||
|
||||
import (
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type clusterRoleSearcher struct {
|
||||
@@ -43,7 +40,6 @@ func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
@@ -55,15 +51,6 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
|
||||
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
|
||||
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:
|
||||
if v == "true" {
|
||||
if !isUserFacingClusterRole(item) {
|
||||
@@ -71,8 +58,7 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
|
||||
}
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -80,43 +66,15 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
|
||||
func (s *clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything())
|
||||
|
||||
@@ -137,11 +95,9 @@ func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Condit
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -18,16 +18,12 @@
|
||||
package configmap
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type configMapSearcher struct {
|
||||
@@ -42,68 +38,22 @@ func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
|
||||
func (s *configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range fuzzy {
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
@@ -128,7 +78,7 @@ func (s *configMapSearcher) Search(namespace string, conditions *params.Conditio
|
||||
if reverse {
|
||||
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)
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package cronjob
|
||||
|
||||
import (
|
||||
"k8s.io/api/batch/v1beta1"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/batch/v1beta1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
@@ -50,26 +46,15 @@ func cronJobStatus(item *v1beta1.CronJob) string {
|
||||
return v1alpha2.StatusRunning
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Status:
|
||||
if cronJobStatus(item) != v {
|
||||
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 {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool {
|
||||
func (*cronJobSearcher) compare(left, right *v1beta1.CronJob, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case v1alpha2.LastScheduleTime:
|
||||
if a.Status.LastScheduleTime == nil {
|
||||
if left.Status.LastScheduleTime == nil {
|
||||
return true
|
||||
}
|
||||
if b.Status.LastScheduleTime == nil {
|
||||
if right.Status.LastScheduleTime == nil {
|
||||
return false
|
||||
}
|
||||
return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime)
|
||||
case v1alpha2.CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
return left.Status.LastScheduleTime.Before(right.Status.LastScheduleTime)
|
||||
default:
|
||||
fallthrough
|
||||
case v1alpha2.Name:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +107,7 @@ func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions
|
||||
}
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
i, j = j, i
|
||||
}
|
||||
return c.compare(result[i], result[j], orderBy)
|
||||
return c.compare(result[i], result[j], orderBy) && !reverse
|
||||
})
|
||||
|
||||
r := make([]interface{}, 0)
|
||||
|
||||
@@ -18,16 +18,12 @@
|
||||
package daemonset
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type daemonSetSearcher struct {
|
||||
@@ -52,7 +48,6 @@ func daemonSetStatus(item *v1.DaemonSet) string {
|
||||
}
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
@@ -60,18 +55,8 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo
|
||||
if daemonSetStatus(item) != v {
|
||||
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:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -79,48 +64,15 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo
|
||||
return true
|
||||
}
|
||||
|
||||
func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
func (*daemonSetSearcher) fuzzy(kv map[string]string, item *v1.DaemonSet) bool {
|
||||
for k, v := range kv {
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
if reverse {
|
||||
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)
|
||||
|
||||
155
pkg/models/resources/v1alpha2/deployment/deployments.go
Normal file
155
pkg/models/resources/v1alpha2/deployment/deployments.go
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
*
|
||||
* 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
|
||||
|
||||
import (
|
||||
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type hpaSearcher struct {
|
||||
@@ -58,17 +54,8 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
|
||||
if !hpaTargetMatch(item, kind, name) {
|
||||
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:
|
||||
if item.Labels[k] != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -76,47 +63,15 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package ingress
|
||||
|
||||
import (
|
||||
"k8s.io/api/extensions/v1beta1"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
@@ -43,70 +39,24 @@ func (s *ingressSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*ingressSearcher) match(match map[string]string, item *v1beta1.Ingress) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Ingress) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -24,6 +27,7 @@ const (
|
||||
Keyword = "keyword"
|
||||
UserFacing = "userfacing"
|
||||
Status = "status"
|
||||
Owner = "owner"
|
||||
|
||||
StatusRunning = "running"
|
||||
StatusPaused = "paused"
|
||||
@@ -66,7 +70,61 @@ type Interface interface {
|
||||
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]
|
||||
|
||||
@@ -78,3 +136,17 @@ func SearchFuzzy(m map[string]string, key, value string) bool {
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
@@ -64,7 +61,6 @@ func jobStatus(item *batchv1.Job) string {
|
||||
return status
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
@@ -80,18 +76,8 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
|
||||
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") {
|
||||
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:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -143,16 +107,12 @@ func jobUpdateTime(item *batchv1.Job) time.Time {
|
||||
return updateTime
|
||||
}
|
||||
|
||||
func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool {
|
||||
func (*jobSearcher) compare(left, right *batchv1.Job, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case v1alpha2.CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case v1alpha2.UpdateTime:
|
||||
return jobUpdateTime(a).Before(jobUpdateTime(b))
|
||||
case v1alpha2.Name:
|
||||
fallthrough
|
||||
return jobUpdateTime(left).Before(jobUpdateTime(right))
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
i, j = j, i
|
||||
}
|
||||
return s.compare(result[i], result[j], orderBy)
|
||||
})
|
||||
|
||||
@@ -19,16 +19,12 @@ package namespace
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type namespaceSearcher struct {
|
||||
@@ -43,66 +39,24 @@ func (s *namespaceSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Core().V1().Namespaces().Lister().Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
namespaces, err := s.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
|
||||
@@ -123,11 +77,9 @@ func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditio
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -20,16 +20,12 @@ package node
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -80,15 +76,9 @@ func isUnhealthyStatus(condition v1.NodeCondition) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Role:
|
||||
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
|
||||
if _, ok := item.Labels[labelKey]; !ok {
|
||||
@@ -98,13 +88,8 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
if getNodeStatus(item) != v {
|
||||
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 {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -112,43 +97,15 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -19,7 +19,6 @@ package persistentvolumeclaim
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"strconv"
|
||||
|
||||
@@ -60,15 +59,9 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string {
|
||||
return status
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Status:
|
||||
statuses := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(statuses, pvcStatus(item)) {
|
||||
@@ -78,13 +71,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
|
||||
if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v {
|
||||
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 {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -92,47 +80,15 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -20,16 +20,12 @@ package pod
|
||||
import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type podSearcher struct {
|
||||
@@ -153,7 +149,6 @@ func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool
|
||||
return true
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
@@ -177,18 +172,8 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
if !s.podBelongToService(item, v) {
|
||||
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:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -196,52 +181,27 @@ func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool {
|
||||
func (*podSearcher) compare(left, right *v1.Pod, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case v1alpha2.StartTime:
|
||||
if a.Status.StartTime == nil {
|
||||
if left.Status.StartTime == nil {
|
||||
return false
|
||||
}
|
||||
if b.Status.StartTime == nil {
|
||||
if right.Status.StartTime == nil {
|
||||
return true
|
||||
}
|
||||
return a.Status.StartTime.Before(b.Status.StartTime)
|
||||
case v1alpha2.CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case v1alpha2.Name:
|
||||
fallthrough
|
||||
return left.Status.StartTime.Before(right.Status.StartTime)
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
i, j = j, i
|
||||
}
|
||||
return s.compare(result[i], result[j], orderBy)
|
||||
})
|
||||
|
||||
236
pkg/models/resources/v1alpha2/resource/resource_test.go
Normal file
236
pkg/models/resources/v1alpha2/resource/resource_test.go
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
*
|
||||
* 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: ¶ms.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: ¶ms.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: ¶ms.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: ¶ms.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: ¶ms.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: ¶ms.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 (
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob"
|
||||
"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/ingress"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job"
|
||||
@@ -62,11 +63,10 @@ func (r ResourceGetter) Add(resource string, getter v1alpha2.Interface) {
|
||||
func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
|
||||
resourceGetters := make(map[string]v1alpha2.Interface)
|
||||
|
||||
//resourceGetters[v1alpha2.Deployments] = deployments
|
||||
resourceGetters[v1alpha2.ConfigMaps] = configmap.NewConfigmapSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.CronJobs] = cronjob.NewCronJobSearcher(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.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory())
|
||||
@@ -75,18 +75,16 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
|
||||
resourceGetters[v1alpha2.StatefulSets] = statefulset.NewStatefulSetSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.Pods] = pod.NewPodSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.Roles] = role.NewRoleSearcher(factory.KubernetesSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.Nodes] = node.NewNodeSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.Namespaces] = namespace.NewNamespaceSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.ClusterRoles] = clusterrole.NewClusterRoleSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(factory.ApplicationSharedInformerFactory())
|
||||
|
||||
return &ResourceGetter{resourcesGetters: resourceGetters}
|
||||
|
||||
@@ -22,13 +22,10 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type roleSearcher struct {
|
||||
@@ -43,19 +40,9 @@ func (s *roleSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Rbac().V1().Roles().Lister().Roles(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range match {
|
||||
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:
|
||||
if v == "true" {
|
||||
if !isUserFacingRole(item) {
|
||||
@@ -63,8 +50,7 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
}
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -72,43 +58,15 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -20,15 +20,11 @@ package s2buildertemplate
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type s2iBuilderTemplateSearcher struct {
|
||||
@@ -43,66 +39,24 @@ func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, e
|
||||
return s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
builderTemplates, err := s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything())
|
||||
|
||||
@@ -123,11 +77,9 @@ func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -22,13 +22,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type s2iBuilderSearcher struct {
|
||||
@@ -43,66 +40,24 @@ func (s *s2iBuilderSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -22,12 +22,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type s2iRunSearcher struct {
|
||||
@@ -42,26 +39,15 @@ func (s *s2iRunSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Status:
|
||||
if string(item.Status.RunState) != v {
|
||||
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 {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -69,43 +55,15 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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,
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -19,16 +19,12 @@ package secret
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type secretSearcher struct {
|
||||
@@ -43,26 +39,15 @@ func (s *secretSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case "type":
|
||||
if string(item.Type) != v {
|
||||
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 {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -70,47 +55,15 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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,
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -19,16 +19,12 @@ package service
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type serviceSearcher struct {
|
||||
@@ -43,70 +39,24 @@ func (s *serviceSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Core().V1().Services().Lister().Services(namespace).Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -19,16 +19,12 @@ package statefulset
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"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/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type statefulSetSearcher struct {
|
||||
@@ -56,26 +52,15 @@ func statefulSetStatus(item *v1.StatefulSet) string {
|
||||
return v1alpha2.StatusStopped
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool {
|
||||
for k, v := range match {
|
||||
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:
|
||||
if statefulSetStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
@@ -19,16 +19,12 @@ package storageclass
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type storageClassesSearcher struct {
|
||||
@@ -43,66 +39,24 @@ func (s *storageClassesSearcher) Get(namespace, name string) (interface{}, error
|
||||
return s.informers.Storage().V1().StorageClasses().Lister().Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
storageClasses, err := s.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything())
|
||||
|
||||
@@ -125,7 +79,7 @@ func (s *storageClassesSearcher) Search(namespace string, conditions *params.Con
|
||||
if reverse {
|
||||
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)
|
||||
|
||||
@@ -20,15 +20,11 @@ package workspace
|
||||
import (
|
||||
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type workspaceSearcher struct {
|
||||
@@ -43,66 +39,24 @@ func (s *workspaceSearcher) Get(namespace, name string) (interface{}, error) {
|
||||
return s.informers.Tenant().V1alpha1().Workspaces().Lister().Get(name)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range match {
|
||||
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
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range fuzzy {
|
||||
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
|
||||
}
|
||||
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
|
||||
@@ -124,11 +78,9 @@ func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditio
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
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)
|
||||
|
||||
78
pkg/models/resources/v1alpha3/application/applications.go
Normal file
78
pkg/models/resources/v1alpha3/application/applications.go
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
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)
|
||||
}
|
||||
109
pkg/models/resources/v1alpha3/application/applications_test.go
Normal file
109
pkg/models/resources/v1alpha3/application/applications_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
78
pkg/models/resources/v1alpha3/configmap/configmaps.go
Normal file
78
pkg/models/resources/v1alpha3/configmap/configmaps.go
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
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)
|
||||
}
|
||||
96
pkg/models/resources/v1alpha3/configmap/configmaps_test.go
Normal file
96
pkg/models/resources/v1alpha3/configmap/configmaps_test.go
Normal file
@@ -0,0 +1,96 @@
|
||||
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)
|
||||
}
|
||||
@@ -1,149 +1,103 @@
|
||||
package deployment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
appsv1 "k8s.io/api/apps/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"
|
||||
"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) {
|
||||
tests := []struct {
|
||||
description string
|
||||
namespace string
|
||||
deployments []*v1.Deployment
|
||||
query *query.Query
|
||||
expected api.ListResult
|
||||
expected *api.ListResult
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
"test name filter",
|
||||
"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{
|
||||
Pagination: &query.Pagination{
|
||||
Limit: 1,
|
||||
Offset: 1,
|
||||
Offset: 0,
|
||||
},
|
||||
SortBy: query.FieldName,
|
||||
Ascending: false,
|
||||
Filters: []query.Filter{
|
||||
{
|
||||
Field: query.FieldName,
|
||||
Value: query.Value("foo"),
|
||||
Value: query.Value("foo2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
api.ListResult{
|
||||
&api.ListResult{
|
||||
Items: []interface{}{
|
||||
&v1.Deployment{
|
||||
ObjectMeta: metaV1.ObjectMeta{
|
||||
Name: "foo-2",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
foo2,
|
||||
},
|
||||
TotalItems: 2,
|
||||
TotalItems: 1,
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
getter := prepare()
|
||||
|
||||
for _, test := range tests {
|
||||
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)
|
||||
|
||||
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 != "" {
|
||||
if diff := cmp.Diff(got, 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 {
|
||||
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 FilterFunc func(runtime.Object, query.Filter) bool
|
||||
@@ -41,9 +42,9 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa
|
||||
// sort by sortBy field
|
||||
sort.Slice(filtered, func(i, j int) bool {
|
||||
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)
|
||||
@@ -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 {
|
||||
switch sortBy {
|
||||
// ?sortBy=name
|
||||
@@ -62,6 +64,10 @@ func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field)
|
||||
return strings.Compare(left.Name, right.Name) > 0
|
||||
// ?sortBy=creationTimestamp
|
||||
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)
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"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/namespace"
|
||||
)
|
||||
@@ -17,11 +18,12 @@ type ResourceGetter struct {
|
||||
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[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: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(factory.ApplicationSharedInformerFactory())
|
||||
|
||||
return &ResourceGetter{
|
||||
getters: getters,
|
||||
|
||||
@@ -22,8 +22,8 @@ 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"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/apimachinery/pkg/apis/meta/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"
|
||||
@@ -34,37 +34,7 @@ import (
|
||||
|
||||
func TestResourceGetter(t *testing.T) {
|
||||
|
||||
namespaces := make([]interface{}, 0)
|
||||
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)
|
||||
resource := prepare()
|
||||
|
||||
tests := []struct {
|
||||
Name string
|
||||
@@ -89,8 +59,8 @@ func TestResourceGetter(t *testing.T) {
|
||||
},
|
||||
ExpectError: nil,
|
||||
ExpectResponse: &api.ListResult{
|
||||
Items: namespaces,
|
||||
TotalItems: 2,
|
||||
Items: []interface{}{foo2, foo1, bar1},
|
||||
TotalItems: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -99,7 +69,6 @@ func TestResourceGetter(t *testing.T) {
|
||||
|
||||
result, err := resource.List(test.Resource, test.Namespace, test.Query)
|
||||
|
||||
t.Logf("%+v", result)
|
||||
if err != test.ExpectError {
|
||||
t.Errorf("expected error: %s, got: %s", test.ExpectError, err)
|
||||
}
|
||||
@@ -107,5 +76,44 @@ func TestResourceGetter(t *testing.T) {
|
||||
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 (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
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/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
ListWorkspaces(username string) (*api.ListResult, error)
|
||||
ListNamespaces(username, workspace string) (*api.ListResult, error)
|
||||
ListWorkspaces(user user.Info) (*api.ListResult, error)
|
||||
ListNamespaces(user user.Info, workspace string) (*api.ListResult, error)
|
||||
}
|
||||
|
||||
type tenantOperator struct {
|
||||
informers informers.InformerFactory
|
||||
am am.AccessManagementInterface
|
||||
informers informers.InformerFactory
|
||||
am am.AccessManagementInterface
|
||||
authorizer authorizer.Authorizer
|
||||
}
|
||||
|
||||
func New(k8sClient k8s.Client, informers informers.InformerFactory) Interface {
|
||||
amOperator := am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory())
|
||||
opaAuthorizer := authorizerfactory.NewOPAAuthorizer(amOperator)
|
||||
return &tenantOperator{
|
||||
informers: informers,
|
||||
am: am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory()),
|
||||
informers: informers,
|
||||
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 {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
workspaces := make([]*tenantv1alpha1.Workspace, 0)
|
||||
if decision == authorizer.DecisionAllow {
|
||||
workspaces, err = t.informers.KubeSphereSharedInformerFactory().
|
||||
Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
|
||||
|
||||
for _, role := range workspaceRoles {
|
||||
|
||||
// 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) {
|
||||
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)
|
||||
} else {
|
||||
workspaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, user.GetName())
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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
|
||||
}, 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)
|
||||
|
||||
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, username)
|
||||
listNSInWS := authorizer.AttributesRecord{
|
||||
User: user,
|
||||
Verb: "list",
|
||||
APIGroup: "",
|
||||
APIVersion: "v1",
|
||||
Workspace: workspace,
|
||||
Resource: "namespaces",
|
||||
}
|
||||
|
||||
decision, _, err := t.authorizer.Authorize(listNSInWS)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespaces := make([]*corev1.Namespace, 0)
|
||||
if decision == authorizer.DecisionAllow {
|
||||
namespaces, err = t.informers.KubernetesSharedInformerFactory().
|
||||
Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
|
||||
for _, role := range namespaceRoles {
|
||||
|
||||
// all workspaces are allowed
|
||||
if role.Target.Name == iamv1alpha2.TargetAll {
|
||||
namespaces, err = t.informers.KubernetesSharedInformerFactory().
|
||||
Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
break
|
||||
}
|
||||
|
||||
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)
|
||||
} else {
|
||||
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, workspace)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user