From a2efda820d3f5771abf5d34875f89b50245baf7c Mon Sep 17 00:00:00 2001 From: f10atin9 Date: Tue, 24 Aug 2021 10:59:59 +0800 Subject: [PATCH 1/3] add pv.go Signed-off-by: f10atin9 --- pkg/apiserver/apiserver.go | 1 + .../persistentvolume/persistentvolume.go | 87 +++++++++++ .../persistentvolume/persistentvolume_test.go | 140 ++++++++++++++++++ .../resources/v1alpha3/resource/resource.go | 2 + 4 files changed, 230 insertions(+) create mode 100644 pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go create mode 100644 pkg/models/resources/v1alpha3/persistentvolume/persistentvolume_test.go diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 09f171b4b..783ca0fda 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -390,6 +390,7 @@ func (s *APIServer) waitForResourceSync(ctx context.Context) error { {Group: "", Version: "v1", Resource: "pods"}, {Group: "", Version: "v1", Resource: "services"}, {Group: "", Version: "v1", Resource: "persistentvolumeclaims"}, + {Group: "", Version: "v1", Resource: "persistentvolumes"}, {Group: "", Version: "v1", Resource: "secrets"}, {Group: "", Version: "v1", Resource: "configmaps"}, {Group: "", Version: "v1", Resource: "serviceaccounts"}, diff --git a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go new file mode 100644 index 000000000..65b7f2658 --- /dev/null +++ b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go @@ -0,0 +1,87 @@ +/* +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 persistentvolume + +import ( + "strings" + + v1 "k8s.io/api/core/v1" + "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" +) + +const ( + storageClassName = "storageClassName" +) + +type persistentVolumeGetter struct { + informers informers.SharedInformerFactory +} + +func New(informer informers.SharedInformerFactory) v1alpha3.Interface { + return &persistentVolumeGetter{informers: informer} +} + +func (p *persistentVolumeGetter) Get(namespace, name string) (runtime.Object, error) { + pv, err := p.informers.Core().V1().PersistentVolumes().Lister().Get(name) + if err != nil { + return pv, err + } + return pv, nil +} + +func (p *persistentVolumeGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { + all, err := p.informers.Core().V1().PersistentVolumes().Lister().List(query.Selector()) + if err != nil { + return nil, err + } + var result []runtime.Object + for _, pv := range all { + result = append(result, pv) + } + return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil +} + +func (p *persistentVolumeGetter) compare(obj1, obj2 runtime.Object, field query.Field) bool { + pv1, ok := obj1.(*v1.PersistentVolume) + if !ok { + return false + } + pv2, ok := obj2.(*v1.PersistentVolume) + if !ok { + return false + } + return v1alpha3.DefaultObjectMetaCompare(pv1.ObjectMeta, pv2.ObjectMeta, field) +} + +func (p *persistentVolumeGetter) filter(object runtime.Object, filter query.Filter) bool { + pv, ok := object.(*v1.PersistentVolume) + if !ok { + return false + } + switch filter.Field { + case query.FieldStatus: + return strings.EqualFold(string(pv.Status.Phase), string(filter.Value)) + case storageClassName: + return pv.Spec.StorageClassName != "" && pv.Spec.StorageClassName == string(filter.Value) + default: + return v1alpha3.DefaultObjectMetaFilter(pv.ObjectMeta, filter) + } +} diff --git a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume_test.go b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume_test.go new file mode 100644 index 000000000..9f7a01f7e --- /dev/null +++ b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume_test.go @@ -0,0 +1,140 @@ +/* +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 persistentvolume + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" +) + +var ( + testStorageClassName = "test-csi" +) + +func TestListPods(t *testing.T) { + tests := []struct { + description string + namespace string + query *query.Query + expected *api.ListResult + expectedErr error + }{ + { + "test name filter", + "", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{}, + }, + &api.ListResult{ + Items: []interface{}{pv3, pv2, pv1}, + TotalItems: len(persistentVolumes), + }, + nil, + }, + { + "test status filter", + "", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{ + query.FieldStatus: query.Value(pv1.Status.Phase), + }, + }, + &api.ListResult{ + Items: []interface{}{pv1}, + TotalItems: 1, + }, + nil, + }, + } + + getter := prepare() + + for _, test := range tests { + got, err := getter.List(test.namespace, test.query) + if test.expectedErr != nil && err != test.expectedErr { + t.Errorf("expected error, got nothing") + } else if err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("[%s] %T differ (-got, +want): %s", test.description, test.expected, diff) + } + } +} + +var ( + pv1 = &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "pv-1", + }, + Status: corev1.PersistentVolumeStatus{ + Phase: "bound", + }, + } + pv2 = &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pv-2", + }, + Status: corev1.PersistentVolumeStatus{ + Phase: "available", + }, + Spec: corev1.PersistentVolumeSpec{ + StorageClassName: testStorageClassName, + }, + } + pv3 = &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-3", + Namespace: "default", + }, + } + + persistentVolumes = []interface{}{pv1, pv2, pv3} +) + +func prepare() v1alpha3.Interface { + client := fake.NewSimpleClientset() + informer := informers.NewSharedInformerFactory(client, 0) + + for _, pv := range persistentVolumes { + _ = informer.Core().V1().PersistentVolumes().Informer().GetIndexer().Add(pv) + } + return New(informer) +} diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go index 0750bc171..275be51ee 100644 --- a/pkg/models/resources/v1alpha3/resource/resource.go +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -18,6 +18,7 @@ package resource import ( "errors" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolume" snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1" rbacv1 "k8s.io/api/rbac/v1" @@ -113,6 +114,7 @@ func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *Re namespacedResourceGetters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] = job.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(cache) namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}] = persistentvolumeclaim.New(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory()) + namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}] = persistentvolume.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[snapshotv1beta1.SchemeGroupVersion.WithResource("volumesnapshots")] = volumesnapshot.New(factory.SnapshotSharedInformerFactory()) namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRoleBinding)] = rolebinding.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRole)] = role.New(factory.KubernetesSharedInformerFactory()) From faca83436446818034deb516d45849f16e41a892 Mon Sep 17 00:00:00 2001 From: f10atin9 Date: Fri, 3 Sep 2021 14:38:57 +0800 Subject: [PATCH 2/3] update goimports Signed-off-by: f10atin9 --- .../v1alpha3/persistentvolume/persistentvolume.go | 9 +++++---- pkg/models/resources/v1alpha3/resource/resource.go | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go index 65b7f2658..8dad9a4fd 100644 --- a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go +++ b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go @@ -19,9 +19,10 @@ package persistentvolume import ( "strings" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" "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" @@ -60,11 +61,11 @@ func (p *persistentVolumeGetter) List(namespace string, query *query.Query) (*ap } func (p *persistentVolumeGetter) compare(obj1, obj2 runtime.Object, field query.Field) bool { - pv1, ok := obj1.(*v1.PersistentVolume) + pv1, ok := obj1.(*corev1.PersistentVolume) if !ok { return false } - pv2, ok := obj2.(*v1.PersistentVolume) + pv2, ok := obj2.(*corev1.PersistentVolume) if !ok { return false } @@ -72,7 +73,7 @@ func (p *persistentVolumeGetter) compare(obj1, obj2 runtime.Object, field query. } func (p *persistentVolumeGetter) filter(object runtime.Object, filter query.Filter) bool { - pv, ok := object.(*v1.PersistentVolume) + pv, ok := object.(*corev1.PersistentVolume) if !ok { return false } diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go index 275be51ee..0cb811515 100644 --- a/pkg/models/resources/v1alpha3/resource/resource.go +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -18,6 +18,7 @@ package resource import ( "errors" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolume" snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1" From 463feb8a618efd6da636fb8bafca31f14f1b4361 Mon Sep 17 00:00:00 2001 From: f10atin9 Date: Mon, 6 Sep 2021 10:44:46 +0800 Subject: [PATCH 3/3] update return and apiserver Signed-off-by: f10atin9 --- .../resources/v1alpha3/persistentvolume/persistentvolume.go | 5 +---- pkg/models/resources/v1alpha3/resource/resource.go | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go index 8dad9a4fd..32646e268 100644 --- a/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go +++ b/pkg/models/resources/v1alpha3/persistentvolume/persistentvolume.go @@ -42,10 +42,7 @@ func New(informer informers.SharedInformerFactory) v1alpha3.Interface { func (p *persistentVolumeGetter) Get(namespace, name string) (runtime.Object, error) { pv, err := p.informers.Core().V1().PersistentVolumes().Lister().Get(name) - if err != nil { - return pv, err - } - return pv, nil + return pv, err } func (p *persistentVolumeGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go index 0cb811515..51e559d51 100644 --- a/pkg/models/resources/v1alpha3/resource/resource.go +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -114,8 +114,8 @@ func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *Re namespacedResourceGetters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"}] = networkpolicy.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] = job.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(cache) + clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}] = persistentvolume.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}] = persistentvolumeclaim.New(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory()) - namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}] = persistentvolume.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[snapshotv1beta1.SchemeGroupVersion.WithResource("volumesnapshots")] = volumesnapshot.New(factory.SnapshotSharedInformerFactory()) namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRoleBinding)] = rolebinding.New(factory.KubernetesSharedInformerFactory()) namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRole)] = role.New(factory.KubernetesSharedInformerFactory())