diff --git a/pkg/models/resources/v1alpha2/cronjob/cronjobs.go b/pkg/models/resources/v1alpha2/cronjob/cronjobs.go index 6bd33933f98b08ef72a2533206b6fae440fb15f0..4aec0177cc5685ef8317a30278c5d20a16605d4f 100644 --- a/pkg/models/resources/v1alpha2/cronjob/cronjobs.go +++ b/pkg/models/resources/v1alpha2/cronjob/cronjobs.go @@ -106,12 +106,16 @@ func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions } } sort.Slice(result, func(i, j int) bool { - return c.compare(result[i], result[j], orderBy) && !reverse + if reverse { + return !c.compare(result[i], result[j], orderBy) + } else { + return c.compare(result[i], result[j], orderBy) + } }) r := make([]interface{}, 0) - for _, i := range result { - r = append(r, i) + for i := range result { + r = append(r, result[i]) } return r, nil } diff --git a/pkg/models/resources/v1alpha2/interface.go b/pkg/models/resources/v1alpha2/interface.go index 3dc0816ce0ede61cdb095783ef9cb7e59629e564..446fe083482309c801c478eb0c3c12cd0bdb75e7 100644 --- a/pkg/models/resources/v1alpha2/interface.go +++ b/pkg/models/resources/v1alpha2/interface.go @@ -140,8 +140,11 @@ func FuzzyMatch(m map[string]string, key, value string) bool { func ObjectMetaCompare(left, right metav1.ObjectMeta, compareField string) bool { switch compareField { case CreateTime: - if left.CreationTimestamp.Equal(&right.CreationTimestamp) { - return strings.Compare(left.Name, right.Name) <= 0 + if left.CreationTimestamp.Time.Equal(right.CreationTimestamp.Time) { + if left.Namespace == right.Namespace { + return strings.Compare(left.Name, right.Name) < 0 + } + return strings.Compare(left.Namespace, right.Namespace) < 0 } return left.CreationTimestamp.Time.Before(right.CreationTimestamp.Time) case Name: diff --git a/pkg/models/resources/v1alpha3/daemonset/daemonset.go b/pkg/models/resources/v1alpha3/daemonset/daemonset.go index f124985ba7295b14f14baa9fe07ea40b36ec2ca5..41543128dd74d8119d8168291b7d34c527b4246c 100644 --- a/pkg/models/resources/v1alpha3/daemonset/daemonset.go +++ b/pkg/models/resources/v1alpha3/daemonset/daemonset.go @@ -23,6 +23,13 @@ import ( "kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/apiserver/query" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "strings" +) + +const ( + statusStopped = "stopped" + statusRunning = "running" + statusUpdating = "updating" ) type daemonSetGetter struct { @@ -72,5 +79,20 @@ func (d *daemonSetGetter) filter(object runtime.Object, filter query.Filter) boo if !ok { return false } - return v1alpha3.DefaultObjectMetaFilter(daemonSet.ObjectMeta, filter) + switch filter.Field { + case query.FieldStatus: + return strings.Compare(daemonsetStatus(&daemonSet.Status), string(filter.Value)) == 0 + default: + return v1alpha3.DefaultObjectMetaFilter(daemonSet.ObjectMeta, filter) + } +} + +func daemonsetStatus(status *appsv1.DaemonSetStatus) string { + if status.DesiredNumberScheduled == 0 && status.NumberReady == 0 { + return statusStopped + } else if status.DesiredNumberScheduled == status.NumberReady { + return statusRunning + } else { + return statusUpdating + } } diff --git a/pkg/models/resources/v1alpha3/deployment/deployments.go b/pkg/models/resources/v1alpha3/deployment/deployments.go index 8d422d05e2c6d0650af7b09c1e5f5d68a6610f14..6c89bab326d3a257e83d75768505652951afbf28 100644 --- a/pkg/models/resources/v1alpha3/deployment/deployments.go +++ b/pkg/models/resources/v1alpha3/deployment/deployments.go @@ -90,7 +90,6 @@ func (d *deploymentsGetter) filter(object runtime.Object, filter query.Filter) b } switch filter.Field { - case query.FieldStatus: return strings.Compare(deploymentStatus(deployment.Status), string(filter.Value)) == 0 default: diff --git a/pkg/models/resources/v1alpha3/ingress/ingresses.go b/pkg/models/resources/v1alpha3/ingress/ingresses.go new file mode 100644 index 0000000000000000000000000000000000000000..db7f2bdcf1d42a7a07dc3b2c3ab6a00c8b9d19c1 --- /dev/null +++ b/pkg/models/resources/v1alpha3/ingress/ingresses.go @@ -0,0 +1,85 @@ +/* +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 ingress + +import ( + "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" +) + +type ingressGetter struct { + sharedInformers informers.SharedInformerFactory +} + +func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface { + return &ingressGetter{sharedInformers: sharedInformers} +} + +func (g *ingressGetter) Get(namespace, name string) (runtime.Object, error) { + return g.sharedInformers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name) +} + +func (g *ingressGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { + // first retrieves all deployments within given namespace + ingresses, err := g.sharedInformers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(query.Selector()) + if err != nil { + return nil, err + } + + var result []runtime.Object + for _, ingress := range ingresses { + result = append(result, ingress) + } + + return v1alpha3.DefaultList(result, query, g.compare, g.filter), nil +} + +func (g *ingressGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool { + + leftIngress, ok := left.(*v1beta1.Ingress) + if !ok { + return false + } + + rightIngress, ok := right.(*v1beta1.Ingress) + if !ok { + return false + } + + switch field { + case query.FieldUpdateTime: + fallthrough + default: + return v1alpha3.DefaultObjectMetaCompare(leftIngress.ObjectMeta, rightIngress.ObjectMeta, field) + } +} + +func (g *ingressGetter) filter(object runtime.Object, filter query.Filter) bool { + deployment, ok := object.(*v1beta1.Ingress) + if !ok { + return false + } + + switch filter.Field { + default: + return v1alpha3.DefaultObjectMetaFilter(deployment.ObjectMeta, filter) + } +} diff --git a/pkg/models/resources/v1alpha3/ingress/ingresses_test.go b/pkg/models/resources/v1alpha3/ingress/ingresses_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cb72dfcab191de63113a10a547256ba5cf7d1981 --- /dev/null +++ b/pkg/models/resources/v1alpha3/ingress/ingresses_test.go @@ -0,0 +1,114 @@ +/* +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 ingress + +import ( + "github.com/google/go-cmp/cmp" + "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "testing" +) + +func TestListIngresses(t *testing.T) { + tests := []struct { + description string + namespace string + query *query.Query + expected *api.ListResult + expectedErr error + }{ + { + "test name filter", + "bar", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 1, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")}, + }, + &api.ListResult{ + Items: []interface{}{ + foo2, + }, + TotalItems: 1, + }, + nil, + }, + } + + getter := prepare() + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + + got, err := getter.List(test.namespace, test.query) + + if test.expectedErr != nil && err != test.expectedErr { + t.Errorf("expected error, got nothing") + } else if err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("%T differ (-got, +want): %s", test.expected, diff) + } + }) + } +} + +var ( + foo1 = &v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo1", + Namespace: "bar", + }, + } + + foo2 = &v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo2", + Namespace: "bar", + }, + } + bar1 = &v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar1", + Namespace: "bar", + }, + } + + ingresses = []interface{}{foo1, foo2, bar1} +) + +func prepare() v1alpha3.Interface { + client := fake.NewSimpleClientset() + informer := informers.NewSharedInformerFactory(client, 0) + + for _, ingress := range ingresses { + informer.Extensions().V1beta1().Ingresses().Informer().GetIndexer().Add(ingress) + } + + return New(informer) +} diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go index 25c429087b62d30b0ce67d29236399107e03fcdc..f2b1ce6da02001842c4c1ba3370c312ba3049d7f 100644 --- a/pkg/models/resources/v1alpha3/resource/resource.go +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -43,6 +43,7 @@ import ( "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatednamespace" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/globalrole" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/globalrolebinding" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/ingress" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/namespace" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/networkpolicy" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/node" @@ -77,6 +78,7 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter { getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}] = configmap.New(factory.KubernetesSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}] = pod.New(factory.KubernetesSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "nodes"}] = node.New(factory.KubernetesSharedInformerFactory()) + getters[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "ingresses"}] = ingress.New(factory.KubernetesSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(factory.ApplicationSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"}] = networkpolicy.New(factory.KubernetesSharedInformerFactory()) getters[devopsv1alpha3.SchemeGroupVersion.WithResource(devopsv1alpha3.ResourcePluralDevOpsProject)] = devops.New(factory.KubeSphereSharedInformerFactory())