devlopment branch (#1736)

This commit is contained in:
zryfish
2020-01-02 20:52:00 +08:00
committed by GitHub
parent ff0ffe8650
commit eceadec69c
440 changed files with 61524 additions and 3699 deletions

View File

@@ -1,167 +0,0 @@
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resources
import (
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"time"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/api/apps/v1"
)
type deploymentSearcher struct {
}
func (*deploymentSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().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 StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return StatusRunning
} else {
return StatusUpdating
}
}
return StatusStopped
}
// Exactly Match
func (*deploymentSearcher) match(match map[string]string, item *v1.Deployment) bool {
for k, v := range match {
switch k {
case Status:
if deploymentStatus(item) != v {
return false
}
case Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !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
}
func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) bool {
for k, v := range fuzzy {
switch k {
case Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
return false
}
}
}
return true
}
func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
switch orderBy {
case CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case UpdateTime:
return s.lastUpdateTime(a).Before(s.lastUpdateTime(b))
case Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
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 := informers.SharedInformerFactory().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 {
tmp := i
i = j
j = tmp
}
return s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}

View File

@@ -1,120 +0,0 @@
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resources
import (
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/informers"
"strconv"
)
type extraAnnotationInjector struct {
}
func (i extraAnnotationInjector) addExtraAnnotations(item interface{}) interface{} {
switch item.(type) {
case *corev1.PersistentVolumeClaim:
return i.injectPersistentVolumeClaim(item.(*corev1.PersistentVolumeClaim))
case *storagev1.StorageClass:
return i.injectStorageClass(item.(*storagev1.StorageClass))
}
return item
}
func (i extraAnnotationInjector) injectStorageClass(item *storagev1.StorageClass) *storagev1.StorageClass {
count, err := countPvcByStorageClass(item.Name)
if err != nil {
klog.Errorf("inject annotation failed %+v", err)
return item
}
item = item.DeepCopy()
if item.Annotations == nil {
item.Annotations = make(map[string]string, 0)
}
item.Annotations["kubesphere.io/pvc-count"] = strconv.Itoa(count)
return item
}
func (i extraAnnotationInjector) injectPersistentVolumeClaim(item *corev1.PersistentVolumeClaim) *corev1.PersistentVolumeClaim {
podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister()
pods, err := podLister.Pods(item.Namespace).List(labels.Everything())
if err != nil {
klog.Errorf("inject annotation failed %+v", err)
return item
}
item = item.DeepCopy()
if item.Annotations == nil {
item.Annotations = make(map[string]string, 0)
}
if isPvcInUse(pods, item.Name) {
item.Annotations["kubesphere.io/in-use"] = "true"
} else {
item.Annotations["kubesphere.io/in-use"] = "false"
}
return item
}
func isPvcInUse(pods []*corev1.Pod, pvcName string) bool {
for _, pod := range pods {
volumes := pod.Spec.Volumes
for _, volume := range volumes {
pvc := volume.PersistentVolumeClaim
if pvc != nil && pvc.ClaimName == pvcName {
return true
}
}
}
return false
}
func countPvcByStorageClass(scName string) (int, error) {
persistentVolumeClaimLister := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister()
all, err := persistentVolumeClaimLister.List(labels.Everything())
if err != nil {
return 0, err
}
count := 0
for _, item := range all {
if item.Spec.StorageClassName != nil {
if *item.Spec.StorageClassName == scName {
count++
}
} else if item.GetAnnotations()[corev1.BetaStorageClassAnnotation] == scName {
count++
}
}
return count, nil
}

View File

@@ -1,186 +0,0 @@
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resources
import (
"fmt"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"strings"
)
func init() {
resources[ConfigMaps] = &configMapSearcher{}
resources[CronJobs] = &cronJobSearcher{}
resources[DaemonSets] = &daemonSetSearcher{}
resources[Deployments] = &deploymentSearcher{}
resources[Ingresses] = &ingressSearcher{}
resources[Jobs] = &jobSearcher{}
resources[PersistentVolumeClaims] = &persistentVolumeClaimSearcher{}
resources[Secrets] = &secretSearcher{}
resources[Services] = &serviceSearcher{}
resources[StatefulSets] = &statefulSetSearcher{}
resources[Pods] = &podSearcher{}
resources[Roles] = &roleSearcher{}
resources[S2iBuilders] = &s2iBuilderSearcher{}
resources[S2iRuns] = &s2iRunSearcher{}
resources[HorizontalPodAutoscalers] = &hpaSearcher{}
resources[Applications] = &appSearcher{}
resources[Nodes] = &nodeSearcher{}
resources[Namespaces] = &namespaceSearcher{}
resources[ClusterRoles] = &clusterRoleSearcher{}
resources[StorageClasses] = &storageClassesSearcher{}
resources[S2iBuilderTemplates] = &s2iBuilderTemplateSearcher{}
resources[Workspaces] = &workspaceSearcher{}
}
var (
injector = extraAnnotationInjector{}
resources = make(map[string]resourceSearchInterface)
clusterResources = []string{Nodes, Workspaces, Namespaces, ClusterRoles, StorageClasses, S2iBuilderTemplates}
)
const (
Name = "name"
Label = "label"
OwnerKind = "ownerKind"
OwnerName = "ownerName"
TargetKind = "targetKind"
TargetName = "targetName"
Role = "role"
CreateTime = "createTime"
UpdateTime = "updateTime"
StartTime = "startTime"
LastScheduleTime = "lastScheduleTime"
chart = "chart"
release = "release"
annotation = "annotation"
Keyword = "keyword"
UserFacing = "userfacing"
Status = "status"
includeCronJob = "includeCronJob"
storageClassName = "storageClassName"
cronJobKind = "CronJob"
s2iRunKind = "S2iRun"
includeS2iRun = "includeS2iRun"
StatusRunning = "running"
StatusPaused = "paused"
StatusPending = "pending"
StatusUpdating = "updating"
StatusStopped = "stopped"
StatusFailed = "failed"
StatusBound = "bound"
StatusLost = "lost"
StatusComplete = "complete"
StatusWarning = "warning"
StatusUnschedulable = "unschedulable"
app = "app"
Deployments = "deployments"
DaemonSets = "daemonsets"
Roles = "roles"
Workspaces = "workspaces"
WorkspaceRoles = "workspaceroles"
CronJobs = "cronjobs"
ConfigMaps = "configmaps"
Ingresses = "ingresses"
Jobs = "jobs"
PersistentVolumeClaims = "persistentvolumeclaims"
Pods = "pods"
Secrets = "secrets"
Services = "services"
StatefulSets = "statefulsets"
HorizontalPodAutoscalers = "horizontalpodautoscalers"
Applications = "applications"
Nodes = "nodes"
Namespaces = "namespaces"
StorageClasses = "storageclasses"
ClusterRoles = "clusterroles"
S2iBuilderTemplates = "s2ibuildertemplates"
S2iBuilders = "s2ibuilders"
S2iRuns = "s2iruns"
)
type resourceSearchInterface interface {
get(namespace, name string) (interface{}, error)
search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error)
}
func GetResource(namespace, resource, name string) (interface{}, error) {
if searcher, ok := resources[resource]; ok {
resource, err := searcher.get(namespace, name)
if err != nil {
klog.Errorf("resource %s.%s.%s not found: %s", namespace, resource, name, err)
return nil, err
}
return resource, nil
}
return nil, fmt.Errorf("resource %s.%s.%s not found", namespace, resource, name)
}
func ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
items := make([]interface{}, 0)
var err error
var result []interface{}
// none namespace resource
if namespace != "" && sliceutil.HasString(clusterResources, resource) {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if searcher, ok := resources[resource]; ok {
result, err = searcher.search(namespace, conditions, orderBy, reverse)
} else {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if err != nil {
klog.Errorln(err)
return nil, err
}
if limit == -1 || limit+offset > len(result) {
limit = len(result) - offset
}
result = result[offset : offset+limit]
for _, item := range result {
items = append(items, injector.addExtraAnnotations(item))
}
return &models.PageableResponse{TotalCount: len(result), Items: items}, nil
}
func searchFuzzy(m map[string]string, key, value string) bool {
val, exist := m[key]
if value == "" && (!exist || val == "") {
return true
} else if value != "" && strings.Contains(val, value) {
return true
}
return false
}

View File

@@ -16,37 +16,49 @@
* /
*/
package resources
package application
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/informers"
"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 {
informer externalversions.SharedInformerFactory
}
func (*appSearcher) get(namespace, name string) (interface{}, error) {
return informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
func NewApplicationSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &appSearcher{informer: informers}
}
func (s *appSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
}
// exactly Match
func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,16 +75,16 @@ func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bo
func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
@@ -81,7 +93,7 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,17 +103,17 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo
func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *appSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
apps, err := informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
if err != nil {
return nil, err

View File

@@ -15,11 +15,12 @@
limitations under the License.
*/
package resources
package clusterrole
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"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"
@@ -31,34 +32,39 @@ import (
)
type clusterRoleSearcher struct {
informer informers.SharedInformerFactory
}
func (*clusterRoleSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().Get(name)
func NewClusterRoleSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface {
return &clusterRoleSearcher{informer: informer}
}
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 {
case OwnerKind:
case v1alpha2.OwnerKind:
fallthrough
case OwnerName:
kind := match[OwnerKind]
name := match[OwnerName]
case v1alpha2.OwnerName:
kind := match[v1alpha2.OwnerKind]
name := match[v1alpha2.OwnerName]
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
return false
}
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case UserFacing:
case v1alpha2.UserFacing:
if v == "true" {
if !isUserFacingClusterRole(item) {
return false
@@ -78,21 +84,21 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -102,17 +108,17 @@ func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRol
func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,12 @@
limitations under the License.
*/
package resources
package configmap
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +31,28 @@ import (
)
type configMapSearcher struct {
informer informers.SharedInformerFactory
}
func (*configMapSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
func NewConfigmapSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &configMapSearcher{informer: informers}
}
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 {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,25 +69,25 @@ func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) boo
func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,17 +97,17 @@ func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) boo
func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *configMapSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
configMaps, err := informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
if err != nil {
return nil, err
@@ -120,9 +126,7 @@ func (s *configMapSearcher) 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)
})

View File

@@ -15,11 +15,12 @@
limitations under the License.
*/
package resources
package cronjob
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -31,34 +32,39 @@ import (
)
type cronJobSearcher struct {
informer informers.SharedInformerFactory
}
func (*cronJobSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).Get(name)
func NewCronJobSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface {
return &cronJobSearcher{informer: informer}
}
func (c *cronJobSearcher) Get(namespace, name string) (interface{}, error) {
return c.informer.Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).Get(name)
}
func cronJobStatus(item *v1beta1.CronJob) string {
if item.Spec.Suspend != nil && *item.Spec.Suspend {
return StatusPaused
return v1alpha2.StatusPaused
}
return StatusRunning
return v1alpha2.StatusRunning
}
// Exactly Match
func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Status:
case v1alpha2.Status:
if cronJobStatus(item) != v {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -75,25 +81,25 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -104,7 +110,7 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo
func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool {
switch orderBy {
case LastScheduleTime:
case v1alpha2.LastScheduleTime:
if a.Status.LastScheduleTime == nil {
return true
}
@@ -112,17 +118,17 @@ func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool {
return false
}
return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime)
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
default:
fallthrough
case Name:
case v1alpha2.Name:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *cronJobSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
cronJobs, err := informers.SharedInformerFactory().Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).List(labels.Everything())
func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
cronJobs, err := c.informer.Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).List(labels.Everything())
if err != nil {
return nil, err
@@ -134,18 +140,16 @@ func (s *cronJobSearcher) search(namespace string, conditions *params.Conditions
result = cronJobs
} else {
for _, item := range cronJobs {
if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) {
if c.match(conditions.Match, item) && c.fuzzy(conditions.Fuzzy, item) {
result = append(result, item)
}
}
}
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 c.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)

View File

@@ -15,11 +15,12 @@
limitations under the License.
*/
package resources
package daemonset
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,19 +31,24 @@ import (
)
type daemonSetSearcher struct {
informer informers.SharedInformerFactory
}
func (*daemonSetSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
func NewDaemonSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &daemonSetSearcher{informer: informers}
}
func (c *daemonSetSearcher) Get(namespace, name string) (interface{}, error) {
return c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
}
func daemonSetStatus(item *v1.DaemonSet) string {
if item.Status.NumberAvailable == 0 {
return StatusStopped
return v1alpha2.StatusStopped
} else if item.Status.DesiredNumberScheduled == item.Status.NumberAvailable {
return StatusRunning
return v1alpha2.StatusRunning
} else {
return StatusUpdating
return v1alpha2.StatusUpdating
}
}
@@ -50,17 +56,17 @@ func daemonSetStatus(item *v1.DaemonSet) string {
func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool {
for k, v := range match {
switch k {
case Status:
case v1alpha2.Status:
if daemonSetStatus(item) != v {
return false
}
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -77,25 +83,25 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -106,17 +112,17 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo
func (*daemonSetSearcher) compare(a, b *v1.DaemonSet, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *daemonSetSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
daemonSets, err := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err
@@ -128,18 +134,16 @@ func (s *daemonSetSearcher) search(namespace string, conditions *params.Conditio
result = daemonSets
} else {
for _, item := range daemonSets {
if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) {
if c.match(conditions.Match, item) && c.fuzzy(conditions.Fuzzy, item) {
result = append(result, item)
}
}
}
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 c.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)

View File

@@ -15,12 +15,13 @@
* limitations under the License.
* /
*/
package resources
package hpa
import (
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,10 +31,15 @@ import (
)
type hpaSearcher struct {
informers informers.SharedInformerFactory
}
func (*hpaSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).Get(name)
func NewHpaSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &hpaSearcher{informers: informers}
}
func (s *hpaSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).Get(name)
}
func hpaTargetMatch(item *autoscalingv2beta2.HorizontalPodAutoscaler, kind, name string) bool {
@@ -44,21 +50,21 @@ func hpaTargetMatch(item *autoscalingv2beta2.HorizontalPodAutoscaler, kind, name
func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
for k, v := range match {
switch k {
case TargetKind:
case v1alpha2.TargetKind:
fallthrough
case TargetName:
kind := match[TargetKind]
name := match[TargetName]
case v1alpha2.TargetName:
kind := match[v1alpha2.TargetKind]
name := match[v1alpha2.TargetName]
if !hpaTargetMatch(item, kind, name) {
return false
}
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -74,25 +80,25 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) && !searchFuzzy(item.Annotations, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) && !v1alpha2.SearchFuzzy(item.Annotations, k, v) {
return false
}
}
@@ -102,18 +108,18 @@ func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.Hori
func (*hpaSearcher) compare(a, b *autoscalingv2beta2.HorizontalPodAutoscaler, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *hpaSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
horizontalPodAutoscalers, err := informers.SharedInformerFactory().Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything())
horizontalPodAutoscalers, err := s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything())
if err != nil {
return nil, err

View File

@@ -15,39 +15,45 @@
limitations under the License.
*/
package resources
package ingress
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/labels"
)
type ingressSearcher struct {
informers informers.SharedInformerFactory
}
func (*ingressSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name)
func NewIngressSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &ingressSearcher{informers: informers}
}
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 *extensions.Ingress) bool {
func (*ingressSearcher) match(match map[string]string, item *v1beta1.Ingress) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -61,28 +67,28 @@ func (*ingressSearcher) match(match map[string]string, item *extensions.Ingress)
}
// Fuzzy searchInNamespace
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress) bool {
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Ingress) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -90,25 +96,25 @@ func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress)
return true
}
func (*ingressSearcher) compare(a, b *extensions.Ingress, orderBy string) bool {
func (*ingressSearcher) compare(a, b *v1beta1.Ingress, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err
}
result := make([]*extensions.Ingress, 0)
result := make([]*v1beta1.Ingress, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = ingresses

View File

@@ -0,0 +1,80 @@
package v1alpha2
import (
"kubesphere.io/kubesphere/pkg/server/params"
"strings"
)
const (
App = "app"
Chart = "chart"
Release = "release"
Name = "name"
Label = "label"
OwnerKind = "ownerKind"
OwnerName = "ownerName"
TargetKind = "targetKind"
TargetName = "targetName"
Role = "role"
CreateTime = "createTime"
UpdateTime = "updateTime"
StartTime = "startTime"
LastScheduleTime = "lastScheduleTime"
Annotation = "Annotation"
Keyword = "keyword"
UserFacing = "userfacing"
Status = "status"
StatusRunning = "running"
StatusPaused = "paused"
StatusPending = "pending"
StatusUpdating = "updating"
StatusStopped = "stopped"
StatusFailed = "failed"
StatusBound = "bound"
StatusLost = "lost"
StatusComplete = "complete"
StatusWarning = "warning"
StatusUnschedulable = "unschedulable"
Deployments = "deployments"
DaemonSets = "daemonsets"
Roles = "roles"
Workspaces = "workspaces"
WorkspaceRoles = "workspaceroles"
CronJobs = "cronjobs"
ConfigMaps = "configmaps"
Ingresses = "ingresses"
Jobs = "jobs"
PersistentVolumeClaims = "persistentvolumeclaims"
Pods = "pods"
Secrets = "secrets"
Services = "services"
StatefulSets = "statefulsets"
HorizontalPodAutoscalers = "horizontalpodautoscalers"
Applications = "applications"
Nodes = "nodes"
Namespaces = "namespaces"
StorageClasses = "storageclasses"
ClusterRoles = "clusterroles"
S2iBuilderTemplates = "s2ibuildertemplates"
S2iBuilders = "s2ibuilders"
S2iRuns = "s2iruns"
)
type Interface interface {
Get(namespace, name string) (interface{}, error)
Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error)
}
func SearchFuzzy(m map[string]string, key, value string) bool {
val, exist := m[key]
if value == "" && (!exist || val == "") {
return true
} else if value != "" && strings.Contains(val, value) {
return true
}
return false
}

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package job
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"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"
@@ -31,21 +33,33 @@ import (
"k8s.io/apimachinery/pkg/labels"
)
const (
includeCronJob = "includeCronJob"
cronJobKind = "CronJob"
s2iRunKind = "S2iRun"
includeS2iRun = "includeS2iRun"
)
type jobSearcher struct {
informers informers.SharedInformerFactory
}
func (*jobSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Batch().V1().Jobs().Lister().Jobs(namespace).Get(name)
func NewJobSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &jobSearcher{informers: informers}
}
func (s *jobSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).Get(name)
}
func jobStatus(item *batchv1.Job) string {
status := StatusFailed
status := v1alpha2.StatusFailed
if item.Status.Active > 0 {
status = StatusRunning
status = v1alpha2.StatusRunning
} else if item.Status.Failed > 0 {
status = StatusFailed
status = v1alpha2.StatusFailed
} else if item.Status.Succeeded > 0 {
status = StatusComplete
status = v1alpha2.StatusComplete
}
return status
}
@@ -54,7 +68,7 @@ func jobStatus(item *batchv1.Job) string {
func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
for k, v := range match {
switch k {
case Status:
case v1alpha2.Status:
if jobStatus(item) != v {
return false
}
@@ -66,13 +80,13 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") {
return false
}
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -89,25 +103,25 @@ func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -131,19 +145,19 @@ func jobUpdateTime(item *batchv1.Job) time.Time {
func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case UpdateTime:
case v1alpha2.UpdateTime:
return jobUpdateTime(a).Before(jobUpdateTime(b))
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *jobSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
jobs, err := informers.SharedInformerFactory().Batch().V1().Jobs().Lister().Jobs(namespace).List(labels.Everything())
func (s *jobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
jobs, err := s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).List(labels.Everything())
if err != nil {
return nil, err

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package namespace
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type namespaceSearcher struct {
informers informers.SharedInformerFactory
}
func (*namespaceSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().Namespaces().Lister().Get(name)
func NewNamespaceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &namespaceSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,25 +70,21 @@ func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) boo
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,17 +94,17 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo
func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Core().V1().Namespaces().Lister().List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,12 +15,14 @@
limitations under the License.
*/
package resources
package node
import (
"fmt"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,40 +32,47 @@ import (
"k8s.io/apimachinery/pkg/labels"
)
const (
nodeConfigOK v1.NodeConditionType = "ConfigOK"
nodeKubeletReady v1.NodeConditionType = "KubeletReady"
)
type nodeSearcher struct {
informers informers.SharedInformerFactory
}
func (*nodeSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().Nodes().Lister().Get(name)
func NewNodeSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &nodeSearcher{informers: informers}
}
func (s *nodeSearcher) Get(_, name string) (interface{}, error) {
return s.informers.Core().V1().Nodes().Lister().Get(name)
}
func getNodeStatus(node *v1.Node) string {
if node.Spec.Unschedulable {
return StatusUnschedulable
return v1alpha2.StatusUnschedulable
}
for _, condition := range node.Status.Conditions {
if isUnhealthStatus(condition) {
return StatusWarning
if isUnhealthyStatus(condition) {
return v1alpha2.StatusWarning
}
}
return StatusRunning
return v1alpha2.StatusRunning
}
const NodeConfigOK v1.NodeConditionType = "ConfigOK"
const NodeKubeletReady v1.NodeConditionType = "KubeletReady"
var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{
v1.NodeMemoryPressure: v1.ConditionFalse,
v1.NodeDiskPressure: v1.ConditionFalse,
v1.NodePIDPressure: v1.ConditionFalse,
v1.NodeNetworkUnavailable: v1.ConditionFalse,
NodeConfigOK: v1.ConditionTrue,
NodeKubeletReady: v1.ConditionTrue,
nodeConfigOK: v1.ConditionTrue,
nodeKubeletReady: v1.ConditionTrue,
v1.NodeReady: v1.ConditionTrue,
}
func isUnhealthStatus(condition v1.NodeCondition) bool {
func isUnhealthyStatus(condition v1.NodeCondition) bool {
expectedStatus := expectedConditions[condition.Type]
if expectedStatus != "" && condition.Status != expectedStatus {
return true
@@ -75,22 +84,22 @@ func isUnhealthStatus(condition v1.NodeCondition) bool {
func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Role:
case v1alpha2.Role:
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
if _, ok := item.Labels[labelKey]; !ok {
return false
}
case Status:
case v1alpha2.Status:
if getNodeStatus(item) != v {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -107,25 +116,21 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -135,17 +140,17 @@ func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
func (*nodeSearcher) compare(a, b *v1.Node, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Core().V1().Nodes().Lister().List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,14 @@
limitations under the License.
*/
package resources
package persistentvolumeclaim
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"strconv"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -29,21 +32,30 @@ import (
"k8s.io/apimachinery/pkg/labels"
)
const (
storageClassName = "storageClassName"
)
type persistentVolumeClaimSearcher struct {
informers informers.SharedInformerFactory
}
func (*persistentVolumeClaimSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name)
func NewPersistentVolumeClaimSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &persistentVolumeClaimSearcher{informers: informers}
}
func (s *persistentVolumeClaimSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name)
}
func pvcStatus(item *v1.PersistentVolumeClaim) string {
status := StatusPending
status := v1alpha2.StatusPending
if item.Status.Phase == v1.ClaimPending {
status = StatusPending
status = v1alpha2.StatusPending
} else if item.Status.Phase == v1.ClaimBound {
status = StatusBound
status = v1alpha2.StatusBound
} else if item.Status.Phase == v1.ClaimLost {
status = StatusLost
status = v1alpha2.StatusLost
}
return status
}
@@ -52,12 +64,12 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string {
func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Status:
case v1alpha2.Status:
statuses := strings.Split(v, "|")
if !sliceutil.HasString(statuses, pvcStatus(item)) {
return false
@@ -66,8 +78,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -84,25 +96,25 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -112,17 +124,17 @@ func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.Pe
func (*persistentVolumeClaimSearcher) compare(a, b *v1.PersistentVolumeClaim, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err
@@ -150,7 +162,29 @@ func (s *persistentVolumeClaimSearcher) search(namespace string, conditions *par
r := make([]interface{}, 0)
for _, i := range result {
inUse := s.countPods(i.Name, i.Namespace)
if i.Annotations == nil {
i.Annotations = make(map[string]string)
}
i.Annotations["kubesphere.io/in-use"] = strconv.FormatBool(inUse)
r = append(r, i)
}
return r, nil
}
func (s *persistentVolumeClaimSearcher) countPods(name, namespace string) bool {
pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
if err != nil {
return false
}
for _, pod := range pods {
for _, pvc := range pod.Spec.Volumes {
if pvc.PersistentVolumeClaim != nil && pvc.PersistentVolumeClaim.ClaimName == name {
return true
}
}
}
return false
}

View File

@@ -15,12 +15,14 @@
limitations under the License.
*/
package resources
package pod
import (
appsv1 "k8s.io/api/apps/v1"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -31,16 +33,21 @@ import (
)
type podSearcher struct {
informers informers.SharedInformerFactory
}
func (*podSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().Pods().Lister().Pods(namespace).Get(name)
func NewPodSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &podSearcher{informers: informers}
}
func podBelongTo(item *v1.Pod, kind string, name string) bool {
func (s *podSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Pods().Lister().Pods(namespace).Get(name)
}
func (s *podSearcher) podBelongTo(item *v1.Pod, kind string, name string) bool {
switch kind {
case "Deployment":
if podBelongToDeployment(item, name) {
if s.podBelongToDeployment(item, name) {
return true
}
case "ReplicaSet":
@@ -108,8 +115,8 @@ func podBelongToStatefulSet(item *v1.Pod, statefulSetName string) bool {
return false
}
func podBelongToDeployment(item *v1.Pod, deploymentName string) bool {
replicas, err := informers.SharedInformerFactory().Apps().V1().ReplicaSets().Lister().ReplicaSets(item.Namespace).List(labels.Everything())
func (s *podSearcher) podBelongToDeployment(item *v1.Pod, deploymentName string) bool {
replicas, err := s.informers.Apps().V1().ReplicaSets().Lister().ReplicaSets(item.Namespace).List(labels.Everything())
if err != nil {
return false
}
@@ -133,8 +140,8 @@ func podBindPVC(item *v1.Pod, pvcName string) bool {
return false
}
func podBelongToService(item *v1.Pod, serviceName string) bool {
service, err := informers.SharedInformerFactory().Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName)
func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool {
service, err := s.informers.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName)
if err != nil {
return false
}
@@ -147,15 +154,15 @@ func podBelongToService(item *v1.Pod, serviceName string) bool {
}
// exactly Match
func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
for k, v := range match {
switch k {
case OwnerKind:
case v1alpha2.OwnerKind:
fallthrough
case OwnerName:
kind := match[OwnerKind]
name := match[OwnerName]
if !podBelongTo(item, kind, name) {
case v1alpha2.OwnerName:
kind := match[v1alpha2.OwnerKind]
name := match[v1alpha2.OwnerName]
if !s.podBelongTo(item, kind, name) {
return false
}
case "nodeName":
@@ -167,16 +174,16 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
return false
}
case "serviceName":
if !podBelongToService(item, v) {
if !s.podBelongToService(item, v) {
return false
}
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -193,25 +200,25 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -221,7 +228,7 @@ func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool {
switch orderBy {
case StartTime:
case v1alpha2.StartTime:
if a.Status.StartTime == nil {
return false
}
@@ -229,18 +236,18 @@ func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool {
return true
}
return a.Status.StartTime.Before(b.Status.StartTime)
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *podSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
func (s *podSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
pods, err := informers.SharedInformerFactory().Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
if err != nil {
return nil, err

View File

@@ -0,0 +1,137 @@
/*
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 resource
import (
"fmt"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/application"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"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/hpa"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/ingress"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/namespace"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/node"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/persistentvolumeclaim"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/pod"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2buildertemplate"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2ibuilder"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2irun"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/secret"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/service"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/statefulset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/storageclass"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/workspace"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
)
type ResourceGetter struct {
resourcesGetters map[string]v1alpha2.Interface
}
func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
resourceGetters := make(map[string]v1alpha2.Interface)
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.Ingresses] = ingress.NewIngressSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Secrets] = secret.NewSecretSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Services] = service.NewServiceSearcher(factory.KubernetesSharedInformerFactory())
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.S2iSharedInformerFactory())
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.S2iSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.S2iSharedInformerFactory())
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(factory.ApplicationSharedInformerFactory())
return &ResourceGetter{resourcesGetters: resourceGetters}
}
var (
//injector = v1alpha2.extraAnnotationInjector{}
clusterResources = []string{v1alpha2.Nodes, v1alpha2.Workspaces, v1alpha2.Namespaces, v1alpha2.ClusterRoles, v1alpha2.StorageClasses, v1alpha2.S2iBuilderTemplates}
)
func (r *ResourceGetter) GetResource(namespace, resource, name string) (interface{}, error) {
if searcher, ok := r.resourcesGetters[resource]; ok {
resource, err := searcher.Get(namespace, name)
if err != nil {
klog.Errorf("resource %s.%s.%s not found: %s", namespace, resource, name, err)
return nil, err
}
return resource, nil
}
return nil, fmt.Errorf("resource %s.%s.%s not found", namespace, resource, name)
}
func (r *ResourceGetter) ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
items := make([]interface{}, 0)
var err error
var result []interface{}
// none namespace resource
if namespace != "" && sliceutil.HasString(clusterResources, resource) {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if searcher, ok := r.resourcesGetters[resource]; ok {
result, err = searcher.Search(namespace, conditions, orderBy, reverse)
} else {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if err != nil {
klog.Errorln(err)
return nil, err
}
if limit == -1 || limit+offset > len(result) {
limit = len(result) - offset
}
result = result[offset : offset+limit]
return &models.PageableResponse{TotalCount: len(result), Items: items}, nil
}

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package role
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,26 +32,31 @@ import (
)
type roleSearcher struct {
informers informers.SharedInformerFactory
}
func (*roleSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Rbac().V1().Roles().Lister().Roles(namespace).Get(name)
func NewRoleSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &roleSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case UserFacing:
case v1alpha2.UserFacing:
if v == "true" {
if !isUserFacingRole(item) {
return false
@@ -69,21 +76,21 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -93,17 +100,17 @@ func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
func (*roleSearcher) compare(a, b *rbac.Role, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,12 +15,14 @@
limitations under the License.
*/
package resources
package s2buildertemplate
import (
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type s2iBuilderTemplateSearcher struct {
informers externalversions.SharedInformerFactory
}
func (*s2iBuilderTemplateSearcher) get(namespace, name string) (interface{}, error) {
return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name)
func NewS2iBuidlerTemplateSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iBuilderTemplateSearcher{informers: informers}
}
func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, error) {
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,21 +70,21 @@ func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1
func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -87,17 +94,17 @@ func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1
func (*s2iBuilderTemplateSearcher) compare(a, b *v1alpha1.S2iBuilderTemplate, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -16,13 +16,15 @@
*/
package resources
package s2ibuilder
import (
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type s2iBuilderSearcher struct {
informers externalversions.SharedInformerFactory
}
func (*s2iBuilderSearcher) get(namespace, name string) (interface{}, error) {
return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name)
func NewS2iBuilderSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iBuilderSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,25 +70,21 @@ func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuil
func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,17 +94,17 @@ func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuil
func (*s2iBuilderSearcher) compare(a, b *v1alpha1.S2iBuilder, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -16,15 +16,17 @@
*/
package resources
package s2irun
import (
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/server/params"
"k8s.io/apimachinery/pkg/labels"
@@ -33,27 +35,32 @@ import (
)
type s2iRunSearcher struct {
informers externalversions.SharedInformerFactory
}
func (*s2iRunSearcher) get(namespace, name string) (interface{}, error) {
return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name)
func NewS2iRunSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iRunSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Status:
case v1alpha2.Status:
if string(item.Status.RunState) != v {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -70,25 +77,21 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo
func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -98,17 +101,17 @@ func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) boo
func (*s2iRunSearcher) compare(a, b *v1alpha1.S2iRun, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package secret
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,17 +32,22 @@ import (
)
type secretSearcher struct {
informers informers.SharedInformerFactory
}
func (*secretSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).Get(name)
func NewSecretSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &secretSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
@@ -49,8 +56,8 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
if string(item.Type) != v {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -67,25 +74,25 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -95,17 +102,17 @@ func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
func (*secretSearcher) compare(a, b *v1.Secret, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package service
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type serviceSearcher struct {
informers informers.SharedInformerFactory
}
func (*serviceSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Core().V1().Services().Lister().Services(namespace).Get(name)
func NewServiceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &serviceSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,25 +70,25 @@ func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool {
func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,17 +98,17 @@ func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
func (*serviceSearcher) compare(a, b *v1.Service, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Core().V1().Services().Lister().Services(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package statefulset
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,39 +32,44 @@ import (
)
type statefulSetSearcher struct {
informers informers.SharedInformerFactory
}
func (*statefulSetSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name)
func NewStatefulSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &statefulSetSearcher{informers: informers}
}
func (s *statefulSetSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name)
}
func statefulSetStatus(item *v1.StatefulSet) string {
if item.Spec.Replicas != nil {
if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 {
return StatusStopped
return v1alpha2.StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return StatusRunning
return v1alpha2.StatusRunning
} else {
return StatusUpdating
return v1alpha2.StatusUpdating
}
}
return StatusStopped
return v1alpha2.StatusStopped
}
// Exactly Match
func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool {
for k, v := range match {
switch k {
case Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
case Status:
case v1alpha2.Status:
if statefulSetStatus(item) != v {
return false
}
@@ -80,25 +87,25 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet)
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
case v1alpha2.App:
if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -109,17 +116,17 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet)
func (*statefulSetSearcher) compare(a, b *v1.StatefulSet, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything())
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())
if err != nil {
return nil, err

View File

@@ -15,11 +15,13 @@
limitations under the License.
*/
package resources
package storageclass
import (
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type storageClassesSearcher struct {
informers informers.SharedInformerFactory
}
func (*storageClassesSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister().Get(name)
func NewStorageClassesSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &storageClassesSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,21 +70,21 @@ func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageCl
func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -87,17 +94,17 @@ func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageCl
func (*storageClassesSearcher) compare(a, b *v1.StorageClass, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
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 := informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister().List(labels.Everything())
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())
if err != nil {
return nil, err
@@ -116,16 +123,36 @@ func (s *storageClassesSearcher) search(namespace string, conditions *params.Con
}
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)
})
r := make([]interface{}, 0)
for _, i := range result {
count := s.countPersistentVolumeClaims(i.Name)
if i.Annotations == nil {
i.Annotations = make(map[string]string)
i.Annotations["kubesphere.io/pvc-count"] = string(count)
}
r = append(r, i)
}
return r, nil
}
func (s *storageClassesSearcher) countPersistentVolumeClaims(name string) int {
pvcs, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().List(labels.Everything())
if err != nil {
return 0
}
var count int
for _, pvc := range pvcs {
if *pvc.Spec.StorageClassName == name || (pvc.Annotations != nil && pvc.Annotations[corev1.BetaStorageClassAnnotation] == name) {
count++
}
}
return count
}

View File

@@ -15,12 +15,14 @@
limitations under the License.
*/
package resources
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/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
@@ -30,23 +32,28 @@ import (
)
type workspaceSearcher struct {
informers externalversions.SharedInformerFactory
}
func (*workspaceSearcher) get(namespace, name string) (interface{}, error) {
return informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().Get(name)
func NewWorkspaceSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &workspaceSearcher{informers: informers}
}
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 Name:
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
default:
@@ -63,25 +70,21 @@ func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Wo
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool {
for k, v := range fuzzy {
switch k {
case Name:
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
case v1alpha2.Label:
if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
case v1alpha2.Annotation:
if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false
}
}
@@ -91,18 +94,18 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Wo
func (*workspaceSearcher) compare(a, b *tenantv1alpha1.Workspace, orderBy string) bool {
switch orderBy {
case CreateTime:
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name:
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *workspaceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
workspaces, err := informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
if err != nil {
return nil, err

View File

@@ -0,0 +1,131 @@
/*
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/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"strings"
"time"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/api/apps/v1"
)
const (
applicationLabel = "app.kubernetes.io/name"
ReleaseLabel = "relase"
statusStopped = "stopped"
statusRunning = "running"
statusUpdating = "updating"
)
type deploymentsGetter struct {
sharedInformers informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &deploymentsGetter{sharedInformers: sharedInformers}
}
func (d *deploymentsGetter) Get(namespace, name string) (interface{}, error) {
return d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
}
func (d *deploymentsGetter) List(namespace string) ([]interface{}, error) {
// first retrieves all deployments within given namespace
all, err := d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var result []interface{}
for _, deploy := range all {
result = append(result, deploy)
}
return result, nil
}
func (d *deploymentsGetter) Compare(left interface{}, right interface{}, field query.Field) bool {
leftDeployment, ok := left.(*v1.Deployment)
if !ok {
return false
}
rightDeployment, ok := right.(*v1.Deployment)
if !ok {
return false
}
switch field {
case query.FieldCreationTimeStamp:
return leftDeployment.CreationTimestamp.After(rightDeployment.CreationTimestamp.Time)
case query.FieldLastUpdateTimestamp:
return lastUpdateTime(leftDeployment).After(lastUpdateTime(rightDeployment))
default:
fallthrough
case query.FieldName:
return strings.Compare(leftDeployment.Name, rightDeployment.Name) > 0
}
}
func (d *deploymentsGetter) Filter(object interface{}, filter query.Filter) bool {
deployment, ok := object.(*v1.Deployment)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return query.ComparableString(deployment.Name).Contains(filter.Value)
case query.FieldApplication:
if app, ok := deployment.Labels[applicationLabel]; ok {
return query.ComparableString(app).Contains(filter.Value)
}
case query.FieldStatus:
return filter.Value.Compare(query.ComparableString(deploymentStatus(deployment.Status))) == 0
default:
return false
}
return false
}
func deploymentStatus(status v1.DeploymentStatus) string {
if status.ReadyReplicas == 0 && status.Replicas == 0 {
return statusStopped
} else if status.ReadyReplicas == status.Replicas {
return statusRunning
} else {
return statusUpdating
}
}
func lastUpdateTime(deployment *v1.Deployment) time.Time {
lut := deployment.CreationTimestamp.Time
for _, condition := range deployment.Status.Conditions {
if condition.LastUpdateTime.After(lut) {
lut = condition.LastUpdateTime.Time
}
}
return lut
}

View File

@@ -0,0 +1,150 @@
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"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"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
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,
Page: 1,
},
SortBy: query.FieldName,
Ascending: false,
Filters: []query.Filter{
{
Field: query.FieldName,
Value: query.ComparableString("foo"),
},
},
},
api.ListResult{
Items: []interface{}{
v1.Deployment{
ObjectMeta: metaV1.ObjectMeta{
Name: "foo-2",
Namespace: "bar",
},
},
},
TotalItems: 2,
},
nil,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
objs := deploymentsToRuntimeObjects(test.deployments...)
client := fake.NewSimpleClientset(objs...)
//client := fake.NewSimpleClientset()
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}

View File

@@ -0,0 +1,19 @@
package v1alpha3
import (
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
type Interface interface {
// Get retrieves a single object by its namespace and name
Get(namespace, name string) (interface{}, error)
// List retrieves a collection of objects matches given query
List(namespace string) ([]interface{}, error)
//
Filter(item interface{}, filter query.Filter) bool
//
Compare(left interface{}, right interface{}, field query.Field) bool
}

View File

@@ -0,0 +1,98 @@
package resource
import (
"errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/deployment"
"sort"
)
var ErrResourceNotSupported = errors.New("resource is not supported")
type NamespacedResourceGetter struct {
getters map[schema.GroupVersionResource]v1alpha3.Interface
}
func New(informers informers.SharedInformerFactory) *NamespacedResourceGetter {
getters := make(map[schema.GroupVersionResource]v1alpha3.Interface)
getters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(informers)
return &NamespacedResourceGetter{
getters: getters,
}
}
// tryResource will retrieve a getter with resource name, it doesn't guarantee find resource with correct group version
// need to refactor this use schema.GroupVersionResource
func (r *NamespacedResourceGetter) tryResource(resource string) v1alpha3.Interface {
for k, v := range r.getters {
if k.Resource == resource {
return v
}
}
return nil
}
func (r *NamespacedResourceGetter) Get(resource, namespace, name string) (interface{}, error) {
getter := r.tryResource(resource)
if getter == nil {
return nil, ErrResourceNotSupported
}
return getter.Get(namespace, name)
}
func (r *NamespacedResourceGetter) List(resource, namespace string, query *query.Query) (*api.ListResult, error) {
getter := r.tryResource(resource)
if getter == nil {
return nil, ErrResourceNotSupported
}
all, err := getter.List(namespace)
if err != nil {
return nil, err
}
// selected matched ones
var filtered []interface{}
for _, deploy := range all {
for _, filter := range query.Filters {
if getter.Filter(deploy, filter) {
filtered = append(filtered, deploy)
}
}
}
// sort
sort.Slice(filtered, func(i, j int) bool {
if !query.Ascending {
return !getter.Compare(filtered[i], filtered[j], query.SortBy)
}
return getter.Compare(filtered[i], filtered[j], query.SortBy)
})
start, end := query.Pagination.GetPaginationSettings(len(filtered))
if query.Pagination.IsPageAvailable(len(filtered), start) {
var result []interface{}
for i := start; i < end; i++ {
result = append(result, filtered[i])
}
return &api.ListResult{
Items: result,
TotalItems: len(filtered),
}, nil
}
return &api.ListResult{
Items: nil,
TotalItems: len(filtered),
}, nil
}